load more than 18 sectors

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
GLneo

load more than 18 sectors

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

Re:load more than 18 sectors

Post 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.
GLneo

Re:load more than 18 sectors

Post 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 ;)
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:load more than 18 sectors

Post 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 ;)
GLneo

Re:load more than 18 sectors

Post 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 ;)
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:load more than 18 sectors

Post 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 !)
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:load more than 18 sectors

Post by Pype.Clicker »

(better if picture attached ::) )
GLneo

Re:load more than 18 sectors

Post 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:
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:load more than 18 sectors

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
GLneo

Re:load more than 18 sectors

Post 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 :)
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:load more than 18 sectors

Post 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 ...
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:load more than 18 sectors

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
GLneo

Re:load more than 18 sectors

Post 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 ;)
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:load more than 18 sectors

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
GLneo

Re:load more than 18 sectors

Post by GLneo »

i hope im not becoming a nuisance :P

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

Post Reply