Introduction
This blog post continues the MSI PRO B850-P coreboot porting series. In Part 1 we brought up the bootblock and romstage and mapped all USB, SATA, and PCIe ports. In Part 2 we added the USB and PCIe devicetree descriptors and integrated Phoenix openSIL as a submodule. In Part 3 we ported the MPIO, SMU, NBIO, FCH SD, FCH ACPI, and RcMgr IP blocks, reaching a state where the platform almost booted into Linux.
This post covers the work that followed: porting the CCX and FCH IP blocks for the AM5 desktop variant of Phoenix and adding the missing USB initialization code in openSIL. The relevant coreboot changes are tracked in this pull request on the Dasharo coreboot downstream repository. The openSIL changes are split across two pull requests: first for CCX changes and second for FCH changes, both on the 3mdeb openSIL downstream repository.
The milestones covered in this post are:
Task 6. Port Phoenix AM5 specific code to OpenSIL:
-
Milestone b. Cover Phoenix mobile and desktop silicon initialization differences in OpenSIL (CCX, FCH, MEM)
Most of the code is similar or identical between desktop and mobile parts. However, care must be taken for possible small differences. The goal is to analyze and compare the desktop and mobile differences. This milestone covers CCX, FCH and MEM blocks.
-
Milestone d. Cover Phoenix mobile and desktop silicon initialization differences in OpenSIL (DF, RcMgr, APOB)
Most of the code is similar or identical between desktop and mobile parts. However, care must be taken for possible small differences. The goal is to analyze and compare the desktop and mobile differences. This milestone covers DF, RcMgr and APOB blocks.
Task 8. Validation & stabilization:
-
Milestone b. Test environment preparation for MSI PRO B850-P
Prepare test environment and laboratory infrastructure for automated testing of MSI PRO B850-P platform.
Previous USB initialization failures
In the previous blog posts one could observe messages like:
|
|
These errors came from inactive CPU-integrated USB controllers. When coreboot
or the OS attempted to read the MMIO resources of an uninitialized controller,
the hardware returned 0xFF bytes for all reads. Linux’s xHCI driver correctly
interpreted this as the absence of extended capabilities and missing port
definitions - but the root cause was that openSIL had never properly
initialized the USB controllers in the first place.
The Phoenix PoC openSIL was written for mobile Phoenix CPUs, which do not expose all of the USB controllers that the desktop AM5 variant has. As a result, the USB initialization code was effectively absent for desktop parts. This made the SoC USB controllers invisible to the OS despite being physically present on the silicon.
To fix this, we had to implement the missing USB initialization logic in openSIL. The effort turned out to be substantially larger than anticipated - roughly 1000 lines of new code spread across the FCH USB subsystem. The FCH pull request is a single commit that adds the missing initialization for the USB controllers and several related FCH subsystems. The changes touch 14 files across the openSIL tree. From the finished work perspective, it almost seemed like only half of the necessary initialization was added to openSIL by AMD, despite it not being sufficient to properly enumerate USB devices or even start the USB controller. Not sure why the code was left in such a state nor if it was tested to work with EDK2 or any operating system.
HFP and HID controller initialization
Phoenix AM5 exposes three MMIO-mapped controllers that the mobile PoC never
initialized: the Host Finger Print (HFP) controller at 0xFEC11000 and two
HID (Human Interface Device) controllers at 0xFEC12000 and 0xFEC13000. The
new code adds base address constants for these controllers:
|
|
Two new initialization functions, ProgramFchEnvHfpInit() and
ProgramFchEnvHidInit(), are called from FchHwAcpiPrePcieInit(). For each
HID controller, the helper FchHidInitPerCtrlr() configures the SPI read mode
and speed. Without these calls, the HFP and HID devices would appear as MMIO
holes and could confuse the OS during PCI resource allocation.
On the coreboot side, a corresponding
commit
declares the three devices in chipset_opensil.cb:
|
|
SPI TPM decode
A new lpc.c file for the Phoenix SoC implements soc_lpc_tpm_decode_spi(),
which writes two registers to enable SPI TPM operation. This ensures the
discrete SPI TPM on the MSI PRO B850-P is accessible to coreboot and the OS.
Previously, while the address decode was programmed by coreboot, some
silicon-specific settings to make the SPI TPM work properly were required.
A similar situation occurred with the Turin platform.
USB initialization via SMU service
The most significant new function in the FCH PR is
FchXhciUsbInitSmuService(), which initializes the xHCI USB controllers by
sending initialization requests through the SMU (System Management Unit)
communication channel. The SMU is the power management microcontroller
embedded in the SoC, and on Phoenix AM5 it is responsible for enabling the USB
controller power domains and clocking before the xHCI controllers become
accessible.
Previously, the openSIL USB initialization flow skipped the SMU service call
entirely on the PoC branch, which meant the controllers were powered down and
returned garbage on MMIO reads. Adding FchXhciUsbInitSmuService() and
integrating it into the post-MPIO (post PCI Express training) initialization
sequence corrects this.
New USB-related register definitions were added for both USB3 and USB4
controllers, and a new Xfer function call type
FCH_USB_AFTER_PCIE_TRAINING_DONE allows FCH USB initialization to be
scheduled after PCIe training completes - the correct point at which USB4
ports can be brought up (because USB4 depends on PCIe ports to provide PCIe
tunnelling).
USB configuration structures
The FCH PR also restructures the USB configuration interface. New structures
and the USB_INIT_DATA give coreboot a clean set of mainboard-customizable
variables to specify per-controller and per-port enablement, PHY tuning
parameters, and overcurrent protection via the mainboard’s devicetree.
coreboot side: USB PHY configuration
With the openSIL FCH PR in place, the coreboot mainboard code can now provide
meaningful USB PHY configuration. Commit
0c72118 in the coreboot PR
adds the USB controller configuration to devicetree.cb, with tuned PHY
parameters derived from vendor BIOS register dumps.
Eight USB 2.0 ports receive PHY tuning:
|
|
Three USB 3.0 ports receive transmitter configuration:
|
|
All three combo PHY ports are set to USB-only mode (USB_COMBO_PHY_MODE_USB_ONLY),
disabling the PCIe/SATA multiplexing on those lanes. Ports 0 and 2 are forced
to USB3 Gen1 speed to avoid link instability during bring-up.
The commit also adds detailed overcurrent protection pin mappings for both USB 2.0 and 3.0 controllers, matching the pin assignments found in the vendor BIOS.
CCX changes for AM5
The CCX pull request adds several Zen 4 / AM5 specific settings to the CCX IP block.
New CPU feature flags
Three new boolean fields are added to the CCX API structure and initialized with AM5-appropriate defaults:
| Field | Default | Description |
|---|---|---|
AmdEnableFSRM |
true |
Fast Short REP Move |
AmdEnableERMS |
true |
Enhanced REP Move String |
AmdStatisticalCorrectPredictor |
false |
Statistical Correct Predictor |
FSRM and ERMS are string operation optimizations that are beneficial on modern CPUs. The SCP feature is disabled by default.
CPU pause delay configuration
A new switch statement in CcxMiscInit.c handles five pause delay modes
(0–4) plus a default (0xFF), each writing a different value into
MSRxC00110E2. Pause delay tuning affects CPU power management transitions
and can impact latency in workloads that use spin-wait loops. Getting this
right on a desktop part requires values different from what the mobile PoC
had hardcoded.
APIC ID read fix
A subtle but important fix changes how the BSP (Bootstrap Processor) reads
its own APIC ID during early initialization. The original code used CPUID leaf
0x00000001 and extracted the APIC ID from bits 31:24 of EBX. The corrected
code uses CPUID leaf 0x0000000B (Extended Topology Enumeration) and reads the
full 32-bit APIC ID from EDX:
|
|
On desktop AM5 CPUs, CPUID leaf 0x1 only returns an 8-bit initial APIC ID,
which is insufficient for systems with more than 255 logical CPUs. The 0xB
leaf returns the full 32-bit x2APIC ID. While a single-socket consumer desktop
is unlikely to exceed 255 logical CPUs, using the correct leaf ensures future
compatibility and eliminates a potential source of mis-enumeration.
Zen 4 MSR table updates
CcxResetTablesZen4.c receives several MSR table adjustments:
MSR_LS_CFGmask is narrowed:0x007C400000000000→0x005C400000000000, removing a bit that should not be modified on desktop Phoenix parts- A new entry for
MSR_C0011004is added MSR_FP_CFGentries are updated for Zen 4 variants
MEM IP block: no adaptation needed
A pleasant surprise during this phase was that the Memory (MEM) IP block required no changes for the AM5 desktop variant. After a careful analysis of the MEM initialization path in the Phoenix PoC, the code is sufficiently generic to handle both mobile and desktop memory topologies. This is consistent with what was observed during the Turin and Genoa porting work, where the memory subsystem was also largely common across socket types.
Since no budget was needed for MEM, the effort was redirected to the FCH IP block where the USB initialization gap was significantly larger than anticipated. Together with the CCX changes and the FCH changes, Milestone 6b is fully completed.
Data Fabric MMIO coverage: completing the RcMgr picture
In the previous blog post we made small changes to the Resource Manager (RcMgr) IP block. After a deeper analysis, it occurred that these changes complete the adaptation of the RcMgr IP block for AM5. The crucial fix was the coverage of MMIO space below the PCIe MMCONF base address, which was previously unallocated.
The RcMgr code missed a hardcoded macro, causing the code to assign a second MMIO entry for the primary root bridge - a somewhat underhanded workaround, especially given that the RcMgr code is otherwise written generically to support both small systems and complex servers. After the fix, the Data Fabric MMIO configuration registers show full coverage:
|
|
Entry index 2 (0xc0000000 – 0xdfffffff) was not present before the RcMgr
changes. Without it, PCI devices with 32-bit BARs were forced to fit in the
range 0xf0000000 to 0xfebfffff, which in certain scenarios would not be
sufficient (e.g. a desktop system with many add-on PCIe cards, like GPUs). Now
the full MMIO space below 4 GiB is properly covered and the range from
0xc0000000 to 0xdfffffff is usable by PCI devices.
DF and APOB: no AM5-specific differences
The analysis of the Data Fabric (DF) and APOB (AMD Platform Onboarding Buffer) IP blocks revealed that there are no differences in initialization between the mobile Phoenix and the AM5 desktop platform. The DF initialization path is generic enough to handle both, and the APOB structures parsing code does not depend on socket/package type (at least for Phoenix processor family).
This is the same situation as with the MEM block: the PoC code generalizes well, and no porting effort was required. As a result, Milestone 6d is completed at 33% - RcMgr has been adapted (the most substantial piece), but the DF and APOB budget was redirected towards the GFX IP block, where the work remains.
GFX: new attempts, still blocked
Since the previous blog post, we tried two new approaches to bring up integrated graphics:
-
Force 32-bit framebuffer resources. The UMA on Phoenix AM5 is allocated above 4 GiB. Attempting to force the GFX resources to be 32-bit to allow VBIOS access below the 4 GiB boundary was not sufficient. The UMA allocation is controlled by APCB, which is static in coreboot and cannot be changed without reconfiguring the APCB and rebuilding the firmware image. Attempts to reconfigure UMA below 4GiB in APCB also failed.
-
Run the Phoenix VBIOS Option ROM in Yabel/x86emu. We attempted to execute the VBIOS via the x86 emulator (
CONFIG_PCI_OPTION_ROM_RUN_YABEL) with verbose debug output enabled. The attempt required a build fix - the Yabel and x86emu debug headers were missingstring.handstdio.h, and the monotonic timer API used in debug macros was outdated. These build issues have been fixed in coreboot PR, but the VBIOS execution itself still did not succeed in initializing the display engine, nor did the debug output give us any hints about what was going wrong.
Despite the fixes enabling the VBIOS path to be exercised, the integrated graphics remain non-functional. GFX initialization will continue to be investigated in subsequent weeks. The remaining 20% budget from Milestone 6d and the CXL budget freed in the previous phase will be directed toward this effort, as stated in the part 3 post.
Boot progress: almost to the login prompt
The coreboot console
log
with all the changes from this phase applied demonstrates the clearest sign of
progress yet. The platform no longer hangs during PCIe enumeration in Linux,
an issue that had been present since Part 2 and was caused by the inactive CPU
USB controllers returning 0xFF on MMIO reads, which confused the Linux
kernel.
With proper USB controller initialization in place, PCIe enumeration completes and Linux continues booting. The platform now almost reaches the login prompt. The only component that reports hard faults is the Promontory B850 chipset, for which initialization has not been implemented yet:
|
|
This is expected - Promontory support is reserved for a dedicated milestone:
Task 6. Port Phoenix AM5 specific code to openSIL:
-
Milestone a. Port Promontory I/O expansion chipset support to OpenSIL
The Phoenix OpenSIL support only covers mobile Phoenix CPUs. Board designs with desktop CPUs also use the Promontory chipset to provide additional I/O expansion on the board. The goal is to add Promontory 21 initialization to Phoenix OpenSIL by adding a new IP block and a Kconfig option to differentiate between mobile and desktop Phoenix CPUs.
Test environment integration
With the platform reaching an advanced state of boot, it is now practical to integrate the MSI PRO B850-P into an automated testing infrastructure. The open-source-firmware-validation pull request adds the relevant platform configuration to 3mdeb’s laboratory infrastructure for automated testing of the MSI PRO B850-P WIFI variant.
The initial test setup validates that the platform boots to the setup menu and parses the information printed on the main menu via serial console. Sample test results are available here (the content is raw HTML; save and open in a browser to view).

