An EFI application starts execution at its entry point, then continues execution until it reaches a return from its entry point or it calls the Exit() boot service function. When done, the image is unloaded from memory. Some examples of common EFI applications include the EFI shell, EFI shell commands, flash utilities, and diagnostic utilities. It is perfectly acceptable to invoke EFI applications from inside other EFI applications.
OS LoaderA special type of EFI application, called an OS boot loader, calls the ExitBootServices() function when the OS loader has set up enough of the OS infrastructure to be ready to assume ownership of the system resources. At ExitBootServices(), the EFI core frees all of its boot time services and drivers, leaving only the run-time services and drivers.
EFI drivers differ from EFI applications in that the driver stays resident in memory unless an error is returned from the driver's entry point. The EFI core firmware, the boot manager, or other EFI applications may load drivers.
EFI 1.02 Drivers
Several types of EFI drivers exist, having evolved with subsequent levels of the specification. In EFI 1.02, drivers were constructed without a defined driver model. The EFI 1.10 Specification provides a driver model that replaces the way drivers were built in EFI 1.02 but that still maintains backward compatibility with EFI 1.02 drivers. EFI 1.02 immediately started the driver inside the entry point. Following this method meant that the driver searched immediately for supported devices, installed the necessary I/O protocols, and started the timers that were needed to poll the devices. However, this method did not give the system control over the driver loading and connection policies, so the EFI Driver Model was introduced in section 1.6 of the EFI 1.10 Specification to resolve these issues.
The Floating-Point Software Assist (FPSWA) driver is a common example of an EFI 1.02 driver; other EFI 1.02 drivers can be found in the EFI Application Toolkit 1.02.12.38. For compatibility, EFI 1.02 drivers can be converted to EFI 1.10 drivers that follow the EFI Driver Model.
Boot Service and Runtime Drivers
Boot-time drivers are loaded into area of memory that are marked as EfiBootServicesCode, and the drivers allocate their data structures from memory marked as EfiBootServicesData. These memory types are converted to available memory after gBS->ExitBootServices() is called.
Runtime drivers are loaded in memory marked as EfiRuntimeServicesCode, and they allocate their data structures from memory marked as EfiRuntimeServicesData. These types of memory are preserved after gBS->ExitBootServices() is called, thereby enabling the runtime driver to provide services to an operating system while the operating system is running. Runtime drivers must publish an alternative calling mechanism, because the EFI handle database does not persist into OS runtime. The most common examples of EFI runtime drivers are the Floating-Point Software Assist driver (FPSWA.efi) and the network Universal Network Driver Interface (UNDI) driver. Other than these examples, runtime drivers are not very common. In addition, the implementation and validation of runtime drivers is much more difficult than boot service drivers because EFI supports the translation of runtime services and runtime drivers from a physical addressing mode to a virtual addressing mode. With this translation, the operating system can make virtual calls to the runtime code. The OS typically runs in virtual mode, so it must transition into physical mode to make the call. Transitions into physical mode for modern, multiprocessor operating systems are expensive because they entail flushing translation look-up blocks (TLB), rendezvousing coordinating all CPUs, and other tasks. As such, EFI runtime offers an efficient invocation mechanism because no transition is required.