New adventure: Porting MSI PRO B850-P to coreboot

Introduction

This new blog post describes the progress of the first phases of enabling AMD AM5 Phoenix support in coreboot and porting MSI PRO B850-P. The effort is a continuation of the Gigabyte MZ33-AR1 porting project, and is also funded by NLnet Foundation.

The project was inspired by AMD’s efforts to bring open-source firmware for their most recent CPUs. Initially, the target was set for Phoenix CPUs and desktops, however, AMD published their CPU initialization code for AMD Turin server processor family on GitHub much earlier than for Phoenix processors. That fact forced a slight change in the plans, putting a server board as a first priority. What goes up must come down (or vice versa in this case)? Turin server support was still a good stepping stone and a solid base for the desktop parts, providing knowledge, experience, and insights into AMD silicon initialization, which can be used now to enable more boards in open-source firmware. Of course, this is not the end of efforts related to Gigabyte MZ33-AR1. See our latest achievements showcasing SEV-SNP.

For those who don’t know, the OpenSIL is a new initiative to unify the silicon initialization for the AMD platform across multiple firmware frameworks, like EDK2 and coreboot. Following the successful integration of Genoa Proof of Concept in coreboot (and now even Turin Proof of Concept), we are continuing the growth of AMD OpenSIL adoption dominance in coreboot.

In case you haven’t read the blog posts about Gigabyte MZ33-AR1, we encourage you to do so, because a lot of terms and the thinking process will not be repeated or explained again in the new blog post series. Instead, we will rely on the techniques and knowledge shared in the previous posts, and only describe what is new or different for Phoenix.

As usual, the project is divided into a couple of phases/tasks with milestones. We will run through the following milestones in this post:

  1. Task 1. Tools:

    • Milestone a. Improve PSPTool to reliably parse AMD combo UEFI images

      The effort focuses on contributing improvements to PSPTool to reliably parse AMD combo UEFI images. The AMD UEFI images for client (desktop and mobile) platforms are quite significantly different from server images. The combo images can support more than 2 processor families, which makes the firmware structures even more complicated and difficult to parse. The goal is to enable analysis of the AMD platforms firmware to determine if the platform can potentially be fused to vendor keys, similarly to the previous phase. But also it is necessary for the AMD UEFI image analysis and a proper coreboot image construction to obtain a bootable build.

  2. Task 2. Just enough to boot:

    • Milestone a. Extend Phoenix SoC in coreboot to support AM5 platforms

      Currently, there is mobile Phoenix support in coreboot with initialization done by AMD FSP. Also, there is a stub implementation for Phoenix OpenSIL that does nothing. This milestone will add basic support for desktop AM5 Phoenix platform to distinguish mobile CPUs from desktop CPUs in coreboot. This will serve as a base to cover the differences between the mobile and desktop Phoenix SoC.

    • Milestone b. MSI PRO B850-P mainboard structure

      Add mainboard/msi/ms-7e56 (MS-7E56 is the baseboard part number of MSI PRO B850-P), wire it to the new Phoenix AM5 SoC options, enable serial console, and confirm the bootblock executes on hardware. Reuse the Nuvoton NCT6687 Super I/O driver for the serial console. The coreboot image may replace the vendor BIOS parts that are copied to RAM by PSP.

  3. Task 3. AM5 Phoenix blobs integration

    • Milestone a. Phoenix AM5 PSP firmware package

      Extend the amdfwtool to stitch the Phoenix AM5 PSP blobs properly using combo directory. Use the AMD PSP BIOS Integration Guide to provide necessary extensions to Phoenix SoC image stitching. Create a proper fw.cfg file in the Phoenix SoC structure. The goal is for the amdfwtool to be able to produce a functional firmware image from the blobs available in Combo AM5 Platform Initialization Package.

  4. Task 4. Hardware-topology discovery

    • Milestone a. USB connector map

      Enumerate every USB-A/C header with lsusb and document controller-to-connector mapping.

    • Milestone b. SATA connector map

      Attach drives to each SATA port, record port numbers from dmesg, and create a definitive mapping table.

    • Milestone c. PCIe lane map

      Use AMDXIO to correlate root-port numbers with slots and create a definitive mapping table.

  5. Task 7. Platform-feature enablement

    • Milestone b. Super I/O initialization

      Initialize the NUVOTON NCT6687-R chip by providing mainboard-specific settings for NCT6687 driver in coreboot. The goal is to provide sensor reading and fan control.

Let’s run through each of them and explain what was done to fulfill the goals.

Improve PSPTool to reliably parse AMD combo UEFI images

After the initial work on PSPTool during the Turin project, the tool was able to correctly parse most images available in the PSPTool testing pool. However, some issues may arise when parsing combo images for AM5 desktop platforms. The desktop images are more complex than server ones. A single PSP directory may support multiple CPU families, whereas on servers, each CPU family required separate PSP directory. This adds complexity, a need to distinguish PSP directories from each other, and determine the supported CPUs by given directory. But first things first:

  1. Reliability of parsing. The simplest test: parse vendor BIOS image from our target board:

    1
    
    psptool -E 7E56v2A75/E7E56AMSI.2A75
    

    Results contained some ParseErrors for types that do not have a PSP file header. The following PRs have fixed those:

  2. Exposing PSP IDs that indicate supported processor families. Based on coreboot’s amdfwtool sources, the PSPTool has been extended to report PSP IDs and Zen generations in the combo directories with ISH structures. Thanks to that, we could determine the directory from which we needed to extract the APCB files for Phoenix CPUs.

The final result of vendor BIOS parsing can be found here.

The above pull request concludes the planned effort to improve the PSPTool, fulfilling the milestone:

  • Task 1. Tools - Milestone a. Improve PSPTool to reliably parse AMD combo UEFI images

Just enough to boot

“Just enough to boot” is most likely the best way to start the firmware development. As soon as the first signs of life are seen on the debug interface, debugging gets easier, and moving forward is less troublesome. However, these steps may sometimes require a lot of work. Unlike Intel systems, where you just need to extract ME and flash descriptor to run coreboot, for AMD systems we have to integrate all PSP blobs properly first to make coreboot run.

The same techniques were used to inject the coreboot image into the vendor BIOS, as we did with Gigabyte MZ33-AR1 in this post The injection worked like a charm, but we also got the PSP firmware package working already. So, in favor of clean and working implementation, the hacky configuration for coreboot image injection into the vendor BIOS has not been kept. More about the PSP firmware package later, let’s focus on the changes required to build and boot the platform.

Phoenix SoC changes for AM5

Typical standard process of adding a SoC variant is to go through the processor documentation and compare the existing code against it. Sometimes the register definitions may be different between desktops and mobile processors (especially on Intel systems).

After thoroughly investigating existing Phoenix SoC sources, the changes added for AM5 are present in this commit in pull request.

What has changed are the CPUIDs, APOB size (which drastically modifies the program memory layout looks like, thus changes in ROMSTAGE_ADDR and VERSTAGE_ADDR were made), and PCIe bridges.

The above commit in pull request concludes the effort of the following milestone:

  • Task 2. Just enough to boot - Milestone a. Extend Phoenix SoC in coreboot to support AM5 platforms

Mainboard structure