Because the OS does not fully boot yet, the set of tests that can run is limited to early firmware-visible functionality: boot order, UEFI setup menu navigation, and serial console output parsing. Once Promontory chipset support is added, we believe the OS will boot fully, and the test set will be expanded significantly.
This fulfills Task 8 Milestone b, which is the foundation required to deliver Milestone 8c (automated test results for MSI PRO B850-P).
A note on PoC code quality
The work in this phase reinforced an observation about the Phoenix PoC openSIL code quality that deserves to be called out explicitly. The PoC code did not initialize the USB controllers almost at all. For many firmware engineers, USB controller initialization is table stakes - a basic requirement for a bootable system. Skipping it entirely could be considered a significant gap in the PoC scope.
This continues a trend we have observed across the entire Phoenix porting effort: many components require substantial amounts of new initialization code to reach a working state. The FCH USB work alone accounted for roughly 1000 lines of new code. We did not encounter gaps of this magnitude during the Turin project. We also have the GFX IP block initialization coming, which currently does nothing but dump PHY tuning values.
It is worth noting that the Phoenix PoC was released significantly later than the Turin PoC - over half a year of delay - which may reflect the difficulty of adapting the common openSIL infrastructure to a consumer desktop platform where the number of IP blocks and their interdependencies are different from a server platform. Without a sample UEFI board reference implementation for Phoenix (which exists for Turin and Genoa), the reference material available to guide the porting work is also more limited.
Summary
This post covered the fourth phase of the MSI PRO B850-P coreboot port:
-
USB initialization in openSIL: Added approximately 1000 lines of missing USB initialization code to the FCH IP block, including xHCI controller bring-up via SMU service, HFP and HID controller initialization, and USB configuration structures. This resolves the
xhci_resource_for_each_ext_capandxhci_acpi_nameerrors seen in previous posts. -
CCX AM5 changes: Added FSRM, ERMS, and SCP CPU feature flags with AM5-appropriate defaults, fixed the APIC ID enumeration to use the correct CPUID leaf, and updated the Zen 4 MSR initialization tables.
-
MEM IP block: No adaptation required; the existing code is generic enough for desktop AM5. Budget redirected to FCH USB work.
-
USB configuration in coreboot: Added per-port PHY tuning, overcurrent protection pin mappings, and combo PHY mode configuration to the MSI PRO B850-P devicetree.
-
SPI TPM decode: Added
soc_lpc_tpm_decode_spi()for explicit SPI TPM address decode programming, and disabled USB PHY CMCLK Z-state gating to prevent link failures during initialization. -
RcMgr MMIO coverage: Confirmed and completed the MMIO space coverage fix from the previous phase. Data Fabric entry index 2 now covers
0xc0000000–0xdfffffff, ensuring sufficient MMIO space for 32-bit PCI devices. -
DF and APOB: No AM5-specific differences found. Budget redirected toward the GFX IP block.
-
GFX: Two new approaches (forced 32-bit resources and Yabel VBIOS execution) were attempted without success. Investigation continues.
-
Test infrastructure: MSI PRO B850-P WIFI has been integrated into 3mdeb’s automated testing infrastructure, fulfilling Milestone 8b.
The milestone completion status is as follows:
Task 6. Port Phoenix AM5 specific code to OpenSIL:
- Milestone b. Cover Phoenix mobile and desktop silicon initialization differences in OpenSIL (CCX, FCH, MEM) - 100% complete
- Milestone d. Cover Phoenix mobile and desktop silicon initialization differences in OpenSIL (DF, RcMgr, APOB) - 33% complete (RcMgr done; DF and APOB had no AM5 differences; remaining budget redirected to GFX)
Task 8. Validation & stabilization:
- Milestone b. Test environment preparation for MSI PRO B850-P - 100% complete
The most visible proof of progress is that the platform no longer hangs during PCIe enumeration in Linux and almost reaches the login prompt - something that was not possible at the end of Part 3. The remaining blocker seems to be the Promontory B850 chipset, which will be addressed in the next dedicated milestone.
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.
Unlock the full potential of your hardware and secure your firmware with the
experts at 3mdeb! If you’re looking to boost your product’s performance and
protect it from potential security threats, our team is here to help.
Schedule a call with
us
or drop us an email at contact<at>3mdeb<dot>com to start unlocking the
hidden benefits of your hardware. And if you want to stay up-to-date on all
things firmware security and optimization, be sure to sign up for our
newsletter:
Huge kudos to the NLnet Foundation for sponsoring the project.
