Page 1 of 1
load more than 18 sectors
Posted: Mon May 16, 2005 3:29 pm
by GLneo
hello everybody, i'm writing a boot sector which will need to load 25+ sectors from a floppy disk, I know I will need a load sector loop but i dont know much asm. can i have some code examples
Code: Select all
floppy_read:
mov ax, 0
mov es, ax
mov bx, 0x1000
mov ah, 2
mov dl, 0
mov dh, 0
mov ch, 0
mov cl, 2
mov al, 25
int 13h
or ah, ah
jnz floppy_read
P.S. first post, this forum is great ;D
Re:load more than 18 sectors
Posted: Mon May 16, 2005 5:04 pm
by Ushma
GLneo wrote:
I know I will need a load sector loop but i dont know much asm.
So learn the x86 assembly language you need. It will make your OS-creating experience much more pleasant. Once you've learned the assembly language, a loop would be a cakewalk.
That said, on to the sectors. To work the BIOS call correctly, you're going to need to not only change the sector value but the cylinder and heads values. I would suggest that you write a routine that will convert LBA to CHS and fetch the appropriate sector. That having been done, loop 1-25+ telling it to fetch the sectors.
Re:load more than 18 sectors
Posted: Mon May 16, 2005 7:00 pm
by GLneo
well, i do now x86 asm(some), and i have tried LBA to CHS but all atemps failed, it was why I need working LBA to CHS loops... thx
Re:load more than 18 sectors
Posted: Tue May 17, 2005 1:35 am
by Pype.Clicker
1. you could shamelessly reuse the 'load sector' loop of some working bootloader (see ChrisGiese's OSD, for instance)
2. you could shamelessly write a sequence of INT13 with proper values (no loop whatsoever
but then make sure you have proper error check
3. you could pick a pencil and a sheet of paper and figure out what's exactly required, what registers need to be kept, etc. and synthetise a loop out of this
Re:load more than 18 sectors
Posted: Tue May 17, 2005 5:53 am
by GLneo
hmm...
1.) tryed it
2.) tryed it
3.) hmmm.... that is a good idea but i dont know much about writing loops in asm or a WORKING LBA to CHS... thing
Re:load more than 18 sectors
Posted: Tue May 17, 2005 7:06 am
by Pype.Clicker
well, actually the 'LBA to CHS' will much depend on how you want LBA to work. The usual computation is to start with block 0 (C=0,H=0, S=1) as disk's first block and go on forward.
The BIOS will use CHS as follow:
- when 'sectors' count is over the 'sectors_per_track', reset sectors to 1 and go to the next head
- when 'head' count is over the 'heads_on_disk', reset head to 0 and increment cylinder count
- when cylinder count is over 'cylinders_on_disk', panic.
That means you'll need to perform divisions and extract remainders if you want a 'LBA2CHS' function but for the purpose of loading a bunch of sectors from a known position (e.g. a valid CHS), you can simply add the amount of sectors by what you've just read and do the 'ajust CHS' logic from above.
About doing the loop, just use 'jmp' to a given label ... Old-fashionned "computograms" nicely translates into assembler code. See attached picture.
Code: Select all
read_sectors:
;; asm stuff here
.read_sector:
;; asm stuff calling INT13 here
jnc .adjust_chs:
;; asm stuff (increment error counter) here
jmp .read_sector
.adjust_chs:
;; sector+=sectors_read
;; if (sectors > MAX) {sectors=0; head++}
;; etc
cmp [sectors_left],0
ja .readsector
;; end of code
ret
now, you should *certainly* not be toying with INT13 out of the bochs unless you're confirmed assembly coder... e.g. if you happen to trash the register containing disk number (dx iirc) accidently, you might end up with HDD I/O instead of floppy I/O ... so be careful (i used to lose 2 MBRs that way !)
Re:load more than 18 sectors
Posted: Tue May 17, 2005 7:13 am
by Pype.Clicker
(better if picture attached ::) )
Re:load more than 18 sectors
Posted: Tue May 17, 2005 4:12 pm
by GLneo
heres my 90% copy/paste kenel loader, can anyone tell me if there is any obvious errors, thx
Code: Select all
absoluteTrack db 0
absoluteSector db 0
absoluteHead db 0
BootDrv db 0
BytesPerSector db 512
floppy_reset:
mov ah, 0
int 13h
or ah, ah
jnz floppy_reset
jmp floppy_read
LBAtoCHS:
push dx
xor dx,dx
mov bx, 18
div bx
inc dx
mov [absoluteSector], dx
xor dx,dx
mov bx, 2
div bx
mov [absoluteTrack], dx
mov [absoluteHead], ax
pop dx
ret
floppy_read:
mov ax, 0
mov es, ax
mov bx, 0x1000
mov dx, 50
main:
mov di, 5
sectorloop:
push ax
push bx
push cx
call LBAtoCHS
mov ah, 02
mov al, 01
mov ch, BYTE [absoluteTrack]
mov cl, BYTE [absoluteSector]
mov dh, BYTE [absoluteHead]
mov dl, BYTE [BootDrv]
int 0x13
jnc success
dec di
pop cx
pop bx
pop ax
jnz sectorloop
call $
success:
pop cx
pop bx
pop ax
add bx, WORD [BytesPerSector]
inc ax
dec cx
jz endread
loop main
endread:
Re:load more than 18 sectors
Posted: Tue May 17, 2005 7:49 pm
by Brendan
Hi,
Just a couple little things...
It's probably a good idea to count the number of times the BIOS returns an error for "floppy_reset:", just like you do for "floppy_read:".
In "LBAtoCHS:" you can divide by a value in memory (which prevents messing with BX). This makes it easier to change the boot sector code for other disk formats.
For the floppy read code you are updating the destination address with "add bx, WORD [BytesPerSector]", which works for now but when you need to load more than 64 KB it will overflow. Rather than changing the offset you could change the ES segment register - that way you could load until you run out of memory. The instruction "call $" is a bug (infinite recursion causing stack overflow), and there's nothing after "endread:" - not sure if this is correct or if there should be be a "ret" after it. You don't set CX to the number of sectors to load, so I'm assuming that this is done by the calling code. There's also no need to use the "loop" instruction and "dec cx; jz endread" - you'd only load half the sectors as CX is decreased twice. AX (the LBA address) isn't set either, but is used for setting ES so you'll accidentally start loading at sector number 0 (I assume you'd prefer to start with sector number 1, the sector after this boot code).
IMHO it's a good idea to tell the user something went wrong rather than using "jmp $" (I left the code to display an error message up to you). Also, by putting all of the values that specify the disk format together at a known offset these values can be changed by other software (for e.g. the "format" command could set them). That way the same boot code can be used for any floppy disk formats (e.g. 1.2 MB disks) and for booting from hard drive (as long as the LBA address and absoluteTrack don't overflow) - this is similar to what DOS does (the "BIOS Parameter Block", which doesn't actually have anything to do with the BIOS).
Combining all of this results in the following:
Code: Select all
sectorsPerTrack dw 18
headsPerDisk dw 2
ParagraphsPerSector dw 512/16
absoluteTrack db 0
absoluteSector db 0
absoluteHead db 0
BootDrv db 0
floppy_reset:
mov di,3
retryReset:
mov ah, 0
int 13h
or ah, ah
jz floppy_read
sub di,1
jnz retryReset
jmp displayError
LBAtoCHS:
push dx
xor dx,dx
div word [sectorsPerTrack]
inc dx
mov [absoluteSector], dx
xor dx,dx
div word [headsPerDisk]
mov [absoluteTrack], dx
mov [absoluteHead], ax
pop dx
ret
;Read Sectors
;
;Input
; ax = starting sector number (LBA)
; cx = number of sectors to read
floppy_read:
mov bx, 0x0100
mov es, bx
main:
mov di, 5
sectorloop:
push ax
push cx
call LBAtoCHS
mov ah, 02
mov al, 01
mov ch, BYTE [absoluteTrack]
mov cl, BYTE [absoluteSector]
mov dh, BYTE [absoluteHead]
mov dl, BYTE [BootDrv]
xor bx,bx
int 0x13
pop cx
pop ax
jnc success
sub di,1
jnz sectorloop
jmp displayError
success:
mov bx,es
add bx, WORD [ParagraphsPerSector]
mov es,bx
inc ax
loop main
ret???
There might still be bugs in this, but I think I got them all (and hopefully haven't introduced many more)..
Cheers,
Brendan
Re:load more than 18 sectors
Posted: Wed May 18, 2005 6:06 am
by GLneo
thx thats great but bochs is still giving me errors:
Code: Select all
00008158128e[HD ] device set to 0 which does not exist
00008158421e[HD ] device set to 1 which does not exist
00008171167i[BIOS ] floppy: drive>1 || head>1 ...
00008173475i[BIOS ] floppy: drive>1 || head>1 ...
00008175783i[BIOS ] floppy: drive>1 || head>1 ...
00008178091i[BIOS ] floppy: drive>1 || head>1 ...
00008180399i[BIOS ] floppy: drive>1 || head>1 ...
00008180505i[CPU ] WARNING: HLT instruction with IF=0!
then it locks up???
P.S. i did want it continue without ret
Re:load more than 18 sectors
Posted: Wed May 18, 2005 6:10 am
by Pype.Clicker
writing AX to a byte variable will trash what's on the next byte.
Code: Select all
mov [absoluteSector], dx
xor dx,dx
div word [headsPerDisk]
mov [absoluteTrack], dx
mov [absoluteHead], ax
should rather be
Code: Select all
mov [absoluteSector], dl
xor dx,dx
div word [headsPerDisk]
mov [absoluteTrack], dl
mov [absoluteHead], al
(at least). Make sure you assigned something to BootDrv variable too ...
Re:load more than 18 sectors
Posted: Wed May 18, 2005 6:23 am
by Brendan
Hi,
I did miss one last bug
.
In the code to convert LBA into CHS, change:
Code: Select all
div word [headsPerDisk]
mov [absoluteTrack], dx
mov [absoluteHead], ax
pop dx
ret
To:
Code: Select all
div word [headsPerDisk]
mov [absoluteTrack], ax
mov [absoluteHead], dx
pop dx
ret
With DX and AX around the wrong way you'd be asking for the third head (head number 2) or something, which is why Bochs responds with "floppy: drive>1 || head>1" (as the head number isn't 0 or 1).
The locking up part is caused by using "hlt" when interrupts are disabled (as there's no way for the CPU to come out of it's halted state). I'm not sure where this HLT instruction would be, but I assume it'd be after the "floppy_read:" gets 5 errors from the BIOS and jump to it's error handling code.
[EDIT] Pype is right too - I've missed 2 bugs!
The (hopefully!) correct code would be:
Code: Select all
LBAtoCHS:
push dx
xor dx,dx
div word [sectorsPerTrack]
inc dx
mov [absoluteSector], dl
xor dx,dx
div word [headsPerDisk]
mov [absoluteTrack], al
mov [absoluteHead], dl
pop dx
ret
[/EDIT]
Cheers,
Brendan
Re:load more than 18 sectors
Posted: Wed May 18, 2005 3:04 pm
by GLneo
hmm... fixed the head>1 thing but
Code: Select all
00008158128e[HD ] device set to 0 which does not exist
00008158421e[HD ] device set to 1 which does not exist
00008169683i[FDD ] read() on floppy image returns 0
00024356000p[CPU ] >>PANIC<< prefetch: running in bogus memory
i load my kernel to 0x1000 and my boot sector is at 0x7C00 if i load 50 * 512 sectors dose it get over wrote ???
P.S. my entire boot sector is included
Re:load more than 18 sectors
Posted: Wed May 18, 2005 11:38 pm
by Brendan
Hi,
GLneo wrote:i load my kernel to 0x1000 and my boot sector is at 0x7C00 if i load 50 * 512 sectors dose it get over wrote ???
You should be able to load 54 sectors before overwriting your boot sector code, but where is your stack?
The very first thing your boot sector code should do is to set things up in a known state, for example:
Code: Select all
[ORG 0x7C00]
jmp 0x00:start
<-other stuff->
start:
xor ax,ax
cli
mov ds,ax
mov ss,ax
mov esp,0x8000
sti
If the BIOS decides to start your boot code with DS=0x07C0 or something else, then instructions like "div word [sectorsPerTrack]" will get the value from the wrong address. In general the BIOS gives no guarantees, except that the first instruction will be at 0x00007C00 (either 0x07C0:0x0000 or 0x0000:0x7C00), and that DL will contain the BIOS's "drive number" for the disk that was booted.
Cheers,
Brendan
Re:load more than 18 sectors
Posted: Thu May 19, 2005 5:40 am
by GLneo
i hope im not becoming a nuisance
Code: Select all
00024529581i[BIOS ] FATAL: floppy recal:f07: ctrl not ready
00024529880p[BIOS ] >>PANIC<< BIOS panic at rombios.c, line 1558
00024539147i[BIOS ] FATAL: int13_diskette:f02: ctrl not ready
00024539446p[BIOS ] >>PANIC<< BIOS panic at rombios.c, line 1558
00024547547i[BIOS ] FATAL: int13_diskette: ctrl not ready
00024547846p[BIOS ] >>PANIC<< BIOS panic at rombios.c, line 1558
00024554908e[CPU ] jump_protected: S=1: descriptor not executable
00024554908e[CPU ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00024559233i[BIOS ] rombios.c,v 1.103.2.2 2004/02/02 22:39:22 cbothamy Exp $
00024873544i[KBD ] reset-disable command received
00032712112e[HD ] device set to 0 which does not exist
00032712405e[HD ] device set to 1 which does not exist
00032723503i[BIOS ] FATAL: floppy recal:f07: ctrl not ready
00032723802p[BIOS ] >>PANIC<< BIOS panic at rombios.c, line 1558
00032733069i[BIOS ] FATAL: int13_diskette:f02: ctrl not ready
00032733368p[BIOS ] >>PANIC<< BIOS panic at rombios.c, line 1558
00032741469i[BIOS ] FATAL: int13_diskette: ctrl not ready
00032741768p[BIOS ] >>PANIC<< BIOS panic at rombios.c, line 1558
00032748830e[CPU ] jump_protected: S=1: descriptor not executable
00032748830e[CPU ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00032753155i[BIOS ] rombios.c,v 1.103.2.2 2004/02/02 22:39:22 cbothamy Exp $
00033067542i[KBD ] reset-disable command received