It’s the core needed to build any image in coreboot. A mainboard target, even minimal, is crucial to start building and testing, even in upstream coreboot gerrit as done by Jenkins. The following commit adds the minimal mainboard code, including Super I/O initialization (which I will talk about in the next chapter). Let’s break down the changes:

  • Kconfig it is mainly based on Intel Z790-P for SMBIOS values and MAD Birman board for AMD-specific board setting. What has been added is: MEMORY_MAPPED_TPM (because our board supports discrete TPM over SPI), SUPERIO_NUVOTON_NCT6687D for Super I/O, HAVE_X86_64_SUPPORT and USE_X86_64_SUPPORT for 64-bit coreboot support, required to get 32MiB ROMs working properly.

    Besides that, we have EFS and speed settings that replicate vendor BIOS settings as seen by coreboot’s amdfwtool when dumping the image:

    1
    
    ./util/amdfwtool -d 7E56v2A75/E7E56AMSI.2A75
    

    CPU_PT_ROM_MAP_GB set to 1024 instructs coreboot to create page tables to map a total of 1TiB of memory. It has to be at least 1TiB, because flash bigger than 16MiB is mapped at address 0xfd00000000, which is higher than 4GiB addressable memory in 32bit mode (thus we needed USE_X86_64_SUPPORT) and higher than the default value for this option (512 GiB, not big enough to cover the address in page tables). We also select SPI_FLASH_FORCE_4_BYTE_ADDR_MODE to avoid flash access problems. Lessons learned from the Turin work!

  • data*.apcb these are the APCB files extracted from Phoenix PSP BIOS directory. If you look at the output from PSPTool, this is the directory 4 with PSP ID 0xbc0d0400 (you can verify this ID in amdfwtool). To extract these blobs, we needed to invoke the following command:

    1
    
    psptool -X -d 4 -o 7e56_blobs 7E56v2A75/E7E56AMSI.2A75
    

    Then move the files:

    1
    2
    3
    
    cp 7e56_blobs/d00_e01_APCB~0x60  <coreboot>/src/mainboard/msi/ms7e56/data.pacb
    cp 7e56_blobs/d00_e00_APCB_COPY~0x68  <coreboot>/src/mainboard/msi/ms7e56/data_rec.pacb
    cp 7e56_blobs/d00_e02_APCB_COPY~0x68_SUB_0x0_INS_0x8  <coreboot>/src/mainboard/msi/ms7e56/data_rec68.pacb
    

    And hook them up in Makefile.mk:

    1
    2
    3
    4
    5
    6
    7
    
    ifneq ($(wildcard $(src)/mainboard/$(MAINBOARDDIR)/data*.apcb),)
    APCB_SOURCES = $(src)/mainboard/$(MAINBOARDDIR)/data.apcb
    APCB_SOURCES_RECOVERY = $(src)/mainboard/$(MAINBOARDDIR)/data_rec.apcb
    APCB_SOURCES_68 = $(src)/mainboard/$(MAINBOARDDIR)/data_rec68.apcb
    else
    show_notices:: warn_no_apcb
    endif
    
  • bootblock.c handles the early initialization of the debug interface and basic GPIOs (definitions in early_gpio.c, also based on Birman board, but with TPM IRQ pin commented out). The early Super I/O initialization for the debug interface is based on MSI Z690-A/Z790-P with values adapted to the B850-P specific needs. Those values are taken from the HCL report we took before starting the development, precisely the log from superiotool, which can be found here.

  • mainboard.c mainly describes the interrupt routing for integrated chipset devices and PIC/IOAPIC IRQs. The settings are based on the log from the amdtool, which we developed in the Turin project. The output can be found here (look at the IRQ routing section specifically). The tool basically prints us the settings we need to put in coreboot.

  • devicetree.cb contains AMD Birman board structure stripped from PCIe port descriptors and any other Birman-specific settings. The espi_config was updated to match vendor BIOS, see the ESPI section in the amdtool log, e.g.: the following ranges map to the first four I/O windows (the second one is unused)

    1
    2
    3
    4
    5
    6
    7
    8
    
    0x0044: 0x03f0     (IO_BASE[0])
    0x0046: 0x0000     (IO_BASE[1])
    0x0048: 0x004e     (IO_BASE[2])
    0x004a: 0x0a00     (IO_BASE[3])
    0x004c: 0x0f       (IO_SIZE[0])
    0x004d: 0x00       (IO_SIZE[1])
    0x004e: 0x02       (IO_SIZE[2])
    0x004f: 0xff       (IO_SIZE[3])
    

    The above translates to:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    .generic_io_range[0] = {
      .base = 0x3f0,
      .size = 16,
    },
    // I/O range 1 not programmed
    .generic_io_range[2] = {
      .base = 0x4e,
      .size = 2,
    },
    .generic_io_range[3] = {
      .base = 0xa00,
      .size = 256,
    },
    

    Next ranges are derived from IO_BASE/IO_SIZE[4-6] register pair present in the log. Another thing added is the TPM device in the lpc_bridge scope, so that coreboot will generate appropriate ACPI code for the discrete SPI TPM. There is also the nct6687d configuration, which I will talk about in more detail in next chapter.

Phoenix PSP firmware package

With all the lessons learned from the Turin PSP blob integration and the fact that there are no public blobs for Phoenix AM5 processors on the AMD’s repository on the day of writing this post, we went straight into the integration of the newest PSP firmware blobs from the AMD’s Platform Initialization package for AM5 processors. The configuration file required to integrate the PSP blobs has been prepared and can be found here. Currently, it is hosted with all blobs on a private repository in 3mdeb’s git, and we are discussing with AMD the terms on which we can publish the blobs and let them be used to build coreboot images for both Turin and Phoenix processors. So stay tuned for the updates!

Simply creating the PSP firmware configuration file was not enough to make the PSP release the CPU from the reset vector. To investigate the possible reasons, a thorough inspection of the vendor BIOS was necessary. To achieve that, we have extended the parsing and dumping capabilities of coreboot’s amdfwtool. Since the BIOSes supporting multiple processor families often include multiple copies or pointers to the same blobs from the same processor families, it was necessary to skip the error path and allow the tool to process duplicated PSP directories. Also, these pointers to directories are wrapped into an ISH structure. The ISH contains the pointer to the PSP level 2 directory and PSP IDs the given directory supports (which is equivalent to the processor family). So to get a grasp of what the ISH contains, the commit also adds dumping its contents.

Now we are able to get a full view of the PSP directories and their settings on vendor BIOS image:

1
./util/amdfwtool -d --ro-list 7E56v2A75/E7E56AMSI.2A75

Full dump available here. Taking the same dump on the non-working coreboot build resulted in a couple details that were different when compared to the vendor BIOS. The most important one was the fact that all level 1 directories had the address mode 1 (which means relative to BIOS flash address, AMD_ADDR_REL_BIOS in the tool’s sources) and all level 2 directories had address mode 2 (which means relative to table/directory, AMD_ADDR_REL_TAB in the tool’s sources) on vendor BIOS. While our first coreboot builds were setting address mode 2 for all directories. So we fixed it immediately in this commit from pull request.

