Newer
Older
AMI-Aptio-BIOS-Reversed / FatPkg / EnhancedFatDxe / Fat.h
/** @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__