Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

intel_fw

This is both a command-line interface (CLI) and a library for analyzing and editing firmware images for Intel platforms.

The architecture is based on knowledge from prior research.

CLI

The CLI is made with the clap command line argument parser in derive mode. To familiarize yourself with Rust and common approaches to CLI tools, take a look at the Rust CLI book.

For more understanding, see also any of these additional resources:

Architecture and Design

The following considerations around specifics in the domain of Intel platforms and firmware are meant to offer a deeper understanding of design choices.

Goals

Separate detection from action

me_cleaner mixes both, and assessing the exact actions to happen is hard. Via its CLI, everything a one-shot operation, and the user needs to know the options beforehand. Note that it is very Unixesque to wrap CLIs in shell scripts as if they were intended as APIs. That is not meant here.

For programmatic and interactive use, provide an analysis result and let the programmer/user then choose what they want to do. The programmer has to deal with all possibilities and may choose strategies around them, whereas the user can benefit from seeing the options fitting their actual case.

E.g., in a GUI app such as Fiedka or a TUI that could be created with ratatui, setting a HAP bit vs legacy (Alt)MeDisable bit(s) can be elaborated on in a help message or tooltip. Removable partitions and files can be listed rather than expected to be provided by the user who, before the analysis, doesn’t know what their firmware contains.

Comprehensible and useful API

Provide an API that requires little knowledge of internal details. The job of an API is to simplify, after all. Otherwise, both caller and callee would duplicate efforts.

Encapsulate rather than exposing many raw structs directly. Make relationships and containment clear.

E.g., wrap partition entry structs in another struct that carries supporting metadata with it, such as offset and size, parsing result of what the partition entry points to, etc..

Follow the guidelines for extending intel_fw.

Approaches

Replies to a StackOverflow question on separating preparation from execution reference the Composite pattern and the Command pattern.

The Composite pattern helps in that there is a hierarchical structure, i.e., IFD, FIT and ME firmware on a high level, and then IFD has its underlying data, the ME firmware has its FPT and partitions therein, and the FIT points to many things. Underlying details are very different though, so there are no meaningful abstractions for common interfaces.

The Command pattern may make sense on a higher level, for example, to collect the actions resulting from command line switches or API options. At the same time, it creates more boilerplate code, which may be hard to follow.

Note that we need to check the applicability of operations on two levels: Some operations exclude others, and some only apply if their assumptions fit with findings from analyzing the given firmware image.

Fiano/utk implements the visitor pattern, which is meant for objects that are quite similar in some regard.

One issue with firmware images is that while many things are related to each other, they also have their very specific purposes and semantics, and there is a rather fixed structure. It would thus be simpler to deal with specific operations on a higher level that understands the domain and carries clear semantics with it rather than having a visitor/executor encoding each possible operation for each bit and requiring more understanding from the user and programmer. I.e., just have each entity offer its own unique set of clearly understandable helpers and assisting parameters, possibly following a loose pattern when multiple entities are similar.

For example, some partitions contain directories in the case of generation 2 and generation 3 ME: For both generations, certain directories can be partially cleared (whole ranges of data set to 0xff), and both can take a list of things to retain. That requires helpers which may implement a common trait (interface). Similarly, other partitions can be cleared, but entirely, so they do not need extra functionality themselves. Trying to force the same interface on them only results in unnecessary extra code.

On the other hand, the FPT itself is a small memory slice (found to be <2K), so it can take care of itself. It has a checksum in its header. Offer helpers for editing and returning a new slice to replace the original one. The IFD is similar in that it is also small, but has its own unique features. And the FIT is yet again very different.

See also the strategy pattern.

Extend with new variants and features

These guiding principles are meant to help extending intel_fw over time. As a library, it should adhere to those as requirements in order to provide guarantees to applications working with it. Generally, it should follow the Rust API guidelines.

Do not panic!

