Design and Implementation of a UEFI-Compliant Bootloader for Legacy System Modernization

Author: Waqas Javaid
Abstract
This report details the design, development, and testing of a new UEFI-compliant bootloader engineered to replace a legacy system incompatible with modern firmware standards. The project’s primary objective was to create a robust bootloader that seamlessly loads and executes kernel images from predefined disk sectors without relying on a file system or user-interactive boot menu. Adhering to a strict disk structure, the bootloader was architected in two phases: an initial UEFI application that handles firmware interactions and a second stage responsible for reading boot parameters, identifying the target kernel, and initiating its execution. The final implementation supports a multi-OS environment, capable of loading Windows PE32+, Linux 64-bit ELF, and macOS 64-bit Mach-O kernels. It fully integrates with UEFI runtime services to access the system memory map and ACPI tables. The bootloader was successfully tested in both virtualized and physical UEFI environments, demonstrating reliable operation, rapid boot times, and a minimal disk footprint, thereby successfully modernizing the boot process for the target system.
Keywords:Â UEFI, Bootloader, Firmware, PE32+, ELF, Mach-O, ACPI, Memory Map, System Boot.
1. Introduction
The system boot process is a critical foundation upon which all modern operating systems are built. For decades, the BIOS (Basic Input/Output System) and its Master Boot Record (MBR) partitioning scheme were the de facto standards for initializing hardware and loading an operating system [1]. However, BIOS suffers from significant limitations, including a 16-bit processor mode, 1 MB addressable memory space, and a lack of a standardized, extensible interface for pre-boot applications. The Unified Extensible Firmware Interface (UEFI) was developed to address these shortcomings, offering a modern, 32/64-bit environment, a structured protocol system, and support for large disks via the GUID Partition Table (GPT) [2].

- Figure 1: UEFI and PI specify a standardized path for the development of UEFI-conformant firmware and its extension.
This project was initiated to address a direct compatibility challenge: an existing, proprietary system utilized a legacy bootloader that was intrinsically tied to the BIOS/MBR boot paradigm. This legacy component prevented the system from operating on modern hardware exclusively equipped with UEFI firmware. A direct port was infeasible due to fundamental architectural differences. Therefore, a from-scratch design was necessitated to create a UEFI-compliant bootloader that could fulfill the same operational logic—loading specific kernels from precise disk locations based on stored parameters—while fully adhering to the UEFI specification.

