boot code needs fix [FIXED]

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.
GLneo
Member
Member
Posts: 237
Joined: Wed Dec 20, 2006 7:56 pm

boot code needs fix [FIXED]

Post 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!
Last edited by GLneo on Sat Feb 17, 2007 10:23 am, edited 1 time in total.
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post 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.
GLneo
Member
Member
Posts: 237
Joined: Wed Dec 20, 2006 7:56 pm

Post by GLneo »

well thats the thing, if i make it more than 53 the thing locks up?!?!

but thanks for the idea :D
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Post 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 
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
GLneo
Member
Member
Posts: 237
Joined: Wed Dec 20, 2006 7:56 pm

Post by GLneo »

thx, but i dont understand what

Code: Select all

[bpbHiddenSect], [bpbTrackSect], ect... 
are?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Post 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
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post 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!
Every good solution is obvious once you've found it.
GLneo
Member
Member
Posts: 237
Joined: Wed Dec 20, 2006 7:56 pm

Post 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?
Otter
Member
Member
Posts: 75
Joined: Sun Dec 31, 2006 11:56 am
Location: Germany

Post 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.
GLneo
Member
Member
Posts: 237
Joined: Wed Dec 20, 2006 7:56 pm

Post by GLneo »

where does my boot loader end( where is it safe to put 100+ sectors )?
Otter
Member
Member
Posts: 75
Joined: Sun Dec 31, 2006 11:56 am
Location: Germany

Post 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
GLneo
Member
Member
Posts: 237
Joined: Wed Dec 20, 2006 7:56 pm

Post 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!
xsix
Member
Member
Posts: 59
Joined: Tue Oct 24, 2006 10:52 am

Post 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
Otter
Member
Member
Posts: 75
Joined: Sun Dec 31, 2006 11:56 am
Location: Germany

Post 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
Post Reply