Parsing firmware means looking for and acting on offsets and sizes frequently, and they always need to be checked to stay within the bounds of the given data. Never .unwrap() or .expect(), which mean an intentional panic, in case something cannot be found, read, or recognized. Instead, return instances of Self for structs, wrapped in a Result<Self, CustomError> or possibly Option<Self>. Do not assert!() or explicitly panic!() either.

Option or Result

In general, use Option<Self> for things that might not be found. For example, a full image from a production system would have an IFD at the beginning, whereas an ME-only image would not. On the other hand, either image is expected to contain an FPT, so in this case, provide a Result<Self, CustomError>, because not finding an FPT means that something is clearly wrong with the image.

Continuous parsing

There are circumstances under which a parser encounters an issue. It can be that offsets do not make sense, magic bytes (struct markers) are not as they were expected, or new variants are found with samples not encountered before. In those situations, it is desirable to follow a best-effort strategy. I.e., when there is still remaining data that could be parsed, keep going.

Let apps provide feedback

Finally, let the consuming application take care of taking the result apart. Nested structures can be thought of as trees, similar to ASTs in programming languages. Whenever a node in the tree that is a parsing result turns into an Error or None, other nodes beside it may still provide useful information. That information helps the user of an app to understand the context and possibly report what they are facing or look into the issue themselves.

Errors and context

In order to make sense of an error, context is important. During development, it can be helpful to print out information right within a specific parser. However, a final app is typically not run in development mode, but as a release. In that moment, semantic errors will help to identify possible problems. Include offsets and sizes (or Ranges) for the application to tell exactly where the problem is, and it can choose to e.g. dump a contextual hex view on the data.

Additional information

To provide additional information, instead of returning an Err(String), wrap it in an enum CustomError, i.e., for example,

enum CustomError {
    TooSmall(String),
}

so you would return Err(CustomError:TooSmall(format!("{n{ bytes needed"))).

Analysis process

Analyzing (unknown) firmware means that we need to find or build tools to help us look at the given binary. Common utilities are hex viewers and editors, such xxd, hexdump and hexedit, or the ImHex app. In addition, to help with unpacking, dd, unxz, unlzma and similar utilities to cut out and decompress data are very handy.

Recognizing data

The following example shall help understanding the thought process when trying to get behind the meaning of unknown data. Mind that this takes a lot of time. It often starts with the simple question: What is this?

A first helpful step is to try to identify headers and formats. Binary data structures often start with markers called signatures, magic bytes or numbers, commonly four ASCII characters or significant numbers that suggest a meaning. There are tools such as file to recognize them, as well as lists of common file signatures and magic bytes. Search engines and communities are quick to assist with a first effort.

Often enough, other researchers have already performed initial work to build on top of. In the case of Intel ME generation 3 hardware, there are manifests with lots of metadata, described through what are called extensions by Positive Technologies. They have created the following utilities:

  • https://github.com/ptresearch/unME11
  • https://github.com/ptresearch/unME12

New extension in CPD manifest: 0x30

With ME version 15 firmware, there are new manifest extensions. The following is a hex dump of the data described by extension 0x30, as printed by xxd. Additional spaces and markers are there to assist the elaboration:

