OSDev.org https://forum.osdev.org/ |
|
Any better FAT16 bootsectors out there? https://forum.osdev.org/viewtopic.php?f=1&t=21155 |
Page 1 of 1 |
Author: | IanSeyler [ Fri Nov 06, 2009 11:32 am ] |
Post subject: | Any better FAT16 bootsectors out there? |
I tried to use the FAT16 boot sector code from FreeDOS and the one on osdever.net but had no luck with either of them. I've decided to switch from FAT32 (aka FAT28) to FAT16 since it seems a bit easier to maintain. In the end I wrote my own and the code is below. It works correctly but has no error checking. Anything better out there? bootsec.asm: Code: org 0x7C00 entry: jmp short begin nop %define bsOemName bp+0x03 ; OEM label (8) %define bsBytesPerSec bp+0x0B ; bytes/sector (dw) %define bsSecsPerClust bp+0x0D ; sectors/allocation unit (db) %define bsResSectors bp+0x0E ; # reserved sectors (dw) %define bsFATs bp+0x10 ; # of fats (db) %define bsRootDirEnts bp+0x11 ; Max # of root dir entries (dw) %define bsSectors bp+0x13 ; # sectors total in image (dw) %define bsMedia bp+0x15 ; media descriptor (db) %define bsSecsPerFat bp+0x16 ; # sectors in a fat (dw) %define bsSecsPerTrack bp+0x18 ; # sectors/track %define bsHeads bp+0x1A ; # heads (dw) %define bsHidden bp+0x1C ; # hidden sectors (dd) %define bsSectorHuge bp+0x20 ; # sectors if > 65536 (dd) %define bsDriveNumber bp+0x24 ; (dw) %define bsSigniture bp+0x26 ; (db) %define bsVolumeSerial bp+0x27 ; (dd) %define bsVolumeLabel bp+0x2B ; (11) %define bsSysID bp+0x36 ; (8) times 0x3B db 0 ; Code starts at offset 0x3E begin: mov [bsDriveNumber], dl ; BIOS passes drive number in DL xor eax, eax xor esi, esi xor edi, edi mov ds, ax mov es, ax mov bp, 0x7c00 ; read in the root cluster ; check for the filename ; if found save the starting cluster ; if not then error ;fatstart = bsResSectors ;rootcluster = bsResSectors + (bsFATs * bsSecsPerFat) ; 4 + (2 * 254) = sector 512 ;datastart = bsResSectors + (bsFATs * bsSecsPerFat) + ((bsRootDirEnts * 32) / bsBytesPerSec) ; 4 + (2 * 254) + ((512 * 32) / 512) = sector 544 ;cluster X starting sector ; starting sector = (bsSecsPerClust * (cluster# - 2)) + datastart ff: mov ax, [bsSecsPerFat] shl ax, 1 ; quick multiply by two add ax, [bsResSectors] mov [rootstart], ax mov bx, [bsRootDirEnts] shr bx, 4 ; bx = (bx * 32) / 512 add bx, ax ; BX now holds the datastart sector number mov [datastart], bx ff_next_sector: mov bx, 0x8000 mov si, bx mov di, bx call readsector ; Search for file name, and find start cluster. ff_next_entry: mov cx, 11 mov si, filename repe cmpsb jz ff_done ; note that di now is at dirent+11 add di, byte 0x20 and di, byte -0x20 cmp di, [bsBytesPerSec] jnz ff_next_entry ; load next sector dec dx ; next sector in cluster jnz ff_next_sector ff_done: add di, 15 mov ax, [di] ; AX now holds the starting cluster # ; At this point we have found the file we want and know the cluster where the file starts mov bx, 0x8000 ; We want to load to 0x0000:0x8000 loadfile: call readcluster cmp ax, 0xFFF8 ; Have we reached the end cluster marker? jg loadfile ; If not then load another jmp 0x0000:0x8000 ;------------------------------------------------------------------------------ ; Read a sector from disk, using LBA ; input: EAX - 32-bit DOS sector number ; ES:BX - destination buffer ; output: ES:BX points one byte after the last byte read ; EAX - next sector readsector: push dx push si push di read_it: push eax ; Save the sector number mov di, sp ; remember parameter block end push byte 0 ; other half of the 32 bits at [C] push byte 0 ; [C] sector number high 32bit push eax ; [8] sector number low 32bit push es ; [6] buffer segment push bx ; [4] buffer offset push byte 1 ; [2] 1 sector (word) push byte 16 ; [0] size of parameter block (word) mov si, sp mov dl, [bsDriveNumber] mov ah, 42h ; EXTENDED READ int 0x13 ; http://hdebruijn.soo.dto.tudelft.nl/newpage/interupt/out-0700.htm#0651 mov sp, di ; remove parameter block from stack pop eax ; Restore the sector number jnc read_ok ; jump if no error push ax xor ah, ah ; else, reset and retry int 0x13 pop ax jmp read_it read_ok: inc eax ; next sector add bx, 512 ; Add bytes per sector jnc no_incr_es ; if overflow... incr_es: mov dx, es add dh, 0x10 ; ...add 1000h to ES mov es, dx no_incr_es: pop di pop si pop dx ret ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ ; Read a cluster from disk, using LBA ; input: AX - 16-bit cluster number ; ES:BX - destination buffer ; output: ES:BX points one byte after the last byte read ; AX - next cluster readcluster: push cx mov [tcluster], ax ; save our cluster value ;cluster X starting sector ; starting sector = (bsSecsPerClust * (cluster# - 2)) + datastart xor cx, cx sub ax, 2 mov cl, byte [bsSecsPerClust] imul cx ; EAX now holds starting sector add ax, word [datastart] ; add the datastart offset xor cx, cx mov cl, byte [bsSecsPerClust] readcluster_nextsector: call readsector dec cx cmp cx, 0 jne readcluster_nextsector ; Great! We read a cluster.. now find out where the next cluster is push bx ; save our memory pointer mov bx, 0x7E00 ; load a sector from the root cluster here push bx mov ax, [bsResSectors] call readsector pop bx ; bx points to 0x7e00 again mov ax, [tcluster] ; ax holds the cluster # we just read shl ax, 1 ; multipy by 2 add bx, ax mov ax, [bx] pop bx ; restore our memory pointer pop cx ret ;------------------------------------------------------------------------------ msg_Load db "Loading... ", 0 msg_Error db "No " filename db "PURE64 SYS", 0 datastart dw 0x0000 rootstart dw 0x0000 tcluster dw 0x0000 times 510-$+$$ db 0 sign dw 0xAA55 -Ian |
Author: | earlz [ Sat Nov 07, 2009 2:39 pm ] |
Post subject: | Re: Any better FAT16 bootsectors out there? |
ReturnInfinity wrote: I tried to use the FAT16 boot sector code from FreeDOS and the one on osdever.net but had no luck with either of them. I've decided to switch from FAT32 (aka FAT28) to FAT16 since it seems a bit easier to maintain. In the end I wrote my own and the code is below. It works correctly but has no error checking. Anything better out there? <snip> -Ian I don't think your going to find many bootloaders in general with much error checking.. |
Author: | bewing [ Sun Nov 08, 2009 8:52 pm ] | ||
Post subject: | Re: Any better FAT16 bootsectors out there? | ||
Here is a bootsector that quok and I wrote together, and optimized heavily. (GAS at&t syntax) Currently it works with both FAT12 and FAT16, looks in the home directory for a second-stage bootloader called "osloader" (ELF format, load address 0x40000, entry address 0x40120), loads it, and jumps to it. It's been moderately tested, and actually exposes a bug in some versions of the bochs BIOS.
|
Author: | pcmattman [ Wed Nov 11, 2009 9:46 am ] |
Post subject: | Re: Any better FAT16 bootsectors out there? |
I'm surprised nobody has commented on bewing's contribution to this thread. This is a high quality bootsector in only 512 bytes that supports both FAT12 and FAT16 - no small feat! My hat's off to you guys for a fantastic contribution to the community |
Author: | Brynet-Inc [ Thu Nov 12, 2009 12:36 pm ] |
Post subject: | Re: Any better FAT16 bootsectors out there? |
And thanks to quok losing much hair, and sending countless images via email.. it's one of the very few bootloaders that work on my older 486 laptop. |
Author: | IanSeyler [ Fri Nov 13, 2009 11:51 am ] |
Post subject: | Re: Any better FAT16 bootsectors out there? |
bewing, thanks for the post .. I'll take a look at that code. |
Author: | FlashBurn [ Fri Nov 13, 2009 2:35 pm ] | ||
Post subject: | Re: Any better FAT16 bootsectors out there? | ||
@bewing I haven´t looked that deep into the source, but maybe with mine you could get your bootsector even smaller. For this you should look how I handled my vars.
|
Author: | bewing [ Fri Nov 13, 2009 8:24 pm ] |
Post subject: | Re: Any better FAT16 bootsectors out there? |
You are assuming that a sector is 512 bytes, which simplifies the code but will not work on (for example) CDROMs that are not doing emulation. You are also using Int13h extensions (for your READ EXTENDED function), which will not work on floppies at all -- but from what I can see, this code is FAT16-specific anyway. You are also assuming that the FAT will fit in one 64k memory page, which is not at all certain. But, in general, pretty good code! Using bp the way you do may actually save a few bytes, truly -- since all my addresses are 2 bytes, and the bp offset may only be one byte, and there is no sib byte in rmode. |
Author: | FlashBurn [ Sat Nov 14, 2009 1:00 am ] |
Post subject: | Re: Any better FAT16 bootsectors out there? |
Yeah this code is fat16 specific and I also have a bootsector which works with CHS and the "old" int13h code. You are wrong that I assuming that the FAT goes into one 64k page, I (and my code) know that the FAT can be as large as 2 64k pages and I´m testing for it. I would have one question. Why should someone use FAT for a CD (w/o emulation)? |
Author: | bewing [ Sat Nov 14, 2009 5:59 pm ] |
Post subject: | Re: Any better FAT16 bootsectors out there? |
> Why should someone use FAT for a CD (w/o emulation)? That was just a hypothetical example. There will (in the future) be devices that have sectorsizes that are not 512 bytes -- because they already exist. It may not be reasonable for CDs to use FAT, but it may be reasonable on some kind of non-512b-sector flash memory device that I don't know about. > You are wrong that I assuming that the FAT goes into one 64k page From what I saw, you load the FAT in one gulp. There are many BIOSes that cannot handle more than 127 sectors, 128 sectors, or 64K in one read using Int13h ax=42. When using that BIOS function, I always stick to 32K per read, just to make sure -- and keep page boundaries as aligned as reasonably possible. |
Author: | FlashBurn [ Sun Nov 15, 2009 2:15 am ] |
Post subject: | Re: Any better FAT16 bootsectors out there? |
Yeah, you are right, I think I will change this. In my bootsector which doesn´t use the extended int13h functions there my "load_chs" function is also looping and loads only 0x7f (I think so) sectors. But if I will find some time I will change my bootsector so that it will use the values which are in the bpb. |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |