mirror of
https://github.com/reactos/reactos.git
synced 2025-05-29 14:08:22 +00:00
206 lines
4.9 KiB
C
206 lines
4.9 KiB
C
![]() |
/*
|
||
|
vfdfat.c
|
||
|
|
||
|
Virtual Floppy Drive for Windows
|
||
|
Driver control library
|
||
|
Formats the image with FAT12
|
||
|
|
||
|
Copyright (C) 2003-2005 Ken Kato
|
||
|
*/
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
#pragma message(__FILE__": Compiled as C++ for testing purpose.")
|
||
|
#endif // __cplusplus
|
||
|
|
||
|
#define WIN32_LEAN_AND_MEAN
|
||
|
#include <windows.h>
|
||
|
|
||
|
#include "vfdtypes.h"
|
||
|
#include "vfdio.h"
|
||
|
#include "vfdlib.h"
|
||
|
#include "vfdver.h"
|
||
|
|
||
|
#pragma pack(1)
|
||
|
//
|
||
|
// BIOS parameter block
|
||
|
//
|
||
|
typedef struct _DOS_BPB
|
||
|
{
|
||
|
USHORT BytesPerSector;
|
||
|
UCHAR SectorsPerCluster;
|
||
|
USHORT ReservedSectors;
|
||
|
UCHAR NumberOfFATs;
|
||
|
USHORT RootEntries;
|
||
|
USHORT SmallSectors;
|
||
|
UCHAR MediaDescriptor;
|
||
|
USHORT SectorsPerFAT;
|
||
|
USHORT SectorsPerTrack;
|
||
|
USHORT NumberOfHeads;
|
||
|
ULONG HiddenSectors;
|
||
|
ULONG LargeSectors;
|
||
|
}
|
||
|
DOS_BPB, *PDOS_BPB;
|
||
|
|
||
|
//
|
||
|
// Extended BIOS parameter block for FAT12/16/HUGE
|
||
|
//
|
||
|
typedef struct _EXBPB
|
||
|
{
|
||
|
UCHAR PhysicalDriveNumber;
|
||
|
UCHAR Reserved;
|
||
|
UCHAR BootSignature;
|
||
|
ULONG VolumeSerialNumber;
|
||
|
CHAR VolumeLabel[11];
|
||
|
CHAR FileSystemType[8];
|
||
|
}
|
||
|
EXBPB, *PEXBPB;
|
||
|
|
||
|
//
|
||
|
// Partition Boot Record
|
||
|
//
|
||
|
typedef struct _DOS_PBR { // Partition Boot Record
|
||
|
UCHAR jump[3]; // Jump Instruction (E9 or EB, xx, 90)
|
||
|
CHAR oemid[8]; // OEM ID (OS type)
|
||
|
DOS_BPB bpb; // BIOS parameter block
|
||
|
EXBPB exbpb; // Extended BIOS parameter block
|
||
|
}
|
||
|
DOS_PBR, *PDOS_PBR;
|
||
|
|
||
|
#pragma pack()
|
||
|
|
||
|
#define FAT_DIR_ENTRY_SIZE 32
|
||
|
|
||
|
// We need to have the 0xeb and 0x90 in the jump code
|
||
|
// because the file system recognizer checks these values
|
||
|
#define VFD_JUMP_CODE "\xeb\x3c\x90"
|
||
|
#define VFD_OEM_NAME "VFD" VFD_DRIVER_VERSION_STR " "
|
||
|
#define VFD_VOLUME_LABEL "NO NAME "
|
||
|
#define VFD_FILESYSTEM "FAT12 "
|
||
|
|
||
|
//
|
||
|
// Select DOS BPB parameters from media size
|
||
|
//
|
||
|
static const DOS_BPB *SelectDosBpb(
|
||
|
USHORT nSectors)
|
||
|
{
|
||
|
static const DOS_BPB bpb_tbl[] = {
|
||
|
// b/s s/c r fat root sec desc s/f s/t h
|
||
|
{VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 320, 0xFE, 1, 8, 1, 0, 0}, // 160KB 5.25"
|
||
|
{VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 360, 0xFC, 1, 9, 1, 0, 0}, // 180KB 5.25"
|
||
|
{VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 640, 0xFF, 1, 8, 2, 0, 0}, // 320KB 5.25"
|
||
|
{VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 720, 0xFD, 2, 9, 2, 0, 0}, // 360KB 5.25"
|
||
|
{VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 1280, 0xFB, 2, 8, 2, 0, 0}, // 640KB 5.25" / 3.5"
|
||
|
{VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 1440, 0xF9, 3, 9, 2, 0, 0}, // 720KB 5.25" / 3.5"
|
||
|
{VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 1640, 0xF9, 3, 10, 2, 0, 0}, // 820KB 3.5"
|
||
|
{VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 2400, 0xF9, 7, 15, 2, 0, 0}, // 1.20MB 5.25" / 3.5"
|
||
|
{VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 2880, 0xF0, 9, 18, 2, 0, 0}, // 1.44MB 3.5"
|
||
|
{VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 3360, 0xF0, 10, 21, 2, 0, 0}, // 1.68MB 3.5"
|
||
|
{VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 3444, 0xF0, 10, 21, 2, 0, 0}, // 1.72MB 3.5"
|
||
|
{VFD_BYTES_PER_SECTOR, 2, 1, 2, 240, 5760, 0xF0, 9, 36, 2, 0, 0}, // 2.88MB 3.5"
|
||
|
};
|
||
|
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < sizeof(bpb_tbl) / sizeof(bpb_tbl[0]); i++) {
|
||
|
if (nSectors == bpb_tbl[i].SmallSectors) {
|
||
|
return &bpb_tbl[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Format the buffer with FAT12
|
||
|
//
|
||
|
DWORD FormatBufferFat(
|
||
|
PUCHAR pBuffer,
|
||
|
ULONG nSectors)
|
||
|
{
|
||
|
const DOS_BPB *bpb; // BIOS Parameter Block
|
||
|
PDOS_PBR pbr; // Partition Boot Record
|
||
|
PUCHAR fat; // File Allocation Table
|
||
|
USHORT idx;
|
||
|
|
||
|
VFDTRACE(0,
|
||
|
("[VFD] VfdFormatImage - IN\n"));
|
||
|
|
||
|
//
|
||
|
// Select DOS BPB parameters from media size
|
||
|
//
|
||
|
bpb = SelectDosBpb((USHORT)nSectors);
|
||
|
|
||
|
if (!bpb) {
|
||
|
VFDTRACE(0,
|
||
|
("[VFD] Unsupported media size %lu\n",
|
||
|
nSectors));
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Initialize the whole area with the fill data
|
||
|
//
|
||
|
FillMemory(pBuffer,
|
||
|
VFD_SECTOR_TO_BYTE(nSectors),
|
||
|
VFD_FORMAT_FILL_DATA);
|
||
|
|
||
|
//
|
||
|
// Make up the FAT boot record
|
||
|
//
|
||
|
ZeroMemory(pBuffer, VFD_BYTES_PER_SECTOR);
|
||
|
|
||
|
pbr = (PDOS_PBR)pBuffer;
|
||
|
|
||
|
CopyMemory(pbr->jump, VFD_JUMP_CODE, sizeof(pbr->jump));
|
||
|
CopyMemory(pbr->oemid, VFD_OEM_NAME, sizeof(pbr->oemid));
|
||
|
CopyMemory(&pbr->bpb, bpb, sizeof(pbr->bpb));
|
||
|
|
||
|
// Make up the extended BPB
|
||
|
|
||
|
pbr->exbpb.BootSignature = 0x29;
|
||
|
|
||
|
// use the tick count as the volume serial number
|
||
|
pbr->exbpb.VolumeSerialNumber = GetTickCount();
|
||
|
|
||
|
CopyMemory(pbr->exbpb.VolumeLabel,
|
||
|
VFD_VOLUME_LABEL, sizeof(pbr->exbpb.VolumeLabel));
|
||
|
|
||
|
CopyMemory(pbr->exbpb.FileSystemType,
|
||
|
VFD_FILESYSTEM, sizeof(pbr->exbpb.FileSystemType));
|
||
|
|
||
|
// Set the boot record signature
|
||
|
|
||
|
*(pBuffer + VFD_BYTES_PER_SECTOR - 2) = 0x55;
|
||
|
*(pBuffer + VFD_BYTES_PER_SECTOR - 1) = 0xaa;
|
||
|
|
||
|
//
|
||
|
// Clear FAT areas
|
||
|
//
|
||
|
fat = pBuffer + VFD_SECTOR_TO_BYTE(bpb->ReservedSectors);
|
||
|
|
||
|
ZeroMemory(
|
||
|
fat,
|
||
|
VFD_SECTOR_TO_BYTE(bpb->SectorsPerFAT * bpb->NumberOfFATs));
|
||
|
|
||
|
//
|
||
|
// Make up FAT entries for the root directory
|
||
|
//
|
||
|
for (idx = 0; idx < bpb->NumberOfFATs; idx++) {
|
||
|
*fat = bpb->MediaDescriptor;
|
||
|
*(fat + 1) = 0xff;
|
||
|
*(fat + 2) = 0xff;
|
||
|
|
||
|
fat += VFD_SECTOR_TO_BYTE(bpb->SectorsPerFAT);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Clear root directory entries
|
||
|
//
|
||
|
ZeroMemory(fat, bpb->RootEntries * FAT_DIR_ENTRY_SIZE);
|
||
|
|
||
|
VFDTRACE(0,
|
||
|
("[VFD] VfdFormatImage - OUT\n"));
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|