00196500:          [fd01 0000]>[3082]01f9 a003 0201  ........0.......
00196510: 0202 0101 300a 0608   2a86 48ce 3d04 0303  ....0...*.H.=...
00196520: 301a 3118 3016 0603   5504 030c 0f43 534d  0.1.0...U....CSM
00196530: 4520 4d43 4320 524f   4d20 4341 301e 170d  E MCC ROM CA0...
00196540: 3230 3131 3235 3030   3030 3030 5a17 0d34  201125000000Z..4
00196550: 3931 3233 3132 3335   3935 395a 3023 3121  91231235959Z0#1!
00196560: 301f 0603 5504 030c   1843 534d 4520 4d43  0...U....CSME MC
00196570: 4320 5356 4e30 3120   4b65 726e 656c 2043  C SVN01 Kernel C
00196580: 4130 7630 1006 072a   8648 ce3d 0201 0605  A0v0...*.H.=....
00196590: 2b81 0400 2203 6200   04aa aaaa aaaa aaaa  +...".b.........
001965a0: aaaa aaaa aaaa aaaa   aaaa aaaa aaaa aaaa  ................
001965b0: aaaa aaaa aaaa aaaa   aaaa aaaa aaaa aaaa  ................
001965c0: aaaa aaaa aaaa aaaa   aabb bbbb bbbb bbbb  ................
001965d0: bbbb bbbb bbbb bbbb   bbbb bbbb bbbb bbbb  ................
001965e0: bbbb bbbb bbbb bbbb   bbbb bbbb bbbb bbbb  ................
001965f0: bbbb bbbb bbbb bbbb   bba3 8201 0830 8201  .............0..
00196600: 0430 1f06 0355 1d23   0418 3016 8014 dddd  .0...U.#..0.....
00196610: dddd dddd dddd dddd   dddd dddd dddd dddd  ................
00196620: dddd 301d 0603 551d   0e04 1604 14cc cccc  ..0...U.........
00196630: cccc cccc cccc cccc   cccc cccc cccc cccc  ................
00196640: cc30 0f06 0355 1d13   0101 ff04 0530 0301  .0...U.......0..
00196650: 01ff 300e 0603 551d   0f01 01ff 0404 0302  ..0...U.........
00196660: 02ac 3081 a006 0355   1d1f 0481 9830 8195  ..0....U.....0..
00196670: 3081 92a0 4aa0 4886   4668 7474 7073 3a2f  0...J.H.Fhttps:/
00196680: 2f74 7363 692e 696e   7465 6c2e 636f 6d2f  /tsci.intel.com/
00196690: 636f 6e74 656e 742f   4f6e 4469 6543 412f  content/OnDieCA/
001966a0: 6372 6c73 2f4f 6e44   6965 5f43 415f 4353  crls/OnDie_CA_CS
001966b0: 4d45 5f49 6e64 6972   6563 742e 6372 6ca2  ME_Indirect.crl.
001966c0: 44a4 4230 4031 2630   2406 0355 040b 0c1d  D.B0@1&0$..U....
001966d0: 4f6e 4469 6520 4341   2043 534d 4520 496e  OnDie CA CSME In
001966e0: 7465 726d 6564 6961   7465 2043 4131 1630  termediate CA1.0
001966f0: 1406 0355 0403 0c0d   7777 772e 696e 7465  ...U....www.inte
00196700: 6c2e 636f 6dff ffff   0a00 0000 4800 0000  l.com.......H...
                     ^

The first 4 bytes look like the data size (in little endian). We can quickly see that the actual data is a bit more than 0x200 bytes, so 0x01fd is just below that. A few bytes remain. But what comes next? The ASCII strings suggest that it is something about certificates, often using encodings like ASN.1. The encoding is specified in RFC5280. For example, here we have:

  • 30: sequence
  • 82: length in octets

Let us skip the first 4 bytes, and try to have openssl parse it, assuming DER:

dd if=unk30.bin bs=1 skip=4 | openssl asn1parse -inform der

