Added FAT12 support.

Create random volume serial numbers.

svn path=/trunk/; revision=5829
This commit is contained in:
Eric Kohl 2003-08-24 16:15:31 +00:00
parent 26532ec2d6
commit c466a4450e
6 changed files with 454 additions and 14 deletions

View file

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.4 2003/08/22 13:53:02 ekohl Exp $
# $Id: Makefile,v 1.5 2003/08/24 16:15:31 ekohl Exp $
PATH_TO_TOP = ../../..
@ -10,6 +10,7 @@ TARGET_NAME = vfatlib
TARGET_CFLAGS += -D_DISABLE_TIDENTS
TARGET_OBJECTS = \
fat12.o \
fat16.o \
fat32.o \
vfatlib.o

View file

@ -0,0 +1,376 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS VFAT filesystem library
* FILE: fat12.c
* PURPOSE: Fat12 support
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Eric Kohl (ekohl@rz-online.de)
* REVISIONS:
* EK 05/04-2003 Created
*/
#define NDEBUG
#include <debug.h>
#define NTOS_MODE_USER
#include <ntos.h>
#include <ddk/ntddscsi.h>
#include "vfatlib.h"
static ULONG
GetShiftCount(ULONG Value)
{
ULONG i = 1;
while (Value > 0)
{
i++;
Value /= 2;
}
return i - 2;
}
static ULONG
CalcVolumeSerialNumber(VOID)
{
LARGE_INTEGER SystemTime;
TIME_FIELDS TimeFields;
ULONG Serial;
PUCHAR Buffer;
NtQuerySystemTime (&SystemTime);
RtlTimeToTimeFields (&SystemTime, &TimeFields);
Buffer = (PUCHAR)&Serial;
Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
return Serial;
}
static NTSTATUS
Fat12WriteBootSector(IN HANDLE FileHandle,
IN PFAT16_BOOT_SECTOR BootSector)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING Name;
NTSTATUS Status;
PUCHAR NewBootSector;
LARGE_INTEGER FileOffset;
/* Allocate buffer for new bootsector */
NewBootSector = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
0,
SECTORSIZE);
if (NewBootSector == NULL)
return(STATUS_INSUFFICIENT_RESOURCES);
/* Zero the new bootsector */
memset(NewBootSector, 0, SECTORSIZE);
/* Copy FAT16 BPB to new bootsector */
memcpy((NewBootSector + 3),
&BootSector->OEMName[0],
59); /* FAT16 BPB length (up to (not including) Res2) */
/* Write sector 0 */
FileOffset.QuadPart = 0ULL;
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
NewBootSector,
SECTORSIZE,
&FileOffset,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
return(Status);
}
/* Free the new boot sector */
RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
return(Status);
}
static NTSTATUS
Fat12WriteFAT(IN HANDLE FileHandle,
ULONG SectorOffset,
IN PFAT16_BOOT_SECTOR BootSector)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING Name;
NTSTATUS Status;
PUCHAR Buffer;
LARGE_INTEGER FileOffset;
ULONG i;
ULONG Size;
ULONG Sectors;
/* Allocate buffer */
Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
0,
32 * 1024);
if (Buffer == NULL)
return(STATUS_INSUFFICIENT_RESOURCES);
/* Zero the buffer */
memset(Buffer, 0, 32 * 1024);
/* FAT cluster 0 & 1*/
Buffer[0] = 0xf8; /* Media type */
Buffer[1] = 0xff;
Buffer[2] = 0xff;
/* Write first sector of the FAT */
FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors) * BootSector->BytesPerSector;
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
Buffer,
BootSector->BytesPerSector,
&FileOffset,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
return(Status);
}
/* Zero the begin of the buffer */
memset(Buffer, 0, 3);
/* Zero the rest of the FAT */
Sectors = 32 * 1024 / BootSector->BytesPerSector;
for (i = 1; i < (ULONG)BootSector->FATSectors; i += Sectors)
{
/* Zero some sectors of the FAT */
FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors + i) * BootSector->BytesPerSector;
Size = (ULONG)BootSector->FATSectors - i;
if (Size > Sectors)
{
Size = Sectors;
}
Size *= BootSector->BytesPerSector;
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
Buffer,
Size,
&FileOffset,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
return(Status);
}
}
/* Free the buffer */
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
return(Status);
}
static NTSTATUS
Fat12WriteRootDirectory(IN HANDLE FileHandle,
IN PFAT16_BOOT_SECTOR BootSector)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
PUCHAR Buffer;
LARGE_INTEGER FileOffset;
ULONG FirstRootDirSector;
ULONG RootDirSectors;
ULONG Sectors;
ULONG Size;
ULONG i;
DPRINT("BootSector->ReservedSectors = %hu\n", BootSector->ReservedSectors);
DPRINT("BootSector->FATSectors = %hu\n", BootSector->FATSectors);
DPRINT("BootSector->SectorsPerCluster = %u\n", BootSector->SectorsPerCluster);
/* Write cluster */
RootDirSectors = ((BootSector->RootEntries * 32) +
(BootSector->BytesPerSector - 1)) / BootSector->BytesPerSector;
FirstRootDirSector =
BootSector->ReservedSectors + (BootSector->FATCount * BootSector->FATSectors);
DPRINT("RootDirSectors = %lu\n", RootDirSectors);
DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector);
/* Allocate buffer for the cluster */
Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
0,
32 * 1024);
if (Buffer == NULL)
return(STATUS_INSUFFICIENT_RESOURCES);
/* Zero the buffer */
memset(Buffer, 0, 32 * 1024);
Sectors = 32 * 1024 / BootSector->BytesPerSector;
for (i = 1; i < RootDirSectors; i += Sectors)
{
/* Zero some sectors of the root directory */
FileOffset.QuadPart = (FirstRootDirSector + i) * BootSector->BytesPerSector;
Size = RootDirSectors - i;
if (Size > Sectors)
{
Size = Sectors;
}
Size *= BootSector->BytesPerSector;
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
Buffer,
Size,
&FileOffset,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
return(Status);
}
}
/* Free the buffer */
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
return(Status);
}
NTSTATUS
Fat12Format (HANDLE FileHandle,
PPARTITION_INFORMATION PartitionInfo,
PDISK_GEOMETRY DiskGeometry,
PUNICODE_STRING Label,
BOOL QuickFormat,
DWORD ClusterSize,
PFMIFSCALLBACK Callback)
{
FAT16_BOOT_SECTOR BootSector;
ANSI_STRING VolumeLabel;
ULONG SectorCount;
ULONG RootDirSectors;
ULONG TmpVal1;
ULONG TmpVal2;
ULONG TmpVal3;
NTSTATUS Status;
/* Calculate cluster size */
if (ClusterSize == 0)
{
/* 4KB Cluster (Harddisk only) */
ClusterSize = 4096;
}
SectorCount = PartitionInfo->PartitionLength.QuadPart >>
GetShiftCount(DiskGeometry->BytesPerSector); /* Use shifting to avoid 64-bit division */
// SectorCount =
// PartitionInfo->PartitionLength.u.LowPart / DiskGeometry->BytesPerSector;
DPRINT1("SectorCount = %lu\n", SectorCount);
memset(&BootSector, 0, sizeof(FAT16_BOOT_SECTOR));
memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8);
BootSector.BytesPerSector = DiskGeometry->BytesPerSector;
BootSector.SectorsPerCluster = ClusterSize / BootSector.BytesPerSector;
BootSector.ReservedSectors = 1;
BootSector.FATCount = 2;
BootSector.RootEntries = 512;
BootSector.Sectors = (SectorCount < 0x10000) ? (unsigned short)SectorCount : 0;
BootSector.Media = 0xf8;
BootSector.FATSectors = 0; /* Set later. See below. */
BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack;
BootSector.Heads = DiskGeometry->TracksPerCylinder;
BootSector.HiddenSectors = DiskGeometry->SectorsPerTrack; //PartitionInfo->HiddenSectors; /* FIXME: Hack! */
BootSector.SectorsHuge = (SectorCount >= 0x10000) ? (unsigned long)SectorCount : 0;
BootSector.Drive = 0xff; /* No BIOS boot drive available */
BootSector.ExtBootSignature = 0x29;
BootSector.VolumeID = CalcVolumeSerialNumber();
if ((Label == NULL) || (Label->Buffer == NULL))
{
memcpy(&BootSector.VolumeLabel[0], "NO NAME ", 11);
}
else
{
RtlUnicodeStringToAnsiString(&VolumeLabel, Label, TRUE);
memset(&BootSector.VolumeLabel[0], ' ', 11);
memcpy(&BootSector.VolumeLabel[0], VolumeLabel.Buffer,
VolumeLabel.Length < 11 ? VolumeLabel.Length : 11);
RtlFreeAnsiString(&VolumeLabel);
}
memcpy(&BootSector.SysType[0], "FAT12 ", 8);
RootDirSectors = ((BootSector.RootEntries * 32) +
(BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector;
/* 341 FAT entries (12bit) fit into one 512 byte sector */
TmpVal1 = SectorCount - (BootSector.ReservedSectors + RootDirSectors);
TmpVal2 = (341 * BootSector.SectorsPerCluster) + BootSector.FATCount;
TmpVal3 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
BootSector.FATSectors = (unsigned short)(TmpVal3 & 0xffff);
DPRINT1("BootSector.FATSectors = %hx\n", BootSector.FATSectors);
Status = Fat12WriteBootSector(FileHandle,
&BootSector);
if (!NT_SUCCESS(Status))
{
DPRINT("Fat12WriteBootSector() failed with status 0x%.08x\n", Status);
return Status;
}
/* Write first FAT copy */
Status = Fat12WriteFAT(FileHandle,
0,
&BootSector);
if (!NT_SUCCESS(Status))
{
DPRINT("Fat12WriteFAT() failed with status 0x%.08x\n", Status);
return Status;
}
/* Write second FAT copy */
Status = Fat12WriteFAT(FileHandle,
(ULONG)BootSector.FATSectors,
&BootSector);
if (!NT_SUCCESS(Status))
{
DPRINT("Fat12WriteFAT() failed with status 0x%.08x.\n", Status);
return Status;
}
Status = Fat12WriteRootDirectory(FileHandle,
&BootSector);
if (!NT_SUCCESS(Status))
{
DPRINT("Fat12WriteRootDirectory() failed with status 0x%.08x\n", Status);
}
return Status;
}

View file

@ -3,7 +3,8 @@
* PROJECT: ReactOS VFAT filesystem library
* FILE: fat16.c
* PURPOSE: Fat16 support
* PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Eric Kohl (ekohl@rz-online.de)
* REVISIONS:
* EK 05/04-2003 Created
*/
@ -28,6 +29,27 @@ GetShiftCount(ULONG Value)
}
static ULONG
CalcVolumeSerialNumber(VOID)
{
LARGE_INTEGER SystemTime;
TIME_FIELDS TimeFields;
ULONG Serial;
PUCHAR Buffer;
NtQuerySystemTime (&SystemTime);
RtlTimeToTimeFields (&SystemTime, &TimeFields);
Buffer = (PUCHAR)&Serial;
Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
return Serial;
}
static NTSTATUS
Fat16WriteBootSector(IN HANDLE FileHandle,
IN PFAT16_BOOT_SECTOR BootSector)
@ -254,6 +276,7 @@ Fat16Format (HANDLE FileHandle,
{
FAT16_BOOT_SECTOR BootSector;
ANSI_STRING VolumeLabel;
ULONG SectorCount;
ULONG RootDirSectors;
ULONG TmpVal1;
ULONG TmpVal2;
@ -285,6 +308,9 @@ Fat16Format (HANDLE FileHandle,
}
}
SectorCount = PartitionInfo->PartitionLength.QuadPart >>
GetShiftCount(DiskGeometry->BytesPerSector); /* Use shifting to avoid 64-bit division */
memset(&BootSector, 0, sizeof(FAT16_BOOT_SECTOR));
memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8);
BootSector.BytesPerSector = DiskGeometry->BytesPerSector;
@ -292,17 +318,16 @@ Fat16Format (HANDLE FileHandle,
BootSector.ReservedSectors = 1;
BootSector.FATCount = 2;
BootSector.RootEntries = 512;
BootSector.Sectors = 0; //(SectorCount < 0x10000) ? SectorCount : 0;
BootSector.Sectors = (SectorCount < 0x10000) ? (unsigned short)SectorCount : 0;
BootSector.Media = 0xf8;
BootSector.FATSectors = 0; /* Set later. See below. */
BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack;
BootSector.Heads = DiskGeometry->TracksPerCylinder;
BootSector.HiddenSectors = DiskGeometry->SectorsPerTrack; //PartitionInfo->HiddenSectors; /* FIXME: Hack! */
BootSector.SectorsHuge = PartitionInfo->PartitionLength.QuadPart >>
GetShiftCount(BootSector.BytesPerSector); /* Use shifting to avoid 64-bit division */
BootSector.SectorsHuge = (SectorCount >= 0x10000) ? (unsigned long)SectorCount : 0;
BootSector.Drive = 0xff; /* No BIOS boot drive available */
BootSector.ExtBootSignature = 0x29;
BootSector.VolumeID = 0x45768798; /* FIXME: */
BootSector.VolumeID = CalcVolumeSerialNumber();
if ((Label == NULL) || (Label->Buffer == NULL))
{
memcpy(&BootSector.VolumeLabel[0], "NO NAME ", 11);
@ -322,7 +347,8 @@ Fat16Format (HANDLE FileHandle,
RootDirSectors = ((BootSector.RootEntries * 32) +
(BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector;
TmpVal1 = BootSector.SectorsHuge - (BootSector.ReservedSectors + RootDirSectors);
/* 265 FAT entries (16bit) fit into one 512 byte sector */
TmpVal1 = SectorCount - (BootSector.ReservedSectors + RootDirSectors);
TmpVal2 = (256 * BootSector.SectorsPerCluster) + BootSector.FATCount;
TmpVal3 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
BootSector.FATSectors = (unsigned short)(TmpVal3 & 0xffff);

View file

@ -1,9 +1,10 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS VFAT filesystem library
* FILE: fat16.c
* PURPOSE: Fat16 support
* PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
* FILE: fat32.c
* PURPOSE: Fat32 support
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Eric Kohl (ekohl@rz-online.de)
* REVISIONS:
* EK 05/04-2003 Created
*/
@ -28,6 +29,27 @@ GetShiftCount(ULONG Value)
}
static ULONG
CalcVolumeSerialNumber(VOID)
{
LARGE_INTEGER SystemTime;
TIME_FIELDS TimeFields;
ULONG Serial;
PUCHAR Buffer;
NtQuerySystemTime (&SystemTime);
RtlTimeToTimeFields (&SystemTime, &TimeFields);
Buffer = (PUCHAR)&Serial;
Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
return Serial;
}
static NTSTATUS
Fat32WriteBootSector(IN HANDLE FileHandle,
IN PFAT32_BOOT_SECTOR BootSector)
@ -377,7 +399,7 @@ Fat32Format (HANDLE FileHandle,
BootSector.BootBackup = 6;
BootSector.Drive = 0xff; /* No BIOS boot drive available */
BootSector.ExtBootSignature = 0x29;
BootSector.VolumeID = 0x45768798; /* FIXME: */
BootSector.VolumeID = CalcVolumeSerialNumber ();
if ((Label == NULL) || (Label->Buffer == NULL))
{
memcpy(&BootSector.VolumeLabel[0], "NO NAME ", 11);
@ -416,6 +438,14 @@ Fat32Format (HANDLE FileHandle,
BootSector.FATSectors32 = TmpVal2;
}
#if 0
/* experimental */
/* 128 FAT entries (32bit) fit into one 512 byte sector */
TmpVal1 = BootSector.SectorsHuge - BootSector.ReservedSectors;
TmpVal2 = (128 * BootSector.SectorsPerCluster) + BootSector.FATCount;
BootSector.FATSectors32 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
#endif
Status = Fat32WriteBootSector(FileHandle,
&BootSector);
if (!NT_SUCCESS(Status))

View file

@ -129,8 +129,7 @@ VfatFormat(
ClusterSize,
Callback);
}
#if 0
else if (PartitionInfo.PartitionType == PARTITION_FAT12)
else if (PartitionInfo.PartitionType == PARTITION_FAT_12)
{
Status = Fat12Format (FileHandle,
&PartitionInfo,
@ -140,7 +139,6 @@ VfatFormat(
ClusterSize,
Callback);
}
#endif
else
{
Status = Fat16Format (FileHandle,

View file

@ -87,6 +87,15 @@ typedef struct _FAT32_FSINFO
} __attribute__((packed)) FAT32_FSINFO, *PFAT32_FSINFO;
NTSTATUS
Fat12Format (HANDLE FileHandle,
PPARTITION_INFORMATION PartitionInfo,
PDISK_GEOMETRY DiskGeometry,
PUNICODE_STRING Label,
BOOL QuickFormat,
DWORD ClusterSize,
PFMIFSCALLBACK Callback);
NTSTATUS
Fat16Format (HANDLE FileHandle,
PPARTITION_INFORMATION PartitionInfo,