Why my bootloader can't find the kernel?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Mohamed007
Posts: 14
Joined: Fri Jul 08, 2016 8:44 pm

Why my bootloader can't find the kernel?

Post by Mohamed007 »

I wrote a simple bootloader and i tried it and it works very well but when i copy 2 files to the floppy drive the bootloader failed to catch the kernel
I copy the kernel.bin file to the floppy drive then write the bootloader to the bootsector using debug command

And this is the root directory and FAT setup, what's wrong?

Code: Select all

MOV [BOOT_DEVICE], DL         

;1- SETTING UP AND LOADING THE ROOT DIR.
MOV AH, 02H					
MOV AL, 14						
MOV BX, TEMP					      
MOV CH, 0 						
MOV CL, 2						
MOV DH, 1						
PUSHA							
LOAD_RD:
INT 13H
JNC LOAD_RD_DONE			        	
CALL RESET_DRIVE				        
JMP LOAD_RD						


LOAD_RD_DONE:
POPA

MOV DI, TEMP					       
MOV CX, 224						

FIND_KERNEL:
PUSH CX							
POP DX						
MOV SI, FILE_NAME				       
MOV CX, 11						
REP CMPSB						

JE FOUND_KERNEL					       

ADD AX, 32
MOV DI, TEMP
ADD DI, AX
PUSH DX
POP CX

LOOP FIND_KERNEL
MOV SI, FAILED_TO_LOAD_KERNEL
CALL ECHO
CLI
INT 18H	


FOUND_KERNEL:                                        
MOV AX, WORD [DI+15]			               
MOV [ENTERY_POINT], AX




MOV AX, 1
MOV BX, TEMP					       
CALL LOG_TO_HTS
MOV AH, 2				
MOV AL, 9						
PUSHA				
LOAD_FAT:
INT 13H
JNC LOAD_FAT_DONE				      
CALL RESET_DRIVE				        
JMP LOAD_FAT					        


LOAD_FAT_DONE:					     
MOV AH, 2
MOV AL, 1 
PUSH AX

LOAD_SECTOR:					 
MOV AX, WORD [ENTERY_POINT]
ADD AX, 31			

LOG_TO_HTS:
PUSH BX
PUSH AX
MOV BX, AX
MOV DX, 0
DIV WORD[ALL_SECTORS]
ADD DL, 01H
MOV CL, DL
MOV AX, BX
MOV DX, 0
DIV WORD [ALL_SECTORS]
MOV DX, 0 
DIV WORD[FACES]
MOV DH, DL
MOV CH, AL
POP AX
POP BX
MOV DL, BYTE [BOOT_DEVICE]
RET

Thanks
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: Why my bootloader can't find the kernel?

Post by BenLunt »

Mohamed007 wrote:I wrote a simple bootloader and i tried it and it works very well but when i copy 2 files to the floppy drive the bootloader failed to catch the kernel I copy the kernel.bin file to the floppy drive then write the bootloader to the bootsector using debug command.
And this is the root directory and FAT setup, what's wrong?
How do you know it works very well with no files on the disk. You state that it doesn't work as soon as you copy a file (or two). Are there already files on the disk and then you try to copy your kernel.bin file to the disk, replacing an existing one? Do I take it as when you replace an existing kernel.bin file with a new one, then it stops working as expected? If this is the case, this would give a clue.

Anyway, my comments are as follows:

Code: Select all

;;; this assumes DS has been set up and usable.
MOV [BOOT_DEVICE], DL

;1- SETTING UP AND LOADING THE ROOT DIR.
MOV AH, 02H     ;;;  ah = read service
MOV AL, 14      ;;;  al = count of sectors
MOV BX, TEMP    ;;;  offset to place read sector(s) (assumes ES has been set and usable)
MOV CH, 0       ;;;  7:0 of cylinder  (first cylinder)
MOV CL, 2       ;;;  7:6 = 9:8 of cylinder, 5:0 are sector (2nd sector since sectors are 1 based)
MOV DH, 1       ;;;  head (second head)

;;; so this means that, assuming 18 sectors per track, you are reading from LBA 19, yes?
;;;  the second sector from the second side on track/cyl 0?
;;;  how do you know the root directory starts there?
;;;  Boot Sector = 1, FAT = 9, 2 FAT's
;;;     ...okay LBA 19 it is.

;;; since the BIOS won't read past a 64k boundary *and* will probably error if (BX + (AL * 512)) > 0xFFFF
;;;  what combination does your ES:BX hold?

PUSHA

;;; In my opinion, rather than PUSHA, why not just jump back up to ";1- SETTING UP...".  Time is not
;;;  really and issue here and you won't have to worry about restoring the stack later.

LOAD_RD:
INT 13H
JNC LOAD_RD_DONE
CALL RESET_DRIVE

;;; You might want to have a count down and then error if it is reached.  If there is an error,
;;;  you will infinitely loop here...

JMP LOAD_RD

LOAD_RD_DONE:
POPA

MOV DI, TEMP
MOV CX, 224

FIND_KERNEL:
PUSH CX
POP DX

;;; MOV  DX,CX instead???

MOV SI, FILE_NAME
MOV CX, 11
REP CMPSB

;;; are ES and DS set correctly before the CMPSB above?
;;; for readability, maybe use 'REPZ' instead.
;;; Also, to come back to the clue I first stated above, what OS are you using to copy the
;;;  files to the floppy?  Does it use Long File Names?  If so, they are probably lowercase
;;;  now, where your FILE_NAME will probably be uppercase.
;;;  (Note though that an uppercase entry will still exist)

JE FOUND_KERNEL

ADD AX, 32
MOV DI, TEMP
ADD DI, AX
PUSH DX
POP CX

LOOP FIND_KERNEL

;;; Since you are using the stack, I would suggest you save DI and add 32 to DI each
;;;  time.  Saves you a bit of code here.

;  mov  cx,224
; find_kernel:
;  push di
;  push cx
;  mov  si,file_name
;  mov  cx,11
;  repz cmpsb
;  pop  cx
;  pop  di
;  jz   found_kernel
;  add  di,32
;  loop find_kernel

MOV SI, FAILED_TO_LOAD_KERNEL
CALL ECHO
CLI
INT 18H

FOUND_KERNEL:
MOV AX, WORD [DI+15]
MOV [ENTERY_POINT], AX

;;; Just out of curiousity, what assembler are you using.
;;; Without sounding like I am pushing my assembler, I want to show you something.
;;; (I think FASM does this too)
;;;
;;; With NBASM, you can do the following:
;;; ASTRUCT struct
;;; member0  word
;;; member1  byte
;;;  ...
;;; member6  dword
;;; ASTRUCT ends
;;;
;;;   mov  ax,word [DI+ASTRUCT->member0]
;;;
;;; which is the equivalent of
;;;
;;;   mov  ax,word [DI+0]
;;;
;;; now you can modify ASTRUCT as you wish and all of your code reflect the
;;;  change without a single modification.  I thing FASM does it like this:
;;;
;;;  mov  ax,word [DI+ASTRUCT.member0]
;;;
;;; anyway, this is a lot better to read than [DI+15] if you give the members
;;;  descriptive names.  For example, the word at offset 15 is not an entry point
;;;  as your code above assumes it is.  You probably want the word at 0x1A.
;;;
;;; my version of the loop above leave DI pointing to the start of the Directory Entry.
;;;   yours does not.  Is this why you use '+15' instead?  
;;;   If found, DI = (start of entry + 11).  11 + 15 = 26 (0x1A).  Yep  :-)
;;;   I suggest you change that.  Makes for bad assumptions...

MOV AX, 1
MOV BX, TEMP
CALL LOG_TO_HTS

;;; This is usually called LBA to CHS, not LOG to HTS (Head Track Sector?)
;;; Also, you use this conversion here (which I assume converts an LBA to CHS, i haven't
;;;  gotten to the code below yet), why didn't you use it above at ";1- SETTING UP ..."

MOV AH, 2
MOV AL, 9
PUSHA
LOAD_FAT:
INT 13H
JNC LOAD_FAT_DONE
CALL RESET_DRIVE
JMP LOAD_FAT

LOAD_FAT_DONE:

;;; a comment:  As soon as you have read the FAT to the memory pointed to by TEMP,
;;;  you have overwritten your DIRectory ENTRY data.  Except for assuming that you will
;;;  stop reading at the first End of Cluster marker, how do you know how many bytes in 
;;;  size your kernel is.

