How UEFI Handles File System Directory Structures

The Unified Extensible Firmware Interface (UEFI) abstracts storage hardware through a standardized set of protocols that present diverse physical media and partition layouts as a unified hierarchical file system. This article explores how UEFI manages directory structures using the Simple File System Protocol and File Protocol, detailing path traversal, directory iteration, and driver-level abstractions that maintain consistency across different platforms.

The UEFI File System Architecture

UEFI decouples firmware applications, boot loaders, and hardware drivers using an object-oriented protocol model. Instead of requiring applications to implement specific storage controller logic or raw block device access, UEFI relies on a layered architecture:

  1. Block I/O Protocol (EFI_BLOCK_IO_PROTOCOL): Provides raw access to block devices like NVMe drives, SATA SSDs, and USB storage.
  2. Disk I/O Protocol (EFI_DISK_IO_PROTOCOL): Adds byte-level addressing on top of block devices.
  3. Simple File System Protocol (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL): Bridges low-level disk access with a high-level file system representation.
  4. File Protocol (EFI_FILE_PROTOCOL): Provides handles to individual files and directories, exposing operations like open, read, write, and close.

By relying on this pipeline, the firmware does not need to know the physical geometry or interface of the drive; it interacts purely with logical volumes.

Root Initialization and Directory Representation

The abstraction layer views any compatible partition—most commonly the EFI System Partition (ESP)—as a volume containing a root directory.

Handling a directory begins with the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.OpenVolume() function. This call returns an EFI_FILE_PROTOCOL pointer representing the root directory token (\). In UEFI, directories and files use the exact same interface structure (EFI_FILE_PROTOCOL). The difference between a directory and a standard data file is marked by an attribute flag (EFI_FILE_DIRECTORY) within the file's metadata.

Path Resolution and Navigation

UEFI standardizes path syntax regardless of the operating system that generated the files:

  • Separators: UEFI strictly uses the backslash (\) as the path separator, following DOS-style conventions. Forward slashes are treated as invalid characters unless translated by a custom driver or shell.
  • Relative vs. Absolute Paths: Paths starting with \ are resolved relative to the root handle of the volume. Paths without a leading backslash are evaluated relative to the current directory handle from which the Open() method was called.
  • Parent References: The special token .. allows traversal to parent directories, while . refers to the current directory.

When an application calls EFI_FILE_PROTOCOL.Open(), the abstraction layer parses the path string token by token. The underlying driver traverses the tree structure by resolving each node sequentially until it locates the target file or directory handle.

Directory Enumeration via EFI_FILE_INFO

Because UEFI lacks the POSIX-style opendir() or readdir() functions, directory enumeration is handled directly through the Read() function of the EFI_FILE_PROTOCOL:

  1. Opening the Directory: The caller opens the target directory with read access.
  2. Reading Entries: Calling Read() on an open directory handle does not read binary file data. Instead, it populates a caller-allocated buffer with an EFI_FILE_INFO structure corresponding to the next directory entry.
  3. Metadata Retrieval: Each EFI_FILE_INFO record contains critical attributes:
    • File name (null-terminated UTF-16 string)
    • File size and physical space allocated
    • Creation, last access, and modification timestamps
    • Attribute masks (Read-Only, Hidden, System, Directory, Archive)
  4. End of Directory: The driver advances its internal cursor with each read. When the end of the directory is reached, the buffer size is returned as zero.
  5. Rewinding: Setting the file position to zero via the SetPosition() function resets the directory cursor back to the first entry.

Supporting Different Underlying File Systems

The UEFI specification mandates support for the FAT family (FAT12, FAT16, and FAT32) for the EFI System Partition. However, the abstraction layer is agnostic to the underlying on-disk layout.

Third-party or custom UEFI drivers can implement the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL for non-FAT file systems such as ext4, Btrfs, or NTFS. As long as the driver's implementation translates the file system's native inode tables, B-trees, or Master File Tables into the standard EFI_FILE_PROTOCOL methods, the UEFI boot manager and applications can navigate the resulting directory structures identically without modifications to the core firmware.