Page 1 of 2

boot code needs fix [FIXED]

Posted: Wed Feb 14, 2007 6:18 pm
by GLneo
hi all, ok, basically my boot sector breaks after it reads 53 sectors, i just ignored this then forgot about this and my kernel grew, so my boot sector stopped loading all of my kernel(so i had some hellish bugs) but luckily I've remembered this and now it's time to fix the boot sector.

here is my code: http://lemonos.cvs.sourceforge.net/lemo ... iew=markup

i dont know much asm, so i hope someone can help!

thx!

Posted: Wed Feb 14, 2007 7:25 pm
by frank

Code: Select all

kernel_load:
mov ax, 0
mov es, ax
mov bx, 0x1000
mov ax, 1
mov cx, 53
call LoadSectors
On the line where it says mov cx, 53 (line 80) you could just change the 53 to the number of sectors that the kernel occupies.

Posted: Wed Feb 14, 2007 7:32 pm
by GLneo
well thats the thing, if i make it more than 53 the thing locks up?!?!

but thanks for the idea :D

Posted: Wed Feb 14, 2007 7:54 pm
by bubach
Here's John S. Fine's readsector code as it looks in my bootsector, it
works really well for me.

Code: Select all

;-------------------------------------------------------------------;
;   read_16 & read_32                                               ;
;                     input:  dx:ax = sector within partition       ;
;                             si    = sector count                  ;
;                             di    = destination segment / 32      ;
;                                                                   ;
; The sector number is converted from a partition-relative to a     ;
; whole-disk (LBN) value, and then converted to CHS form, and       ;
; then the sectors are read into (di*32):0.                         ;
;                                                                   ;
;                     output: dx:ax = updated (sector count added)  ;
;                             di    = updated (sector count added)  ;
;                             si    = 0                             ;
;                                                                   ;
;                             bp, ds preserved                      ;
;                             bx, cx, es modified                   ;
;-------------------------------------------------------------------;
read_16:
          xor     dx, dx
