Reactos
at master 205 lines 5.0 kB view raw
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// 27typedef 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} 42DOS_BPB, *PDOS_BPB; 43 44// 45// Extended BIOS parameter block for FAT12/16/HUGE 46// 47typedef struct _EXBPB 48{ 49 UCHAR PhysicalDriveNumber; 50 UCHAR Reserved; 51 UCHAR BootSignature; 52 ULONG VolumeSerialNumber; 53 CHAR VolumeLabel[11]; 54 CHAR FileSystemType[8]; 55} 56EXBPB, *PEXBPB; 57 58// 59// Partition Boot Record 60// 61typedef 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} 67DOS_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// 83static 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// 116DWORD 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}