There were also other things necessary to be fixed or added, because coreboot does not support any modern AMD desktops (yet, we are implementing it now), like:

  1. New types of PSP firmwares:

  2. Fix for checking offsets

With these changes, the coreboot build system was able to produce a bootable image. The results are presented in the next section. This concludes the efforts related to PSP firmware package milestone.

Results

Finally, when all the bits and pieces are glued together, we can build the image and try to boot the platform. While the coreboot injection method worked right at first try, we had a couple of failures when trying to boot with PSP blobs integrated by the coreboot build system, until we fixed it. And these are the first signs of life from coreboot on MSI PRO B850-P when the PSP blobs are integrated by the coreboot build system:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
[NOTE ]  coreboot-25.06-1751-g6ed532f2b691-dirty Thu Jan 22 20:34:16 UTC 2026 x86_64 bootblock starting (log level: 8)...
[DEBUG]  Family_Model: 00a70f52
[INFO ]  Set power off after power failure.
[DEBUG]  PMxC0 STATUS: 0x10800 UserRst BIT11
[DEBUG]  SPI normal read speed: 33.33 MHz
[DEBUG]  SPI fast read speed: 66.66 Mhz
[DEBUG]  SPI alt read speed: 66.66 Mhz
[DEBUG]  SPI TPM read speed: 16.66 MHz
[DEBUG]  SPI100: Enabled
[DEBUG]  SPI Read Mode: Quad IO (1-4-4)
[DEBUG]  SPI ROM mapping: 0-1-2-3
[DEBUG]  Starting cbfs_boot_device
[DEBUG]  Starting cbfs_boot_device
[DEBUG]  FMAP: Found "FLASH" version 1.1 at 0x1e1f000.
[DEBUG]  FMAP: base = 0x0 size = 0x2000000 #areas = 6
[DEBUG]  FMAP: area COREBOOT found @ 0 (31584256 bytes)
[INFO ]  Booting from COREBOOT region
[INFO ]  CBFS: mcache @0x02101200 built for 12 files, used 0x280 of 0x4000 bytes
[INFO ]  CBFS: Found 'fallback/romstage' @0x2c80 size 0x4cbf in mcache @0x0210128c
[DEBUG]  BS: bootblock times (exec / console): total (unknown) / 434 ms


[NOTE ]  coreboot-25.06-1751-g6ed532f2b691-dirty Thu Jan 22 20:34:16 UTC 2026 x86_64 romstage starting (log level: 8)...
[INFO ]  GPIO Control Switch: 0xff000000, Wake Stat 0: 0x00000000, Wake Stat 1: 0x00000000
[DEBUG]  TOM1: 0xc0000000
[NOTE ]  openSIL stub: opensil_get_low_usable_dram_address returns c0000000
[DEBUG]  CBMEM:
[DEBUG]  IMD: root @ 0xbf7ff000 254 entries.
[DEBUG]  IMD: root @ 0xbf7fec00 62 entries.
[DEBUG]  Starting cbfs_boot_device
[DEBUG]  FMAP: area COREBOOT found @ 0 (31584256 bytes)
[INFO ]  ROM2 Decode Window: SPI flash base=0x0, Host base=0xff000000, Size=0x1000000
[INFO ]  ROM3 Decode Window: SPI flash base=0x1000000, Host base=0xfd01000000, Size=0x1000000
[INFO ]  Booting from COREBOOT region
[DEBUG]  Starting cbfs_boot_device
[INFO ]  CBFS: Found 'fallback/ramstage' @0x5af000 size 0x1d237 in mcache @0x021013ec
[DEBUG]  Loading module at 0xbf66d000 with entry 0xbf66d000. filesize: 0x4e1b0 memsize: 0x16fce8
[DEBUG]  Processing 9865 relocs. Offset value of 0x9f66d000
[DEBUG]  BS: romstage times (exec / console): total (unknown) / 137 ms


[NOTE ]  coreboot-25.06-1751-g6ed532f2b691-dirty Thu Jan 22 20:34:16 UTC 2026 x86_64 ramstage starting (log level: 8)...
[INFO ]  Reserved BERT region base: 0xbf668000, size: 0x4000
[DEBUG]  BS: BS_PRE_DEVICE exit times (exec / console): 0 / 7 ms
[NOTE ]  openSIL stub: setup_opensil
...

It went pretty far, up to the CPU initialization in ramstage, where it halted (full log available here), because the other CPU cores did not respond to startup requests. It is expected at the current stage of development, because we haven’t even run OpenSIL yet! The current build uses OpenSIL stub, an empty implementation that does nothing but allows build testing of OpenSIL common drivers in coreboot. Before the other cores can be started by coreboot, OpenSIL has to wake them with a proper System Management Unit (SMU) command. But that’s a story for later.

