Sunday, February 24, 2013

Anniversary Day.Next, Arch P*'s, and some stack history

Today makes 16 years at Intel.  Sunday is usually my catch-up day for work tasks or extra credit work (e.g., patent drafting), but given that I posted an entry on this day last year, I'll steal a few minutes to post something today.  If I keep my wits about me maybe this can become a tradition?  Induction will argue that it might be so if I hit the 'publish' button before the end of the day.  0, 1, ... infinity, right?  OK.  Enough of that.   Popper and Hume might rise from their graves and smite me for induction invective if I go on that path.

The first topic I wanted to touch upon today includes the intent behind the architectural p*'s in the UEFI Platform Initialization (PI) Specifications.  Namely the architectural PEIM-to-PEIM interfaces (PPI's) and Architectural Protocols (AP's) in Volumes 1 and 2, respectively.  I have been meaning to cover this topic for a while, but today's posting is motivated by James B's foils @ http://blog.hansenpartnership.com/wp-uploads/2013/02/UEFI-Secure-Boot-2013.pdf, namely slide 15.  In this presentation deck, not 'paper' as some people are wont to describe foils these days, James discusses overloading the security protocol from the PI specification from his UEFI application.   As James' loader is a pure UEFI application, any dependency upon an underlying PI interface breaks portability.  There is no reason that UEFI interfaces need be built upon a PI-based underlying implementation, for example.

We mention this in many places, including page 12 of UEFI_Networking_and_Pre-OS_Security or http://noggin.intel.com/technology-journal/2011/151/uefi-today-bootstrapping-continuum, viz., "PI, on the other hand, should be largely opaque to the pre-OS boot devices, operating systems, and their loaders since it covers many software aspects of platform construction that are irrelevant to those consumers."

The history of the PPI's and AP's in Intel Framework, and subsequently the UEFI PI specifications, was to abstract a portable PEI and DXE core from the respective platform.   The sources for the cores are intended to be kept platform neutral such that they can be seamlessly compiled to any target architecture, which today includes IA32, x64, Itanium, and 32-bit ARM for the edk2 at http://sourceforge.net/apps/mediawiki/tianocore/index.php?title=EDK2.  As such, the arch PPI's and AP's provide a hardware or platform abstraction lay (H/PAL) to the cores.  Back to James' foils above, he took advantage of a design choice where the protocol's were left in the UEFI protocol database after the DXE core had bound itself to those call-points.  A conformant PI implementation of UEFI could have uninstalled that protocols prior to entering BDS and invoking 3rd party UEFI drivers and applications, for example.

Omission of the AP's from the database and precluding usage by 3rd parties is not just hygiene.  Abuse of the timer AP, for example, by an errant or malevolent UEFI application could change the timer tick in a way that was not consistent with the DXE core's original programming of the time base via the timer AP.

So the lesson from above includes (1) if you want to be a portable UEFI driver and application, don't invoke UEFI PI AP's, and (2) as a platform creator, be wary of the protocols you leave installed in the database prior to invoking 3rd party UEFI content.

Next on the list today includes a short history of the UEFI networking stack.  The original EFI networking stack was part of the EFI1.02 specification back in 1999.  We modeled the network stack on the PC/AT networking support, including the PXE base code (BC) and UNDI interfaces.  The latter 2 API's were defined in the PXE2.1 specification.  The PXE (pre-boot execution environment) specification contains both a wire protocol for network boot and a set of API's that a network boot program (NBP) uses so that when it is downloaded onto a PC/AT BIOS client machine it can continue usage of the client machine's network stack.   For EFI1.02, we adapted the PXE BC and UNDI API's into EFI equivalents, while preserving the network wire protocol aspects, such as the DHCP control channel, TFTP-based file download, etc.  EFI added an additional software API on top of UNDI called the Simple Network Protocol (SNP), too.  So from BIOS to EFI we preserved PXE BC, UNDI, and added a SNP between the former two.

After EFI1.10 and its inclusion of EBC and the EFI Driver Model, we thought of what a "EFI1.2" specification might entail.  One aspect of the pre-OS we explored included more efficient networks.  The problem we discovered was that SNP could only be opened by one agent, namely the PXE BC.  When other network drivers were added, such as the circa-1999 BSD TCP/IP port to EFI, we had to unload the PXE BC in order to have the TCP/IP stack active.   Against this background of a single SNP consumer, we designed the Managed Network Protocol (MNP).   MNP provides for multiple listeners and also provides a non-blocking interface, unlike the single consumer, blocking nature of SNP and UNDI.  We took the concept of multiple consumers and non-blocking for the higher layer protocols, including UDP, TFTP, DHCP, and TCP/IP.   In doing so, we were able to rewrite the PXE BC application to be a small consumer of the below-listed services versus the monolithic stack embedded in the original PXE BC.

Since EFI1.2 never came to light, MNP and the rest of the modular stack definition were contributed into the UEFI2.0 specification as part of the UEFI Forum's effort.  This was timely in that ISCSI was added to the UEFI2.0 corpus, and implementing ISCSI and PXE on the same modular stack proved to be feasible.   The next question posed to the pre-OS networking stack was what to do with PXE.  Recall that the EFI, and now UEFI, interfaces to PXE included the PXE 2.1 wire protocol.  We were faced with evolving PXE to an alternate wire protocol or augmenting PXE and the rest of the networking stack to meet the emergent needs in the industry, such as internet protocol version 6 (IPV6).   Given the extant infrastructure of PXE servers and associated scenarios, included blended scenarios such as 'PXE boot the NBP OS installer, mount an ISCSI share, install into the ISCSI block device', etc, we opted to draft PXE into IPV6 with parallel capabilities.   We coined the effort to have network boot on IPV6 'netboot6' and codified the elements of this capability in RFC 5970 http://tools.ietf.org/pdf/rfc5970.pdf and chapter 21 of the UEFI 2.3.1c specification.  5970 was evolved as part of the DHC WG in the IETF and describes a broad class of network boot transports described by a URL, which includes HTTP, TFTP, ISCSI, NFS, etc.  Netboot6 opted for the TFTP-based transport to have a parallel flow to the PXE 2.1 wire protocol, but there is no reason going forward that alternate boot transports can be used.

Seeing is believing, though, so you can find the networking infrastructure mentioned above at http://edk2.svn.sourceforge.net/viewvc/edk2/trunk/edk2/NetworkPkg/.

I regret that this blog and many of the white papers referenced in the past have not treated the UEFI networking stack with much detail.  I'm working to get some more collateral out in the open, especially given how to compose pre-OS networking and fast-boot.  One piece of wisdom that I want to mention is that the UEFI system should not attempt to start any of the networking stack elements unless there is a boot target that includes PXE or other networking-facing service.  This is in the spirit of the UEFI driver model where you should not connect a driver unless needed to boot.  This sparse connect is how UEFI achieves its fast boot times relative to PC/AT BIOS's that had to spin up all of their spindles and network interfaces in absence of having a stylized boot object like the UEFI boot targets with their device paths.  Given that IEEE 802.3 Ethernet devices can take 7 to 20 seconds to effect cable detect actions, any touch to the network will kill chances of achieving the 2-3 second boot times expected by modern operating systems.

Other advice I will include on network boot includes policy decisions of orchestrating IPV4 versus IPV6 on network accesses, etc.  So beyond having a more detailed overview of the stack, fast boot and network selection policy, let me know if there are additional topics on the network stack that you would like to see treated.

Well, that's it for anniversary year 16 blog.  Let's hope that the inductive argument holds true and I am creating the year 17 variant of this blog.

Cheers

No comments: