/** @file
Fat.h - UEFI FAT Filesystem Driver header.
UEFI FAT filesystem driver for HR650X server. Implements EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
and EFI_FILE_PROTOCOL.
Supports FAT12, FAT16, and FAT32.
Copyright (c) 2025, Intel Corporation. All rights reserved.
**/
#ifndef __FAT_H__
#define __FAT_H__
#include <Uefi.h>
//=============================================================================
// Forward declarations
//=============================================================================
typedef struct _FAT_VOLUME FAT_VOLUME;
typedef struct _FAT_OFILE FAT_OFILE;
typedef struct _FAT_IFILE FAT_IFILE;
typedef struct _FAT_DIRENT FAT_DIRENT;
typedef struct _FAT_TASK FAT_TASK;
typedef struct _FAT_SUBTASK FAT_SUBTASK;
//=============================================================================
// Constants
//=============================================================================
#define FAT_SIGNATURE_VOLUME 0x4D495455 // "FAT_VOL"
#define FAT_SIGNATURE_OFILE 0x454C4946 // "FILE"
#define FAT_SIGNATURE_IFILE 0x454C4946 // "FILE"
#define FAT_SIGNATURE_DIRENT 0x65726944 // "Dire"
#define FAT_SIGNATURE_TASK 0x6B736154 // "Task"
#define FAT_SIGNATURE_SUBTASK 0x42465341 // "ASFB"
#define FAT_SIGNATURE_CACHE_PAGE 0x65676150 // "Page"
#define FAT_CLUSTER_LAST32 0x0FFFFFF8
#define FAT_CLUSTER_LAST16 0xFFF8
#define FAT_CLUSTER_LAST12 0xFF8
#define FAT_CLUSTER_EOF ((UINT64)-16)
#define FAT_CLUSTER_FREE32 0x00000000
#define FAT_CLUSTER_RESERVED32 0x0FFFFFF7
#define FAT_CLUSTER_BAD32 0x0FFFFFF7
#define FAT_ENTRY_FREE 0xE5
#define FAT_ENTRY_END 0x00
#define FAT_ATTRIBUTE_READ_ONLY 0x01
#define FAT_ATTRIBUTE_HIDDEN 0x02
#define FAT_ATTRIBUTE_SYSTEM 0x04
#define FAT_ATTRIBUTE_VOLUME_ID 0x08
#define FAT_ATTRIBUTE_DIRECTORY 0x10
#define FAT_ATTRIBUTE_ARCHIVE 0x20
#define FAT_ATTRIBUTE_LFN 0x0F
#define FAT_MAX_PATH_LEN 260
#define FAT_VOLUME_LABEL_MAX 12
#define FAT_CLASSNAME_LEN 120
//=============================================================================
// FAT Volume structure (size ~0x340 = 832 bytes)
//=============================================================================
struct _FAT_VOLUME {
UINT64 Signature; // 0x00: FAT_SIGNATURE_VOLUME
BOOLEAN Valid; // 0x08: is initialized
BOOLEAN Dirty; // 0x09: sync needed
//
// Pointers to block-level protocols
//
UINT64 BlockIo; // 0x10: EFI_BLOCK_IO_PROTOCOL
UINT64 BlockIo2; // 0x18: EFI_BLOCK_IO2_PROTOCOL
UINT64 DiskIo; // 0x20: EFI_DISK_IO_PROTOCOL
UINT64 DiskInfo; // 0x28: EFI_DISK_INFO_PROTOCOL
//
// Derived geometry
//
UINT64 VolumeSize; // 0x30: total volume bytes
UINT64 FatSizeBytes; // 0x38: total FAT size in bytes
UINT64 RootDirSectors; // 0x40: root dir sectors
UINT64 FirstDataSector; // 0x48: first data cluster LBA
UINT64 DataClusters; // 0x50: number of data clusters
UINT64 BytesPerCluster; // 0x58: bytes per cluster
UINT64 SectorsPerFat; // 0x60: sectors per FAT table
UINT64 NumFats; // 0x68: number of FAT copies
UINT64 Media; // 0x70: media descriptor
UINT64 RootEntries; // 0x78: root dir entries (FAT12/16)
UINT64 SectorsPerCluster; // 0x80: SectorsPerCluster from BPB
UINT64 FatShift; // 0x88: cluster shift for FAT byte offset
UINT64 ClusterSizeMask; // 0x90: BytesPerCluster - 1
UINT64 FatBufferSize; // 0x98: single FAT copy size
UINT64 ReadCount; // 0xA0: read tracking counter
// FAT parameters
UINT32 FatType; // 0xA4: 0=FAT12, 1=FAT16, 2=FAT32
UINT32 ReservedSectors; // 0xA8: BPB_RsvdSecCnt
UINT32 RootDirCluster; // 0xAC: first cluster of root dir (FAT32)
UINT32 VolumeID; // 0xB0: volume serial number
// Flags
UINT8 FatNumShift; // 0xB4: shift for FAT entry size
UINT8 Fat32Flag; // 0xB5: FAT32 extended boot signature
UINT8 FreeClusterValid; // 0xB6: free cluster count is valid
UINT8 Pad1; // 0xB7
// Tracking
UINT64 LastCluster; // 0xB8
LIST_ENTRY OpenFiles; // 0xC0: root OFILE list head
FAT_OFILE *RootOfile; // 0xD0: root directory OFILE
UINT8 *FatCache; // 0xD8: cached FAT table data
UINT64 FatCacheSize; // 0xE0: cached FAT size
};
#define FAT_VOLUME_SIGNATURE 0x4D495455
//=============================================================================
// FAT Open File structure (size = 184 bytes)
//=============================================================================
struct _FAT_OFILE {
UINT64 Signature; // 0x00: FAT_SIGNATURE_OFILE
FAT_OFILE *Parent; // 0x08: parent OFILE
UINT64 FileCluster; // 0x10: first cluster of file
LIST_ENTRY ChildHead; // 0x18: linked list of child OFILEs
LIST_ENTRY ChildLink; // 0x28: link in parent's child list
UINT64 FileSize; // 0x38: file size in bytes
UINT64 CurrentCluster; // 0x40: current cluster for sequential access
UINT64 CurrentBytePos; // 0x48: byte offset in current cluster
FAT_VOLUME *Volume; // 0x50: back to volume
UINT64 StartingCluster; // 0x58: first cluster for cluster chain
UINT64 CurrentPhysicalPos; // 0x60: disk byte position
UINT64 CurrentClusterStart; // 0x68: byte offset of cluster start
UINT64 Attributes; // 0x70: file attributes
UINT64 FullFileSize; // 0x78: full file size from dir entry
UINT64 WriteTime; // 0x80: last write time+date
UINT64 CreateTime; // 0x88: create time+date
UINT64 AccessTime; // 0x90: access time+date
BOOLEAN IsRoot; // 0x98: is root directory
BOOLEAN IsDirty; // 0x99: has been modified
};
//=============================================================================
// FAT_IFILE - Instance of EFI_FILE_PROTOCOL (size = 184 bytes)
//=============================================================================
struct _FAT_IFILE {
UINT64 Signature; // 0x00: FAT_SIGNATURE_IFILE
// EFI_FILE_PROTOCOL function table
UINT64 Revision; // 0x08: 0x00010000
UINT64 Open; // 0x10: EFI_FILE_PROTOCOL.Open
UINT64 Close; // 0x18: EFI_FILE_PROTOCOL.Close
UINT64 Delete; // 0x20: EFI_FILE_PROTOCOL.Delete
UINT64 Read; // 0x28: EFI_FILE_PROTOCOL.Read
UINT64 Write; // 0x30: EFI_FILE_PROTOCOL.Write
UINT64 GetPosition; // 0x38: EFI_FILE_PROTOCOL.GetPosition
UINT64 SetPosition; // 0x40: EFI_FILE_PROTOCOL.SetPosition
UINT64 GetInfo; // 0x48: EFI_FILE_PROTOCOL.GetInfo
UINT64 SetInfo; // 0x50: EFI_FILE_PROTOCOL.SetInfo
UINT64 Flush; // 0x58: EFI_FILE_PROTOCOL.Flush
UINT64 OpenEx; // 0x60: EFI_FILE_PROTOCOL.OpenEx
UINT64 ReadEx; // 0x68: EFI_FILE_PROTOCOL.ReadEx
UINT64 WriteEx; // 0x70: EFI_FILE_PROTOCOL.WriteEx
UINT64 FlushEx; // 0x78: EFI_FILE_PROTOCOL.FlushEx
FAT_OFILE *OFile; // 0x80: owning OFILE
UINT64 Position; // 0x88: current file position
BOOLEAN OpenForRead; // 0x90: opened for reading
BOOLEAN OpenForWrite; // 0x91: opened for writing
BOOLEAN IsReadOnly; // 0x92: read only access
UINT8 Pad[5]; // 0x93
UINT64 OpenMode; // 0x98
UINT64 Attributes; // 0xA0
LIST_ENTRY Link; // 0xA8
CHAR16 *FileName; // 0xB8
};
//=============================================================================
// FAT Directory Entry (32 bytes, on-disk format)
//=============================================================================
struct _FAT_DIRENT {
UINT8 Name[11]; // 0x00: 8.3 filename
UINT8 Attributes; // 0x0B: file attributes
UINT8 NtReserved; // 0x0C: NT reserved
UINT8 CreateTimeMs; // 0x0D: creation time ms
UINT16 CreateTime; // 0x0E: creation time
UINT16 CreateDate; // 0x10: creation date
UINT16 AccessDate; // 0x12: last access date
UINT16 FirstClusterHi; // 0x14: high 16 bits first cluster (FAT32)
UINT16 WriteTime; // 0x16: last write time
UINT16 WriteDate; // 0x18: last write date
UINT16 FirstClusterLo; // 0x1A: low 16 bits first cluster
UINT32 FileSize; // 0x1C: file size in bytes
} __attribute__((packed));
//=============================================================================
// FAT LFN Directory Entry (32 bytes, on-disk format)
//=============================================================================
typedef struct {
UINT8 SequenceNumber; // 0x00: seq (0x40=last, 0x01-0x14)
CHAR16 NamePart1[5]; // 0x01: chars 1-5
UINT8 Attributes; // 0x0B: always 0x0F
UINT8 Type; // 0x0C: reserved
UINT8 Checksum; // 0x0D: checksum of short name
CHAR16 NamePart2[6]; // 0x0E: chars 6-11
UINT16 Reserved; // 0x1A: must be 0
CHAR16 NamePart3[2]; // 0x1C: chars 12-13
} __attribute__((packed)) FAT_LFN_ENTRY;
//=============================================================================
// FAT Task and Subtask (for async I/O)
//=============================================================================
struct _FAT_TASK {
UINT64 Signature; // 0x00: FAT_SIGNATURE_TASK
LIST_ENTRY Subtasks; // 0x08: list of FAT_SUBTASK
UINT64 TotalBytes; // 0x18: total transfer size
UINT64 Result; // 0x20: overall result
FAT_IFILE *IFile; // 0x28: owning IFile
};
struct _FAT_SUBTASK {
UINT64 Signature; // 0x00: FAT_SIGNATURE_SUBTASK
BOOLEAN IsWrite; // 0x08: TRUE=write, FALSE=read
UINT64 DiskOffset; // 0x10: disk byte offset
UINT64 Buffer; // 0x18: data buffer
UINT64 Length; // 0x20: length in bytes
LIST_ENTRY Link; // 0x28: list link
UINT64 PageAddress; // 0x38: cached page address
};
//=============================================================================
// FAT Cache Page (80 bytes)
//=============================================================================
typedef struct {
UINT64 Signature; // 0x00: FAT_SIGNATURE_CACHE_PAGE
UINT64 PageAddress; // 0x08: disk offset
UINT64 PageSize; // 0x10: page size
UINT64 *Data; // 0x18: data buffer
BOOLEAN Dirty; // 0x20: modified
LIST_ENTRY Link; // 0x28: list link
UINT64 PageStatus; // 0x38
} FAT_CACHE_PAGE;
//=============================================================================
// Global variables
//=============================================================================
extern EFI_HANDLE gImageHandle;
extern EFI_SYSTEM_TABLE *gSystemTable;
extern EFI_BOOT_SERVICES *gBootServices;
extern UINT64 gLockCount;
extern UINT64 gLockValue;
//=============================================================================
// Function prototypes
//=============================================================================
//
// Entry Point
//
EFI_STATUS
EFIAPI
FatEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
//
// Driver Binding Protocol
//
EFI_STATUS
EFIAPI
FatSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
FatStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
FatStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
//
// Simple File System Protocol: OpenVolume
//
EFI_STATUS
EFIAPI
FatOpenVolume (
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **Root
);
//
// EFI_FILE_PROTOCOL
//
EFI_STATUS
EFIAPI
FatOpenFile (
IN EFI_FILE_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
);
EFI_STATUS
EFIAPI
FatCloseFile (
IN EFI_FILE_PROTOCOL *This
);
EFI_STATUS
EFIAPI
FatDeleteFile (
IN EFI_FILE_PROTOCOL *This
);
EFI_STATUS
EFIAPI
FatReadFile (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
);
EFI_STATUS
EFIAPI
FatWriteFile (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
IN VOID *Buffer
);
EFI_STATUS
EFIAPI
FatGetFilePosition (
IN EFI_FILE_PROTOCOL *This,
OUT UINT64 *Position
);
EFI_STATUS
EFIAPI
FatSetFilePosition (
IN EFI_FILE_PROTOCOL *This,
IN UINT64 Position
);
EFI_STATUS
EFIAPI
FatGetFileInfo (
IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
);
EFI_STATUS
EFIAPI
FatSetFileInfo (
IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType,
IN UINTN BufferSize,
IN VOID *Buffer
);
EFI_STATUS
EFIAPI
FatFlushFile (
IN EFI_FILE_PROTOCOL *This
);
//
// Volume and file allocation
//
EFI_STATUS
FatAllocVolume (
IN FAT_VOLUME *Volume,
IN UINT64 BlockIo,
IN UINT64 BlockIo2,
IN UINT64 DiskIoInterface,
IN UINT64 DiskInfo
);
VOID
FatFreeVolume (
FAT_VOLUME *Volume
);
EFI_STATUS
FatOpenRoot (
FAT_VOLUME *Volume,
FAT_OFILE **RootOFile
);
//
// FAT cluster operations
//
UINTN
FatReadClusterChain (
FAT_VOLUME *Volume,
UINTN Cluster,
UINTN Offset,
UINTN *BufferSize,
VOID *Buffer,
UINTN IoAlign
);
UINTN
FatWriteClusterChain (
FAT_VOLUME *Volume,
UINTN Cluster,
UINTN Offset,
UINTN *BufferSize,
VOID *Buffer,
UINTN IoAlign
);
UINT64
FatGetNextCluster (
FAT_VOLUME *Volume,
UINT64 Cluster
);
VOID
FatSetNextCluster (
FAT_VOLUME *Volume,
UINT64 Cluster,
UINT64 NextCluster
);
UINT64
FatAllocCluster (
FAT_VOLUME *Volume,
UINT64 StartCluster
);
EFI_STATUS
FatExpandFile (
FAT_IFILE *IFile,
UINT64 NewSize
);
EFI_STATUS
FatTruncateFile (
FAT_IFILE *IFile
);
//
// Directory operations
//
EFI_STATUS
FatReadDirEntry (
FAT_VOLUME *Volume,
UINTN DirCluster,
UINTN EntryIndex,
FAT_DIRENT *Entry
);
EFI_STATUS
FatWriteDirEntry (
FAT_VOLUME *Volume,
UINTN DirCluster,
UINTN EntryIndex,
FAT_DIRENT *Entry
);
EFI_STATUS
FatCreateDirEntry (
FAT_OFILE *Parent,
CHAR16 *FileName,
UINT8 Attributes,
FAT_OFILE **NewOFile
);
EFI_STATUS
FatRemoveDirEntry (
FAT_OFILE *OFile
);
//
// File name / path operations
//
BOOLEAN
FatIsValidChar (
IN CHAR16 Char
);
EFI_STATUS
FatParsePath (
IN CHAR16 *FileName,
IN UINTN FileNameLen,
IN CHAR16 **ParsedName
);
VOID
FatNameToStr (
IN FAT_DIRENT *Entry,
OUT CHAR16 *Name
);
UINTN
FatStrLen (
IN CHAR16 *String
);
INTN
FatStrCmp (
IN CHAR16 *String1,
IN CHAR16 *String2
);
INTN
FatStrNICmp (
IN CHAR16 *String1,
IN CHAR16 *String2,
IN UINTN Length
);
//
// Disk I/O helpers
//
EFI_STATUS
FatReadDisk (
FAT_VOLUME *Volume,
UINT64 Offset,
UINTN *BufferSize,
VOID *Buffer,
UINTN IoAlign
);
EFI_STATUS
FatWriteDisk (
FAT_VOLUME *Volume,
UINT64 Offset,
UINTN *BufferSize,
VOID *Buffer,
UINTN IoAlign
);
//
// Mem / pool helpers
//
VOID*
FatAllocPool (
UINTN Size
);
VOID*
FatAllocZeroPool (
UINTN Size
);
VOID
FatFreePool (
VOID *Buffer
);
VOID
FatCopyMem (
VOID *Dest,
const VOID *Src,
UINTN Length
);
INTN
FatCompareMem (
const VOID *Buf1,
const VOID *Buf2,
UINTN Length
);
VOID
FatZeroMem (
VOID *Buffer,
UINTN Length
);
//
// Locking
//
VOID
FatAcquireLock (
VOID
);
VOID
FatReleaseLock (
VOID
);
#endif // __FAT_H__