A lot of the time, we talk about creating a partition to serve as the EFI System Partition. This partition is mandated by the UEFI specification for several tasks. Adam covered what’s going on at a relatively high level on his recent blog post, and you should read the whole thing:
An ‘EFI system partition’ is really just any partition formatted with one of the UEFI spec-defined variants of FAT and given a specific GPT partition type to help the firmware find it. And the purpose of this is just as described above: allow everyone to rely on the fact that the firmware layer will definitely be able to read data from a pretty ‘normal’ disk partition.
There’s nothing truly special about an ESP. It isn’t an ESP because of the GPT GUID and label, nor because of the file system type. Those are how the firmware identifies a partition, and the file system it contains, as candidates to treat as the ESP, when it really needs to find one. The only factor in determining if a partition is the ESP is this: is the firmware attempting to use it as the ESP?
At the same time, the requirements for the ESP give us latitude; we know that we can use UEFI’s APIs to find correctly constructed FAT file systems, but there’s no need for those to be the ESP. In fact, even when we create multiple partitions with the ESP’s GUID and label, there’s no requirement that the firmware looks at more than one of them if it needs to find the ESP, and there’s no guarantee as to which one it will pick, either.
Thankfully, most of the time we don’t care. Under normal circumstances,
the system isn’t actually looking for something to fill the role of the
ESP. When the system starts up, it consults the
BootOrder, which is
just a list of 16-bit numbers, such as
When this is found, the firmware will iterate the list, as you might
expect. For each entry in the list, it looks for a corresponding
Boot#### variable —
Boot0001 for 0001,
Boot001A for 0x001a, and so
on, with the value from
BootOrder rendered in capitalized
hexadecimal. If it doesn’t find the variable, it continues to the next
BootOrder. If it does find the variable, it reads the contents
of the variable to try to decide what to do. Generally speaking, what’s in
there is a human friendly label, a Device Path like
ACPI(a0341d0,0)PCI(1f,2)SATA(0,0,0)HD(1,800,64000,12029cda-8961-470d-82ba-aeb17dba91a5)File(\EFI\fedora\shim.efi), and optional data to be passed to whatever program is to be loaded.
This Device Path reflects the series of parts that need to be initialized
in order to find the ultimate media device
HD(1,800,64000,12029cda-8961-470d-82ba-aeb17dba91a5)1, which specifies a partition number, the partition’s
offset and size, and the partition’s GUID.
This partition need not be an “EFI System Partition” properly; the firmware doesn’t care if the GUID in the partition table is the ESP GUID, only that it matches the GUID in the Device Path. Likewise, it doesn’t care about the label. This file system may be the ESP, but there’s no requirement. The only real requirement here is that we have to use FAT, because it’s the only file system the firmware is guaranteed to know about.
At this point, the system firmware is going to initialize each device that’s
part of that Device Path, in order, that hasn’t already been initialized.
Some things will always be initialized — it’s unlikely that ACPI tables
and the PCI root hub specified in this particular path2 weren’t already
needed to get this far — but other things, like the SATA controller or
its port 0, port multiplier 0, LUN 0 device,
SATA(0,0,0)3, will probably
need to be initialized. Once that is done, the firmware will examine the
disk and see if it has a partition matching the
HD() path above. If it
finds that, and it contains a FAT file system, it looks for
If any of that goes wrong, it moves on to the next
and follow the exact same process, initializing one peripheral at a time
until it can load a file from the FAT it finds.
What if everything we know is wrong?
If all of that fails, and there is no working boot entry found by
BootOrder, there are still things to do. At this point, the
firmware will start initializing all peripherals it can find, in whatever
order it happens to choose — for some peripherals this will be linear and
predictable, for some it will start things all at once and they’ll respond
in whatever order they become ready. For each media device it finds, it will
check if it’s a removable device, such as optical media, or a fixed device
like a hard drive. At this phase, the firmware only considers removable
devices. On each of those, it looks for an
EFI System Partition4 with
a FAT file system using whatever method it knows for that type of media,
and if it finds one, it checks for
Typically, if it finds a removable device it can boot, that’s because you have your OS install image connected in some way, which may well be an indicator that you’re trying to start the OS installer. It’s also possible you’ve installed to removable media, or you’re running off a live image.
If it doesn’t find suitable removable media, or if a failure condition is returned by the application it tries to start, it continues traversing all removable media until it has exhausted the possibilities.
If it still hasn’t found any removable media it can boot, the firmware
will move on to fixed media. At this point, all media is probably
discovered — you may have hot-plugged a USB stick or something, but don’t
plan on that sort of action working reliably at this stage. Since there’s
no real device or media discovery left to do, the firmware is going to
iterate back over the devices once more, and will try to start each fixed
media device in the same manner it previously did with the removable
devices – it will look for an ESP, and try to start
\EFI\BOOT\BOOTX64.efi. This is known as the “Default Boot Behavior”.
The Default Boot Behavior
On Fedora systems, and likely any other OS using shim, we handle the Default
Boot Behavior through a utility shim provides named
signed shim package provides several files, all of which reside on
whichever partition we’ve mounted as the ESP, which is mounted at
1 2 3 4 5 6
When we’re operating under the Default Boot Behavior, the system
firmware launches the Device Path
/boot/efi/EFI/BOOT/BOOTX64.EFI on our file system.
This is actually just another copy of
but it behaves slightly differently.
shim checks to see if it’s been launched from
\EFI\BOOT6. If it has, it checks to see if there’s another file in
this directory called
fallback.efi, which our
provides on an installed system, but which we purposefully omit from
removable media. If it finds
fallback.efi, it executes it as a normal
It is expected that this default boot will load an operating system or a maintenance utility. If this is an operating system setup program it is then responsible for setting the requisite environment variables for subsequent boots.
As you may well have come to realize, the purpose of
to rebuild boot options in the case that
BootOrder or the
variables it references have been destroyed, or the case that you’ve
moved a fixed disk between machines with the intent on booting from it.
When fallback runs, it queries the firmware for the disk from which it
was loaded. It then iterates over every subdirectory of
\EFI on that
disk that isn’t
BOOT, looking for files named
BOOT.CSV. On Fedora,
we provide such a file in
\EFI\fedora\BOOT.CSV. This file is a UCS-2
file of comma separated values, and its contents look like this:
For each valid entry in each BOOT.CSV file it finds, fallback creates a
Boot#### variable and appends it to
BootOrder. In this case
it creates a boot entry with the label ‘Fedora’, with a Device Path
that points to the disk fallback was run from, and the file path
corresponding to the directory in which shim found this particular
with the first entry in the CSV appended:
Once fallback has finished iterating all the CSV files in all the
directories other than BOOT, it boots the first option it has added. On
the next reboot, there will be a
BootOrder variable, and its first
entries will be whichever
Boot#### variables fallback created.
Astute readers will no doubt notice that often we have device paths with only the
File(\EFI\fedora\shim.efi)components. The spec allows this explicitly, and in this case it initializes every peripheral in no particular order until it finds a partition matching that Hard Disk Media Device Path, and the appropriate file on it.↩
In this case
ACPI(a0341d0,0)represents the PCI Express Root Port on my CPU, and
lspciwhould show as
00:1f.2 SATA controller: Intel Corporation 6 Series/C200 Series Chipset Family SATA AHCI Controller (rev 05).↩
SATA(0,0,0)represents the disk and
HD(1,800,64000,12029cda-8961-470d-82ba-aeb17dba91a5)represents the partition on it. I’m so sorry.↩
Strictly speaking, the firmware is required to check one partition which has the correct GUID and label in GPT and is a FAT file system. It is allowed to check partitions without that GUID and label, but you can’t depend on it, and it is allowed to check other partitions that have file systems it understands, but you can’t depend on that either.↩
Or whatever file name is appropriate on your architecture.↩
I’m using backslashes for paths seen by code that’s running under UEFI, and forward slashes for code running under Linux, because that’s what those parts of the system typically use.↩