read_32:
     .1:
          push    dx                                  ; (high) relative sector
          push    ax                                  ; (low) relative sector

          add     ax, word [bpbHiddenSect]            ; Convert to LBN
          adc     dx, word [bpbHiddenSect+2]

          mov     bx, [bpbTrackSect]                  ; Sectors per track
          div     bx                                  ; ax = track ; dx = sector-1
          sub     bx, dx                              ; Sectors remaining, this track
          cmp     bx, si                              ; More than we want?
          jbe     .2                                  ; No
          mov     bx, si                              ; Yes: Transfer just what we want
     .2:
          inc     dx                                  ; Sector number
          mov     cx, dx                              ; cl = sector ; ch = 0
          cwd                                         ; (This supports up to 32767 tracks
          div     word [bpbHeads]                     ; Track number / Number of heads
          mov     dh, dl                              ; dh = head

          xchg    ch, al                              ; ch = (low) cylinder  ; al=0
          ror     ah, 1                               ; rotate (high) cylinder
          ror     ah, 1
          add     cl, ah                              ; cl = combine: sector, (high) cylinder

          sub     ax, di
          and     ax, 0x7F                            ; ax = sectors to next 64Kb boundary
          jz      .3                                  ; On a 64Kb boundary already
          cmp     ax, bx                              ; More than we want?
          jbe     .4                                  ; No
     .3:
          xchg    ax, bx                              ; Yes: Transfer just what we want
     .4:
          push    ax                                  ; Save length
          mov     bx, di                              ; Compute destination seg
          push    cx
          mov     cl, 5
          shl     bx, cl
          pop     cx
          mov     es, bx
          xor     bx, bx                              ; es:bx = address
          mov     dl, [bpbDriveNo]                    ; dl = Drive number
          mov     ah, 2                               ; ah = Read command
          int     0x13                                ; Do it
          jc      error
          pop     bx                                  ; Length
          pop     ax                                  ; (low) relative sector
          pop     dx                                  ; (high) relative sector
          add     ax, bx                              ; Update relative sector
          adc     dl, dh
          add     di, bx                              ; Update destination
          sub     si, bx                              ; Update count
          jnz     .1                                  ; Read some more
          ret 
example usage:

Code: Select all

          mov     ax, [bpbReservedSec]                ; Sector number of FAT
          mov     si, [bpbFatSize]                    ; Length of FAT
          mov     di, 0x40                            ; segment / 32 (0x800 / 32)
          call    read_16                             ; Read FAT 

Posted: Wed Feb 14, 2007 8:17 pm
by GLneo
thx, but i dont understand what

Code: Select all

[bpbHiddenSect], [bpbTrackSect], ect... 
are?

Posted: Thu Feb 15, 2007 1:04 am
by Combuster
The two methods differ significantly:
GLNeo loads everything from a fixed location on disk, while bubach's bootloader seems to parse the filesystem and locate the kernel that way. What you see is the reference to the BPB (the drive structure that tells you the properties of your disk).

However, this is not the problem:

when you try to load >53 sectors (take for example 54) you will overwrite the area from 0x1000 to 0x1000 + 54 * 512. = 0x7C00 (!). If you try loading even more, you'll be overwriting your bootsector with the obvious consequences.

To solve this properly you should choose another location, and then you possibly have to update your kernel and the likes to match the new address.

Posted: Thu Feb 15, 2007 7:20 am
by bubach
The variables is from the BPB, but you'll need some of those values to read sectors even if you don't care about FAT.
The function is to read sectors, so it's the same wheter you use FAT12 or not.

GLneo, you have the BPB in your bootsector so all you have to do is change
the names in the read function like this:

Code: Select all

bpbHiddenSect -> HiddenSectors
bpbTrackSect  -> SectorsPerTrack
bpbHeads      -> NumberOfHeads
bpbDriveNo    -> DriveNumber

Posted: Thu Feb 15, 2007 7:42 am
by Solar
Combuster wrote:when you try to load >53 sectors (take for example 54) you will overwrite the area from 0x1000 to 0x1000 + 54 * 512. = 0x7C00 (!).
The "(!)" did remind me of chess notation. Nice bughunting!

Posted: Thu Feb 15, 2007 11:42 am
by GLneo
@Combuster: thx that would be a problem!

this question has probably been asked a thousand times, but how do you put your kernel at the 1MB spot?

Posted: Thu Feb 15, 2007 12:23 pm
by Otter
That's only possible if your bootloader switches to protected mode. But if you are in pm, you can not use the BIOS interupts to load your kernel any more. The simplest way is to load your kernel to a position after your bootloader ( you could define a label at the end to get the position ), then switch to pm and move it to 1 MB.

There are other ways like long mode but I think if your kernel is not too big this one should be good.

Posted: Thu Feb 15, 2007 12:29 pm
by GLneo
where does my boot loader end( where is it safe to put 100+ sectors )?

Posted: Thu Feb 15, 2007 1:15 pm
by Otter
As I said ... add a label to the end of your boot loader ( bootloader_end ) . You could move it there. I don't know where you put the stack cause I have not readed your code but If you put it at the end of your 640K it should be save ... should

Posted: Thu Feb 15, 2007 1:33 pm
by GLneo
my sp is 0xFFFF, so i told it to put my kernel at 0x8000, then linked my kernel to that spot and tryed to boot: IT WORKS!

so now how do i move 60+ sectors from 0x8000 to 0x10000(or wherever) in protectaed mode ( i dont now much asm and i think there is some easy loop instruction to do it)

thx, everyone!

Posted: Thu Feb 15, 2007 1:38 pm
by xsix
your bootloader ends up on 0x7c00+0x200 and just write a routine which call INT 13h with CX=1 as many times as much sectors you want to read

Posted: Thu Feb 15, 2007 4:19 pm
by Otter
If you want to move it to 0x00100000 ( 1 MB ) you need to switch to protected mode. This is not easy, but there are lots of tutorials for that. If you use 32 bit code ( in protected mode you can ) you can move it using "rep movsd"

Code: Select all

mov esi,0x00008000
mov edi,0x00100000
mov ecx,( kernelSize+3)/4
rep movsd