The log above proves that the Task 2. Just enough to boot, has been fulfilled with all its milestones:

  • Milestone a. Extend Phoenix SoC in coreboot to support AM5 platforms
  • Milestone b. MSI PRO B850-P mainboard structure

Also, it proves that the PSP firmwares have been properly prepared and the Task 3. AM5 Phoenix blobs integration, Milestone a. Phoenix AM5 PSP firmware package can be considered fulfilled.

Super I/O initialization

Adding Super I/O initialization is not that complicated if one has a supported chip driver in coreboot already. Especially if there are existing boards from the same vendor using the same chip. The NCT6687D settings for MSI PRO B850-P are not much different from MSI PRO Z690-A/Z90-P. However, it must be noted that MSI PRO B850-P is a board for AMD processors, so probing the CPU temperature will definitely be different.

The overall process of porting the board-specific configuration of Super I/O consists of moving the register values from superiotool log. to the board’s devicetree in coreboot, so that after the coreboot driver programs the registers, they will look pretty much the same as on the vendor BIOS. The definitions of the registers can be found in NCT6687D driver directory in coreboot. Now matching it against the EC pages gives us the configuration we need. For example, the sensor configuration registers are on EC page 1 offset 0xa0: SENSOR_CFG_REG(x) EC_PAGE_REG(1, 0xa0 + (x)). If we look at the dump of EC page 1:

1
2
3
4
5
6
7
8
9
Page 1:

00: 18 00 1a 00 16 00 1a 00 00 00 00 00 00 00 00 00
...
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
a0: 46 82 89 8c 80 80 00 00 00 00 00 00 00 00 00 00
b0: e6 e7 e8 e9 ea 6b 6c ed 60 61 62 63 64 65 00 09
c0: a1 a3 ab ad 20 20 20 20 20 20 20 20 b8 b8 b8 b8
...

We can see that the first sensor configuration register has a value of 0x46. We have to match that value with the sensor type in the chip.h file, which is AMD_TSI_ADDRESS_0x98. It means the first sensor is the CPU temperature sensor using the AMD SB-TSI, and we can put it in the board’s devicetree:

1
2
chip superio/nuvoton/nct6687d
    register "sensors[0]" = "AMD_TSI_ADDRESS_0x98"

Then we repeat the process for all 32 available sensor registers. There are a couple of things to consider here, too. Some sensor configuration registers have the FILTER_EN field set (bit 7th, the sensor type is actually only 7-bit long). Furthermore, the NCt6687d support was mainly validated on Intel platforms, so SB-TSI was not implemented. However, now that we have a board that configures the AMD SB-TSI sensor, we were able to write proper code to support it. This and the FITLER_EN settings were added in this commit from the pull request. Enabling the filter on a sensor is done by specifying a boolean value of true for given sensor in board’s devicetree, like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
register "sensor_filter_en[1]" = "true"
register "sensor_filter_en[2]" = "true"
register "sensor_filter_en[3]" = "true"
register "sensor_filter_en[4]" = "true"
register "sensor_filter_en[5]" = "true"
register "sensor_filter_en[16]" = "true"
register "sensor_filter_en[17]" = "true"
register "sensor_filter_en[18]" = "true"
register "sensor_filter_en[19]" = "true"
register "sensor_filter_en[20]" = "true"
register "sensor_filter_en[23]" = "true"

Compared to the Intel MSI boards, the fan configuration was pretty much the same, so the configuration has been copied from the Intel Z790-P board and reducing the number of fans to 6 (CPU_FAN, PUMP_FAN and 4 SYS_FANs, as per board’s manual). There were also slight differences in the SMBus sensor configuration, which has been matched against the content of EC page 4 (SMBUS sensor configuration page) from the superiotool log.

This concludes the Super I/O initialization and fulfills the planned work for the Task 7. Platform-feature enablement - Milestone b. Super I/O initialization.

Hardware-topology discovery

As a preparation step for future milestones, we have performed the mapping of USB, SATA, and PCI Express ports. These maps will later be used to add the board-specific configuration for these communication buses. The process is no different from what we did for Gigabyte MZ33-AR1 SATA and USB ports as well as PCI Express. We will skip the general explanation (you may read these two blog posts for Gigabyte MZ33-AR1 to catch up), and focus only on differences, and AM5-specific aspects.

USB

As previously, we used the lspci Linux command to identify the USB controllers and lsusb to identify ports on the USB controller where devices are connected to. We have probed every possible port and USB header on the mainboard. The complete log from the mapping can be found here.