Which yields:

    0:d=0  hl=4 l= 505 cons: SEQUENCE
    4:d=1  hl=2 l=   3 cons: cont [ 0 ]
    6:d=2  hl=2 l=   1 prim: INTEGER           :02
    9:d=1  hl=2 l=   1 prim: INTEGER           :01
   12:d=1  hl=2 l=  10 cons: SEQUENCE
   14:d=2  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA384
   24:d=1  hl=2 l=  26 cons: SEQUENCE
   26:d=2  hl=2 l=  24 cons: SET
   28:d=3  hl=2 l=  22 cons: SEQUENCE
   30:d=4  hl=2 l=   3 prim: OBJECT            :commonName
   35:d=4  hl=2 l=  15 prim: UTF8STRING        :CSME MCC ROM CA
   52:d=1  hl=2 l=  30 cons: SEQUENCE
   54:d=2  hl=2 l=  13 prim: UTCTIME           :201125000000Z
   69:d=2  hl=2 l=  13 prim: UTCTIME           :491231235959Z
   84:d=1  hl=2 l=  35 cons: SEQUENCE
   86:d=2  hl=2 l=  33 cons: SET
   88:d=3  hl=2 l=  31 cons: SEQUENCE
   90:d=4  hl=2 l=   3 prim: OBJECT            :commonName
   95:d=4  hl=2 l=  24 prim: UTF8STRING        :CSME MCC SVN01 Kernel CA
  121:d=1  hl=2 l= 118 cons: SEQUENCE
  123:d=2  hl=2 l=  16 cons: SEQUENCE
  125:d=3  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
  134:d=3  hl=2 l=   5 prim: OBJECT            :secp384r1
  141:d=2  hl=2 l=  98 prim: BIT STRING
  241:d=1  hl=4 l= 264 cons: cont [ 3 ]
  245:d=2  hl=4 l= 260 cons: SEQUENCE
  249:d=3  hl=2 l=  31 cons: SEQUENCE
  251:d=4  hl=2 l=   3 prim: OBJECT            :X509v3 Authority Key Identifier
  256:d=4  hl=2 l=  24 prim: OCTET STRING      [HEX DUMP]:30168014DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
  282:d=3  hl=2 l=  29 cons: SEQUENCE
  284:d=4  hl=2 l=   3 prim: OBJECT            :X509v3 Subject Key Identifier
  289:d=4  hl=2 l=  22 prim: OCTET STRING      [HEX DUMP]:0414CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
  313:d=3  hl=2 l=  15 cons: SEQUENCE
  315:d=4  hl=2 l=   3 prim: OBJECT            :X509v3 Basic Constraints
  320:d=4  hl=2 l=   1 prim: BOOLEAN           :255
  323:d=4  hl=2 l=   5 prim: OCTET STRING      [HEX DUMP]:30030101FF
  330:d=3  hl=2 l=  14 cons: SEQUENCE
  332:d=4  hl=2 l=   3 prim: OBJECT            :X509v3 Key Usage
  337:d=4  hl=2 l=   1 prim: BOOLEAN           :255
  340:d=4  hl=2 l=   4 prim: OCTET STRING      [HEX DUMP]:030202AC
  346:d=3  hl=3 l= 160 cons: SEQUENCE
  349:d=4  hl=2 l=   3 prim: OBJECT            :X509v3 CRL Distribution Points
  354:d=4  hl=3 l= 152 prim: OCTET STRING      [HEX DUMP]:308195308192A04AA048864668747470733A2F2F747363692E696E74656C2E636F6D2F636F6E74656E742F4F6E44696543412F63726C732F4F6E4469655F43415F43534D455F496E6469726563742E63726CA244A442304031263024060355040B0C1D4F6E4469652043412043534D4520496E7465726D6564696174652043413116301406035504030C0D7777772E696E74656C2E636F6D
  509:d=0  hl=5 l=   0 cons: priv [ 2097034 ]
  514:d=0  hl=2 l=   0 prim: EOC

Success! Next up, we need to find a suitable library to parse this data. Further development is omitted here.

Intel platforms

Over the years and decades, Intel has developed many hardware platforms1.

Since the 4-bit 4004 in 1971, they have progressed over 8-bit up to 64-bit systems, retaining a lot of backwards compatibility. Starting with the ICH7 based platforms, Intel introduced their AMT (Active Management Technology)2, an out-of-band management solution3 for remote provisioning and support.

