reactos/modules/rosapps/lib/vfdlib/vfdfat.c
Pierre Schweitzer 25c7e1a8d0
[VFD] Import the VFD project (Virtual Floppy Drive) which allows creating virtual
floppy drives in ReactOS and mount images on them.
Only the cmd got imported. The GUI interface may come later on.
Note that, as for vcdrom, the driver is left disabled and you need to explicitely
start it through vfd command line interface.

CORE-14090
2017-12-16 21:48:34 +01:00

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