The results from the mapping are as follows:

  1. xhci_hcd 0000:0c:00.0: B850 chipset:

    • 12 USB 2.0 ports:
      • port 1 and 2: JUSB3 header
      • port 3 header 4: JUSB4
      • port 5: JUSBC5 header
      • port 6 unused?
      • port 7 and 8: JUSB1 header
      • port 9 and 10: JUSB2 header
      • port 11: onboard WiFi/BT Foxconn
      • port 12: MSI Mystic Light MCU
    • 6 USB 3.x ports:
      • port 1 and 2: JUSB3 header
      • port 3 and 4: JUSB4 header
      • port 5: JUSBC5 header
      • port 6: unused?
  2. xhci_hcd 0000:0e:00.3: SoC USB1, xHCI USB 3.1 controller:

    • 2 USB 2.0 ports:
      • port 1: rear USB-A 3.0 5G
      • port 2: rear USB-C near antennas
    • 2 USB 3.x ports:
      • port 1: rear USB-A 3.0 5G
      • port 2: rear USB-C near antennas
  3. xhci_hcd 0000:0e:00.4 SoC USB2, USB for Secure Biometrics:

    • 1 USB 2.0 port
      • port 1: Hub Genesys
        • port 1-4: rear USB2.0 4 ports column
    • 0 USB 3.x ports
  4. xhci_hcd 0000:10:00.3 SoC USB3, 1-port for USB4:

    • 1 USB 2.0 port:
      • port 1: rear USB-A 3.x 10G
    • 1 USB 3.x port:
      • port 1: rear USB-A 3.x 10G
  5. xhci_hcd 0000:10:00.4 SoC USB4, 1-port for USB4:

    • 1 USB 2.0 port:
      • port 1: rear USB-C near HDMI
    • 1 USB 3.x port:
      • port 1: rear USB-C near HDMI

It is worth noting that having multiple USB controllers is a significant advantage for Qubes users, since they may dedicate a whole controller, e.g., the USB Secure Biometrics (rear 4 USB2.0 ports column) to input devices, without undermining the Qubes security model.

The map above fulfills the 4. Task 4. Hardware-topology discovery - Milestone a. USB connector map.

SATA

Mapping SATA ports was done using dmesg. The MSI PRO B850-P has a total of 4 SATA ports. According to the logs, the SoC itself does not have any SATA controllers, only the chipset has. The complete log from mapping can be found here.

It occurs that all 4 SATA ports come from the B850 chipset in unchanged order:

  • 0000:0f:00.0 - SATA controller from B850 chipset:
    • port 1: SATA1
    • port 2: SATA2
    • port 3: SATA3
    • port 4: SATA4

To determine that the SATA controller comes from the chipset, lspci and lspci -t command may be used. Example output from MSI PRO B850-P can be found here. From the log, we can see that the SATA controller is connected to the 03:0d.0 600 Series Chipset PCIe Switch Downstream Port, and can be observed as 0d:00.0 SATA controller [0106]: Advanced Micro Devices, Inc. [AMD] 600 Series Chipset SATA Controller. Note that the bus numbers are different, because it depends on the current population of PCIe devices. As we were performing the mapping for PCIe and SATA simultaneously, the PCI address of the SATA controller was changing. Unlike the Turin system, which has SATA controllers integrated into the SoC, Phoenix processors do not have any SATA. Thus the initialization will not use MPIO/DXIO lines like on the Turin server, but will be incorporated into the Promontory chipset initialization in subsequent project milestones.

The map above fulfills the Task 4. Hardware-topology discovery - Milestone b. SATA connector map

PCIe

Mapping of the PCIe ports on MSI PRO B850-P was also done using the AMD XIO tool and lspci, like we did for Turin. Thankfully, this time, the output of the tool also contains logical to SERDES/controller lane maps. It will help a lot in determining the MPIO/DXIO lanes which will have to be used. Also the AMD’s documentation about the Phoenix mainboard design clearly explains the architecture of DXIO lanes. So the Phoenix AM5 SoC has the following PCIe structure:

  1. PCIE0:

    • Up to 4 bridges
    • 12 lanes total
    • PCI addresses of the bridges 00:01.1 - 00:01.5
    • Lanes 0-7 map to DXIO lanes 0-7
    • Lanes 8-11 map to DXIO lanes 16-19
  2. PCIE1:

    • Up to 6 bridges
    • 8 lanes total
    • PCI addresses of the bridges 00:02.1 - 00:01.6
    • The lanes map to DXIO lanes 20-27

Complete mapping log from populating all possible slots using an Nvidia GPU card and an additional Samsung NVMe drive on the MSI PRO B850-P can be found here. In the first mapping attempt, we plugged an Nvidia GPU to slot PCIE_E1 and the NVMe drive to PCI_E3 (through an M.2 to PCIe adapter). The devices showed up on the following PCIe bridges:

