ExitBootServices
Overview
ExitBootServices() is the UEFI function that ends the firmware boot phase and transfers control of the system to the operating system loader.
After this call succeeds, most UEFI Boot Services become unavailable.
This is the critical transition point between firmware control and operating system control.
Why It Exists
During startup, firmware provides services such as:
- Memory allocation
- Protocol discovery
- File access
- Event handling
- Image loading
An operating system cannot continue using these firmware services indefinitely because it must manage memory and hardware itself.
ExitBootServices() cleanly terminates the firmware-managed environment.
Boot Process Context
A simplified boot sequence:
Power on
|
v
Firmware initialization
|
v
Boot Services available
|
v
EFI application / boot loader
|
v
Get final memory map
|
v
ExitBootServices()
|
v
Operating system takes control
The call is usually performed immediately before jumping to the kernel entry point.
Function Signature
The firmware exposes:
EFI_STATUS
(EFIAPI *ExitBootServices)(
EFI_HANDLE ImageHandle,
UINTN MapKey
);
Two parameters are required:
ImageHandle— the handle of the current EFI imageMapKey— the key returned by the final successfulGetMemoryMap()call
The MapKey Requirement
This is the most important rule.
The boot loader must:
- Call
GetMemoryMap() - Receive a
MapKey - Avoid changing the memory map
- Call
ExitBootServices()with that exact key
If the memory map changes after retrieving the key, the call fails.
Example failure sequence:
GetMemoryMap() -> MapKey = 42
|
v
AllocatePool() changes memory map
|
v
ExitBootServices(ImageHandle, 42)
|
v
EFI_INVALID_PARAMETER
This is why boot loaders retrieve the memory map as late as possible.
What Happens After Success?
Once ExitBootServices() succeeds:
No longer available
AllocatePool()FreePool()LocateProtocol()- File access through Boot Services
- Most firmware-managed services
Still available
- CPU execution
- Physical memory
- Framebuffer memory (if configured)
- Runtime Services (through a separate mechanism)
At this point the kernel is responsible for managing the system.
Why This Is Difficult
The transition is deceptively small in code:
Status = ExitBootServices(ImageHandle, MapKey);
but it represents a major architectural change:
| Before | After |
|---|---|
| Firmware manages memory | Kernel manages memory |
| Boot Services available | Boot Services unavailable |
| Protocol discovery possible | No new protocols can be located |
| File access available | Loader must already have loaded required files |
A single additional allocation between GetMemoryMap() and ExitBootServices() can invalidate the MapKey.
Relationship to This Project
The current applications run entirely before ExitBootServices().
Examples:
- Memory Map Viewer
- Filesystem Explorer
- Graphics Demo
The planned Linux loader will be the first component that must:
- Load the kernel
- Retrieve the final memory map
- Call
ExitBootServices() - Jump to the kernel entry point
This makes ExitBootServices() the central milestone for the boot loader phase of the project.