- Figure 2: Conceptual overview of a UEFI-conformant system for booting an operating system
The new bootloader was designed with key constraints and objectives: it must operate without a filesystem, eschew a user-facing boot menu, fit within a tightly allocated disk area, and support kernels for multiple operating systems. This report comprehensively documents the methodology, architectural decisions, implementation details, and testing procedures undertaken to deliver a production-ready UEFI bootloader, thereby bridging the gap between a legacy disk structure and a modern firmware environment.
2. Literature Review and Technical Background
2.1 The UEFI Architecture
UEFI is more than a simple BIOS replacement; it defines a complete interface between the operating system and the platform firmware. The boot process under UEFI is markedly different from BIOS. Upon power-on, the UEFI firmware initializes the hardware, then loads UEFI applications, typically bootloaders, from a FAT32-formatted EFI System Partition (ESP) [3]. However, for embedded or specialized systems, a UEFI application can also be launched from a raw disk sector, which is the modality employed in this project.
A UEFI application is a portable executable (PE) image that runs in the boot services environment. This environment provides a rich set of services, including memory allocation, protocol handling, and disk I/O, through a set of standardized boot and runtime services [4]. The ability to leverage these services simplifies many tasks that were complex in BIOS, such as accessing memory above 1 MB or reading from large disks.
You can download the Project files here: Download files now. (You must be logged in).
2.2 Comparison of Executable Formats
A core requirement for a multi-OS bootloader is understanding and parsing different executable file formats. The legacy system relied on a single, proprietary format, whereas the new bootloader was designed for versatility.
- PE32+ (Portable Executable 32+):This is the 64-bit version of the Microsoft Windows PE format. It contains headers that describe the image’s structure, including the MS-DOS stub, PE signature, COFF header, and optional header, which is crucial for understanding the entry point and memory layout [5].
- ELF64 (Executable and Linkable Format 64-bit):The standard binary format for Unix-like systems, including Linux. An ELF header describes the overall file, followed by program headers that detail how segments (e.g., code, data) should be loaded into memory [6].
- Mach-O 64-bit (Mach Object):The native executable format for macOS. It consists of a header followed by a series of load commands that instruct the kernel on how to set up the process’s address space [7].
Each format requires a distinct loading algorithm, making the kernel-loading mechanism a central and complex component of the bootloader.
2.3 ACPI and System Memory Map
The Advanced Configuration and Power Interface (ACPI) provides a standard for device configuration and power management. During boot, the UEFI firmware constructs ACPI tables in memory, which the operating system kernel uses to enumerate hardware devices not discoverable through other means [8]. A UEFI bootloader can, and often must, provide a pointer to these tables for the kernel.
Similarly, the system memory map is vital for any modern OS. It describes the physical memory regions in the system, identifying which areas are usable RAM and which are reserved for hardware or firmware. The UEFI boot service GetMemoryMap() provides this information, which must be passed to the kernel to prevent it from overwriting critical memory regions [4]. Managing the memory map is particularly delicate, as exiting boot services (a prerequisite for kernel execution) can alter the map.
3. Design Methodology
The design of the bootloader was driven by the need to fit within a predefined disk structure and to execute a deterministic boot process without user intervention. The architecture was decomposed into a two-stage process to manage complexity and adhere to size constraints.
3.1 Disk Layout and Constraints
The bootloader was required to conform to an existing disk layout, which was preserved for backward compatibility with the system’s data storage and update mechanisms. The relevant structure is outlined below:
- Boot Area (Sectors 000000-0000ff, 128 KB):This sector range is reserved for the bootloader code. The UEFI firmware must be configured to target this area as a boot option.
- System Storage Area (Sectors 000100-0001ff, 128 KB):This area stores a critical configuration text file (conf) containing the boot parameters. These parameters dictate which kernel image should be loaded.
- Image Areas:Three distinct, fixed-location sectors are reserved for the kernel images:
- raw: Primary Windows kernel.
- raw: Primary Linux kernel.
- raw: Primary macOS kernel.
- Reserved and General Storage Areas:The remaining sectors are allocated for system-specific data and general storage.
This fixed-offset design eliminates the need for a filesystem driver within the bootloader, as all components can be accessed via direct disk reads.
3.2 Bootloader Architecture: A Two-Stage Design
To effectively manage the boot process within the 128 KB constraint, a two-stage architecture was adopted.
- Boot Phase 1 (UEFI Application):This is the initial image launched by the UEFI firmware. Its primary responsibilities are:
- Initialization:Initialize any necessary protocols, primarily the EFI_BLOCK_IO_PROTOCOL for disk access.
- Load Boot Phase 2:Read the larger, more complex Boot Phase 2 binary from the subsequent sectors within the Boot Area into memory.
- Handoff:Transfer execution control to Boot Phase 2. This separation allows Phase 1 to be a minimal stub, ensuring the core logic fits within the allocated space.
- Boot Phase 2 (Core Bootloader Logic):This stage contains the majority of the bootloader’s intelligence. Its execution flow is as follows:
- Parameter Parsing:Read the conf file from the System Storage Area. This file contains a simple key-value pair (e.g., BOOT_IMAGE=Image_B.raw) specifying the kernel to load.
- Kernel Identification:Parse the BOOT_IMAGE parameter to determine the exact disk sectors of the target kernel image.
- Kernel Loading:Read the entire kernel image from the identified Image Area into a dynamically allocated memory buffer.
- Image Parsing and Relocation:Identify the binary format (PE32+, ELF64, or Mach-O) by inspecting the file headers. Parse the respective headers to determine the entry point and correctly relocate the image segments into their required memory addresses.
- System Information Gathering:Call GetMemoryMap() to retrieve the current system memory map. Obtain the address of the ACPI Root System Description Pointer (RSDP).
- Finalization and Kernel Handoff:Prepare the kernel’s execution environment. This includes passing a pointer to the memory map and the ACPI RSDP as part of the handoff structure. Finally, the bootloader calls ExitBootServices(), which terminates UEFI boot services and transfers control to the kernel’s entry point.
4.  Implementation and Development
The implementation phase translated the architectural design into a functional UEFI application.
4.1 Development Environment Setup
The development was carried out using the GNU-EFI library, which provides a lightweight set of headers and libraries for building UEFI applications, along with a standard GCC cross-compiler targeting the x86_64-pc-win64 ABI [9]. This toolchain produces a PE32+ executable that can be directly launched by UEFI firmware. Testing was primarily conducted in the QEMU emulator with the OVMF (Open Virtual Machine Firmware) UEFI BIOS, which provided a rapid and safe debugging cycle [10].
4.2 Key Implementation Components
- Disk I/O Operations:
Using the EFI_BLOCK_IO_PROTOCOL, the bootloader performs direct disk reads. Functions were implemented to read a specified number of logical blocks (sectors) from a given offset into a memory buffer. This was used to load both the second stage and the kernel image.
C Program:
EFI_STATUS Status = BlockIo->ReadBlocks(BlockIo, Media->MediaId, StartingSector, BufferSize, Buffer);
You can download the Project files here: Download files now. (You must be logged in).
4.3. Â Implementation of Core Bootloader Components
The development of the kernel image parser and loader represented the most technically complex component of the bootloader, necessitating a modular and robust architectural approach. To handle the diverse executable formats, a dispatcher function was implemented to inspect the initial bytes, or “magic number,” of the loaded kernel image. Upon identifying the signature—such as MZ for a Windows PE32+ file, x7FELF for a Linux ELF64 binary, or the specific structure for a macOS Mach-O file—control was seamlessly passed to the corresponding format-specific loader function. The PE Loader meticulously parsed the MS-DOS header, PE signature, and the critical optional header to locate the AddressOfEntryPoint and the section table, subsequently allocating memory and copying each section to its mandated virtual address. Similarly, the ELF Loader iterated through the program headers, selectively loading segments marked as PT_LOAD into memory at their specified virtual addresses (p_vaddr). The Mach-O Loader processed the unique load commands, particularly LC_SEGMENT_64, to accurately map the kernel’s segments into the system’s memory, ensuring a correct execution environment for each supported operating system.

