3

I am helping a friend write a bootloader for his operating system. I have gotten as far as writing a boot parameter block for him. It seems valid, however, when I use DD to burn it to the 1st sector of a 1.44MiB floppy disk image, it is not mountable as a FAT16 filesystem. I do not see any real issue with the code however. Here it is (it is quite well commented too):

BITS 16

jmp short start

iOEM db "ShapeOS"
iSectSize dw 0x200 ; bytes / sector
iClustSize db 1    ; 1 sector per cluster (for simplicity)
iResCnt dw 1       ; number of reserved sectors
iFatCnt db 2       ; # of fat copies
iRootSize dw 224   ; size of root dir
iTotalSect dw 2880 ; total sectors
iMedia db 0xF0     ; media descriptor
iFatSize dw 9      ; size of each FAT
iTrackSect dw 9    ; sectors per track
iHeadCnt dw 2      ; number of r/w heads
iHiddentSect dd 0  ; number of hidden sectors
iSect32 dd 0       ; number of > 32MB sectors
iBootDrive db 0    ; holds drive of bootsector
iReserved db 0     ; empty reserved attribute
iBootSign db 0x29  ; extended bootsig
iVolID db "seri"   ; disk serial
acVolumeLabel db "MYVOLUME  " ; volume label
acFSType db "FAT16  "         ; fs type

start:
    cli
    mov ax, 0x07C0  
    add ax, 288     
    mov ss, ax
    mov sp, 4096

    mov ax, 0x07C0      
    mov ds, ax
    sti

    call clear_screen

    mov si, intro
    call puts16
    mov si, loadmsg
    call puts16
    mov si, failed
    call puts16

    jmp $           


    intro db 'Shaper Bootloader, written by KingLuigi4932 and Kerndever', 0xD, 0xA, 0
    loadmsg db 'Loading kernel... ', 0
    failed db 'Failed!', 0xD, 0xA, 0


puts16:
    mov ah, 0Eh     

.repeat:
    lodsb           
    cmp al, 0
    je .done        
    int 10h         
    jmp .repeat

.done:
    ret

clear_screen:
    mov AX, 1003h
    mov BL, 00h
    int 10h

    ; Clear screen
    ;; Set mode to clear screen for all bioses
    mov AH, 00h
    int 10h

    ;; Fill screen with blue background
    mov AH, 09h
    mov AL, 20h
    mov BH, 00h
    mov BL, 1Eh
    mov CX, 2000h
    int 10h

    ret

times 510-($-$$) db 0
dw 0xAA55

The commands I use to put this on the first sector of a floppy disk image are:

dd if=/dev/zero of=fat.img bs=512 count=2880

And then:

dd status=noxfer conv=notrunc if=bootloader.bin of=fat.img

Thanks!

Safal Aryal
  • 155
  • 1
  • 8
  • And... where is your actual file allocation table? Where is the sector bitmap? Where is the root directory? Just because the first sector is present doesn't mean this is a valid FAT16 file system. – fuz Jan 26 '18 at 16:36
  • 2
    Everything is in the wrong place because there needs to be a NOP after jump over BPB and `iSectSize` needs to start at offset 0x0B, so `iOEM` needs to be 8 bytes. If you still have problems after that, then you need to check all the other values to make sure they are the right size. – Shift_Left Jan 26 '18 at 16:51
  • Possible duplicate of [FAT 12 Implementation](https://stackoverflow.com/questions/10457120/fat-12-implementation) – Ross Ridge Jan 26 '18 at 17:20
  • Creating a boot sector doesn't automatically give you a mountable file system. Also, you may want to verify that your OEM section is the correct number of bytes in length. I'm not saying it isn't, but I don't see anything there verifying that it's correct. – David Hoelzer Jan 26 '18 at 21:23
  • All the other comments are valid. Want to add - a 1.44MB floppy is 18 sectors per track not 9. Formatting any floppy with less than 4085 clusters is a bad idea. The reason is that many OSes including Windows determine the type of a FAT file system not by the FSType string, but by number of clusters.This was also captured in https://staff.washington.edu/dittrich/misc/fatgen103.pdf General Overview of On-Disk Format for their OSes) .Page 15 discusses the determination for FAT12/16/32. – Michael Petch Mar 16 '18 at 17:00
  • If you (and your own OS) will be the only one mounting the file system of this floppy you can do this if you know it is FAT16. If other OSes (like Windows and Linux) try to mount it they may make a false determination of what file system type it is when they check the cluster count. In linux you have to manually override the mount with a special option, on Windows I don't believe you can alter the behaviour. – Michael Petch Mar 16 '18 at 17:00
  • General rule of thumb is, if you are using a floppy and the total cluster count < 4085 (all the standard **floppy** disk sizes on the PC are less than < 4085 clusters) then you should be using FAT12 – Michael Petch Mar 16 '18 at 17:00
  • My Comment above meant to say "Formatting any floppy with less than 4085 clusters is a bad idea **WITH FAT16**". – Michael Petch Mar 16 '18 at 19:41

1 Answers1

4

As commented by Shift_Left everything in your BPB is in the wrong place.

  • The BIOS Parameter Block must start at offset 3 within the Boot Sector.
    The jump instruction at offset 0 can be a near jump (jmp near start) or a short jump followed by a padding nop instruction (jmp short start nop).

  • The BPB contains 3 string fields and you've defined them all 1 character short!

    iOEM          db "ShapeOS "     ; Must have 8 characters!
    acVolumeLabel db "MYVOLUME   "  ; Must have 11 characters!
    acFSType      db "FAT16   "     ; Must have 8 characters!
    

Given that the Boot Sector will sit in memory at linear address 7C00h and that you initialize the DS segment register to 07C0h, it will be best to assemble this code with an ORG 0 directive on top.

ORG 0
BITS 16

jmp near start

iOEM          db "ShapeOS "
iSectSize     dw 0x200         ; bytes / sector
iClustSize    db 1             ; 1 sector per cluster (for simplicity)
iResCnt       dw 1             ; number of reserved sectors
iFatCnt       db 2             ; # of fat copies
iRootSize     dw 224           ; size of root dir
iTotalSect    dw 2880          ; total sectors
iMedia        db 0xF0          ; media descriptor
iFatSize      dw 9             ; size of each FAT
iTrackSect    dw 9             ; sectors per track
iHeadCnt      dw 2             ; number of r/w heads
iHiddentSect  dd 0             ; number of hidden sectors
iSect32       dd 0             ; number of > 32MB sectors
iBootDrive    db 0             ; holds drive of bootsector
iReserved     db 0             ; empty reserved attribute
iBootSign     db 0x29          ; extended bootsig
iVolID        db "seri"        ; disk serial
acVolumeLabel db "MYVOLUME   " ; volume label
acFSType      db "FAT16   "    ; fs type

start:
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • For 2880 sectors (1.44MB floppy with 512 sectors per track) would require iTrackSect to be 18 for this to be a proper 1.44MB floppy. There use to be some esoteric BIOSes with USB booting that may refuse to boot this if the JMP it finds is NOT a `short jmp`.(strange but true). Usually it is best not to use a near jump. – Michael Petch Mar 16 '18 at 01:54