MOV AH, 2
MOV AL, 1
PUSH AX

LOAD_SECTOR:
MOV AX, WORD [ENTERY_POINT]
ADD AX, 31

;;; 31 may be in error.  Most 1.44 meg floppies are:
;;;   1 = boot sector, 9 + 9 = FAT, 14 = root
;;;  that is 33.  However, maybe you are accounting for the "LBA-2" before hand... ?
;;;  (cutting corners is going to leave you with a round square really fast...)

;;; Am I missing some code here.  You get to the point to read in the kernel file
;;;  and you now convert AX to CHS and return.

LOG_TO_HTS:
PUSH BX
PUSH AX
MOV BX, AX
MOV DX, 0
DIV WORD[ALL_SECTORS]
ADD DL, 01H
MOV CL, DL
MOV AX, BX
MOV DX, 0
DIV WORD [ALL_SECTORS]
MOV DX, 0
DIV WORD[FACES]
MOV DH, DL
MOV CH, AL
POP AX
POP BX
MOV DL, BYTE [BOOT_DEVICE]
RET

;;; (I didn't check your LBA->CHS code above).
Can you please include your whole boot sector (loader) code so that we can see the setting of ES and DS too, among other things?

I hope my comments/suggestions have helped you a bit. Be sure to spend some time re-writing your code and see if it works. If not, come back and ask us again, this time (please) giving more details.

Thanks,
Ben

P.S. FASM can be found at http://flatassembler.net/ while NBASM can be found at http://www.fysnet.net/newbasic.htm.
Mohamed007
Posts: 14
Joined: Fri Jul 08, 2016 8:44 pm

Re: Why my bootloader can't find the kernel?

Post by Mohamed007 »

Ok, Thanks for responding then i want to make one thing clear..this loader works well when there is only the kernel in the floppy disk
if i copy 2 files, the kernel and anything else it will not work. If the kernel only there on the disk it will work. This is the problem
And here is the whole code

Code: Select all

JMP MAIN

WAIT_FOR_KEY:
MOV AH, 00H
INT 16H
RET

CLEAR:
MOV AH, 0H                       
MOV AL, 03H                 
INT 10H
RET

LOG_TO_HTS:
PUSH BX
PUSH AX
MOV BX, AX
MOV DX, 0
DIV WORD[ALL_SECTORS]
ADD DL, 01H
MOV CL, DL
MOV AX, BX
MOV DX, 0
DIV WORD [ALL_SECTORS]
MOV DX, 0 
DIV WORD[FACES]
MOV DH, DL
MOV CH, AL
POP AX
POP BX
MOV DL, BYTE [BOOT_DEVICE]
RET

ECHO:                
LODSB                 
CMP AL, 0            
JE DONE                 
CMP AL, 59
JE NEWLINE
MOV AH, 0EH             
INT 10H              
JMP ECHO               
                        

DONE:                 
RET                    

NEWLINE:
PUSHA
MOV AH, 0EH
MOV AL, 13
INT 10H
MOV AL, 10
INT 10H 
POPA
RET

RESET_DRIVE:				                ;RESET FLOPPY DRIVE FUNCTION
MOV AX, 0       					;THE FUNCTION CODE TO RESET DRIVE
MOV DL, BYTE [BOOT_DEVICE]	                        ;DRIVE ID TO RESET
INT 13H
RET


MAIN:                            


CLI                             
MOV AX, 0X0000                  
MOV SS, AX
MOV SP, 0XFFFF                 
STI                          


MOV AX, 07C0H
MOV DS, AX
MOV ES, AX

CALL CLEAR
MOV SI, WELCOME_MSG
CALL ECHO

MOV [BOOT_DEVICE], DL         

;1- SETTING UP AND LOADING THE ROOT DIR.
MOV AH, 02H               
MOV AL, 14                  
MOV BX, TEMP                     
MOV CH, 0                   
MOV CL, 2                  
MOV DH, 1                  
PUSHA                     
LOAD_RD:
INT 13H
JNC LOAD_RD_DONE                    
CALL RESET_DRIVE                    
JMP LOAD_RD                  


LOAD_RD_DONE:
POPA

MOV DI, TEMP                      
MOV CX, 224                  

FIND_KERNEL:
PUSH CX                     
POP DX                  
MOV SI, FILE_NAME                   
MOV CX, 11                  
REP CMPSB                  

JE FOUND_KERNEL                      

ADD AX, 32
MOV DI, TEMP
ADD DI, AX
PUSH DX
POP CX

LOOP FIND_KERNEL
MOV SI, FAILED_TO_LOAD_KERNEL
CALL ECHO
CLI
INT 18H   


FOUND_KERNEL:                                        
MOV AX, WORD [DI+15]                        
MOV [ENTERY_POINT], AX




MOV AX, 1
MOV BX, TEMP                      
CALL LOG_TO_HTS
MOV AH, 2            
MOV AL, 9                  
PUSHA            
LOAD_FAT:
INT 13H
JNC LOAD_FAT_DONE                  
CALL RESET_DRIVE                    
JMP LOAD_FAT                       


LOAD_FAT_DONE:                    
MOV AH, 2
MOV AL, 1 
PUSH AX

LOAD_SECTOR:                
MOV AX, WORD [ENTERY_POINT]
ADD AX, 31  

CALL LOG_TO_HTS					        
MOV AX, 2000H
MOV ES, AX
MOV BX, WORD[OFFSET_]
POP AX
PUSH AX

INT 13H
JNC GET_NEXT
CALL RESET_DRIVE
JMP LOAD_SECTOR

GET_NEXT:
MOV AX, [ENTERY_POINT]
MOV DX, 0
MOV BX, 6
MUL BX
MOV BX, 4
DIV BX
MOV SI, TEMP
ADD SI, AX
MOV AX, WORD[SI]

OR DX, DX
JZ EVEN

ODD:
SHR AX, 4
JMP SHORT COMP_SECTOR

EVEN:
AND AX, 0FFFH

COMP_SECTOR:
MOV WORD [ENTERY_POINT], AX
CMP AX, 0FF8H
JAE END
ADD WORD[OFFSET_], 512
JMP LOAD_SECTOR

END:
MOV SI, KERNEL_LOADED_MSG
CALL ECHO

CALL WAIT_FOR_KEY

POP AX
MOV DL, BYTE[BOOT_DEVICE]
JMP 2000H:0000H

OFFSET_					DW		0
ALL_SECTORS				DW 		18
FACES					DW		2
ENTERY_POINT			        DW		0
FAILED_TO_LOAD_KERNEL	                DB		"Error, Cannot Load The Kernel. Booting Process Aborted;",0
BOOT_DEVICE                             DB              0
FILE_NAME				DB		"KERNEL  BIN"
WELCOME_MSG                             DB              "Worked, Cool;",0
KERNEL_LOADED_MSG                       DB              "Kernel Loaded, Press Any Key To Continue...",0
TIMES	510 - ($-$$)	DB		0               
                                                      
DW	0xAA55                                          

TEMP: 	
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: Why my bootloader can't find the kernel?

Post by BenLunt »

I started to go through your code and found a few items you may want to look at:
1. You assume the BIOS won't modify DL via the CLEAR and ECHO calls.
2. Your NewLine code returns (using a RET) to the ECHO caller. Does a ';' char indicate end of string, or does a NULL char?

I made it a little ways through and then realized you didn't take any of my suggestions, you didn't modify your code at all to my suggestions.

As for it failing to work after you copy another file to the floppy, here are a few ideas:
1. The OS/copy util that you are using doesn't correctly copy it to the floppy.
2. The copy is overwriting the kernel.bin file and/or the boot code.
3. the OS sees that there is not a vaild BPB at the start of the disk, so it has no idea what type of floppy format it is, therefore (maybe) assumes 720k ?????

You didn't answer my question about what OS you are using to copy the files to the floppy.
I am guessing it can't be Windows/DOS or even Linux because you don't have a valid BPB and neither of those OSes will identify the floppy as being formatted.

What utility are you using to copy the files to the floppy? Check that utility. Make a copy of the floppy as an image, do the copy of the file, then make another copy of the floppy image and compare the differences. See where the changes are.

When the code works before you copy a file, but doesn't after, check to copy utility, not the boot code.

We need more details, and I strongly suggest you go back and read the suggestions I made earlier. It might work now, but it makes a lot of assumptions. A single change and it will be broken with a difficult task to find the assumption that is breaking it.

Ben
Post Reply