Bootloader woes

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
DaveHK

Bootloader woes

Post by DaveHK »

It is interesting that everyone who writes their own bootloaders, seem to load the kernel sector by sector, is that just because its easy or do you all know something I don't

I use a two stage bootloader, stage 1, loaded of course to 07c0:0000, loads stage 2 at 2000:0000 and also does some other set up, then passes control to stage 2

Stage 2 loads my kernel to 1000:00000, the kernel is currently 64K located on disk from logical sector 3 to logical sector 130.

now my bootloader tries to be clever, and fetches as many sectors off each track as it can, obviously it can only get 14 from the first track (we started 4 sectors in), but it then switches to a full 18 sectors per track, but should fetch just the last 5 from the last track.

So far all well and good, but for some reason it hangs, I have tried to run it through bochs to see what is happening, and it seems to read the first 5 tracks fine, but then only reads the first 2 sectors off track 6 when is goes haywire with bochs reporting illegal instruction (why that should happen now and not on the previous 5 reads god only knows). It does not appear to be memory related, as if I change the kernel load address to 3000:0000 it still crashes at exactly the same point, so I am lost as to how I can repeat the load 5 times without incident, but not 6 or more

So I have to ask all you guys who load a sector at the time, although this method is slow, are you doing it for a reason ?
Adek336

RE:Bootloader woes

Post by Adek336 »

can you attach the code?
Jamethiel

RE:Bootloader woes

Post by Jamethiel »

If the people who load sector by sector know something you don't, then it has escaped me as well.

I use a single-stage bootloader. I forget if it loads 18 or 36 sectors at a time, with the obvious exception of the first track, but it does so until it has read 21 tracks worth of disk (the kernel fits within the first track and I have a 360k ramdisk). The only problems I have with this bootloader are that it's the last piece of my system that wasn't compiled from within the system, and that it no longer matches (due to incessant binary patching) the most recent source that I have for it.

I'm trying to come up with a plausible scenario that involves using the BIOS disk services to trash your stage2 loader, but nothing's coming to me.

If you stop at 5 tracks, is the information you have loaded correct and where you expected it? Where did you put your stacks? The state for your stage2 loader (how many tracks have been loaded, where the next track goes, etc)?

--Jamethiel
DaveHK

RE:Bootloader woes

Post by DaveHK »

This is the relevant stuff :

goboot: push ds ; save current data segment pointer
mov ax,es
mov ds,ax ; point ds to 0100h (same as es)
mov si,4 ; offset to sector count
mov di,5 ; offset to boot drive
mov al,[bootdrv] ; fetch boot drive
stosb ; save to bootloader
lodsb ; fetch sector count into al
xor ah,ah ; clear ah
pop ds ; restore segment pointer

cmp ax,1 ; check the number of sectors required
jle SetCPU ; if less than or equal to 1 then we already have it !

mov [SectCount],al ; store number of sectors required

mov al,1 ; Num Sectors read so far
call Update ; update CHS settings

ReRead: call GetSect ; how many sectors to read

mov bx,[CurrAddr] ; start 512 bytes into segment - to skip past the 1st sector already loaded

mov ah,2 ; function 2 - read sector
mov ch,[BLCyl] ; cylinder
mov cl,[BLSect] ; sector
mov dh,[BLHead] ; head
mov dl,[bootdrv] ; disk = what we booted from
int 13h ; read it
jnc ReadOK ; if there's no error then we got it

dec byte [ErrorCount] ; decrement our error count
jne ReRead ; if not zero then try again
jmp DError

ReadOK: call Update ; update by number of sectors actually read
mov al,[SectCount] ; number of sectors left
cmp al,0
jg ReRead ; if not finished then get next

; This routine is used to update track, head and sector pointers for start of next read, also updates current address

Update: push ax
sub [SectCount],al ; reduce sector count by processed amount
mov ah,[BLSect] ; fetch current sector pointer
add ah,al ; add number of sectors we have just processed
mov [BLSect],ah
cmp ah,[NumSect] ; compare this number to max sectors
jle DoneSect ; if less than or equal, then do nothing
sub ah,[NumSect] ; reduce the count
mov [BLSect],ah
inc byte [BLHead]
mov al,[BLHead] ; head count
cmp al,[NumHead] ; compare this number to max heads
jl DoneSect ; if less than, then do nothing
mov al,0
mov [BLHead],al ; reset head
inc word [BLCyl] ; increment cylinder
DoneSect: pop ax
mov ah,0 ; ax = num sectors processed
rol ax,9 ; multiply by 512 (bytes)
mov bx,[CurrAddr] ; fetch current address
add bx,ax
mov [CurrAddr],bx ; store new value
ret

; this routine returns the number of sectors to read on our next disk read

GetSect: mov al,[NumSect] ; number of sectors on 1 track
sub al,[BLSect] ; subtract where we are now
inc al ; sectors start at 1 !
cmp al,[SectCount] ; compare this number to number left
jle DoneGet
mov al,[SectCount] ; if this value is less then use it instead
DoneGet: ret
DaveHK

RE:Bootloader woes

Post by DaveHK »

stack is currently 0x800 - 0x9ff, the data loaded up till the crash is correct and where it should be, in fact until the last (big)kernel update, when the kernel grew past 5 tracks in length, it used to load and run fine !

It is very much beyond me too ! Any geniuses out there got any ideas ?
Jamethiel

RE:Bootloader woes

Post by Jamethiel »

Umm... Check me on this, but I don't see ES being set at all, and I see a comment to the effect that it contains the known value 0x0100. Doesn't the BIOS disk service usually take ES:BX as a buffer pointer?
DaveHK

RE:Bootloader woes

Post by DaveHK »

yes,ES has been set prior to this to 0x0100

This only a code snippet, not the whole loader
DaveHK

RE:Bootloader woes

Post by DaveHK »

Hey - I fixed it, silly me - I was overwriting the stack (I forgot where I had put it in the early stages of loading, it was not where I said at all - it is changed in the next stage anyway). Once I moved the stack - we are back up and running.

So I still don't know why other people are loading a sector at a time - VERY slow !
Post Reply