Chapter 14 – Putting It All Together—Firmware Emulation

An expert is a man who has made all the mistakes which can be made in a very narrow field.

—Niels Bohr

In the preceding chapters, various stages of the firmware initialization process were described. In addition, various possible usage models have been described that can be implemented on a target hardware platform. By now it should have become evident that many of the UEFI firmware interfaces do not in and of themselves talk directly to hardware; instead they actually talk to underlying components that are responsible for talking to hardware. Traditionally, firmware development has not been an activity that could be performed without an in-circuit emulator (ICE) or other hardware debug facility. Taking into consideration UEFI’s design and the fact that very few components in the firmware actually have direct interaction with hardware devices, it is possible to introduce a mechanism that allows the emulation of vast amounts of the firmware in a standard deployment operation system environment.

In the UEFI sample implementation, a new target platform was introduced called NT32. This environment features the ability to run much of the firmware code as an application running from the operating system, and provides the ability to establish a robust development and debug environment. Much of the firmware codebase was developed initially using the emulation environment with off-the-shell compilers and debuggers, and without the need of a real hardware debugger. Of course, this emulation has its limitations, since some components of the firmware must talk to hardware. It is much more difficult to emulate such components, though later in this chapter, some possibilities are discussed to alleviate some of this issue. Figure 14.1 shows an example of a firmware emulation environment running the UEFI shell within an operating system context.

Figure 14.1: An Emulation Environment Contained within an Operating System Environment

Virtual Platform

This NT32 platform can be described as a hardware-agnostic platform in that it uses operating system APIs for its primary hardware abstractions. Figure 14.2 shows how the firmware emulation environment gets launched. It is part of a normal boot process, and will essentially launch a firmware emulation environment as an application running from the operating system. For most developers, this simply means launching a standard platform, loading an operating system, and then building and executing the NT32 emulation environment as a native operating system application. This application effectively executes the firmware that was built, and emulates the launch of a new system.

Figure 14.2: The Normal Boot Process Launching an Operating System that Will Launch the Emulation Environment

In Figure 14.3, the timeline is actually intended to illustrate the emulated firmware timeline. It has the capability of processing all of the firmware evolution stages, yet of course certain operations are emulated due to lack of direct hardware initialization. An example would be the direct initialization of memory, which would be somewhat different in this environment, whereas in a real platform, this process would be much more involved.

Figure 14.3: The Firmware Emulation Environment Itself

Emulation Firmware Phases

It should be noted that the emulation environment has several distinct phases:

Establishing a WinNtThunk capability for the emulation environment.

This phase constructs a means by which firmware components can make reference to some “hardware” components. This is done by associating firmware-visible constructs that will then be associated with operating system native API calls.

Figure 14.4 is an example where several firmware constructs are being associated with operating system native APIs. For example, to create a file, we establish a firmware calling mechanism (such as WinNtCreateFile) to call an operating system API known as CreateFile. The following examples illustrate a mechanism of associating firmware calls to Windows APIs, but this could just as easily happen for any underlying operation system.

Figure 14.4: Thunk Protocol that Associates Some Firmware Names with Operating System APIs

Construct an UEFI hardware API handler that will be specific to the emulation platform.

In Figure 14.5, the EFI_SERIAL_IO_PROTOCOL interface is being seeded with a variety of information associated with platform specific function data. In this case, these platform-specific functions are tuned to the emulation environment.

Figure 14.5: Establishing an UEFI API to Call Platform-Specific Operations

Platform-specific functions (such as emulation platform) that are handling the calls to UEFI interfaces and in turn will call the established WinNtThunk APIs that will end up making operating specific API calls.

Figure 14.6 features several calls that could occur from within an API handler to accomplish several tasks.

Figure 14.6: Example Calls to the WinNtThunk Protocol

In summary, Figure 14.7 shows the software logic contained within the operating system, firmware emulation component, and their associated interaction logic. It should be noted that this logical software flow has three primary components:

Firmware component under development

Basic firmware codebase

Firmware-to-Operating System thunk code

Figure 14.7: Firmware Emulation Software Logic Flow

Hardware Pass-Through

As is evident through the previous examples, the underlying firmware can enable calling to several operating system APIs. However, since the firmware emulation environment is essentially an operating system application, certain functions are not going to be available. This is true since most operating systems have the concept of separating a user space from a more privileged kernel space to prevent applications from inadvertently crashing the entire operating system. Using this type of separation allows for the operating system to detect an error and simply kill the user session without perturbing the remaining portions of the operating system.

It is possible to introduce several extensions to what is currently defined in the sample implementations that enable even further capabilities. An operating system kernel driver could be constructed to facilitate access to even more functions than would otherwise be available. This of course circumvents some of the inherent safety of the operating system and can introduce inadvertent crashes when care is not taken. By constructing a kernel driver that can reserve certain hardware resources and is able to advertise an interface that the emulation environment can call, the emulation environment can allow for an enhanced penetration into the hardware.

Figure 14.8 shows the logic flow associated with the various components and how they interact.

Figure 14.8: Software Flow for Hardware Enhanced Firmware Emulation

Summary

This chapter illustrated how the majority of the UEFI code can be run in an emulated environment so that development can occur on some modules even in the absence of physical hardware that would otherwise have been necessary. This emulation, which is publicly available, advances the accessibility of the overall UEFI programming infrastructure. It can also facilitate a wider distribution of its use due to the relative simplicity of establishing such a development environment.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset