Bridging Worlds: Major Improvements to U-Boot’s EFI App and Device Tree Handling

The U-Boot EFI application is a powerful tool, allowing U-Boot to run on top of existing UEFI firmware. This is increasingly important as we see new platforms, especially in the ARM64 world, shipping with complex, ACPI-based firmware. A prime example is the recent wave of laptops powered by the Qualcomm X-Elite, which rely on this boot model.
However, booting a traditional, device-tree-based OS like ARM Linux from this environment presents a unique set of challenges. A recent comprehensive patch series lands with a host of fixes and new features designed to bridge the gap between the EFI world and the device tree world, dramatically improving the experience and reliability of the U-Boot EFI app.
Let’s dive into what’s new.
The Core Challenge: Memory Map Misalignment
When Linux boots using a device tree, it trusts the /reserved-memory
nodes in the FDT to know which memory regions to avoid. But when running as an EFI application, the underlying UEFI firmware has its own, separate memory map with regions reserved for runtime services, ACPI data, and other critical functions.
If U-Boot doesn’t transfer this information into the device tree, Linux has no idea these regions are off-limits. It might try to use them, leading to mysterious crashes and instability.
The Solution: Automatic Memory Map Synchronization
Enter a new mechanism to synchronize these two views of memory. A new command, efi memsync
, has been introduced.
This command:
- Reads the memory map provided by the EFI boot services.
- Parses the existing
/reserved-memory
nodes in U-Boot’s working device tree. - Compares the two, identifying any reserved regions from EFI that are missing in the device tree.
- Automatically creates new
no-map
reserved-memory nodes in the device tree for these missing regions.
This process is now automatically run during the boot flow when using the EFI app, ensuring that the device tree passed to Linux is a complete and accurate representation of the hardware’s memory layout.
=> efi memsync -v Comparing EFI memory-map with reserved-memory EFI Memory Map Analysis: ID Type Start End In DT? ------------------------------------------------------------------------ 0 EFI_RUNTIME_SERVICES_CODE 0x001f9ef000 0x001faef000 no -> adding 1 EFI_ACPI_RECLAIM_MEMORY 0x001fb6f000 0x001fb7f000 no -> adding 2 EFI_ACPI_MEMORY_NVS 0x001fb7f000 0x001fbff000 yes Regions added: 2
New command: fdt reserved
To complement efi memsync
, you can now easily inspect the result with the fdt reserved
command. It provides a clean, readable list of all regions in the /reserved-memory
node.
=> fdt reserved ID Name Start Size ---------------------------------------------------------------- 0 secmon@1f000000 0x1f000000 0x1000000 1 efi-runtime@1f9ef000 0x1f9ef000 0x100000
Stability and Polish
Beyond the major new features, this series includes critical fixes that make the EFI app more robust and stable:
- Correct Device Naming: A subtle bug was fixed where block devices were being named based on a temporary placeholder, leading to confusing device names. Names are now set correctly before the device is bound.
- ARM64 Exception Level Handling: The app now correctly avoids trying to change CPU exception levels, which it is not permitted to do, preventing crashes on ARM platforms.
- Graceful Exit: The app no longer tries to free its own memory right before exiting, which could cause a crash. It now relies on the underlying UEFI firmware to clean up resources.
- Simple Framebuffer: For a better user experience, the app now automatically adds a
simple-framebuffer
node to the device tree, ensuring Linux has an early graphics console.
Conclusion
This is a small step forward for U-Boot’s capabilities as an EFI application. These changes are already proving essential for bringing up Linux on platforms like the Qualcomm X-Elite, showcasing U-Boot’s adaptability and continued importance in a complex and evolving boot ecosystem.