# AMD x86_64 Firmware - AMD Firmware Entry Table - PSP Directories - Code Entries - Data Entries - XHCI Firmware - AGESA - UEFI --- ## But why? ```graphviz digraph hierarchy { node [color=Black,fontname=Courier,shape=box] //All nodes will this shape and colour edge [color=Darkblue, style=dashed] //All the lines look like this "ASUS-Fetcher" ->Downloader "Lenovo-Fetcher" ->Downloader "ACER-Fetcher" ->Downloader "SuperMicro-Fetcher" ->Downloader "Apple-Fetcher" ->"Downloader" "MSI-Fetcher" ->Downloader Downloader->Importer "IFD-Analyser"->"ME-Analyser" "Importer"->"IFD-Analyser" "Importer"-> "Certificate-Analyser" "Importer" -> "ME-Analyser" "IFD-Analyser"->"AMD-Analyser" "IFD-Analyser"->"EFI-Analyser" "IFD-Analyser"->"MicroCode-Analyser" "EFI-Analyser" -> "FSP-Analyser" "AMD-Analyser" -> "AGESA-Analyser" } ``` ---- ### "Mimoja Firmware Toolkit" - Microservice architecture - Auto-fetch Biosupdates - Auto-unpack - Analyse - Write to elastic ---- ### Scope - Several tenthousand images - Rate Vendor qualities - Provide updates for EOL systems --- ## AMD Firmware Entry Table - PSP looks at offset `0x20000` in the flash. - Flashmapping for 16MB is 0xFF000000 - Mapping depends on Flashsize - Finds the "Firmware Entry Table" ---- ```golang type AMDFirmwareEntryTable struct { Signature uint32 ImcRomBase uint32 GecRomBase uint32 XHCRomBase uint32 PSPDirBase uint32 NewPSPDirBase uint32 BDHDirBase uint32 Unknown1 uint32 } ``` ---- ## Signature 0x55AA55AA ---- ## ImcRomBase - _AMD_IMC_C magic - AMDs embedded controler implementation - Found in most CPUs - Almost never used ---- ## GecRomBase - Gigabit ethernet - very hardware specific - ignored --- ## XHCI - Two versions - Old and new - Running on V850E1 ---- ### OLD XHCI - quoting coreboot wiki: ``` 0x0000 2 Signature 0x55aa 0x0002 2 Offset to the BCD (type0?) 0x0004 2 BCD size 0x0006 2 Offset to Main FW (type1?) 0x0008 2 Main FW size 0x000a 2 Offset to the ACD (type2?) 0x000c 2 Offset to the ACD ``` - Main FW ``` Offset Size in bytes What 0x0000 2 Firmware version - 0x3032 means 3.0.3.2 0x0002 - Firmware data, most likely V850E1 controller ``` ---- ### NEW XHCI ``` 00000000 80 07 f8 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000010 e0 07 40 01 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............| 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000040 80 07 3a 03 e0 07 40 01 00 00 00 00 00 00 00 00 |..:...@.........| 00000050 e0 07 40 01 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............| 00000060 80 07 34 01 e0 07 40 01 00 00 00 00 00 00 00 00 |..4...@.........| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000080 80 07 4a 01 e0 07 40 01 00 00 00 00 00 00 00 00 |..J...@.........| 00000090 80 07 70 01 e0 07 40 01 00 00 00 00 00 00 00 00 |..p...@.........| 000000a0 80 07 96 01 e0 07 40 01 00 00 00 00 00 00 00 00 |......@.........| 000000b0 80 07 bc 01 e0 07 40 01 00 00 00 00 00 00 00 00 |......@.........| 000000c0 80 07 e2 01 e0 07 40 01 00 00 00 00 00 00 00 00 |......@.........| 000000d0 80 07 08 02 e0 07 40 01 00 00 00 00 00 00 00 00 |......@.........| 000000e0 80 07 2e 02 e0 07 40 01 00 00 00 00 00 00 00 00 |......@.........| 000000f0 80 07 54 02 e0 07 40 01 00 08 00 10 00 18 00 20 |..T...@........ | ``` ---- ### NEW XHCI ``` .data:00000000 8007f800 jr 0x000000f8 ``` - We found ourself the vector table - reset vector first - Ghidra next? --- ## AGESA - All binary blobs are shipped as "AGESA Bundle" - Only with NDA - Format is documented - AMD Generic Encapsulated Software Architecture (AGESA™)Interface Specification for Arch2008 ---- ## AGESA ### What we have: - Binary blobs needed to boot - AGESA header ```yara rule AGESA { strings: $AMDGESA = {41 4d 44 21 47 45 53 41 ?? ?? ?? ??} $AGESA = /AGESA![0-9a-zA-Z]{0,10}\x00{0,1}[0-9a-zA-Z .\-]*/ $AAGESA = /!!AGESA[0-9a-zA-Z .\-]*/ $AMD_PI = /\$AMD[A-Z][0-9a-zA-Z]*[PIVpiv][0-9a-zA-Z.\-]*/ condition: any of them } ``` ---- ``` !!AGESABristolPI V1.0.0.1X !!AGESACarrizoFM2r2PI V1.2.0.0X !!AGESACarrizoFM2r2PI V1.2.0.2X !!AGESACarrizoFM2r2PI V1.3.0.1X !!AGESACarrizoLitePI V1.0.0.0 !!AGESACarrizoLitePI V1.0.0.1 !!AGESACarrizoLitePI V1.0.0.2 !!AGESACarrizoLitePI V1.0.0.4 !!AGESACarrizoPI V1.0.0.6 !!AGESACarrizoPI V1.0.8.0 !!AGESACarrizoPI V1.1.0.0 !!AGESA DanNiPI V0.0.9.2 !!AGESA DanNiPI V1.0.0.0 !!AGESA DanNiPI V1.0.0.1 !!AGESA DanNiPI V1.0.0.2 !!AGESA DanNiPI V1.0.0.3 !!AGESA DanNiPI V1.0.0.4 !!AGESAGodavariPI V0.0.9.1 !!AGESAGodavariPI V1.0.0.0 !!AGESAGodavariPI V1.0.0.1 !!AGESAKabiniPI V1.0.0.5 !!AGESAKabiniPI V1.0.0.6 !!AGESAKabiniPI V1.0.0.7 !!AGESAKabiniPI V1.0.0.8 !!AGESAKabiniPI V1.0.0.9 !!AGESAKabiniPI V1.0.0.A !!AGESAKabiniPI V1.0.0.B !!AGESAKabiniPI V1.1.0.0 !!AGESAKabiniPI V1.1.0.1 !!AGESAKaveriPI V0.0.6.2 !!AGESAKaveriPI V0.0.8.1 !!AGESAKaveriPI V1.0.0.0 !!AGESAKaveriPI V1.1.0.2 !!AGESAKaveriPI V1.1.0.5 !!AGESA LlanoPI V1.0.0.6 !!AGESA LlanoPI V1.1.0.0 !!AGESA LlanoPI V1.1.0.2 !!AGESA LlanoPI V1.1.0.3 !!AGESA LlanoPI V1.1.0.4 !!AGESA LlanoPI V1.1.0.5 !!AGESA LlanoPI V1.1.0.6 !!AGESA LlanoPI V1.1.0.7 !!AGESA LlanoPI V1.1.0.8 !!AGESA MarG34PIV1.1.0.4 !!AGESA MarG34PIV1.1.0.7 !!AGESAMullinsPI V1.0.0.2 !!AGESAMullinsPI V1.0.0.3 !!AGESAMullinsPI V1.0.0.4 !!AGESAMullinsPI V1.0.0.A !!AGESA Ontar2PIV1.0.0.1 !!AGESA Ontar2PIV1.0.0.2 !!AGESA Ontar2PIV1.0.0.3 !!AGESA OntaroPIV1.0.0.2 !!AGESA OntaroPIV1.0.0.3 !!AGESA OntaroPIV1.0.0.4 !!AGESA OntaroPIV1.0.9.0 !!AGESA OntaroPIV1.1.0.0 !!AGESA OntaroPIV1.1.9.0 !!AGESA OntaroPIV1.2.0.0 !!AGESA OrochiPIV0.0.7.3X !!AGESA OrochiPIV0.0.7.4 !!AGESA OrochiPIV0.0.7.5 !!AGESA OrochiPIV0.0.9.0 !!AGESA OrochiPIV0.0.9.1 !!AGESA OrochiPIV0.0.9.2 !!AGESA OrochiPIV1.1.0.0 !!AGESA OrochiPIV1.1.0.1 !!AGESA OrochiPIV1.1.0.2 !!AGESA OrochiPIV1.2.0.0 !!AGESA OrochiPIV1.2.0.1 !!AGESA OrochiPIV1.2.0.3 !!AGESA OrochiPIV1.2.0.4 !!AGESA OrochiPIV1.2.7.1 !!AGESA OrochiPIV1.2.9.0 !!AGESA OrochiPIV1.4.9.0 !!AGESA OrochiPIV1.5.0.0 !!AGESA OrochiPIV1.5.0.1 !!AGESA OrochiPIV1.5.0.2 !!AGESA OrochiPIV1.5.0.5 !!AGESA OrochiPIV1.5.0.7 !!AGESA OrochiPIV1.5.0.8 !!AGESARichlandPI V1.1.0.1 !!AGESARichlandPI V1.1.0.2 !!AGESAStoneyPI V1.0.0.2 !!AGESAStoneyPI V1.3.0.2 !!AGESAStoneyPI V1.3.0.3 !!AGESAStoneyPI V1.3.0.6 !!AGESAStoneyPI V1.3.0.8 !!AGESAStoneyPI V1.3.0.9 !!AGESAStoneyPI V1.3.0.A !!AGESA TrinyPI V1.1.0.2 !!AGESA TrinyPI V1.1.0.3 !!AGESA TrinyPI V1.1.0.5 !!AGESA TrinyPI V1.1.0.7 !!AGESA TrinyPI V1.1.0.8 !!AGESA V3.1.1.0 !!AGESA V3.1.3.0 !!AGESA V3.1.3.1 !!AGESA V3.1.4.0 !!AGESA V3.1.5.0 !!AGESA V3.1.6.0 !!AGESA V3.1.7.0 !!AGESA V3.1.8.0 !!AGESA V3.1.9.0 !!AGESA V3.1.9.1 !!AGESA V3.2.7.2 !!AGESA V3.3.0.0 !!AGESA V3.3.1.0 !!AGESA V3.3.2.0 !!AGESA V3.3.2.2 !!AGESA V3.3.2.3 !!AGESA V3.3.2.4 !!AGESA V3.3.2.5 !!AGESA V3.3.2.7 !!AGESA V3.5.0.0 !!AGESA V3.5.0.1 !!AGESA V3.5.0.2 !!AGESA V3.5.2.0 !!AGESA V3.5.2.1 !!AGESA V3.5.3.1 !!AGESA V3.5.4.0 !!AGESA V3.5.5.0 !!AGESA V3.6.9.0 !!AGESA V3.7.0.0 !!AGESA V3.7.0.1 !!AGESA V3.7.1.0 !!AGESA V3.7.1.1 !!AGESA V4.1.0.3 !!AGESA V4.3.0.0 !!AGESA V4.4.0.0 !!AGESA V4.6.0.1 !!AGESA V4.6.1.0 !!AGESA V6.0.9.0 !!AGESA V6.1.0.0 !!AGESA V6.1.1.0 !!AGESA V6.1.2.0 !!AGESA V6.1.2.2 !!AGESA V6.1.5.0 AGESA!V9\x00NaplesPI-SP3 1.0.0.9 AGESA!V9\x00NaplesPI-SP3 1.0.0.A AGESA!V9\x00NaplesPI-SP3 1.0.0.B AGESA!V9\x00PinnaclePI-AM4 1.0.0.0a AGESA!V9\x00PinnaclePI-AM4 1.0.0.2 AGESA!V9\x00PinnaclePI-AM4 1.0.0.3 AGESA!V9\x00PinnaclePI-AM4 1.0.0.6 AGESA!V9\x00RavenPI-FP5-AM4 1.0.7.1 AGESA!V9\x00RavenPI-FP5-AM4 1.1.0.2 AGESA!V9\x00RavenPI-FP5-AM4 1.1.0.5 AGESA!V9\x00SummitPI-AM4 1.0.0.4a AGESA!V9\x00SummitPI-AM4 1.0.0.6 AGESA!V9\x00SummitPI-SP3r2-1.1.0.1 AGESA!V9\x00SummitPI-SP3r2-1.1.0.2 AGESA!V9\x00ThreadRipperPI-SP3r2-0.0.6.0 AGESA!V9\x00UnkownPI 0.0.0.0 !!AGESA X3.5.2.0 !!AGESA X4.3.9.0 !!AGESA X4.4.0.0 !!AGESA X4.6.1.0 ``` ---- ### Rage <blockquote class="twitter-tweet" style="width: 100%;" data-lang="de"><p lang="en" dir="ltr">Lenovo did not update their AGESA on their Thinkpad A285.<br>Still on 1.0.0.4, while 1.1.0.5 is in the wild since at least September 4th 2018. (Acer Aspire TC-380)<br><br>Over a year before release(December 2017) ASUS shipped the 1.0.7.1 update.<br><br>Lenovo released with a 2 year old AGESA... </p>&mdash; Mimoja (◕ᴗ◕✿) (@WingsOfMimoja)</a></blockquote> --- ## PSP - AMDs security processor - Boots before the main system - Most of the time - Is required to boot - Most of the time - Only runs signed code - Most of the time ---- ### Boot Process ![](https://4.bp.blogspot.com/-G2jIAokGNB8/WusHOkog9-I/AAAAAAAAACc/XXw3DKgL8PAlE4pqUmel4B40kwwpClfXgCLcBGAs/s1600/img1.png) --- #### Overview ``` Type GUID/Name Size BIOS 0x1000000 BIOS Pad 0x40000 FV 8C8CE578-8A3D-4F1C-9935-896185C32DD3 0x20000 BIOS Pad 0x5b0000 FV 8C8CE578-8A3D-4F1C-9935-896185C32DD3 0x40000 FV 8C8CE578-8A3D-4F1C-9935-896185C32DD3 0x6b0000 FV 8C8CE578-8A3D-4F1C-9935-896185C32DD3 0x300000 ``` --- ## PSP Directories - Found at PSPDirBase and/or NewPSPDirBase ``` PSPDirBase uint32 NewPSPDirBase uint32 BDHDirBase uint32 ``` - BDH is build similiar with different magic values - ignored - Starts with $PSPCOOCKIE ---- ## PSP Header ```golang type AMDPSPDirectoryHeader struct { PspCookie [4]byte Checksum uint32 TotalEntries uint32 Reserved uint32 } ``` - $PSP - 2PSP - Only two entries - Two pointer to $PSP directories ---- ## PSP Entries - $TotalEntries entries ```golang type AMDPSPDirectoryBinaryEntry struct { Type uint32 Size uint32 Location uint32 Reserved uint32 } ``` ---- ## PSP Entry Type - Type - duh - Credit@TU Berlin ```golang var AMDPSPDirectoryEntries = []AMDPSPDirectoryEntryType{ {0x00, "AMD_PUBLIC_KEY", "AMD public key"}, {0x01, "PSP_FW_BOOT_LOADER", "PSP boot loader in SPI space"}, {0x02, "PSP_FW_TRUSTED_OS", "PSP Firmware region in SPI space"}, {0x03, "PSP_FW_RECOVERY_BOOT_LOADER", "PSP recovery region"}, {0x04, "PSP_NV_DATA", "PSP data region in SPI space"}, {0x05, "BIOS_PUBLIC_KEY", "BIOS public key stored in SPI space"}, {0x06, "BIOS_RTM_FIRMWARE", "BIOS RTM code (PEI volume) in SPI space"}, {0x07, "BIOS_RTM_SIGNATURE", "Signed BIOS RTM hash stored in SPI space"}, {0x08, "SMU_OFFCHIP_FW", "SMU image"}, {0x09, "AMD_SEC_DBG_PUBLIC_KEY", "Secure Unlock Public key"}, {0x0A, "OEM_PSP_FW_PUBLIC_KEY", "Optional public part of the OEM PSP Firmware"}, {0x0B, "AMD_SOFT_FUSE_CHAIN_01", "64bit PSP Soft Fuse Chain"}, {0x0C, "PSP_BOOT_TIME_TRUSTLETS", "Boot-loaded trustlet binaries"}, {0x0D, "PSP_BOOT_TIME_TRUSTLETS_KEY", "Key of the boot-loaded trustlet binaries"}, {0x10, "PSP_AGESA_RESUME_FW", "PSP Agsa-Resume-Firmware"}, {0x12, "SMU_OFF_CHIP_FW_2", "Secondary SMU image"}, {0x14, "!PSP_MCLF_TRUSTLETS", "very similiar to ~PspTrustlets.bin~ in coreboot blobs"}, {0x1A, "PSP_S3_NV_DATA", "S3 Data Blob"}, {0x31, "{0x31~ABL_ARM_CODE~", "a _lot_ of strings and also some ARM code"}, {0x38, "!PSP_ENCRYPTED_NV_DATA", ""}, {0x39, "!SEV_APP", ""}, {0x40, "!PL2_SECONDARY_DIRECTORY", ""}, {0x5f, "FW_PSP_SMUSCS", "Software AppConfiguration Settings Data Block"}, {0x60, "FW_IMC", ""}, {0x61, "FW_GEC", ""}, {0x62, "FW_XHCI", ""}, {0x63, "FW_INVALID", ""}, {0x70, "!BL2_SECONDARY_DIRECTORY", ""}, {0x108, "PSP_SMU_FN_FIRMWARE", ""}, {0x112, "!SMU_OFF_CHIP_FW_3", "seems to tbe a tertiary SMU image"}, {0x118, "PSP_SMU_FN_FIRMWARE2", ""}, {0x15f, "!FW_PSP_SMUSCS_2", "seems to be a secondary FW_PSP_SMUSCS"}, {0x30062, "{0x30062~UEFI-IMAGE~", ""}, } ``` ---- ``` +-----------+---------+---------+-------+---------------------+ | Directory | Addr | Type | Magic | Secondary Directory | +-----------+---------+---------+-------+---------------------+ | 2 | 0xd1000 | PSP_NEW | $PSP | 0x261000 | +-----------+---------+---------+-------+---------------------+ +---+-------+----------+---------+------------------------------------+-----------+-----------------------+------------+ | | Entry | Address | Size | Type (Magic) | Version | Signed by | Info | +---+-------+----------+---------+------------------------------------+-----------+-----------------------+------------+ | | 0 | 0xd1400 | 0x240 | AMD_PUBLIC_KEY | | AMD_PUBLIC_KEY | pubkey | | | | | | | | [not verified] | | | | 1 | 0x261400 | 0x20000 | PSP_FW_BOOT_LOADER ($PS1) | 0.9.3.34 | AMD_PUBLIC_KEY | | | | | | | | | [not verified] | | | | 2 | 0xd1700 | 0xbb40 | PSP_FW_RECOVERY_BOOT_LOADER ($PS1) | FF.9.3.34 | AMD_PUBLIC_KEY | | | | | | | | | [not verified] | | | | 3 | 0xdd300 | 0x1d300 | SMU_OFFCHIP_FW (SMUR) | 0.19.4D.0 | AMD_PUBLIC_KEY | compressed | | | | | | | | [not verified] | | | | 4 | 0xfa600 | 0x340 | OEM_PSP_FW_PUBLIC_KEY | | AMD_PUBLIC_KEY | pubkey | | | | | | | | [not verified] | | | | 5 | 0xfaa00 | 0x2740 | SMU_OFF_CHIP_FW_2 (SMUR) | 0.19.4D.0 | AMD_PUBLIC_KEY | compressed | | | | | | | | [not verified] | | | | 6 | 0xfd200 | 0x10 | 0x21 | | | | | | 7 | 0xfd300 | 0x4d0 | 0x30 (0BAR) | 17.5.15.1 | OEM_PSP_FW_PUBLIC_KEY | compressed | | | | | | | | [not verified] | | | | 8 | 0xfd800 | 0xbac0 | 0x31~ABL_ARM_CODE~ (AR1B) | 17.5.15.1 | OEM_PSP_FW_PUBLIC_KEY | compressed | | | | | | | | [not verified] | | | | 9 | 0x109300 | 0x96d0 | 0x32 (AR2B) | 17.5.15.1 | OEM_PSP_FW_PUBLIC_KEY | compressed | | | | | | | | [not verified] | | | | 10 | 0x112a00 | 0xd610 | 0x33 (AR3B) | 17.5.15.1 | OEM_PSP_FW_PUBLIC_KEY | compressed | | | | | | | | [not verified] | | | | 11 | 0x120100 | 0x9960 | 0x34 (AR4B) | 17.5.15.1 | OEM_PSP_FW_PUBLIC_KEY | compressed | | | | | | | | [not verified] | | | | 12 | 0x129b00 | 0xe800 | 0x35 (AR5B) | 17.5.15.1 | OEM_PSP_FW_PUBLIC_KEY | compressed | | | | | | | | [not verified] | | | | 13 | 0x138300 | 0xa7c0 | 0x36 (AR6B) | 17.5.15.1 | OEM_PSP_FW_PUBLIC_KEY | compressed | | | | | | | | [not verified] | | | | 14 | 0x142b00 | 0xb90 | 0x24 ($PS1) | 0.7.0.1 | AMD_PUBLIC_KEY | compressed | | | | | | | | [not verified] | | | | 15 | 0x261000 | 0x400 | !PL2_SECONDARY_DIRECTORY | | | | +---+-------+----------+---------+------------------------------------+-----------+-----------------------+------------+ ``` ---- ## And now? - Understand Chain of Trust - Directory starts with public key - Bootloader next - Was encrypted end of 2018 - New 0x21 Type: "Encrypted Key" - AES ---- ![](https://1.bp.blogspot.com/-euM-RJEmMVU/WusK5zvEUgI/AAAAAAAAADg/1cXJuaq9Cfw0iIDjWGPk-TkpD5jfmnB2QCLcBGAs/s1600/AES_vertical.jpg) ---- ![](https://2.bp.blogspot.com/-UzBO84jaTc0/WusIaJ__46I/AAAAAAAAAC8/PvYg1MXg-ycptjkwfQRwD9Bpt4hBseL_gCLcBGAs/s1600/img6.png) ---- ## Data Entries - Undocumented 0x100 Byte header - Partly reverse engeneeried - Signed ---- Header is verified ```go type AMDPSPEntryBinaryHeader struct { Unknown1 [16]byte ID uint32 SizeSigned uint32 Unknown2 [0x18]byte AlwaysOne uint32 // Could be a type? Unknown3 [4]byte SigFingerprint [16]byte IsCompressed uint32 Unknown4 uint32 FullSize uint32 Unknown5 [12]byte Version [4]byte Unknown6 [4]byte Unknown7 [4]byte SizePacked uint32 } ``` ---- <!-- .slide: data-background="http://i.giphy.com/90F8aUepslB84.gif" --> ## ... Data was not! -> Ryzenfall ---
{"slideOptions":{"transition":"slide"}}