1
2
3
4
5
6
7
8
9
lspci -tnnvv
-[0000:00]-+-00.0  Advanced Micro Devices, Inc. [AMD] Device [1022:14e8]
           +-00.2  Advanced Micro Devices, Inc. [AMD] Device [1022:14e9]
           +-01.0  Advanced Micro Devices, Inc. [AMD] Device [1022:14ea]
           +-01.1-[01]--+-00.0  NVIDIA Corporation GP108 [GeForce GT 1030] [10de:1d01]
           |            \-00.1  NVIDIA Corporation GP108 High Definition Audio Controller [10de:0fb8]
           +-01.2-[02]----00.0  Phison Electronics Corporation PS5013-E13 PCIe3 NVMe Controller (DRAM-less) [1987:5013]
           +-02.0  Advanced Micro Devices, Inc. [AMD] Device [1022:14ea]
           +-02.1-[03-0e]----00.0-[04-0e]--+-00.0-[05]----00.0  Samsung Electronics Co Ltd NVMe SSD Controller 980 (DRAM-less) [144d:a809]

The Phison NVMe drive holds the operating system and is plugged into M2_1 slot. It will not switch places during the mapping process. From the AMD XIO log we have:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  1.PCIe Bridge               : 0:0:1.1
    Speed                     : 2.5 GT/s
    Width                     : x4
    Secondary Bus             : 0x1
    Subordinate Bus           : 0x1
    PCIe Core & Func          : PCIE0 0x0
    SERDES & Port             : PCIE0 0
    Phy & Version             : C20
    Port Type                 : Root Port
    LC_STATE                  : L0(0x10)
    Logical to SERDES Lane    : [0:0] [1:1] [2:2] [3:3]
    Logical to Controller Lane: [0:0] [1:1] [2:2] [3:3]
    Upstream Link:
        0:0:1.1
    Downstream Link(s):
        0:0:1.1-->0:1:0.0
        0:0:1.1-->0:1:0.1


  2.PCIe Bridge               : 0:0:1.2
    Speed                     : 8 GT/s
    Width                     : x4
    Secondary Bus             : 0x2
    Subordinate Bus           : 0x2
    PCIe Core & Func          : PCIE0 0x1
    SERDES & Port             : PCIE0 1
    Phy & Version             : C20
    Port Type                 : Root Port
    LC_STATE                  : L1(0x1b)
    Logical to SERDES Lane    : [0:8] [1:9] [2:10] [3:11]
    Logical to Controller Lane: [0:0] [1:1] [2:2] [3:3]
    Upstream Link:
        0:0:1.2
    Downstream Link(s):
        0:0:1.2-->0:2:0.0


  3.PCIe Bridge               : 0:0:2.1
    Speed                     : 16 GT/s
    Width                     : x4
    Secondary Bus             : 0x3
    Subordinate Bus           : 0xe
    PCIe Core & Func          : PCIE1 0x0
    SERDES & Port             : PCIE1 0
    Phy & Version             : C20
    Port Type                 : Root Port
    LC_STATE                  : L0(0x10)
    Logical to SERDES Lane    : [0:0] [1:1] [2:2] [3:3]
    Logical to Controller Lane: [0:0] [1:1] [2:2] [3:3]
    Upstream Link:
        0:0:2.1
    Downstream Link(s):
        0:0:2.1-->0:3:0.0-->0:4:0.0-->0:5:0.0
        0:0:2.1-->0:3:0.0-->0:4:4.0
        0:0:2.1-->0:3:0.0-->0:4:5.0
        0:0:2.1-->0:3:0.0-->0:4:6.0
        0:0:2.1-->0:3:0.0-->0:4:7.0
        0:0:2.1-->0:3:0.0-->0:4:8.0
        0:0:2.1-->0:3:0.0-->0:4:a.0-->0:b:0.0
        0:0:2.1-->0:3:0.0-->0:4:b.0-->0:c:0.0
        0:0:2.1-->0:3:0.0-->0:4:c.0-->0:d:0.0
        0:0:2.1-->0:3:0.0-->0:4:d.0-->0:e:0.0

Our Nvidia GPU is connected to the bridge 1.1, so it is the first bridge of PCIE0. Note that the Nvidia GPU uses only x4 link width, and according to the board manual, the PCIE_E1 slot can have x8 width on Phoenix processors. The remaining 4 lanes are not used in this case, of course, but it has to be noted down that this slot uses 8 lanes in total. This is reflected in the second bridge (1.2) logical to SERDES lanes mapping: [0:8] [1:9] [2:10] [3:11]. So, the Phison NVMe drive in M2_1 slot uses lanes 8-11 of the PCIE0, while the Nvidia GPU in the PCIE_E1 slot will use lanes 0-7 respectively. With these two devices we already see that the PCIE0 controller in hardware is fully populated (all 12 lanes occupied).

The third bridge in the log at PCI address 0:0:2.1 is our B850 chipset. In modern AMD systems, chipsets are simply an I/O expansion using the standard PCI Express bus. The chipset uses the first 4 lanes of the PCIE1 controller: Logical to SERDES Lane: [0:0] [1:1] [2:2] [3:3].

