UEFI News and Commentary

Wednesday, October 26, 2016

Intel and Insyde Embedded White Paper

Stephen Gentile, my colleague at Insyde Software, and I wrote a white paper with several Intel IoTG folks that describes how our UEFI-based embedded solution, BlinkBoot®, solves real-world business and technical challenges. You can find the paper here. BlinkBoot includes a unique add-on technology model, called Lenses, and a dedicated suite of tools: BlinkDebug, BlinkFlash and BlinkShell.


Thursday, October 20, 2016

PI 1.5 Released

This is late news, but you should head on over to the UEFI web site and pick up the PI 1.5 specification (here). Here are the highlights:

  1. Change the term System Management Mode (SMM) to Management Mode (MM)
  2. Provide a Management Mode infrastructure on ARM systems by using TrustZone.
  3. Allow initialization of Management Mode, as early as SEC or PEI. Also introduced a new class of MM drivers that launch natively within MM.
  4. Improved I2C support.
  5. Allow SEC to pass HOBs to PEI.
  6. New multi-processor protocol 
  7. Updated Disk Info to support SD/MMC
  8. and more...
As you can see, SMM (or rather MM) was a big part of this update. I started this, but my efforts were dwarfed by others. Part of the reason was that the ARM 64-bit folks had already started down a standardization path for TrustZone and it required some diligent technical and consensus-building work to create an environment that both ARM and x86 architecture firmware could share. We didn't just include Aarch64 systems. We made IA32 and X64 systems more robust and flexible as well. A shout out to Charles Garcia-Tobin (ARM) and Vincent Zimmer (Intel) on this.


Friday, October 03, 2014

Security to Eclipse User Features as Top 2015 Firmware Story

I stepped out on a limb this year and made a prediction. Predictions are notoriously fraught with peril and I am usually off-base or overly optimistic in mine. Nonetheless, as CTO of Insyde Software, I guess its also an unenviable part of my job. So here it goes:
'security' will eclipse 'lost my password', 'can't flash my BIOS' and 'overclocking' as the top firmware story in 2015.
For each of the previous hot firmware topics, the focus was on the user doing something correctly or incorrectly. The assumption was: if you don't do something dumb, your system will be ok.  Now, with security: even if the user doesn't do something dumb, it is possible that the system is not ok.

The OEMs (and firmware vendors) are now find themselves in the hot seat. Recent Black Hat presentations have increasingly focused on the vulnerabilities to be found in open source and closed source firmware implementations. Since firmware occupies such a privileged position in the software stack, successfully compromising it opens up a world of malware possibilities. With UEFI, the firmware has also become more capable and standardized, so more resources are theoretically available

The UEFI Forum has recognized this for a while and responded by creating a flexible OS secure boot and secure firmware update strategy in version 2.4 of the specification. The various software initiatives (including the open source ones) have followed quickly behind to implement these standards. But the security researchers and hackers began picking those apart, looking for and finding corner cases.

So the UEFI Forum responded by creating the USRT (UEFI Security Response Team), headed up by friend and former colleague, Dr. Dick Wilkins. The USRT provides a single point of contact for researchers to report their findings and disseminate those to silicon, software and system vendors.

At the same time, various UEFI Forum members, including Intel and my own company, Insyde Software, are producing domain-specific tools to test for certain well-known classes of vulnerabilities that are specific to our products. Intel has announced support for the CHIPSEC tool which evaluates the register settings in the motherboard chips to see if they are correctly configured to protect the firmware and boot process. Insyde is working on tools which check the various runtime interfaces we provide (and which OEMs extend) for classic API issues including buffer overflow and pointer validation.

Both UEFI's USRT plans and current firmware security tools will be discussed at the upcoming UEFI Plugfest, which is coming to Taipei from 13-17 October.

No one wants their company name featured in a security vulnerability press release. We'll talk again next year and see if my prediction is right.


Wednesday, September 03, 2014

New BIOS-Related Blogs

The first one is by my former colleague at Phoenix, Count Chu. He has already put together a number of interesting articles on parsing PDB files and the Design Pattern of the Report Status Code infrastructure.

