Search notes:

UEFI

UEFI stands for Unified Extensible Firmware Interface
The predecessor of UEFI is BIOS.
UEFI is essentially EFI 2.0.
UEFI requires 64 bit hardware.
When the computer is started up, the UEFI firmware loads files stored on the ESP (EFI System Partition) to start the installed operating system(s).

Boot Manager

The UEFI Boot Manager loads applications or drivers (which of course must adhere to the UEFI specification).
A set of NVRAM variables store the location of these applications or drivers so that the boot manager is able to find them.

UEFI Image

An UEFI Image is a subset of the PE32+ image format with a modified header signature.
The + in PE32+ refers to the 64-bit relocation fix-up extension to the standard PE32 format.

Loading an UEFI Image

An UEFI Image is loaded into memory by EFI_BOOT_SERVICES.LoadImage().

Transferring control to the image

After he image is loaded into memory, and the appropriate fix-ups have been performed, control is transferred to AddressOfEntryPoint.
UEFI passes a pointer to EFI_SYSTEM_TABLE and an EFI_HANDLE to AddressOfEntryPoint.
The function pointer of the entry point could probably be written like so:
typedef EFI_STATUS (/* EFIAPI */ *EFI_IMAGE_ENTRY_POINT) (
  /* IN */ EFI_HANDLE        ImageHandle,
  /* IN */ EFI_SYSTEM_TABLE *SystemTable
);
The details are architecture dependent.
EFI_SYSTEM_TABLE contains
  • the standard output and input handles
  • pointer to EFI_BOOT_SERVICES
  • pointer to EFI_RUNTIME_SERVICES

Exiting

If the image is an UEFI OS loader, then the application executes and either
  • returns (indicating a failure loading the OS) or
  • calls EFI_BOOT_SERVICES.Exit() (also indicating a failure loading the OS), or
  • calls EFI_BOOT_SERVICES.ExitBootServices() (to take control over the system until ResetSystem() is called)
If the image is an UEFI application (i. e. not an OS Loader), then the application executes and either
  • returns or
  • calls EFI_BOOT_SERVICES.Exit().
If the image is an UEFI driver, then the driver executes and either
  • returns success (driver stays resident) or failuer (driver is removed) or
  • calls Exit()

Runtime variables

UEFI can be configured by the operation systems through runtime variables (apparently also called EFI variables)
They can be manipulated via /sys/firmware/efi/efivars, for example: efivar -l

Required kernel config options

These are required kernel config options:
CONFIG_RELOCATABLE=y
CONFIG_EFI=y
CONFIG_EFI_STUB=y
CONFIG_FB_EFI=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_EFIVAR_FS=y seems to be necessary to manipulate Runtime variables.
CONFIG_EFI_VARS=n
CONFIG_EFI_PARTITION=y
See also security/integrity/platform_certs/load_uefi.c, Documentation/x86/x86_64/uefi.rst, Documentation/arm/uefi.rst

EFI boot stub

Documentation/efi-stub.txt, EFI_STUB

UEFI variables

UEFI variables have three parts:
UEFI variables can be modifed in the shell with efivar.

Compatibility Support Module (CSM)

Some (all?) UEFI firmware manufacturers provide a BIOS compatiblity layer, known under CMS (Compatibility Support Module) or Legacy Mode.

efibootmgr

efibootmgr is a command line utility to modify settings of the UEFI Boot Manager such as

Commandline options