By continuing the mapping process, we came up with the following map:

  1. PCIE0:

    • ports 0-8 map to slot PCIE_E1 x8 (DXIO lanes 0-7, bridge 1.1)
    • ports 8-11 map to slot M2_1 x4 (DXIO lanes 16-19, bridge 1.2)
  2. PCIE1:

    • ports 0-3 map to Promontory B850 chipset, link x4 (DXIO lanes 20-23, bridge 2.1)
    • ports 4-7 map to M2_2 x4 (DXIO lanes 24-27, bridge 2.2)
  3. Rest of the slots on the mainboard map to Promontory chipset B850. According to AMD documentation, the Promontory 600 and 800 series chipset architecture is as follows:

    • 8 lanes PCIe Gen 4
    • 4 or 8 linii PCIe Gen3 (depends on chipset model)
    • USB and SATA controller

    In the case of B850, we have 12 lanes in total, divided as follows:

    • GPP 4-7: can be PCIe 3.0 or SATA 6G
    • GPP 0-3 and 8-11: PCIe

    This is reflected in the PCI topology as seen by the lspci command:

    Root port → Switch Upstream → Downstream devices: Device 0.0-3.0 - PCIe (GPP 0-3) Device 4.0-7.0 - PCIe/SATA combo (GPP 4-7) Device 8.0-11.0 - PCIe (GPP 8-11) Device c.0 - xHCI controller Device d.0 - SATA controller

    When GPP 4-7 are used as SATA, then the SATA controller is functional. Otherwise, it is not usable (and probably hidden by BIOS in such a case). In MSI PRO B850-P, we have standard SATA connectors, so these GPP ports are always used as SATA.

    The rest of the GPP ports are PCIe and map to the following slots on the mainboard (according to our mapping log and chipset architecture above):

    • GPP0-1 - device 0.0, link x4, PCIE_E3 slot
    • GPP2 - device 0.2, link x1, PCIE_E2 slot
    • GPP3 - device 0.3, link x1, PCIE_E4 slot
    • GPP8-9 - device 0.8, link x2, M2_3 slot
    • GPP10 - device a.0, link x1, on-board Ethernet Realtek
    • GPP11 - device b.0, link x1, on-board WiFi Qualcomm

    The PCIE_E3 slot has an x4 link width according to the board manual, so it should occupy device 0.0-0.3. However, the manual also adds a note: PCI_E2, PCI_E3 and PCI_E4 share the same bandwidth. PCI_E3 will run at x2 speed when installing the device in the PCI_E2 or PCI_E4 slot., which explains why the PCIE_E2 and PCIE_E4 appear at addresses 0.2 and 0.3, because they share the physical PCIe lanes from the chipset. Since the chipset PCIe initialization differs from the CPU, the chipset does not use the DXIO/MPIO lanes mappings. The AMD PSP requires the chipset firmware blob to be included in PSP directories, what has been done as a part of the PSP firmware package requirements. However, that is not sufficient to initialize the chipset. The OpenSIL will have to configure the GPP ports of the chipset per mainboard-specific needs. But that is foreseen to be done in a separate milestone in the project.

With the mapping above, we have complete information on how to add proper configuration of the processor’s PCIe lanes, and which PCIe ports should be configured by the chipset. The map above fulfills the Task 4. Hardware-topology discovery - Milestone c. PCIe lane map.

Summary

Phoenix OpenSIL is still in the Proof of Concept stage and is not intended for production use - proceed at your own risk. The subsequent phases of the project will bring even more exciting developments, so stay tuned for updates.

The development for MSI PRO B850-P will happen on Dasharo coreboot fork All the coreboot code developed for this blog post is available here (except the blobs and their configuration file). The main reason we chose the approach of developing on a fork is the need of a stable development environment and codebase. The base we used on Dasharo fork already includes the Turin support changes. To avoid creating a very long patch relation chains on the upstream coreboot gerrit review system, we have postponed sending initial patches for a later time, once most of the Turin patches are merged into upstream coreboot. Creating long patch relation chains also occupy the upstream coreboot Jenkins CI for a long time, which is not desirable. Sending initial patches to upstream coreboot has been planned in another, upstream-dedicated milestone of the project.

For OEMs & ODMs

If you are an OEM or ODM and see the value in AMD OpenSIL support for your products, our team can help make it a reality. Reach out to us via our contact form or email us at contact<at>3mdeb<dot>com to start the conversation.


Michał Żygowski
Firmware Engineer with networking background. Feels comfortable with low-level development using C/C++ and assembly. Interested in advanced hardware features, security and coreboot. Core developer of coreboot. Maintainer of Braswell SoC, PC Engines, Protectli and Libretrend platforms.