AMT evolved with more features over time, carrying the vPro label for machines targeting the business market4 and finally converging with more security features such as Boot Guard5, Intel’s secure boot implementation, digital content protection (DRM), and more6.

Now running on a coprocessor called the (Converged Security and) Manageability Engine7, or (CS)ME for short, henceforth abbreviated as ME, a full second operating system of its own is backing the platform.

Boot flow

The ME has its own firmware and bootstraps an Intel platform8. The main x86 cores are held in reset until the ME releases them to boot with their own firmware.

Both the ME firmware and the main x86 firmware are stored in the same flash part on a mainboard, partitioned via the Intel Flash Descriptior (IFD).

The following diagram is based on knowledge from various sources, including the coreboot documentation on Intel.

The boot flow for trusted boot is documented publicly9 by Intel.

ME classification and security

Security researchers have analyzed the ME10 and divided hardware variants into 3 generations11 thus far, each with their own multiple firmware versions, including security patch releases12 13. One core aspect in security research has been Boot Guard14 15, which had been introduced with Haswell, Intel’s 4th generation Core series platforms16, and discussed in the coreboot community17.

Note that the ME generations roughly correspond with the overall platform, in that ranges of Intel platforms are expected to carry a certain ME hardware generation and specific platforms a certain firmware version range. For example, Lenovo ThinkPad X270 laptops came with 6th/7th gen Intel Core processors, which means 3rd generation ME hardware and version 11.x.x.x ME firmware.

Processor names

Intel publicly documents how to interpret procesor names18 and what their suffixes mean19.

Abbreviations

abbr.expansion
ACMAuthenticated Code Module
AMTActive Management Technology
CSMEConverged Security and Manageability Engine
DALDynamic Application Loader
FITFirmware Interface Table
FPTFirmware Partition Table
HAPHigh-Assurance Platform
{I,M,P}CH{I/O,Memory,Platform} Controller Hub20
IFDIntel Flash Descriptor
PTTPlatform Trust Technology
RBEROM Boot Extensions (part of ME firmware)
SPSServer Platform Services
TXETrusted Execution Engine
TXTTrusted Execution Technology

Ambiguities

There are colliding acronyms, even within this domain. The following abbreviations have a second meaning:

  • FIT: Flash Image Tool (sometimes also called FITC)
  • FPT: Flash Programming Tool

  1. https://en.wikipedia.org/wiki/List_of_Intel_processors

  2. https://en.wikipedia.org/wiki/Intel_AMT_versions

  3. https://www.amplicon-usa.com/actions/viewDoc.cfm?doc=iAMT-white-paper.pdf

  4. https://www.intel.com/content/www/us/en/architecture-and-technology/vpro/overview.html

  5. https://edc.intel.com/content/www/us/en/design/ipla/software-development-platforms/client/platforms/alder-lake-desktop/12th-generation-intel-core-processors-datasheet-volume-1-of-2/010/boot-guard-technology/

  6. https://www.intel.com/content/dam/support/us/en/documents/technologies/intel_amt_linux_enablement_guide_revision_1_1.pdf

  7. https://i.blackhat.com/USA-19/Wednesday/us-19-Hasarfaty-Behind-The-Scenes-Of-Intel-Security-And-Manageability-Engine.pdf

  8. https://www.intel.com/content/dam/www/public/us/en/security-advisory/documents/intel-csme-security-white-paper.pdf

  9. https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/resources/key-usage-in-integrated-firmware-images.html

  10. https://bitkeks.eu/blog/2017/12/the-intel-management-engine.html

  11. https://papers.put.as/papers/firmware/2014/2014-10_Breakpoint_Intel_ME_-_Two_Years_Later.pdf

  12. https://www.intel.com/content/www/us/en/support/articles/000029389/software/chipset-software.html?wapkw=csme

  13. https://www.intel.com/content/www/us/en/support/articles/000055675/technologies.html?wapkw=csme

  14. https://prohoster.info/en/blog/administrirovanie/doverennaya-zagruzka-shryodingera-intel-boot-guard

  15. https://github.com/flothrone/bootguard

  16. https://web.archive.org/web/20201129154607/https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/4th-gen-core-family-mobile-brief.pdf

  17. https://web.archive.org/web/20230322090345/https://patrick.georgi.family/2015/02/17/intel-boot-guard/

  18. https://www.intel.com/content/www/us/en/processors/processor-numbers.html

  19. https://www.intel.com/content/www/us/en/support/articles/000058567/processors/intel-core-processors.html

  20. https://en.wikipedia.org/wiki/Intel_Hub_Architecture

Knowledge on Firmware Images for Intel Platforms

The knowledge here focuses on firmware images, their partitioning and data structures.

Official resources

Intel publishes general information on firmware in their developer portal: https://www.intel.com/content/www/us/en/developer/topic-technology/firmware/overview.html Note that the public information mainly focuses on host processor firmware.

Other projects

Research

Many researchers have looked into the Intel Management Engine over the years and presented on their findings:

Forums

People keep asking in Intel’s community forum for tools and information around Intel platform firmware, resorting to third-party forums because Intel does not publish what they need or limits access to necessary resources to certain customers only, notably not end users. Here is a short list of places to find useful information and tools.

Extraction

For older FIT tools, use binwalk to extract resources and then grep for LayoutEntry to find descriptions of straps, which include the HAP bit, e.g.:

<LayoutEntry name="PCH_Strap_CSME_CSE_HAP_Mode" type="bitfield32"
    value="0x0" offset="0x68" bitfield_high="16" bitfield_low="16" />

Note that later generation XML files just call the HAP bit “reserved”. Educated guessing by looking at neighboring bits will help you to locate it.

Newer FIT tools (e.g., v18) contain Python code that can be extracted with pyinstxtractor. Relevant code is in the plugins/ directory:

pyinstxtractor.py ../mfit_18.exe
ls -l tools.exe_extracted/plugins/

Firmware images

There are multiple ways of obtaining firmware images:

  • read out from one’s own mainboard, e.g. using flashprog
  • download from a vendor; however, those are mostly upgrade images, not the same as what would be found on real hardware, usually in a proprietary format
  • download from an archive, obtain a full backup image, or similar

Full images

ChromeOS

The coreboot project offers a utility to download full recovery images for ChromeOS (Chromebooks) including a base system and firmware, and extract the firmware image: util/chromeos/crosfirmware.sh

To download all the images and extract the firmware, run: ./crosfirmware.sh all

As of the time of writing this, that will download: https://dl.google.com/dl/edgedl/chromeos/recovery/recovery.conf

Which looks somewhat like this:

recovery_tool_version=0.9.2
recovery_tool_linux_version=0.9.2
recovery_tool_update=


name=Dell Chromebook 13 (3380)
version=15393.58.0
desc=
channel=STABLE
hwidmatch=^ASUKA .*
hwid=
md5=9e3788b775f0c55f37682a6db6add00a
sha1=b54a3762e22d08dc3b67846e3ab16bd7333e519d
zipfilesize=1275561266
file=chromeos_15393.58.0_asuka_recovery_stable-channel_mp-v2.bin
filesize=2330960384
url=https://dl.google.com/dl/edgedl/chromeos/recovery/chromeos_15393.58.0_asuka_recovery_stable-channel_mp-v2.bin.zip

and so on. Each entry is about 12 lines. How much is in there?

wc recovery.conf
  9186  11369 297858 recovery.conf

More than 650 images?! … no, there are lots of duplicates. But not exactly. Some recovery images contain firmware for multiple devices!

grep url= recovery.conf | uniq | wc
    76     76   9310

A good bunch of downloads would fail, though. I reduced the script to fewer entries. Note that Chromebooks may be based on any platform, not only Intel.

How many images that you downloaded are for Intel?