-a --active Set bootnum active.
-A --inactive Set bootnum inactive.
-b --bootnum XXXX Modify BootXXXX (hex).
-B --delete-bootnum Delete bootnum.
-c --create Create new variable bootnum and add to bootorder.
-C --create-only Create new variable bootnum and and do not add to bootorder.
-d --disk DISK The disk containing the loader (defaults to /dev/sda).
-D --remove-dups Remove duplicated entries from BootOrder.
-e 1|3 --edd 1|3 Force EDD 1.0 or 3.0 creation variables. (-e 3 is deprecated and an alias for --full-dev-path)
-E --edd-device NUM EDD 1.0 device number (default: 0x80). See also --edd
`--full-dev-path Force creation of boot entries use a full UEFI device path, starting at the PCIe root or equivalent on the current platform. The default is to use a hard disk based HD() abbreviated path.
--file-dev-path Force creation of boot entries use an abbreviated UEFI device path which starts with the File() portion of the path. The default is to use a hard disk based HD() abbreviated path.
-f --reconnect Re-connect devices after driver is loaded. Only applicable for driver entries.
-F --do-not-reconnect Do not reconnect devices after driver is loaded. Only applicable for driver entries.
-g --gpt Force disk with invalid PMBR (protective MBR) to be treated as GPT
-i --iface NAME Create a netboot entry for the named interface.
-k --keep NAME Keep old entries when adjusting order.
-l --loader NAME Specify a loader (defaults to \EFI\arch\grub.efi).
-L --label LABEL Boot manager display label (defaults to "Linux").
-m --mirror-below-4G t|f Set t if you want to mirror memory below 4GB.
-M --mirror-above-4G X X percentage memory to mirror above 4GB. Floating-point value with up to 2 decimal places is accepted.
-n --bootnext XXXX Set BootNext to XXXX (hex).
-N --delete-bootnext Delete BootNext.
-o --bootorder XXXX,YYYY,ZZZZ Explicitly set BootOrder (hex). Any value from 0 to FFFF is accepted so long as it corresponds to an existing Boot#### variable, and zero padding is not required.
-O --delete-bootorder Delete BootOrder.
-p --part PART Partition number containing the bootloader (defaults to 1).
-q --quiet Quiet mode - suppresses output.
-r --driver Operate on Driver#### variables instead of Boot#### variables.
-t --timeout seconds Boot Manager timeout, in seconds.
-T --delete-timeout Delete Timeout variable.
-u --unicode | --UCS-2 Handle extra command line arguments as UCS-2 (default is ASCII).
-v --verbose Verbose mode - prints additional information.
-V --version Just print version string and exit.
-w --write-signature Write unique signature to the MBR if needed.
-y --sysprep Operate on SysPrep#### variables instead of Boot#### variables.
-@ --append-binary-args Append extra variable args from file (use - to read from stdin). Data in file is appended as command line arguments to the boot loader command, with no modification to the data, so you can pass any binary or text data necessary.

Structures

EFI_TABLE_HEADER

typedef struct {
    UINT64 Signature;
    UINT32 Revision;
    UINT32 HeaderSize;
    UINT32 CRC32;
    UINT32 Reserved;
} EFI_TABLE_HEADER;
EFI_TABLE_HEADER is included at the start of all other structures.

EFI_SYSTEM_TABLE

typedef struct {
    EFI_TABLE_HEADER                 Hdr;
    CHAR16                           *FirmwareVendor;
    UINT32                            FirmwareRevision;
    EFI_HANDLE                        ConsoleInHandle;
    EFI_SIMPLE_TEXT_INPUT_PROTOCOL   *ConIn;
    EFI_HANDLE                        ConsoleOutHandle;
    EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;
    EFI_HANDLE                        StandardErrorHandle;
    EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *StdErr;
    EFI_RUNTIME_SERVICES             *RuntimeServices;
    EFI_BOOT_SERVICES                *BootServices;
    UINTN                             NumberOfTableEntries;
    EFI_CONFIGURATION_TABLE          *ConfigurationTable;
} EFI_SYSTEM_TABLE;

EFI_BOOT_SERVICES

typedef struct {
  EFI_TABLE_HEADER     Hdr;

  //
  // Task Priority Services
  //
  EFI_RAISE_TPL        RaiseTPL;       // EFI 1.0+
  EFI_RESTORE_TPL      RestoreTPL;     // EFI 1.0+

    //
    // Memory Services
    //
    EFI_ALLOCATE_PAGES   AllocatePages;  // EFI 1.0+
    EFI_FREE_PAGES       FreePages;      // EFI 1.0+
    EFI_GET_MEMORY_MAP   GetMemoryMap;   // EFI 1.0+
    EFI_ALLOCATE_POOL    AllocatePool;   // EFI 1.0+
    EFI_FREE_POOL        FreePool;       // EFI 1.0+

    //
    // Event & Timer Services
    //
    EFI_CREATE_EVENT     CreateEvent;    // EFI 1.0+
    EFI_SET_TIMER        SetTimer;       // EFI 1.0+
    EFI_WAIT_FOR_EVENT   WaitForEvent;   // EFI 1.0+
    EFI_SIGNAL_EVENT     SignalEvent;    // EFI 1.0+
    EFI_CLOSE_EVENT      CloseEvent;     // EFI 1.0+
    EFI_CHECK_EVENT      CheckEvent;     // EFI 1.0+

    //
    // Protocol Handler Services
    //
    EFI_INSTALL_PROTOCOL_INTERFACE     InstallProtocolInterface;            // EFI 1.0+
    EFI_REINSTALL_PROTOCOL_INTERFACE   ReinstallProtocolInterface;          // EFI 1.0+
    EFI_UNINSTALL_PROTOCOL_INTERFACE   UninstallProtocolInterface;          // EFI 1.0+
    EFI_HANDLE_PROTOCOL                HandleProtocol;                      // EFI 1.0+
    VOID*                              Reserved;                            // EFI 1.0+
    EFI_REGISTER_PROTOCOL_NOTIFY       RegisterProtocolNotify;              // EFI 1.0+
    EFI_LOCATE_HANDLE                  LocateHandle;                        // EFI 1.0+
    EFI_LOCATE_DEVICE_PATH             LocateDevicePath;                    // EFI 1.0+
    EFI_INSTALL_CONFIGURATION_TABLE    InstallConfigurationTable;           // EFI 1.0+

    //
    // Image Services
    //
    EFI_IMAGE_UNLOAD               LoadImage;        // EFI 1.0+
    EFI_IMAGE_START                StartImage;       // EFI 1.0+
    EFI_EXIT                       Exit;             // EFI 1.0+
    EFI_IMAGE_UNLOAD               UnloadImage;      // EFI 1.0+
    EFI_EXIT_BOOT_SERVICES         ExitBootServices; // EFI 1.0+

    //
    // Miscellaneous Services
    //
    EFI_GET_NEXT_MONOTONIC_COUNT   GetNextMonotonicCount; // EFI 1.0+
    EFI_STALL                      Stall;                 // EFI 1.0+
    EFI_SET_WATCHDOG_TIMER         SetWatchdogTimer;      // EFI 1.0+

    //
    // DriverSupport Services
    //
    EFI_CONNECT_CONTROLLER         ConnectController;     // EFI 1.1
    EFI_DISCONNECT_CONTROLLER      DisconnectController;  // EFI 1.1+

    //
    // Open and Close Protocol Services
    //
    EFI_OPEN_PROTOCOL              OpenProtocol;           // EFI 1.1+
    EFI_CLOSE_PROTOCOL             CloseProtocol;          // EFI 1.1+
    EFI_OPEN_PROTOCOL_INFORMATION  OpenProtocolInformation;// EFI 1.1+

    //
    // Library Services
    //
    EFI_PROTOCOLS_PER_HANDLE                     ProtocolsPerHandle;                   // EFI 1.1+
    EFI_LOCATE_HANDLE_BUFFER                     LocateHandleBuffer;                   // EFI 1.1+
    EFI_LOCATE_PROTOCOL                          LocateProtocol;                       // EFI 1.1+
    EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES   InstallMultipleProtocolInterfaces;    // EFI 1.1+
    EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES   UninstallMultipleProtocolInterfaces;  // EFI 1.1+*

    //
    // 32-bit CRC Services
    //
    EFI_CALCULATE_CRC32    CalculateCrc32;     // EFI 1.1+

    //
    // Miscellaneous Services
    //
    EFI_COPY_MEM           CopyMem;        // EFI 1.1+
    EFI_SET_MEM            SetMem;         // EFI 1.1+
    EFI_CREATE_EVENT_EX    CreateEventEx;  // UEFI 2.0+
} EFI_BOOT_SERVICES;

EFI_RUNTIME_SERVICES

typedef struct {
    EFI_TABLE_HEADER                 Hdr;

    //
    // Time Services
    //
    EFI_GET_TIME                     GetTime;
    EFI_SET_TIME                     SetTime;
    EFI_GET_WAKEUP_TIME              GetWakeupTime;
    EFI_SET_WAKEUP_TIME              SetWakeupTime;

    //
    // Virtual Memory Services
    //
    EFI_SET_VIRTUAL_ADDRESS_MAP      SetVirtualAddressMap;
  EFI_CONVERT_POINTER                ConvertPointer;

    //
    // Variable Services
    //
    EFI_GET_VARIABLE                 GetVariable;
    EFI_GET_NEXT_VARIABLE_NAME       GetNextVariableName;
    EFI_SET_VARIABLE                 SetVariable;


    //
    // Miscellaneous Services
    //
    EFI_GET_NEXT_HIGH_MONO_COUNT     GetNextHighMonotonicCount;
    EFI_RESET_SYSTEM                 ResetSystem;

   //
   // UEFI 2.0 Capsule Services
   //
   EFI_UPDATE_CAPSULE               UpdateCapsule;
   EFI_QUERY_CAPSULE_CAPABILITIES   QueryCapsuleCapabilities;


 //
 // Miscellaneous UEFI 2.0 Service
 //
  EFI_QUERY_VARIABLE_INFO          QueryVariableInfo;
} EFI_RUNTIME_SERVICES;

Misc

The reference implementation is TianoCore EDK II (Extensible Development Kit II), which is written in C.

Starting a program with EFI_SYSTEM_TABLE and EFI_HANDLE on the stack

Pointers to the EFI_SYSTEM_TABLE and EFI_HANDLE are passed on the stack when UEFI starts a program (at least on some platforms).
See also GRUB source grub-core/kern/i386/efi/startup.S

Links

efivar, ESP, /sys/firmware/efi

See also

UEFI Secure Boot
The (pseudo?) Windows variable %FIRMWARE_TYPE%.

Wikipedia Link

Index