Reactos
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}