The second is by William Leara, a BIOS developer at Dell, who writes on various topics of interest to BIOS developers (as the URL http://www.basicinputoutput.com/ might indicate), including using the UDK2014 and beautifier tools on EDK2.

Add this to Vincent Zimmer's intricate musings on firmware, security and technology in general on his blog and you have a pretty robust set of guru resources on BIOS.

Tuesday, August 19, 2014

ARM, Servers and the Shrink-Wrap OS

ARM just released the Server Base Boot Requirements document (more info here) which "defines the ARMv8 platform firmware abstractions necessary for OS deployment and boot, HW configuration and management, and power control" for servers that follow their SBSA specification. This is an important step so that OS vendors, like Red Hat and Microsoft, can produce "standard" operating systems distributions that work on any SBBR-compliant system.

What do you need to boot? Well, first of all, the operating system needs to detect all of the undetectable devices on the platform without a lot of poking and probing. That's because the standard OS image can only support a limited number of interrupt controllers, CPU memory management schemes, and high-resolution timers. So its a good idea if everyone can agree on a standard hardware architecture for these devices or, if not, a standard abstraction for how to talk to them. You don't want to use kernel configuration files, because that requires that the OS image is not the "standard" OS image, but rather one which has been modified for a specific SoC or specific board. So SBBR recommends the new ACPI 5.1 specification. People may not remember this, but one of the things that ACPI does (the "Configuration" part of the acronym) is provide a way to describe the hardware resources (memory, I/O, IRQ, DMA, etc.) used by non-enumerable devices and providing an identifier that the OS can use to load a specific device. The ACPI 5.1 specification did a few tweaks to that basic model for new ARM devices, but the same ideas are still valid.

Next, the operating system needs to be able to talk to the boot device long enough for it to be able to get its own drivers loaded. It is a sort of contract where the firmware finds the OS loader, validates it, and then jumps into it. But that OS loader then needs to load other files. Now it can try to put everything into a massive super-loader that can handle every device known to man or woman, or it can ask the firmware to read those files. That's why SBBR recommends UEFI 2.4, because UEFI has a well-defined mechanism for handing off control to OS loaders, loading files and then cleanly handing over control of devices to an OS driver.

How does the OS find out more information about the platform? Manufacturer name? DIMM types? Platform UUID? SBBR recommends the SMBIOS specification, version 2.8.0, published by the DMTF , which "addresses how motherboard and system vendors present management information about their products in a standard format" (see DSP0134).

Finally, ARM CPU cores can be arranged in a bewildering array of topologies, with an amazing variety of power states, can be described by the PSCI interface (from ARM and ACPI). This interface allows the interface to manage the tricky business of manipulating individual cores and managing the dependencies between them.

All of these work together to support the shrink-wrap experience. The goal: one DVD or one OS image can boot the system enough to get to the net and download any other updated or missing pieces. So standards that provide the pieces so that I can get my system to that point based on the information built into the firmware make everyone's job easier.




Tuesday, August 12, 2014

UEFI Forum releases the ACPI 5.1 Specification

For years, the ACPI specification was developed by what was essentially a 5-way tangle of an IP agreement between Microsoft, Intel, Toshiba, Phoenix and HP. It was a closed group with no simple way for new ideas and direction from outside.

After ACPI 5.0 was released, it became clear that if ACPI were going to have wider industry adoption, it would need to open up to a different sort of development process. At the UEFI board meetings (when I was with Phoenix), I saw most of the same companies and most of the same people as with ACPI. After much discussion between companies with large contingents of lawyers, the UEFI Forum took over management of ACPI and the UEFI board created the ASWG (ACPI Specification Working Group) to manage ACPI's development.

One of the first challenges after this change in management was to clean up the ACPI specification and make it more ARM AArch64 friendly. ACPI 5.0 had already paved the way with the Hardware-Reduced profile, removing many of the assumptions about hardware registers, processor states and bus hierarchies . These had been driven to some extent by Microsoft when Windows RT was on the horizon. For a description of the ACPI-related changes made by Linaro and other ARM partners, see this summary. Linaro has been very active in submitting kernel patch after kernel patch to modify the X86-only flavor of some of the Linux kernel pieces.

Now, with the release of the new ACPI 5.1 specification in a timely fashion, the remaining bits that didn't fit have been cleared away. There is still more work to be done, but at least Linux, ACPI an ARM have a clear path forward, both in terms of technology and open specification governance.

Thursday, June 19, 2014

Update to Setting Up the EDK2's Windows-Hosted UEFI Environment With Visual Studio 2012

Some of the building components and file names of EDK2 have been update. The article HOW-TO: Set Up the EDK2's Windows-Hosted UEFI Environment With Visual Studio 2012 has been updated to accommodate this.

Click here to view the article.

Tuesday, June 10, 2014

UEFI and SoCs and Chipsets and Firmware Complexity

When I switch back and forth between Insyde's x86 and ARM partners, I have to do a mental vocabulary switch. In the x86 world, we talk about "chipsets" but in the ARM side its almost universally "SoCs" Part of this is historical: the NEAT chipset was, in fact, a set of 3 chips that went alongside of the Intel CPU. More recently, there has been a traditional division of labor between the north bridge (memory controller) and south bridge (I/O controller). This split allowed CPU, memory and I/O technologies to progress at different speeds and allow for different pairings to meet different market requirements. But in the ARM world, the term SoC (system-on-a-chip) is recognized as a single-chip packaging of a CPU and all of the attendant hardware bits that are needed. New technology? Just spin a new SoC. The X86 world has responded with single-chip solutions, but the term 'chipset' still dominates.

In many ways, this difference in philosophy is reflected in firmware architectures. UEFI is designed for many hardware pieces, likely from different vendors, are combined together to boot an operating system. The fundamental unit of UEFI is a driver (or a module if you include PEI and you're a grognard for terminology). You add drivers for specific chips and attendant technologies. You remove drivers that you don't need. Seems logical, right?

But as gate density has increased, the number of technologies that can be stuffed into a single chip has also increased. Then the number of UEFI drivers increases. The difference can be startling: the number of modules (libraries, drivers and modules) required to support one chipset can be 10x more than the number required to support another.

Is this reasonable? If I have one chip on the motherboard, it seems reasonable that I should add 1 thing (driver, module, package, whatever) to the build. That would be my ideal world.

Indeed, there are initiatives going that direction. My friend, Intel guru Vincent Zimmer recently wrote about Intel's FSP (Firmware Support Package) on his blog. The FSP attempts to hide some of the complexity by packaging up most of the chip-support firmware into a single binary blob with three entry points. Dig a little deeper and you find that this "blob" is really a specially formatted UEFI firmware volume with PEI drivers (aka PEIMs). But, along with binary editing of board-specific options, it provides a good starting point to answering the objections of silicon-related firmware complexity. It still struggles with all of the traditional problems of binary deliverables, such as debugging and hot fixes. And it doesn't solve everything for industry standards like ACPI and SMBIOS and even UEFI's own HII. Not to mention OS-specific add-ons (like those for Windows 8.1) It tries to maintain the flexibility of UEFI while simplifying the silicon vendor side of the equation. Good start.

Insyde (my company) has been pursuing this at the source code level, improving  how entire chip "packages" (an EDK2 term) come together to create the final firmware. Our goal: 1 command brings in the entire support for a chip. Sure, tweak it from there. Sure, highlight the couple of places where engineer input is required at build. But don't make them find a read-me. Oh, and do it the same way for every chipset/SoC because when SoCs change often, your mind spins with which/where/what in a codebase.

One of the hidden advantages of the UEFI driver model is that it works well for SoCs as well. In order to keep up with new technologies, silicon vendors keep spinning new versions of their SoCs with new sets of peripherals, new versions of memory controllers and upgraded CPU cores. Many of these SoCs share the exact same IP blocks inside, with only a few tweaks. From a firmware perspective, I'd like to grab the same piece of code and use it to support all of the SoCs in which the IP block is included. Sounds like a driver model to me, based no longer on chips on a motherboard but on IP blocks in a chip.

Longer term, that means that some firmware complexity creep is inevitable as SoCs increase in complexity. But it also means that firmware systems must improve to support the increased rate of SoC/chipset change and reduce the effort required to configure and customize those platforms. Inevitably, the BIOS guys get blamed for every delay: the motherboard is ready, the chip is ready, so why isn't the BIOS ready? Simulation (another topic) is one way. Runtime debug/log infrastructures help catch what you missed. But well-designed build systems and firmware delivery models simplify the problem up front.

Friday, April 04, 2014

The Tale of Three Conferences

This week has been a blizzard of news and announcements from three conferences that I care about, all this week. First, there was EELive! in San Jose, CA which focused on embedded systems (or, as they now like to call it, the IoT). Second, there was Intel's Developer Forum in Shenzhen, China where my company (Insyde Software) was exhibiting and speaking. Finally, there was Microsoft's Build 2014 which I was watching with avid interest with live streaming and press releases flowing. UEFI was there, to either be promoted or vilified or both, in all three.

At first glance, at EELive, you would think that no one is paying attention to UEFI. Part of this was because Intel was busy promoting FSP, touting how it could be plugged into any boot loader, including coreboot. But the Galileo board that they were showing comes with a UEFI solution. And, under the hood, FSP is really extracted firmware drivers from Intel's UEFI-based reference code, packaged in UEFI-standard firmware volume format, with a little director binary inserted to allow direct calls into the driver entry points. The other reason is that 32-bit and smaller processors still dominate the IoT space and many of those are ARM designs. ARM platform 32-bit designs have used other boot loaders traditionally, but with 64-bit ARM itself is heavily pushing UEFI as a standard boot architecture. Many discussions around UEFI have to do with complexity. And there is something to these discussions, since the very power and flexibility of UEFI has led to implementations (like that on tianocore.org) which are broken into hundreds of pieces, where assembling the right one requires the right recipes. Most embedded vendors don't need their firmware distribution to be as complicated as their Linux distribution (see yoctoproject.org).

Then there's IDF. Of course, there was the Insyde poster chat: Implementing Dual OS Solutions with UEFI FIrmware" (how to switch between two active OS sessions w/just firmware support). Intel delivered their obligatory Quark and FSP remarks. But it also put out two additional UEFI-related notes. The first appeared in the unlikely session titled "Delivering Compelling User Experiences on Intel® Platforms: Audio, Voice, Speech and Fingerprint Sensors and Biometric Authentication" But in the very back of this presentation, they talked about security issues pertinent to BIOS, including replay-attack prevention related to Real-Time Clock battery removal and secure firmware updates using the UEFI capsule update method described in the UEFI 2.4 specification. It really seemed out of place, but hey... They also recommend adding their new CHIPSEC tool, which performs security checks on chipset and firmware settings. It is available on github.

And then the Intel Android team showed their Android build tool which would create a BSP for your platform and hey, it would also customize your firmware at the same time. It leverages the Unified Binary Management Suite (UBMS), which you can see here at about the 21 minute mark. This shows the increasing co-design process required for configuring your firmware and your OS installation. Many times, the firmware and the OS need to know the same types of information about the platform. For example, which drivers to include, GPIO routing, etc. Especially on OS' that don't use ACPI and that don't rely on the firmware passing them anything (like Android).

Finally, there's Microsoft Build event. We got a definitive date for the Update 1 (with no major new BIOS requirements! Sigh of relief), Microsoft's plan to offer Windows for $0 for certain platforms, Windows booting on Quark(!). And a lot of advice about how to integrate off-SoC sensors and how to write apps that span Windows and Windows Phone.

Hard to breathe. Need air. Next week I'll have a chance to reflect further on what some of these mean. How can we take advantage of vertical integration? How can we reassure folks of security in a world where firmware is increasingly decentralized and under attack? (Did I mention EELive! had a Black Hat track???) More later....

Tuesday, April 01, 2014

Something About the Game I Made with a Thermometer In It

After making the simple app that uses composite images and transparency to change the appearance of an image based on user input (as described in this article), I decided to expand it a little into the beginnings of a simple game.  As it is now, it is simply a shell for a game, in which you can move a sprite around and change modes.

In this article, I will describe the thought process behind creating this as well as the code I wrote.  This article assumes you have read the referenced article above on composite images and transparency.

Source code for this project can be found here.

I knew I wanted this "game" to include the thermometer I had created, and have something affected by the changing temperature.  I decided I could have a little character run around the screen and his color would change with the temperature.  Because I was using the same thermometer as I did in my last project, I was able to use the same code.  The only change I made was a simple image re-size to make it a little smaller.

The next question was how I wanted the playable area to be laid out.  Would it be laid out in a grid, where each object occupied a square, or would it be free movement?  Since collision detection in a free movement environment is much trickier than a grid, I decided to lay it out in a grid.  This was a fairly easy thing to implement.

First, I created a struct to represent a square in the grid, which I called "Box."  It has it's X and Y coordinates, an array containing pointers to the adjacent Boxes in each of the four cardinal directions, and a boolean value indicating whether or not the box is occupied by an object.


The next step was to initialize the grid, which is simply an array of boxes.  So I started by clearing all the memory and initializing the first box's coordinates to (0, 0).
Now from here, I could have hard-coded all the values for every single box, but if I had decided to change the size of the grid, it would have been a big pain to rewrite, so I wrote a loop that initialized the coordinates and array of adjacent boxes for each box.  For each of the boxes, I first set it's Occupied value to false (since each box is initially empty).  I first then look in the East (right) direction to see if the box is on the right edge of the grid.  If it's not, the East adjacent box is initialized to the next box in the array, and if not, East is set to NULL.  Next, I check the North (up) direction to see if it is on the top edge of the grid.  Like the East check, I initialize the North box if it's not on the top edge, and set it to NULL if it is on the top edge. 

So along with initializing the array of boxes, we also need to initialize the coordinates, which we can do in the checks for the West edge.  We can do as we have done with North and East, and initialize the West value.  However, after that, we can begin initializing coordinates.  If the box is not on the West (left) edge of the grid, then it can base its X coordinate on the box to its left, and simply add the width of an image (which is the same as the width of a box).  Its Y coordinate is simply the same as the box to its left.  If it is a left-edge box, then its X coordinate is 0, and the Y coordinate can be gotten by adding the box height to the Y coordinate of the box above it.  Finally, we do the South check, just like the others were done, and finish initialization of the boxes.

Now I needed to deal with the images.  In this application, I had six images: the background image, the character sprite, an object sprite, and the three thermometer images.  I did the same thing as described in the articles referenced above, except with more images.  All the image setup was done in the same function, and the image buffers stored in global variables.  Details about the image setup can be seen in the previous articles or the source code (link provided above).  In the source code, I have included a miniature .FDF file that includes the additional lines I added which allow the appropriate images to be included.  In order to use this, copy the text from my .FDF file and paste it into the FILE statements section of Nt32Pkg.FDF.

The only thing I did differently with regards to image display was in ConvertBmpToGopBlt().  One of the conditions for images was unnecessarily strict, and would sometimes cause the function to falsely report an invalid bitmap image, so I removed it.  The line used to read:
if ((BmpHeader->Size != BmpImageSize) || 
      (BmpHeader->Size < BmpHeader->ImageOffset) ||
      (BmpHeader->Size - BmpHeader->ImageOffset !=  BmpHeader->PixelHeight * DataSizePerLine)) {
    return EFI_INVALID_PARAMETER;
  }
I removed the third condition so it now reads:
if ((BmpHeader->Size != BmpImageSize) || (BmpHeader->Size < BmpHeader->ImageOffset)) { return EFI_INVALID_PARAMETER; }
Which causes it to work properly.

Before we move onto the components of the actual game, we need to remember that in this game, we will be moving around a character as well as changing the temperature on the thermometer.  We could use different keys to change the temperature and move around, but I decided it would be best if the character were standing still while the temperature changed, so I made it so that the user could change which "mode" they were in, movement, or temperature change.  The mode is implemented using an enum, and stored in a global variable.

Up next is the actual character itself that the user can move around.  It contains a pointer to the buffer containing the original image, a pointer to the altered image (since we are going to change the image's color over the course of the game), its coordinates, and the box it is currently occupying.  We make the character a global variable, since there is only one.

Initializing the character struct is simple and can be done as soon as the images and grid are set up.  We first set the mode to be "MOVE" since we would like that to be the initial setting.  Image is set to point to the buffer referenced by the global variable.  The image is then copied into a new buffer, and ChangedImage points to that new buffer.  This way, ChangedImage can be altered without affecting the base original image.  Then, the coordinates and box are set to be the upper left-hand corner (just an arbitrary position).
After this, I decided to have some sort of additional object on the map along with the character.  So I created a basic Object struct.  It has an Image, ChangedImage, coordinates, and box it occupies.  This is actually basically the same as the Character struct, and in the future, I could go back and combine the two into one.  There is only one non-character object in this application, but multiple objects could simply be stored in a global array.

Initializing and setting up objects is similar to that of initializing the character.  In this program, I only included one object, but it would be simple enough to expand the function to deal with multiple objects.  Like the character image initialization, we set Image to be the globally accessible buffer, and ChangedImage to be a copy of the Image buffer.  The coordinates and grid position are set, and then we set the assigned box to be occupied.

Now we turn our attentions towards player actions.  The first and most basic action a player can take is to move.  Since we used a grid, the movement is easy to do.  Basically all it does is check the box adjacent to where the character currently is, and see if it is null or occupied.  If not, it changes the character's box and coordinates to that of its new location.

The next is its color change.  Now, this method does nothing incredibly special.  It simply multiplies the pixel colors by the percentage height difference of the thermometer.  It makes sure the colors never go above their maximum value, and are never negative.  The nice thing about this is that will not alter black pixels (which, in my implementation are interpreted as transparent), so pixels intended to be transparent will remain that way, whatever color changes might occur.  Notice that the transformations are based on the original image's color.  This way, colors at a given temperature are always the same. Another possible implementation of this is to have the blue color increase and red decrease as the temperature decreases, and vise versa as the temperature increases.  

Finally we get to the actual game loop itself.  It is just a do-while loop that waits until an end condition is reached (in this case, until the END key on the keyboard is pressed).  All it does is sit around and wait for the user to press a key on the keyboard.  If it's one of the arrow keys, and the game is in MOVE mode, it moves the character.  Otherwise, if it's in TEMP mode, it will change the temperature and change the player's color only if it's an up or down arrow key.  In this implementation, the mode is changed by pressing the PgUp key.  After that, it displays the images in their new positions.  Once the end condition has been met, the memory is freed, screen cleared, and we return success! In the images below, the image on the left shows the key scanning, and the right image shows the image display and cleanup.
   


And that's all she wrote!  

Friday, January 24, 2014

UEFI: A Retrospective

This nifty article by my friend and co-author Vincent Zimmer takes a look at the UEFI specification from his perspective as one of its early proponents within Intel, as an author (Beyond BIOS), and more recently as a steward of the specification and innovator post-UEFI.

From my perspective as a BIOS architect, the process was never a smooth one. The rise of the industry specification bodies is something we take for granted. If you look at older PC specifications, like ACPI and APM and BBS, they were cooperatively developed by a small cadre of companies, like Microsoft, Toshiba, Phoenix and Compaq. As EFI was coming along from Intel, the BIOS vendors were also developing standards and promoting these standards. Never heard of PowerBIOS from Award? Or how about Manticore or CSI from Phoenix? With the industry standards group approach, any one of these could have become what UEFI is now. Maybe. If the originating company was willing to loosen their grip. It was, in accepting this key point, what allowed Intel and their partners like HP to gain critical agreement within the PC ecosystem.

Sometimes relinquishing control gets you what you want, but the process is more chaotic. Certainly true for UEFI.


Thursday, October 31, 2013

Linux and UEFI: Linaro and LinuxCon

This week I've spent hanging around Linaro Connect 2013 USA, which is dedicated to bringing all of the open-source (and Linux) goodness to the ARM platform. For the 64-bit ARM architecture (AArch64), they have been promoting UEFI for quite a while but Linaro and its members are doing a lot of the really hard work of making sure that is a reality, with engineers dedicated to working from the reset vector up through the Linux kernel and into some server applications, making sure that all the necessary bits are there in open source. There were a lot of sessions this week that deal with the thorny issues of UEFI (secure boot), power management (PSCI) and ACPI (interaction with existing drivers and FDT).  To top it off, this event was co-located with ARM TechCon which doubled the fun, including an interesting keynote by Simon Segars, CEO or ARM.

This follows on the heels of the UEFI Plugfest, which was co-located also, but with LinuxCon in New Orleans. My colleague, Jeff Wheeler from Insyde got to attend, and he found folks interested in the question, "Does it really work?" And the answer was, "Yes, it does" This is the impression I recently found from  Bruno Cornec's blog article "First UEFI PlugFest for Linuxers". Good communication, good testing and, more importantly, UEFI and Linux work together.

The relationship between Linux and UEFI has not always been easy, with conspiracy theories and suspicious kicking of tires. But these two events have shown that they can and do work together, on x86 and ARM.

Tuesday, October 29, 2013

ACPI Specification Now Managed By UEFI, and Why Anyone Should Care

This article by my UEFI colleagues Dong Wei (HP, VP of UEFI) and Andrew Sloss (ARM, ARM Binding Sub-Team Chair) talks about a large recent development in the firmware world: ACPI is now managed by UEFI. I was a part of the ACPI specification development starting with ACPI 2.0 up through the current ACPI 5.0 specification while I was employed with Phoenix Technologies. That specification seems unusual to me now, in that it was essentially a five-way agreement between Intel, Microsoft, Compaq/HP, Phoenix and Toshiba. But actually, back in the day when it was conceived, it wasn't that unusual, as the BIOS Boot Specification (BBS) or Advanced Power Management (APM) will attest. For every revision of the specification, essentially the 5-way consortium was reborn again, occasionally (such as when Phoenix was added or Compaq was merged with HP) with a change of membership.

Due to the unusual structure and the fact that it was tied in many ways to Microsoft's release schedule and Intel's hardware schedule, releases tended to be big and cumbersome. Adding new members was problematic, since the number of signatures required from legal departments grows exponentially.

On the other hand, UEFI has functioned pretty well since 2005 in taking input, releasing regular errata and specification updates. So with Mark Doran (Intel, UEFI president) assuming the helm of both efforts, it seemed like a good time to push them together. They really address the same target audiences: system firmware providers, OS vendors, OEMs and chip manufacturers, with a smattering of plug-in card and application vendors. It probably helps convince folks like Linaro (working on ARM) and Redhat (working on Linux) to adopt ACPI if more than Intel and Microsoft are represented.

Now the process that is used to gather input, hash out differences and formulate solutions for UEFI can be applied to ACPI with, in my opinion, great effect.

"UEFI brings in an amazing level of standardizaton for boot loaders"

The title comes from one slide in the "Is UEFI EDK II ready for Android mobile" session at the Linaro Connect 2013 event in Santa Clara, this was on one of the slides. Here is what was presented as advantages for UEFI on ARM and Android Mobile:

  • Very detailed specification from UEFI forum of industry experts
  • Reduce cost of development, code is highly organized and structures - easy to add support for new platforms.
  • Drivers can be independenly developed and distributed by peripheral/controller manufacturer, just like in any high level OS
  • Brings in concept of "application" at boot loader level itself, can be used for test suite development, new functionality like flashing utilities, splash screens, etc.


Tuesday, October 22, 2013

PI 1.3 Review, Part 3: Updates to FindSectionData PEI Services

This article is the third in a series describing the changes made in the PI 1.3 specification. This time we look at a new entry added to the PEI Services table: FindSectionData3(). There's only one problem: this function doesn't actually show up in the table of contents, even though it is listed in the PEI Services Table in section 3.2.1 of Volume 1 of the PI.

So what happened? Well, it turns out that this function is an update to another PEI Service: FindSectionData() and simply adds a new parameter: AuthenticationStatus. This returns the result of authentication for a specific single section. The PEI core has access to this information, when it calls the Security Architecture PPI, but never passed it back. This meant that some callers, such as implementations of the Load File PPI, would have to either call the Security Architecture PPI themselves (adding delay and complexity) or hard-code it to 0 (which is what the tianocore implementation was doing). This new PEI Service optionally returns this and does so in a way that the previous function (FindSectionData()) could be implemented by calling the new function, just setting AuthenticationStatus to NULL.

But when the new function was added to the specification, there was an editing error. The new function parameter was added to FindSectionData(), which was the existing function and the new function (FindSectionData3()) is nowhere to be found. I expect this will be fixed in an errata.

Now PI 1.3 has the ability to parse firmware volumes in a secure (!) and fast (!) manner.

Monday, October 21, 2013

IPv6 Network Boot with UEFI

Vincent Zimmer has just put up a nice little post how configuring IPv6 network boot with UEFI over on his blog here. As usual, we need him to write more since so much of the UEFI network stack was overseen by the UEFI Network Sub Team (UNST), of which he is the chair.

Tuesday, October 15, 2013

PI 1.3 Review, Part 2: PI Status Codes

This is the second article in a series describing the changes in the PI 1.3 specification. This article focuses on the updates to the PI status codes. Actually, quite a minor change, these add status codes for the firmware if it implements support for the ATA specification's Self-Monitoring, Analysis and Reporting Technology (SMART) feature set for hard drives. This feature set allows software to query the hard drives and ask about the types of faults experienced with a view of predicting eventual hard drive failure.

These status codes provide a standardized way for the system firmware to report when SMART is being enabled (EFI_IOB_ATA_BUS_SMART_ENABLE) or disabled (EFI_IOB_ATA_BUS_SMART_DISABLE) or whether it is not supported by the drive (EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED). It also allows the firmware to report if it detects on the many classes of alert conditions, using EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD and EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD.

One of the interesting things is why these were not in the PI Specification in the first place, even though they were in the EDK implementation that Intel developed around the same time. After the EFI 1.10 specification was released, there was a relatively long hiatus with no additional specification versions being released with new material, except for minor errata. People (meaning Intel, Microsoft and a few other companies) were fairly satisfied with EFI 1.10 but who was going to do all the dirty work to implement it. So Intel wrote down the Platform Innovation Framework (or PIF) specification and created a corresponding implementation, called Tiano, showing what they considered best practice for creating EFI implementations. From some comments, Intel intended that much of this work would end up in the future EFI (not UEFI) 2.0 specification.

But then UEFI came, forged by the original nine promoter companies, including Insyde. Intel suspended work on the PIF specifications. But work continued internally. When it came time for the PI specification to be created, using the PIF specifications as a starting point, we tried to gather up any loose ends from Intel's on-going development, but we failed to get these status codes. And thus, SMART status codes were all there; everyone knew about them; but they weren't the standard.

And now they are. So PI 1.3 finally catches up with PIF (at least in this area).

Thursday, October 10, 2013

PI 1.3 Review, Part 1: I2C Bus Protocol

This article is the first in a series describing the changes in the Platform Initialization (PI) 1.3 specification. The PI specification is like the unheralded younger brother of the UEFI specification. From the very beginning it was a requirement that PI implementations be able to produce UEFI, but it was also a requirement that UEFI drivers and applications and OS loaders not depend on the PI specification. If something was really needed for UEFI, it would get promoted (yes, that is the word used) from the PI specification. Why? Because there have been (and are) implementations of UEFI which are not built on top of the tianocore.org EDK1 or EDK2 implementations or even Intel's older Platfrom Innovation Framework.

It was named the Platform Initialization (PI) specification because, in the UEFI 2.0 specification (and the earlier EFI 1.x specifications), one of the block diagrams of UEFI had a big blank box labeled (you guessed it): "Platform Initialization" UEFI really deals with booting. Yes, yes, there's a lot of other stuff around user interface (HII) and security and networking, but it is all about finding the right boot device and loading the OS. If you are not a boot device (or a video device or a keyboard), you don't really get a lot of respect in UEFI. That is PI. So, what's in there? Well, there's memory controllers, GPIOs, system management mode (SMM), PCI root bridges, super I/O controllers, embedded controllers, and yes, I2C and SMBus. All in the PI specification.

I2C didn't get a lot of respect either in the UEFI world, ever since Intel began promoting the smarter, enumerable version, called SMBus. But it turns out that, as a simple, low-cost, low speed, low-power bus, it works well for controlling on-the-motherboard devices, like touch panels, MEMS sensors, small EEPROMs and other devices with relatively low data rates. Also, SMBus didn't really like multiple speed devices.

Within PI, SMBus suffered from only have a host controller protocol, but it was never extended out to a true driver stack like, say, USB or PCI. Sad. If you want to see how its really done, look at my presentation from the UEFI plugfest back in 2011.

But back to I2C.  The following diagram shows the typical driver stack. It looks very similar to the typical UEFI driver stack, with a host controller protocol and an I/O protocol. But after that it gets a bit strange: what are the enumerate, bus configuration management and master protocol?


First, it is important to understand the I2C is not really enumerable. You can't poke at some register and discover that a device is present. At least not reliably, from a bus driver perspective. USB and PCI and SMBus are examples of enumerable buses. So, instead, the I2C driver stack relies on a platform driver to produce the I2C Enumerate protocol to return back a list of devices actually present on the platform.

Second, since it is possible for the I2C bus to be one of several different configurations, it is important that the bus be placed in the right configuration before talking to a specific device. For example, if the bus speed must be changed, or a multiplexer must be set so that I2C devices are actually connected to the controller. That control is provided by the I2C Bus Configuration Management protocol.

Third, the host controller support is divided into two pieces: the Master protocol and the Host protocol. In general, the device driver's use the Host protocol to queue an I2C transaction. The Master protocol is used when it is necessary to go out of order and send an I2C command. This happens, for example, when the platform driver needs to send an command to a multiplexer or bus clock device before an I2C command is sent to a device.

With the I2C protocols, the PI 1.3 specification gives a driver stack so that you can write a device driver for an I2C device that works on any platform. But this is only for DXE. In PEI, only the Master capabilities are available through the I2C Master PPI.




Friday, September 27, 2013

UEFI 2.4 Review, Part 15: Capsule on Disk

This article is the fifteenth in a series reviewing the changes in the UEFI 2.4 specification. This time we take a look at a new standard way for capsules to be delivered to the pre-OS environment: on disk.

Going back in history, capsules have been used for various things. Operating systems have tucked away their BSOD information in a capsule, so they could recover it on next boot, even if the debug information couldn't be displayed. But by far the most common usage is to tuck away a firmware update for the pre-OS to deal with on the next reboot.

There's one small problem with that: where does the firmware put the capsule? Well, in some cases, the underlying memory controller would guarantee that the memory contents would persist across certain types of reset. This would allow the firmware to pick up the capsule on the next reset, and mark its memory location as reserved so it would not be stomped on until the appropriate application or driver could get ahold of it. Others hid it away in System Management RAM (SMRAM) or even in the belly of an embedded controller.

In other systems, where the memory holding the capsule could not guarantee that the memory would be valid, some other solution was needed. In UEFI 2.4, there is now the option to store a file on the system partition of the boot disk, in the /EFI/UpdateCapsule directory and set a bit in the OsIndications EFI variable.

On the next boot, the UEFI firmware will detect that bit set and will search for any files within the boot device's system partition and try to load and validate them, in alphabetical order. Once they have been processed, they are deleted (if possible) and the system is reset.

But wait? How do I know what happened when the capsule was processed? Well, there is now a handy-dandy CapsuleNNNN EFI variable that is created to describe both what was processed and the resulting status. Possible results include success (of course), invalid capsule, device error, access denied, unsupported capsule type, no valid driver in the capsule, or there wasn't enough memory to process the capsule. This mechanism shouldn't be confused with Microsoft's own special ACPI table, the ESRT table (little public information available, but here's a hint) which reports the results of firmware updates.

So with UEFI 2.4, the operating system (and related system software) can pass large quantities of data back to the pre-OS for processing without worrying about the size. Much more flexible, and better yet, its a standard.


P.S. A lot of credit for the capsule updates in UEFI 2.4 goes to my Insyde colleague, Jeff Bobzin. He produced a public demonstration of these technologies with Terry Kirch of Emulex at the most recent IDF.

Tuesday, September 24, 2013

Zork on UEFI

Leave it to Matthew Garrett to find some extra time on his hands, and then decide to use it to port Zork (or rather, the Frotz Z-machine interpreter) to UEFI. He wrote about his experiences on his inimitable blog and, during the process, highlighted some of the on-going issues with writing applications for UEFI.

Matthew highlights the fact that the standard C library included in EDK2 only supports UEFI Shell applications, not UEFI applications running directly on UEFI or UEFI drivers. This makes porting code more difficult than necessary, since I've struggled to share code between UEFI drivers and applications, even going to the extreme of writing my "driver" as a UEFI application.

Of course, he just updated Frotz to be a UEFI shell application, and then launched it. This turns out to be trickier than it sounds, since the UEFI shell doesn't set the current working directory where he expected it.

As anyone who follows this blog knows, I am a great fan of stretching UEFI into new areas, like text adventures and utility C libraries. More on that in the next few weeks.