Tuesday, December 18, 2012

Accessing UEFI from the operating system runtime


Sometimes the question arises about accessing UEFI services during the operating system runtime.   Recall that UEFI demarcates its core services into boot services and runtime services.   The former are only available prior to the invocation of ExitBootServices(), whereas the latter are available during the life of the platform for a UEFI-aware operating system.   This is the design intent.   Other boot services components can expose content during runtime if said content is allocated in runtime services memory and exposes itself through infrastructure like an installable GUIDed table.

In practice today, these services are not necessarily exposed 1:1 between an operating system services and the corresponding UEFI runtime service.

For Windows, the only API that I know of for accessing UEFI entail the UEFI variable services.   Check out Get/Set firmware environment variables services http://msdn.microsoft.com/en-us/library/windows/desktop/ms724934(v=vs.85).aspx and http://msdn.microsoft.com/en-us/library/windows/desktop/ms724325(v=vs.85).aspx, respectively.

Linux provides access to the UEFI variable services through sysfs, too.  Some detail can be found at 

Beyond variables, though, UEFI interfaces are opaque at OS runtime for Windows.   For Linux the UEFI system table is a kernel global object for Linux drivers.

The net result is that you cannot get to the UEFI RT or the system table at OS runtime, I'm afraid.   The Linux sysfs is the closest but even there it doesn't expose each UEFI RT call point.  The reason that the UEFI variable services are exposed in the fashion they are via Win32 calls is that OS installer programs have needed them since EFI1.02 back in 1999.   Writing UEFI RT code is pretty tricky because of things like the OS owning the hardware, the virtual mapping of the firmware, etc.(i.e., tough for firmware folks).  Also, the OS guys don't necessarily trust firmware and the UEFI RT code/data isn't hardware isolated from the other OS kernel components and drivers.

As such, the preferred industry approach to having a runtime interface to the platform is ACPI since ACPI runs in a sandbox with an interpreted bytecode AML.  There is some interesting open source implementations of ACPI at http://www.acpica.org/, for example.   UEFI is great for pre-OS applications and usages, of course.  And one model observed today is to stage activities from the OS, such as writing a file to the UEFI system partition, and then rebooting so that an associated UEFI application can act upon the file or directive from the OS agent.

Of course, UEFI runtime services are always available in the pre-OS, namely during the boot services (BS) phase.

3/10/14 update-
Windows now has kernel-mode variants of its access API's http://msdn.microsoft.com/en-us/library/windows/hardware/jj151553(v=vs.85).aspx and there is a nice description of variable access from Linux at firmware.intel.com/blog/accessing-uefi-variables-linux

5/22/14 update-
Regarding the protection of the platform resources by the OS, you need to have administrative privileges in Windows and Linux in order to access the OS API's that abstract the UEFI variable interface from user-land code.

11/5/14 update -
if you boot via Int19h PC/AT BIOS process, the UEFI runtime memory is given back to the OS and is reported as available via the memory map call in E820h Int15h call. As such, there is no way to invoke Get/Set Variable from a PC/AT "Legacy" BIOS boot.

3 comments:

Matt Fleming said...

We've hit our fair share of problems in the Linux kernel because the firmware vendors are not testing the runtime services thoroughly, presumably because they're not used extensively on Windows. The GetTime() function comes to mind.

FYI, the Linux kernel added support for an efivarfs filesystem in v3.7 which will be the preferred method of accessing EFI variables going forward, as it lifts the 1024-byte restriction on the size of variable data.

Anonymous said...

Hi, I was trying to understand the efivars filesystem utility, Does it uses the RT-Set and RT->Get of the UEFI..? I am trying to hook a function into this RT services, the intention here is to invoke an efi application from OS, So wanted to know if this can be possible using the efivars filesystem utility. Can you please provide your comments on this, your response to this can be a great help.
Thanks in advance,
Rohit

Frank said...

good article!

Thanks