1 /* 2 vfdfat.c 3 4 Virtual Floppy Drive for Windows 5 Driver control library 6 Formats the image with FAT12 7 8 Copyright (C) 2003-2005 Ken Kato 9 */ 10 11 #ifdef __cplusplus 12 #pragma message(__FILE__": Compiled as C++ for testing purpose.") 13 #endif // __cplusplus 14 15 #define WIN32_LEAN_AND_MEAN 16 #include <windows.h> 17 18 #include "vfdtypes.h" 19 #include "vfdio.h" 20 #include "vfdlib.h" 21 #include "vfdver.h" 22 23 #pragma pack(1) 24 // 25 // BIOS parameter block 26 // 27 typedef struct _DOS_BPB 28 { 29 USHORT BytesPerSector; 30 UCHAR SectorsPerCluster; 31 USHORT ReservedSectors; 32 UCHAR NumberOfFATs; 33 USHORT RootEntries; 34 USHORT SmallSectors; 35 UCHAR MediaDescriptor; 36 USHORT SectorsPerFAT; 37 USHORT SectorsPerTrack; 38 USHORT NumberOfHeads; 39 ULONG HiddenSectors; 40 ULONG LargeSectors; 41 } 42 DOS_BPB, *PDOS_BPB; 43 44 // 45 // Extended BIOS parameter block for FAT12/16/HUGE 46 // 47 typedef struct _EXBPB 48 { 49 UCHAR PhysicalDriveNumber; 50 UCHAR Reserved; 51 UCHAR BootSignature; 52 ULONG VolumeSerialNumber; 53 CHAR VolumeLabel[11]; 54 CHAR FileSystemType[8]; 55 } 56 EXBPB, *PEXBPB; 57 58 // 59 // Partition Boot Record 60 // 61 typedef struct _DOS_PBR { // Partition Boot Record 62 UCHAR jump[3]; // Jump Instruction (E9 or EB, xx, 90) 63 CHAR oemid[8]; // OEM ID (OS type) 64 DOS_BPB bpb; // BIOS parameter block 65 EXBPB exbpb; // Extended BIOS parameter block 66 } 67 DOS_PBR, *PDOS_PBR; 68 69 #pragma pack() 70 71 #define FAT_DIR_ENTRY_SIZE 32 72 73 // We need to have the 0xeb and 0x90 in the jump code 74 // because the file system recognizer checks these values 75 #define VFD_JUMP_CODE "\xeb\x3c\x90" 76 #define VFD_OEM_NAME "VFD" VFD_DRIVER_VERSION_STR " " 77 #define VFD_VOLUME_LABEL "NO NAME " 78 #define VFD_FILESYSTEM "FAT12 " 79 80 // 81 // Select DOS BPB parameters from media size 82 // 83 static const DOS_BPB *SelectDosBpb( 84 USHORT nSectors) 85 { 86 static const DOS_BPB bpb_tbl[] = { 87 // b/s s/c r fat root sec desc s/f s/t h 88 {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 320, 0xFE, 1, 8, 1, 0, 0}, // 160KB 5.25" 89 {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 360, 0xFC, 1, 9, 1, 0, 0}, // 180KB 5.25" 90 {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 640, 0xFF, 1, 8, 2, 0, 0}, // 320KB 5.25" 91 {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 720, 0xFD, 2, 9, 2, 0, 0}, // 360KB 5.25" 92 {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 1280, 0xFB, 2, 8, 2, 0, 0}, // 640KB 5.25" / 3.5" 93 {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 1440, 0xF9, 3, 9, 2, 0, 0}, // 720KB 5.25" / 3.5" 94 {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 1640, 0xF9, 3, 10, 2, 0, 0}, // 820KB 3.5" 95 {VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 2400, 0xF9, 7, 15, 2, 0, 0}, // 1.20MB 5.25" / 3.5" 96 {VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 2880, 0xF0, 9, 18, 2, 0, 0}, // 1.44MB 3.5" 97 {VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 3360, 0xF0, 10, 21, 2, 0, 0}, // 1.68MB 3.5" 98 {VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 3444, 0xF0, 10, 21, 2, 0, 0}, // 1.72MB 3.5" 99 {VFD_BYTES_PER_SECTOR, 2, 1, 2, 240, 5760, 0xF0, 9, 36, 2, 0, 0}, // 2.88MB 3.5" 100 }; 101 102 int i; 103 104 for (i = 0; i < sizeof(bpb_tbl) / sizeof(bpb_tbl[0]); i++) { 105 if (nSectors == bpb_tbl[i].SmallSectors) { 106 return &bpb_tbl[i]; 107 } 108 } 109 110 return NULL; 111 } 112 113 // 114 // Format the buffer with FAT12 115 // 116 DWORD FormatBufferFat( 117 PUCHAR pBuffer, 118 ULONG nSectors) 119 { 120 const DOS_BPB *bpb; // BIOS Parameter Block 121 PDOS_PBR pbr; // Partition Boot Record 122 PUCHAR fat; // File Allocation Table 123 USHORT idx; 124 125 VFDTRACE(0, 126 ("[VFD] VfdFormatImage - IN\n")); 127 128 // 129 // Select DOS BPB parameters from media size 130 // 131 bpb = SelectDosBpb((USHORT)nSectors); 132 133 if (!bpb) { 134 VFDTRACE(0, 135 ("[VFD] Unsupported media size %lu\n", 136 nSectors)); 137 return ERROR_INVALID_PARAMETER; 138 } 139 140 // 141 // Initialize the whole area with the fill data 142 // 143 FillMemory(pBuffer, 144 VFD_SECTOR_TO_BYTE(nSectors), 145 VFD_FORMAT_FILL_DATA); 146 147 // 148 // Make up the FAT boot record 149 // 150 ZeroMemory(pBuffer, VFD_BYTES_PER_SECTOR); 151 152 pbr = (PDOS_PBR)pBuffer; 153 154 CopyMemory(pbr->jump, VFD_JUMP_CODE, sizeof(pbr->jump)); 155 CopyMemory(pbr->oemid, VFD_OEM_NAME, sizeof(pbr->oemid)); 156 CopyMemory(&pbr->bpb, bpb, sizeof(pbr->bpb)); 157 158 // Make up the extended BPB 159 160 pbr->exbpb.BootSignature = 0x29; 161 162 // use the tick count as the volume serial number 163 pbr->exbpb.VolumeSerialNumber = GetTickCount(); 164 165 CopyMemory(pbr->exbpb.VolumeLabel, 166 VFD_VOLUME_LABEL, sizeof(pbr->exbpb.VolumeLabel)); 167 168 CopyMemory(pbr->exbpb.FileSystemType, 169 VFD_FILESYSTEM, sizeof(pbr->exbpb.FileSystemType)); 170 171 // Set the boot record signature 172 173 *(pBuffer + VFD_BYTES_PER_SECTOR - 2) = 0x55; 174 *(pBuffer + VFD_BYTES_PER_SECTOR - 1) = 0xaa; 175 176 // 177 // Clear FAT areas 178 // 179 fat = pBuffer + VFD_SECTOR_TO_BYTE(bpb->ReservedSectors); 180 181 ZeroMemory( 182 fat, 183 VFD_SECTOR_TO_BYTE(bpb->SectorsPerFAT * bpb->NumberOfFATs)); 184 185 // 186 // Make up FAT entries for the root directory 187 // 188 for (idx = 0; idx < bpb->NumberOfFATs; idx++) { 189 *fat = bpb->MediaDescriptor; 190 *(fat + 1) = 0xff; 191 *(fat + 2) = 0xff; 192 193 fat += VFD_SECTOR_TO_BYTE(bpb->SectorsPerFAT); 194 } 195 196 // 197 // Clear root directory entries 198 // 199 ZeroMemory(fat, bpb->RootEntries * FAT_DIR_ENTRY_SIZE); 200 201 VFDTRACE(0, 202 ("[VFD] VfdFormatImage - OUT\n")); 203 204 return ERROR_SUCCESS; 205 } 206