for f in coreboot*.bin; intel_fw me scan $f; end 2>&1 | grep 'No ME' | wc
    19    133   1235

The remaining images can now be used to test intel_fw.

Win-Raid Forum

Many samples can be found via this forum post: https://winraid.level1techs.com/t/intel-cs-me-cs-txe-cs-sps-gsc-pmc-pchc-phy-orom-firmware-repositories/30869

Unpacking Firmware

Firmware images are typically packed and consist of various pieces henceforth called components. In different places, they may be called more specific terms, such as partitions, directories, modules, files, etc.

Many components are containers, which in turn are comprised of other things. As it happens over time, a firmware image for a platform of today may look very different from one meant for a platform from the past. It may be, however, that the target platform cannot be recognized right away, making analysis harder. Such is the case for Intel. We thus need an architecture that is able to distinguish at any given level and allows for extraction.

Partitions

The following diagram is a generic example of a partitioned firmware image with a container that may be of either one or another kind. And in turn, it would contain one or another kind of entries.

In Rust, we can use enum types to express this:

enum Container {
    AContainer(Vec<AEntry>),
    BContainer(Vec<BEntry>),
}

Intel ME Generation 2

With the second hardware generation, Intel ME based platforms have introduced a partitioning scheme called Flash Partition Table (FPT), starting with a $FPT magic. There are code and data partitions, and the main code partition is called FTPR.

Code partitions start with a manifest that holds metadata over the modules contained in the partition, as a flat directory. Those modules are in part Huffman-encoded and chunked, and the Huffman tables are part of the mask ROM.

The overall manifest format is header + signature + data. The data part lists the modules with their offsets, sizes and hashes, so that the manifest covers the whole partition’s integrity.

Intel ME Generation 3

With the third hardware generation of Intel ME based platforms, a new operating system was introduced, based on MINIX 3. It needs bootstrapping first, starting with phases called RBE (ROM Boot Extensions) and bup (bringup).

There are multiple kinds of partitions, including Code Partition Directory (CPD) partitions. Those contain executables, their corresponding metadata files, and a manifest that holds a signature over the header before it and its other data. The manifest format with the header and signature is the same as for Gen 2.

The signed data in the manifest includes hashes of the metadata files and other things, so that the manifest suffices to verify the entire CPD’s integrity. Each metadata file contains the counterpart binary’s hash. The binaries themselves are mostly compressed, commonly using LZMA and a few via Huffman encoding.

Knowledge on CPDs, manifests, metadata and binaries can be found in PT Research utilities for unpacking:

Integrated Firmware Image

A variant of ME gen 3 firmware exists based on a different layout, as described in the Atom E3900 series platform enabling guide1:

The IFWI region in SPI flash physically follows the SPI Flash Descriptor Region. It contains all platform firmware components and device firmware components.

The IFWI region is divided into two Logical Boot Partitions, which are identical in size. The Logical Boot Partition layout is defined by the Boot Partition Descriptor Table (BPDT) at the head of the Logical Boot Partition.

There are multiple IFWI data structures, and some do not have a magic to detect, so parsing them is not trivial. ME Analyzer has a lot of logic2 for them. In some cases, the FPT is located right after the IFWI.

The BPDT entries mostly point to CPDs, including the FTPR. Some BPDT entries may point to the FPT.

Samples:

  • BPDT v1: Google “Coral” Chromebook
  • BPDT v2: System76 Lemur Pro 10 (Tigerlake), Gigabyte Z5903

  1. https://cdrdv2-public.intel.com/671281/uefi-firmware-enabling-guide-for-the-intel-atom-processor-e3900-series.pdf

  2. https://github.com/platomav/MEAnalyzer/blob/aa148556bbf09e418074c3cea18255a25432fb7c/MEA.py#L11490

  3. https://www.gigabyte.com/us/Motherboard/Z590M-rev-10/support#support-dl