boot code needs fix [FIXED]
boot code needs fix [FIXED]
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!
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.
Code: Select all
kernel_load:
mov ax, 0
mov es, ax
mov bx, 0x1000
mov ax, 1
mov cx, 53
call LoadSectors
Here's John S. Fine's readsector code as it looks in my bootsector, it
works really well for me.
example usage:
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
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
thx, but i dont understand what are?
Code: Select all
[bpbHiddenSect], [bpbTrackSect], ect...
- Combuster
- 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:
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.
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.
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:
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
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.
There are other ways like long mode but I think if your kernel is not too big this one should be good.
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!
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!
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