-// fathelp.S\r
-// FAT12/16 Boot Sector Helper Code\r
-// Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer\r
-\r
-//#include <asm.inc>\r
-\r
-//org 8000h\r
-\r
-//.text\r
-\r
-#define BootSectorStackTop HEX(7bf2)\r
-#define DataAreaStartHigh 2\r
-#define DataAreaStartLow 4\r
-#define BiosCHSDriveSizeHigh 6\r
-#define BiosCHSDriveSizeLow 8\r
-#define BiosCHSDriveSize 8\r
-#define ReadSectorsOffset 10\r
-#define ReadClusterOffset 12\r
-#define PutCharsOffset 14\r
-\r
-#define OEMName 3\r
-#define BytesPerSector 11\r
-#define SectsPerCluster 13\r
-#define ReservedSectors 14\r
-#define NumberOfFats 16\r
-#define MaxRootEntries 17\r
-#define TotalSectors 19\r
-#define MediaDescriptor 21\r
-#define SectorsPerFat 22\r
-#define SectorsPerTrack 24\r
-#define NumberOfHeads 26\r
-#define HiddenSectors 28\r
-#define TotalSectorsBig 32\r
-#define BootDrive 36\r
-#define Reserved 37\r
-#define ExtendSig 38\r
-#define SerialNumber 39\r
-#define VolumeLabel 43\r
-#define FileSystem 54\r
-\r
-#define BootPartition HEX(7dfd)\r
-\r
-\r
-// This code will be stored in the first 512 bytes\r
-// of freeldr.sys. The first 3 bytes will be a jmp\r
-// instruction to skip past the FAT helper code\r
-// that is stored in the rest of the 512 bytes.\r
-//\r
-\r
-PUBLIC start\r
-start:\r
- // This code is loaded at 0000:F800 so we have to\r
- // encode a jmp instruction to jump to 0000:FA00\r
- .byte HEX(e9), HEX(fd), HEX(01)\r
-\r
-// Now starts the extra boot code that we will store\r
-// in the first 512 bytes of freeldr.sys. This code\r
-// allows the FAT12/16 bootsector to navigate the\r
-// FAT table so that we can still load freeldr.sys\r
-// even if it is fragmented.\r
-\r
-\r
-FatHelperEntryPoint:\r
- /* First save AX - the start cluster of freeldr.sys */\r
- push ax\r
-\r
- /* Display "Loading FreeLoader..." message */\r
- mov si, offset msgLoading\r
- call word ptr [bp-PutCharsOffset]\r
-\r
- call ReadFatIntoMemory\r
-\r
- /* Restore AX (start cluster) */\r
- pop ax\r
-\r
- // AX has start cluster of freeldr.sys\r
- mov bx, FREELDR_BASE / 16\r
- mov es,bx\r
-\r
-LoadFile:\r
- push ax\r
- call IsFat12\r
- pop ax\r
- jnc LoadFile2\r
- cmp ax, HEX(0ff8) // Check to see if this is the last cluster in the chain\r
- jmp LoadFile3\r
-\r
-LoadFile2:\r
- cmp ax, HEX(0fff8)\r
-LoadFile3:\r
- jae LoadFile_Done // If so continue, if not then read then next one\r
- push ax\r
- xor bx,bx // Load ROSLDR starting at 0000:8000h\r
- push es\r
- call word ptr [bp-ReadClusterOffset]\r
- pop es\r
-\r
- xor bx,bx\r
- mov bl, [bp+SectsPerCluster]\r
- shl bx,5 // BX = BX * 512 / 16\r
- mov ax,es // Increment the load address by\r
- add ax,bx // The size of a cluster\r
- mov es,ax\r
-\r
- call IsFat12\r
- pop ax\r
- push es\r
- jnc LoadFile4\r
- call GetFatEntry12 // Get the next entry\r
- jmp LoadFile5\r
-LoadFile4:\r
- call GetFatEntry16\r
-LoadFile5:\r
- pop es\r
-\r
- jmp LoadFile // Load the next cluster (if any)\r
-\r
-LoadFile_Done:\r
- mov dl, byte ptr [bp+BootDrive] // Load the boot drive into DL\r
- mov dh, byte ptr ds:[BootPartition] // Load the boot partition into DH\r
-\r
- /* continue where other bootsectors start */\r
- jmp start\r
-\r
-\r
-// Reads the entire FAT into memory at 7000:0000\r
-ReadFatIntoMemory:\r
- mov ax, [bp+HiddenSectors]\r
- mov dx, [bp+HiddenSectors+2]\r
- add ax, [bp+ReservedSectors]\r
- adc dx, 0\r
- mov cx, [bp+SectorsPerFat]\r
- mov bx, HEX(7000)\r
- mov es,bx\r
- xor bx,bx\r
- call word ptr [bp-ReadSectorsOffset]\r
- ret\r
-\r
-\r
-// Returns the FAT entry for a given cluster number for 16-bit FAT\r
-// On entry AX has cluster number\r
-// On return AX has FAT entry for that cluster\r
-GetFatEntry16:\r
- mov cx,2 // AX = AX * 2 (since FAT16 entries are 2 bytes)\r
- mul cx\r
- shl dx,12\r
-\r
- mov bx, HEX(7000)\r
- add bx,dx\r
- mov es,bx\r
- mov bx,ax // Restore FAT entry offset\r
- mov ax, es:[bx] // Get FAT entry\r
-\r
- ret\r
-\r
-\r
-// Returns the FAT entry for a given cluster number for 12-bit FAT\r
-// On entry AX has cluster number\r
-// On return AX has FAT entry for that cluster\r
-GetFatEntry12:\r
- push ax\r
- mov cx,ax\r
- shr ax,1\r
- add ax,cx // AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)\r
-\r
- mov bx, HEX(7000)\r
- mov es,bx\r
- mov bx,ax // Put FAT entry offset into BX\r
- mov ax, es:[bx] // Get FAT entry\r
- pop cx // Get cluster number from stack\r
- and cx,1\r
- jz UseLow12Bits\r
- and ax, HEX(0fff0)\r
- shr ax,4\r
- jmp GetFatEntry12_Done\r
-\r
-UseLow12Bits:\r
- and ax, HEX(0fff)\r
-\r
-GetFatEntry12_Done:\r
-\r
- ret\r
-\r
-\r
-// Returns CF = 1 if this is a FAT12 file system\r
-// Otherwise CF = 0 for FAT16\r
-IsFat12:\r
-\r
- mov ebx, dword ptr [bp-DataAreaStartLow]\r
- // EBX now has the number of the starting sector of the data area\r
- // starting from the beginning of the disk, so subtrace hidden sectors\r
- sub ebx, dword ptr [bp+HiddenSectors]\r
-\r
-\r
- xor eax,eax\r
- mov ax, word ptr [bp+TotalSectors]\r
- cmp ax, 0\r
- jnz IsFat12_2\r
- mov eax, dword ptr [bp+TotalSectorsBig]\r
-\r
- // EAX now contains the number of sectors on the volume\r
-\r
-IsFat12_2:\r
- sub eax,ebx // Subtract data area start sector\r
- xor edx,edx // from total sectors of volume\r
-\r
- // EDX:EAX now contains the number of data sectors on the volume\r
- movzx ebx, byte ptr [bp+SectsPerCluster]\r
- div ebx\r
- // EAX now has the number of clusters on the volume\r
- stc\r
- cmp eax,4085\r
- jb IsFat12_Done\r
- clc\r
-\r
-IsFat12_Done:\r
- ret\r
-\r
-\r
-msgLoading:\r
- .ascii "Loading FreeLoader...", CR, LF, NUL\r
-\r
- .org 510 // Pad to 510 bytes\r
- .word HEX(0aa55) // BootSector signature\r
-\r
+// fathelp.S
+// FAT12/16 Boot Sector Helper Code
+// Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer
+
+//#include <asm.inc>
+
+//org 8000h
+
+//.text
+
+#define BootSectorStackTop HEX(7bf2)
+#define DataAreaStartHigh 2
+#define DataAreaStartLow 4
+#define BiosCHSDriveSizeHigh 6
+#define BiosCHSDriveSizeLow 8
+#define BiosCHSDriveSize 8
+#define ReadSectorsOffset 10
+#define ReadClusterOffset 12
+#define PutCharsOffset 14
+
+#define OEMName 3
+#define BytesPerSector 11
+#define SectsPerCluster 13
+#define ReservedSectors 14
+#define NumberOfFats 16
+#define MaxRootEntries 17
+#define TotalSectors 19
+#define MediaDescriptor 21
+#define SectorsPerFat 22
+#define SectorsPerTrack 24
+#define NumberOfHeads 26
+#define HiddenSectors 28
+#define TotalSectorsBig 32
+#define BootDrive 36
+#define Reserved 37
+#define ExtendSig 38
+#define SerialNumber 39
+#define VolumeLabel 43
+#define FileSystem 54
+
+#define BootPartition HEX(7dfd)
+
+
+// This code will be stored in the first 512 bytes
+// of freeldr.sys. The first 3 bytes will be a jmp
+// instruction to skip past the FAT helper code
+// that is stored in the rest of the 512 bytes.
+//
+
+PUBLIC start
+start:
+ // This code is loaded at 0000:F800 so we have to
+ // encode a jmp instruction to jump to 0000:FA00
+ .byte HEX(e9), HEX(fd), HEX(01)
+
+// Now starts the extra boot code that we will store
+// in the first 512 bytes of freeldr.sys. This code
+// allows the FAT12/16 bootsector to navigate the
+// FAT table so that we can still load freeldr.sys
+// even if it is fragmented.
+
+
+FatHelperEntryPoint:
+ /* First save AX - the start cluster of freeldr.sys */
+ push ax
+
+ /* Display "Loading FreeLoader..." message */
+ mov si, offset msgLoading
+ call word ptr [bp-PutCharsOffset]
+
+ call ReadFatIntoMemory
+
+ /* Restore AX (start cluster) */
+ pop ax
+
+ // AX has start cluster of freeldr.sys
+ mov bx, FREELDR_BASE / 16
+ mov es,bx
+
+LoadFile:
+ push ax
+ call IsFat12
+ pop ax
+ jnc LoadFile2
+ cmp ax, HEX(0ff8) // Check to see if this is the last cluster in the chain
+ jmp LoadFile3
+
+LoadFile2:
+ cmp ax, HEX(0fff8)
+LoadFile3:
+ jae LoadFile_Done // If so continue, if not then read then next one
+ push ax
+ xor bx,bx // Load ROSLDR starting at 0000:8000h
+ push es
+ call word ptr [bp-ReadClusterOffset]
+ pop es
+
+ xor bx,bx
+ mov bl, [bp+SectsPerCluster]
+ shl bx,5 // BX = BX * 512 / 16
+ mov ax,es // Increment the load address by
+ add ax,bx // The size of a cluster
+ mov es,ax
+
+ call IsFat12
+ pop ax
+ push es
+ jnc LoadFile4
+ call GetFatEntry12 // Get the next entry
+ jmp LoadFile5
+LoadFile4:
+ call GetFatEntry16
+LoadFile5:
+ pop es
+
+ jmp LoadFile // Load the next cluster (if any)
+
+LoadFile_Done:
+ mov dl, byte ptr [bp+BootDrive] // Load the boot drive into DL
+ mov dh, byte ptr ds:[BootPartition] // Load the boot partition into DH
+
+ /* continue where other bootsectors start */
+ jmp start
+
+
+// Reads the entire FAT into memory at 7000:0000
+ReadFatIntoMemory:
+ mov ax, [bp+HiddenSectors]
+ mov dx, [bp+HiddenSectors+2]
+ add ax, [bp+ReservedSectors]
+ adc dx, 0
+ mov cx, [bp+SectorsPerFat]
+ mov bx, HEX(7000)
+ mov es,bx
+ xor bx,bx
+ call word ptr [bp-ReadSectorsOffset]
+ ret
+
+
+// Returns the FAT entry for a given cluster number for 16-bit FAT
+// On entry AX has cluster number
+// On return AX has FAT entry for that cluster
+GetFatEntry16:
+ mov cx,2 // AX = AX * 2 (since FAT16 entries are 2 bytes)
+ mul cx
+ shl dx,12
+
+ mov bx, HEX(7000)
+ add bx,dx
+ mov es,bx
+ mov bx,ax // Restore FAT entry offset
+ mov ax, es:[bx] // Get FAT entry
+
+ ret
+
+
+// Returns the FAT entry for a given cluster number for 12-bit FAT
+// On entry AX has cluster number
+// On return AX has FAT entry for that cluster
+GetFatEntry12:
+ push ax
+ mov cx,ax
+ shr ax,1
+ add ax,cx // AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)
+
+ mov bx, HEX(7000)
+ mov es,bx
+ mov bx,ax // Put FAT entry offset into BX
+ mov ax, es:[bx] // Get FAT entry
+ pop cx // Get cluster number from stack
+ and cx,1
+ jz UseLow12Bits
+ and ax, HEX(0fff0)
+ shr ax,4
+ jmp GetFatEntry12_Done
+
+UseLow12Bits:
+ and ax, HEX(0fff)
+
+GetFatEntry12_Done:
+
+ ret
+
+
+// Returns CF = 1 if this is a FAT12 file system
+// Otherwise CF = 0 for FAT16
+IsFat12:
+
+ mov ebx, dword ptr [bp-DataAreaStartLow]
+ // EBX now has the number of the starting sector of the data area
+ // starting from the beginning of the disk, so subtrace hidden sectors
+ sub ebx, dword ptr [bp+HiddenSectors]
+
+
+ xor eax,eax
+ mov ax, word ptr [bp+TotalSectors]
+ cmp ax, 0
+ jnz IsFat12_2
+ mov eax, dword ptr [bp+TotalSectorsBig]
+
+ // EAX now contains the number of sectors on the volume
+
+IsFat12_2:
+ sub eax,ebx // Subtract data area start sector
+ xor edx,edx // from total sectors of volume
+
+ // EDX:EAX now contains the number of data sectors on the volume
+ movzx ebx, byte ptr [bp+SectsPerCluster]
+ div ebx
+ // EAX now has the number of clusters on the volume
+ stc
+ cmp eax,4085
+ jb IsFat12_Done
+ clc
+
+IsFat12_Done:
+ ret
+
+
+msgLoading:
+ .ascii "Loading FreeLoader...", CR, LF, NUL
+
+ .org 510 // Pad to 510 bytes
+ .word HEX(0aa55) // BootSector signature
+