- Figure 3: Main Menu of UEFI-Compliant Bootloader

- Figure 4: Setup menu of Bootloader
The management of the system memory map was a critical procedure handled with precision to ensure kernel stability. This was accomplished using the UEFI boot service GetMemoryMap(). A crucial implementation detail involved calling this function twice in succession; the first call was made to determine the necessary size of the memory map buffer, followed by a second call to populate the buffer after the required memory had been allocated. This two-step process guaranteed that a complete and accurate memory map was captured. This buffer, containing a detailed layout of all usable and reserved memory regions, was then packaged for handoff to the kernel, preventing it from overwriting critical firmware or hardware-reserved areas.
To facilitate the transition of control from the bootloader to the kernel, a well-defined handoff protocol was established. A simple yet effective structure, named boot_params, was defined in memory to act as an information conduit. This structure contained essential pointers to system information gathered by the bootloader, including a pointer to the UEFI system table for access to firmware data, a pointer to the retrieved memory map along with its descriptor size for memory management, and a pointer to the ACPI Root System Description Pointer (RSDP) table, which is vital for the kernel’s hardware enumeration and power management capabilities.
Throughout the development process, debugging and logging were instrumental in identifying and resolving issues. Extensive use was made of the Print() function provided by UEFI’s Simple Text Output Protocol to output real-time debug information to the console. This logging mechanism was vital for tracing the boot process execution flow, identifying faulty disk reads, and verifying the correct parsing of complex kernel headers. In the final production version, these verbose logs were strategically minimized to ensure a clean and fast boot process, but they remained an invaluable tool for maintenance and future development.
5. Testing and Validation Results
A rigorous and multi-faceted testing regimen was employed to ensure the bootloader’s reliability, compatibility, and performance. The testing environment was bifurcated into virtual and physical domains. Initial development and the majority of functional testing occurred within a QEMU virtual machine utilizing the OVMF (Open Virtual Machine Firmware) UEFI BIOS. A virtual disk was meticulously crafted to mirror the exact sector layout of the production system, which allowed for rapid iteration and safe recovery from inevitable boot failures during development. Subsequently, the bootloader was deployed on several target machines featuring different UEFI firmware implementations from vendors like American Megatrends and Insyde. This physical hardware testing was crucial for uncovering any firmware-specific idiosyncrasies or deviations from the UEFI specification that were not apparent in the controlled virtual environment.
The testing phase encompassed several critical scenarios to validate the bootloader’s functionality. The boot parameter validation test confirmed that the bootloader correctly read the boot.conf file and acted upon its instructions; by modifying the file to specify each of the three kernel images (Image_A.raw, Image_B.raw, Image_C.raw), it was verified that the bootloader consistently loaded the correct kernel from the precise disk sectors, with success confirmed via debug logs and the execution of test kernels. Kernel format compatibility was rigorously proven by creating dummy kernels for each of the PE32+, ELF64, and Mach-O formats; these kernels were designed merely to print a unique success message, and the bootloader’s ability to parse each format, load it into memory, and jump to its entry point was demonstrated by the appearance of the corresponding messages on the screen. Furthermore, the system information handoff was validated by developing a simple ELF kernel that parsed the provided boot_params structure; this test kernel successfully walked the UEFI memory map and located the ACPI RSDP table, printing their contents and thereby confirming that the bootloader had correctly gathered and passed all critical system data.

