Saturday, December 29, 2012

More on EFI...

Considering it has been awhile since my last post, I figured I'd write a post to discuss the current status of my tool, Mac Linux USB Loader. The tool essentially copies an EFI binary to the USB stick which boots Linux from the ISO. How simple. In theory, I suppose, yes. In reality? Whole other ballgame.

Perhaps it would be worthwhile to discuss exactly what EFI applications are composed of. EFI programs are very special in that the operating system never executes them. They are run by the computer's firmware itself, independent of the operating system, which effectively makes them truly platform-independent programs. Platform independent programs have existed before; they can be created in Java or C#/Mono. From a technical standpoint, EFI programs are also different from traditional programs in the sense that they must be compiled using a cross-compiler, as no native development tools exist for EFI. This is understandable, considering EFI is firmware: it runs before the operating system, and EFI services are often terminated by the OS upon completion of the boot process.

Therefore, development of EFI programs is exponentially more difficult. First off, EFI programs are written in C, and you cannot rely on any of C's standard libraries to help you. If it's not in the EFI libraries, you either need to write it yourself or find an equivalent function that is already implemented.


// hello.c

#include
#include

EFI_STATUS
efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
{
    InitializeLib(image_handle, systab);
    
    Print(L"Hello, EFI!\n");
    Print(L"You have a working EFI shell.\n");
    
    return EFI_SUCCESS;
}


As you can see from the above example program that I wrote, printing output using printf() is not possible. You have to use a function in the EFI libraries provided by gnu-efi, a EFI toolkit available for POSIX platforms (Mac, Linux, et al) that does the job of TianoCore, the official EFI toolkit that is only available for Windows.

So, why does the firmware for Mac Linux USB Loader need to be implemented in EFI? Simple. OS X's boot manager, accessed by pressing the option/alt key after the boot chimes, only detects EFI programs that are on external drives at the special path* of /EFI/BOOT/BOOT.EFI. So  on a machine with 64-bit firmware (all recent Macs), that file needs to be called BOOTX64.EFI.  And because OS X is not loaded, whatever program is there needs to be written in EFI.

Operating system loaders are not the only programs written in EFI. Oh no. There are EFI shells, which are like bash on a UNIX machine, except they can execute EFI programs like the one above.

More on EFI coming up soon. Happy new year, all (except to you folks not using the Gregorian calendar ;) ).

* - Well, not entirely. A file can be "blessed" with the ability to boot. OS X's boot loader does this, as it is located at /System/Library/CoreServices/boot.efi, which is not located in that special path. But I'm not discussing this further.

No comments: