# Refs: # http://www.win.tue.nl/~aeb/linux/fs/fat/fatgen103.pdf # http://www.win.tue.nl/~aeb/partitions/partition_types-1.html # http://en.wikipedia.org/wiki/Master_Boot_Record # http://en.wikipedia.org/wiki/Partition_type # http://de.wikipedia.org/wiki/File_Allocation_Table # http://en.wikipedia.org/wiki/File_Allocation_Table#Boot_Sector # http://src.iws.cs.ovgu.de/source/xref/illumos-gate/usr/src/uts/common/fs/pcfs/pc_vfsops.c # http://src.iws.cs.ovgu.de/source/xref/illumos-gate/usr/src/cmd/fs.d/pcfs/ # http://www.daniel-baumann.ch/gitweb/?p=software/dosfstools.git;a=tree;f=src;hb=HEAD # http://www.allbootdisks.com/download/dos.html # /usr/include/sys/dktp/fdisk.h # Terms: # Sector or Block: # smallest addressable unit. Usually 512 byte (many progs assume this), # but 1024, 2048, 4096 byte are allowed as well. # Cluster or Allocation unit: # group of consecutive blocks used as addressable unit by FAT # # Drive Number: # Phys. device addressable via INT13 (e.g. 00 == floppy, 0x80 == HDD) # Cylinder: # Phys. device "horizontal" addressable unit via INT13 # Head: # Phys. device "vertical" addressable unit via INT13. Range: 1..255, # floppy 1..2 # Track: # Seq. group of sectors addressed by (cylinder, head) # Sector: # Smallest phys. device unit within a track addressable via INT13. # Range: 1..63. Size usually 512 byte, but big disk start to use 4K. # Versions of MS-DOS earlier than 5.0 require that the first three sectors of # the Io.sys file reside in the first three sectors of the data area of the # hard disk. MS-DOS versions 5.0 and later do not have this requirement. =========================================================================== classic standard MBR (starts at CHS 0/0/1): =========================================================================== Addr bytes Used What 0x000 440 400 bootstrapper (usually compatible wrt. any OS) 0x1B8 2 442 S/N Hi 0x1BA 2 444 S/N Lo 0x1BC 2 446 reserved 0x1BE 16 462 partitionTable 1 0x1BE 1 1 status => 0x80 (active) | 0x0 (inactive) 0x1BF 1 2 begHead => {0..254}h 0x1C0 2 4 begSect=13:8,BegCyl=15:14,7:0 => 0..1022c, 1..63s 0x1C2 1 5 partition type 0x1C3 1 6 endHead 0x1C4 2 8 endSect=13:8,EndCyl=15:14,7:0 0x1C6 4 12 relSect 1st sect to start of disk 0x1CA 4 16 numsect # of sects in partition 0x1CE 16 478 partitionTable 2 0x1DE 16 494 partitionTable 3 0x1EE 16 510 partitionTable 4 0x1FE 2 512 boot signature = 55 aa =========================================================================== Volume Boot Record aka partition boot sector: =========================================================================== # - first primary partition is expected to start @ C/H/S 1/0/1 ({C,H} => track) # on a HDD (flopy has no MBR and thus no hidden track => @ 0/0/1) # - first sector of a track has number 1 (i.e. logical sector 0 is sector 1) # - FAT12/12 only 1 sector/VBR, FAT32 uses 3 (logical sector 0..3), which is # absolute: number of hidden sectors => number of sectors/track # - FAT32 contains a backup at logical sector 6..8 # - contains a BIOS Parameter Block (BPB) @ 0x0B..0x3D = 50 bytes since DOS 2.0 # - in DOS 1.x the 1st byte (lower 8 bits) of FAT[0] decided, whether single # or double sided (not supported anymore). DOS 2.x+ (all) --------------------------------------------------------- Addr bytes Used What 0x00 3 3 jump to bootloader instruction (0xEBxx90 | 0xE9xxxx) 0x03 8 11 OEM ID (system name) ==BPB start== 0x0B 2 13 bytes/sector (usually 512, but {1024|2048|4096} allowed 0x0D 1 14 sectors/cluster {1|2|4|..|64} (avoid 128) 0x0E 2 16 number of reserved sectors (incl. boot sector) FAT12/16: 1 FAT32: 32 (avoid others) 0x10 1 17 number of FATs (should be 2) 0x11 2 19 Max. entries in root dir (32 bit values) (val*32 should be n*bytes/sector), FAT16==512, FAT32==0 0x13 2 21 total volume size [sectors]. If 0 than 0x20 has it. Must be 0 on FAT32. FAT12/16: If < 64K than 0x20 == 0. 0x15 1 22 media type (e.g. 0xF8 == fixed disk) {0xF8..0xFF} This value must also be put in the low byte of FAT[0]! 0x16 2 24 Size of one FAT [sectors]. If FAT32 than 0, 0x24 has it. 0x18 2 26 sectors/track for INT13. Only relevant for media with geometry (C/H/S adressing). 0x1A 2 28 number of heads for INT13. Only relevant for media with geometry (C/H/S adressing). 0x1C 4 32 number hidden sectors preceding the partition (floppy=0) OS specific. Usually only relevant for media visible at INT13. 0x20 4 36 total volume size [sectors]. If 0 than 0x13 has it. Must be != 0 for FAT32. FAT12/16: != 0 if >= 64K DOS 2.x (volumes with < 64K 512B sectors <= 16bit): FAT12/16, DOS 3.x (volumes with < 4G 512B sectors <= 32bit): FAT16B (0x0B .. 0x3D incl.) ------------------------------------------------------------------------------ 0x24 1 37 INT13 drive number (0+n = floppy, 0x80+n = HDD) OS specific. 0x25 1 38 reserved (used by NT). Formatter should set to 0! 0x26 1 39 extended boot signature. If == 0x29 the following three fields are present. 0x27 4 43 volume serial number. (usually date and time combined) 0x2B 11 54 volume label. Set to 'NO NAME ' if unset. 0x36 8 62 file system type ID space padded. "FAT({12|16})? *" informational, only. ==BPB end== WIN95 R2 (volumes with > 4G 512B sectors): FAT32 (0x0B..0x59 incl.) ------------------------------------------------------------------- 0x24 4 40 Size of one FAT [sectors]. 0x16 must be 0! 0x28 2 42 Flags: 3:0 .. 0 base number of active FAT if mirroring is disabled. 6:4 .. reserved 7 .. 0 == FAT mirrored at runtime into all FATs 1 == only one FAT is active (see bits 3:0) 15:8 .. reserved 0x2A 2 44 Filesystem version (HI == major, LO == minor) 0x2C 4 48 number of the 1st cluster of the root dir (usually 2) 0x30 2 50 number of the sector with filesystem info in the reserved area of the volume. Usually 1. 0x32 2 52 If != 0: number of the sector with the boot sector backup in the reserved area of the volume. Sould be 6. 0x34 12 64 reserved. Should be set to 0. 0x40 1 65 INT13 drive number (0+n = floppy, 0x80+n = HDD). OS specific. 0x41 1 66 reserved (used by NT). Formatter should set to 0! 0x42 1 67 extended boot signature. If == 0x29 the following three fields are present. 0x43 4 71 volume serial number. (usually date and time combined) 0x47 11 82 volume label. Set to 'NO NAME ' if unset. 0x52 8 90 file system type ID space padded. Always 'FAT32 ' ==BPB end== 0x5A 278 368 OS bootloader 0x170 11 379 system file name 0x1AC 67 446 error messages ... 59 505 ??? 0x1F9 3 508 Error Message Data 0x1FC 2 510 ??? 0x1FE 2 512 boot signature 55 aa =========================================================================== FAT: =========================================================================== +------------------------------------------------+ | Reserved region (Boot sector 0 + other) | +------------------------------------------------+ | FAT region (cluster lists) | +------------------------------------------------+ | Root Directory region (doesn't exist in FAT32) | +------------------------------------------------+ | File and Data region | +------------------------------------------------+ - FAT entry: - one entry per cluster: the cluster number, or special value - values: 0: empty/unused maxValue-15 .. maxValue-9: reserved maxValue-8: bad cluster maxValue-7 .. maxValue: last cluster in dir/file and should be End Of cluster Chain Marker (EOC). - 1st 2 entries are reserved FAT[0] .. lower 8 bit = HI media type (should be same as in BPB 0x15) all others are set to 1 FAT[1] .. End of ClusterChain Marker (ignore 2 highest bits). Should be maxValue - FAT12: - 12 bit/entry - 2 entries (a2a1a0 b2b1b0) are packed into 3 bytes as: a2b2 b1a1 a0b0 - value: 0x002..0xff0: next cluster in chain 0xff0..0xff6: reserved 0xff7: bad cluster 0xfff: end of cluster chain (last cluster in file) - FAT16: - 16 bit/entry - value: 0x0002..0xffef: next cluster in chain 0xfff0..0xfff6: reserved 0xfff7: bad cluster 0xffff: end of cluster chain (last cluster in file) - FAT32 - 32 bit/entry, only lower 28bit are used => maxValue = 0x0FFF.FFFF.FFFF.FFFF = 256M - value: 0x0fff.fff7: bad cluster 0xffff.ffff: end of cluster chain (last cluster in file) - Each [root] directory entry (which might denote a dir or file) has 32 bytes: 0-10 filename zero padded before extension (no dot) 11 Attributes 12 reserved 13 creation time (1/10s) 14-15 creation time (HHmmSS) 16-17 creation date 18-19 access date 20-21 HI word of 1st cluster number of this file|dir (0 for FAT12/16) 22-23 modified time (HHmmSS) 24-25 modified date 26-27 LO word of 1st cluster number of this file|dir 28-31 File size (0 for dirs) # More or less safe values: # FAT32_SIZE FAT16_SIZE FAT12_SIZE default_ClusterSize (#sectors * 512) # < 32M: < 4.1M: 0 x 512 B = too small # <= 260M: < 2M: 1 x 512 B = ½KB # <= 16M: < 4M: 2 x 512 B = 1KB # <= 128M: 4 x 512 B = 2KB # <= 8G: <= 256M: 8 x 512 B = 4KB # <= 16G: <= 512M: 16 x 512 B = 8KB # <= 32G: <= 1G: 32 x 512 B = 16KB # > 32G: <= 2G: 64 x 512 B = 32KB # 128 x 512 B = 64KB dangerous! # > 2G: > 4M -1 x 512 B = too large # FAT12 FAT16 FAT16B FAT32 # max. clusters 4K-12 64K-12 64K-12 256M-15 (max 4M recom.) # - davon max. im / 14 512 512 64K # max. cluster size 4K 8K 32K 32K # resulting max. disk size ~16M ~512M ~2G ~8T # max. partition size ~16M ~32M ~2G # Relative to Sec 0 of the FAT volume: # FirstSecOfClusterN = ((N – 2) * BPB_SecPerClus) + FirstDataSec; # FirstDataSec = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSecs; # RootDirSecs = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1)) / BPB_BytsPerSec; # DataSec = TotSec – (BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSecs); # CountofClusters = DataSec / BPB_SecPerClus; # FATtype = CountofClusters < 4085 ? 12 : (CountofClusters < 65525 ? 16 : 32 ); # Solaris lofi emulates always phys: # 1 head and 300K/track -> 600 || 601 sectors/track with 512b sectors # => ~ 300K/cylinder # nCp = FileSz / (300 * 1024) # and virtual (as well as for USB): # 255 heads and 63 sectors/track with 512b =~ 32K/track # => ~ (8M - 160K)/cylinder # nCv = FileSz / (255 * 63 * 512) # if (nCv * (255 * 63 * 512) > nCp * (physSectors * 512)) { nCv--; } # which leads to: virt. DiskSz < phys DiskSz <= FileSz # # So to find the best lofi file size wrt. smallest waste of blocks: # vDiskSz = ( diskDesiredSz / 8225280 ) * 8225280 # pDiskSz = (( vDiskSz / 307200 ) + 1) * 307200 # or to have no waste at all: nCv = 20K * N with N = { 1, 2, ... } Finally conclusion of bootloader analysis: FAT12 and FAT16 bootloaders are interchangeable, but a FAT32 bootloader doesn't work with FAT12/16 volumes and vice versa.