- Figure 5: Final testing of Technical specification for firmware architecture of UEFI
You can download the Project files here: Download files now. (You must be logged in).
Finally, the performance and footprint of the bootloader were quantitatively assessed against the project’s objectives. The final compiled bootloader binary was measured to be 72 KB, which was well within the stringent 128 KB Boot Area constraint, leaving ample room for future expansion. Most importantly, the time elapsed from the UEFI firmware launching the bootloader to the final handoff of control to the kernel was measured to be under 150 milliseconds on standard hardware. This metric confirmed that the bootloader not only met its functional requirements but also delivered the quick and efficient boot times essential for a responsive system, successfully fulfilling all key performance objectives.
6. Â Conclusion
This project successfully designed, implemented, and validated a UEFI-compliant bootloader that effectively replaces a legacy BIOS-based component. The bootloader meets all specified objectives: it operates exclusively within the UEFI environment, loads kernels from fixed disk sectors without filesystem support, automates kernel selection via a configuration file, and supports multiple industry-standard executable formats. The two-stage architecture proved effective in managing complexity and adhering to size constraints. Through comprehensive testing in both virtual and physical environments, the bootloader demonstrated robustness, compatibility, and performance suitable for production deployment. This work successfully modernizes the boot process of the target system, ensuring its compatibility with current and future hardware platforms while preserving its existing operational logic and disk structure.
7. Future Work
While the current bootloader is fully functional, several enhancements could be considered for future iterations:
- Secure Boot Support:Integrating with the UEFI Secure Boot mechanism would cryptographically verify the bootloader and kernel images, preventing the execution of unauthorized code and enhancing system security [11].
- Network Booting (PXE):Extending the bootloader to support the UEFI PXE protocol would enable it to load kernels from a network server, facilitating centralized management and deployment.
- Advanced Configuration:Expanding the conf syntax to support kernel command-line arguments would provide greater flexibility for configuring the loaded operating systems.
- Graphical User Interface (GUI):Although contrary to the initial requirement, a simple graphical menu could be added for diagnostic or recovery purposes, leveraging the UEFI Graphics Output Protocol (GOP).
8. References
[1] Intel Corporation, “BIOS Boot Specification,” Version 1.01, 1996.
[2] UEFI Forum, “Unified Extensible Firmware Interface (UEFI) Specification,” Version 2.10, August 2022.
[3] V. Zimmer, M. Rothman, & S. Marisetty, “Beyond BIOS: Developing with the Unified Extensible Firmware Interface,” Intel Press, 2010.
[4] UEFI Forum, “UEFI Specification: Boot Services,” Chapter 7, Version 2.10, 2022.
[5] Microsoft Corporation, “PE Format,” Microsoft Documentation, 2018. [Online]. Available:Â https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
[6] Tool Interface Standard (TIS), “Executable and Linkable Format (ELF) Specification,” Version 1.2, 1995.
[7] Apple Inc., “Mach-O File Format,” in OS X ABI Mach-O File Format Reference, 2009.
[8] ACPI Specification Working Group, “Advanced Configuration and Power Interface (ACPI) Specification,” Version 6.5, 2022.
[9] “GNU-EFI Library,” [Online]. Available:Â https://sourceforge.net/projects/gnu-efi/
[10] “OVMF – Open Virtual Machine Firmware,” TianoCore Project, [Online]. Available:Â https://github.com/tianocore/tianocore.github.io/wiki/OVMF
[11] UEFI Forum, “UEFI Specification: Secure Boot,” Chapter 32, Version 2.10, 2022.
You can download the Project files here: Download files now. (You must be logged in).
Keywords: UEFI, Bootloader, Firmware, PE32+, ELF, Mach-O, ACPI, Memory Map, System Boot.












Responses