
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Sat, 04 Apr 2026 12:06:23 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Is this thing on? Using OpenBMC and ACPI power states for reliable server boot]]></title>
            <link>https://blog.cloudflare.com/how-we-use-openbmc-and-acpi-power-states-to-monitor-the-state-of-our-servers/</link>
            <pubDate>Tue, 22 Oct 2024 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare’s global fleet benefits from being managed by open source firmware for the Baseboard Management Controller (BMC), OpenBMC. This has come with various challenges, some of which we discuss here with an explanation of how the open source nature of the firmware for the BMC enabled us to fix the issues and maintain a more stable fleet. ]]></description>
            <content:encoded><![CDATA[ 
    <div>
      <h2>Introduction</h2>
      <a href="#introduction">
        
      </a>
    </div>
    <p>At Cloudflare, we provide a range of services through our global network of servers, located in <a href="https://www.cloudflare.com/network/"><u>330 cities</u></a> worldwide. When you interact with our long-standing <a href="https://www.cloudflare.com/application-services/products/"><u>application services</u></a>, or newer services like <a href="https://ai.cloudflare.com/?_gl=1*1vedsr*_gcl_au*NzE0Njc1NTIwLjE3MTkzMzEyODc.*_ga*NTgyMWU1Y2MtYTI2NS00MDA3LTlhZDktYWUxN2U5MDkzYjY3*_ga_SQCRB0TXZW*MTcyMTIzMzM5NC4xNS4xLjE3MjEyMzM1MTguMC4wLjA."><u>Workers AI</u></a>, you’re in contact with one of our fleet of thousands of servers which support those services.</p><p>These servers which provide Cloudflare services are managed by a Baseboard Management Controller (BMC). The BMC is a special purpose processor  — different from the Central Processing Unit (CPU) of a server — whose sole purpose is ensuring a smooth operation of the server.</p><p>Regardless of the server vendor, each server has this BMC. The BMC runs independently of the CPU and has its own embedded operating system, usually referred to as <a href="https://en.wikipedia.org/wiki/Firmware"><u>firmware</u></a>. At Cloudflare, we customize and deploy a server-specific version of the BMC firmware. The BMC firmware we deploy at Cloudflare is based on the <a href="https://www.openbmc.org/"><u>Linux Foundation Project for BMCs, OpenBMC</u></a>. OpenBMC is an open-sourced firmware stack designed to work across a variety of systems including enterprise, telco, and cloud-scale data centers. The open-source nature of OpenBMC gives us greater flexibility and ownership of this critical server subsystem, instead of the closed nature of proprietary firmware. This gives us transparency (which is important to us as a security company) and allows us faster time to develop custom features/fixes for the BMC firmware that we run on our entire fleet.</p><p>In this blog post, we are going to describe how we customized and extended the OpenBMC firmware to better monitor our servers’ boot-up processes to start more reliably and allow better diagnostics in the event that an issue happens during server boot-up.</p>
    <div>
      <h2>Server subsystems</h2>
      <a href="#server-subsystems">
        
      </a>
    </div>
    <p>Server systems consist of multiple complex subsystems that include the processors, memory, storage, networking, power supply, cooling, etc. When booting up the host of a server system, the power state of each subsystem of the server is changed in an asynchronous manner. This is done so that subsystems can initialize simultaneously, thereby improving the efficiency of the boot process. Though started asynchronously, these subsystems may interact with each other at different points of the boot sequence and rely on handshake/synchronization to exchange information. For example, during boot-up, the <a href="https://en.wikipedia.org/wiki/UEFI"><u>UEFI (Universal Extensible Firmware Interface)</u></a>, often referred to as the <a href="https://en.wikipedia.org/wiki/BIOS"><u>BIOS</u></a>, configures the motherboard in a phase known as the Platform Initialization (PI) phase, during which the UEFI collects information from subsystems such as the CPUs, memory, etc. to initialize the motherboard with the right settings.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6csPNEksLXsGgt3dq5xZ0S/3236656dbc01f3085bada5af853c3516/image1.png" />
          </figure><p><sup><i>Figure 1: Server Boot Process</i></sup></p><p>When the power state of the subsystems, handshakes, and synchronization are not properly managed, there may be race conditions that would result in failures during the boot process of the host. Cloudflare experienced some of these boot-related failures while rolling out open source firmware (<a href="https://en.wikipedia.org/wiki/OpenBMC"><u>OpenBMC</u></a>) to the Baseboard Management Controllers (BMCs) of our servers. </p>
    <div>
      <h2>Baseboard Management Controller (BMC) as a manager of the host</h2>
      <a href="#baseboard-management-controller-bmc-as-a-manager-of-the-host">
        
      </a>
    </div>
    <p>A BMC is a specialized microprocessor that is attached to the board of a host (server) to assist with remote management capabilities of the host. Servers usually sit in data centers and are often far away from the administrators, and this creates a challenge to maintain them at scale. This is where a BMC comes in, as the BMC serves as the interface that gives administrators the ability to securely and remotely access the servers and carry out management functions. The BMC does this by exposing various interfaces, including <a href="https://en.wikipedia.org/wiki/Intelligent_Platform_Management_Interface"><u>Intelligent Platform Management Interface (IPMI)</u></a> and <a href="https://www.dmtf.org/standards/redfish"><u>Redfish</u></a>, for distributed management. In addition, the BMC receives data from various sensors/devices (e.g. temperature, power supply) connected to the server, and also the operating parameters of the server, such as the operating system state, and publishes the values on its IPMI and Redfish interfaces.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/33dNmfyjqrbAGvcbZLTa0h/db3e6b79b1010081916ee6498b10c297/image2.png" />
          </figure><p><sup><i>Figure 2: Block diagram of BMC in a server system.</i></sup></p><p>At Cloudflare, we use the <a href="https://github.com/openbmc/openbmc"><u>OpenBMC</u></a> project for our Baseboard Management Controller (BMC).</p><p>Below are examples of management functions carried out on a server through the BMC. The interactions in the examples are done over <a href="https://github.com/ipmitool/ipmitool/wiki"><u>ipmitool</u></a>, a command line utility for interacting with systems that support IPMI.</p>
            <pre><code># Check the sensor readings of a server remotely (i.e. over a network)
$  ipmitool &lt;some authentication&gt; &lt;bmc ip&gt; sdr
PSU0_CURRENT_IN  | 0.47 Amps         | ok
PSU0_CURRENT_OUT | 6 Amps            | ok
PSU0_FAN_0       | 6962 RPM          | ok
SYS_FAN          | 13034 RPM         | ok
SYS_FAN1         | 11172 RPM         | ok
SYS_FAN2         | 11760 RPM         | ok
CPU_CORE_VR_POUT | 9.03 Watts        | ok
CPU_POWER        | 76.95 Watts       | ok
CPU_SOC_VR_POUT  | 12.98 Watts       | ok
DIMM_1_VR_POUT   | 29.03 Watts       | ok
DIMM_2_VR_POUT   | 27.97 Watts       | ok
CPU_CORE_MOSFET  | 40 degrees C      | ok
CPU_TEMP         | 50 degrees C      | ok
DIMM_MOSFET_1    | 36 degrees C      | ok
DIMM_MOSFET_2    | 39 degrees C      | ok
DIMM_TEMP_A1     | 34 degrees C      | ok
DIMM_TEMP_B1     | 33 degrees C      | ok

…

# check the power status of a server remotely (i.e. over a network)
ipmitool &lt;some authentication&gt; &lt;bmc ip&gt; power status
Chassis Power is off

# power on the server
ipmitool &lt;some authentication&gt; &lt;bmc ip&gt; power on
Chassis Power Control: On</code></pre>
            <p>Switching to OpenBMC firmware for our BMCs gives us more control over the software that powers our infrastructure. This has given us more flexibility, customizations, and an overall better uniform experience for managing our servers. Since OpenBMC is open source, we also leverage community fixes while upstreaming some of our own. Some of the advantages we have experienced with OpenBMC include a faster turnaround time to fixing issues, <a href="https://blog.cloudflare.com/de-de/thermal-design-supporting-gen-12-hardware-cool-efficient-and-reliable/"><u>optimizations around thermal cooling</u></a>, <a href="https://blog.cloudflare.com/gen-12-servers/"><u>increased power efficiency</u></a> and <a href="https://blog.cloudflare.com/how-we-used-openbmc-to-support-ai-inference-on-gpus-around-the-world/"><u>supporting AI inference</u></a>.</p><p>While developing Cloudflare’s OpenBMC firmware, however, we ran into a number of boot problems.</p><p><b><i>Host not booting:</i></b> When we send a request over IPMI for a host to power on (as in the example above, power on the server), ipmitool would indicate the power status of the host as ON, but we would not see any power going into the CPU nor any activity on the CPU. While ipmitool was correct about the power going into the chassis as ON, we had no information about the power state of the server from ipmitool, and we initially falsely assumed that since the chassis power was on, the rest of the server components should be ON. The <a href="https://documents.uow.edu.au/~blane/netapp/ontap/sysadmin/monitoring/concept/c_oc_mntr_bmc-sys-event-log.html"><u>System Event Log (SEL)</u></a>, which is responsible for displaying platform-specific events, was not giving us any useful information beyond indicating that the server was in a soft-off state (powered off), working state (operating system is loading and running), or that a “System Restart” of the host was initiated.</p>
            <pre><code># System Event Logs (SEL) showing the various power states of the server
$ ipmitool sel elist | tail -n3
  4d |  Pre-Init  |0000011021| System ACPI Power State ACPI_STATUS | S5_G2: soft-off | Asserted
  4e |  Pre-Init  |0000011022| System ACPI Power State ACPI_STATUS | S0_G0: working | Asserted
  4f |  Pre-Init  |0000011023| System Boot Initiated RESTART_CAUSE | System Restart | Asserted</code></pre>
            <p>In the System Event Logs shown above, ACPI is the acronym for Advanced Configuration and Power Interface, a standard for power management on computing systems. In the ACPI soft-off state, the host is powered off (the motherboard is on standby power but CPU/host isn’t powered on); according to the <a href="https://uefi.org/sites/default/files/resources/ACPI_Spec_6_5_Aug29.pdf"><u>ACPI specifications</u></a>, this state is called S5_G2. (These states are discussed in more detail below.) In the ACPI working state, the host is booted and in a working state, also known in the ACPI specifications as status S0_G0 (which in our case happened to be false), and the third row indicates the cause of the restart was due to a System Restart. Most of the boot-related SEL events are sent from the UEFI to the BMC. The UEFI has been something of a black box to us, as we rely on our original equipment manufacturers (OEMs) to develop the UEFI firmware for us, and for the generation of servers with this issue, the UEFI firmware did not implement sending the boot progress of the host to the BMC.</p><p>One discrepancy we observed was the difference in the power status and the power going into the CPU, which we read with a sensor we call CPU_POWER.</p>
            <pre><code># Check power status
$ ipmitool &lt;some authentication&gt; &lt;bmc ip&gt;  power status
Chassis Power is on
</code></pre>
            <p>However, checking the power into the CPU shows that the CPU was not receiving any power.</p>
            <pre><code># Check power going into the CPU
$ ipmitool &lt;some authentication&gt; &lt;bmc ip&gt;  sdr | grep CPU_POWER    
CPU_POWER        | 0 Watts           | ok</code></pre>
            <p>The CPU_POWER being at 0 watts contradicts all the previous information that the host was powered up and working, when the host was actually completely shut down.</p><p><b><i>Missing Memory Modules:</i></b> Our servers would randomly boot up with less memory than expected. Computers can boot up with less memory than installed due to a number of problems, such as a loose connection, hardware problem, or faulty memory. For our case, it happened not to be any of the usual suspects, but instead was due to both the BMC and UEFI trying to simultaneously read from the memory modules, leading to access contentions. Memory modules usually contain a <a href="https://en.wikipedia.org/wiki/Serial_presence_detect"><u>Serial Presence Detect (SPD)</u></a>, which is used by the UEFI to dynamically detect the memory module. This SPD is usually located on an <a href="https://learn.sparkfun.com/tutorials/i2c/all"><u>inter-integrated circuit (i2c)</u></a>, which is a low speed, two write protocol for devices to talk to each other. The BMC also reads the temperature of the memory modules via the i2c. When the server is powered on, amongst other hardware initializations, the UEFI also initializes the memory modules that it can detect via their (i.e. each individual memory modules) Serial Presence Detect (SPD), the BMC could also be trying to access the temperature of the memory module at the same time, over the same i2c protocol. This simultaneous attempted read denies one of the parties access. When the UEFI is denied access to the SPD, it thinks the memory module is not available and skips over it. Below is an example of the related i2c-bus contention logs we saw in the <a href="https://www.freedesktop.org/software/systemd/man/latest/journalctl.html"><u>journal</u></a> of the BMC when the host is booting.</p>
            <pre><code>kernel: aspeed-i2c-bus 1e78a300.i2c-bus: irq handled != irq. expected 0x00000021, but was 0x00000020</code></pre>
            <p>The above logs indicate that the i2c address 1e78a300 (which happens to be connected to the serial presence detect of the memory modules) could not properly handle a signal, known as an interrupt request (irq). When this scenario plays out on the UEFI, the UEFI is unable to detect the memory module.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6Fe8wb6xqwXkanb8iPv8O2/eaecfe0474576a00cdc25bfeb6fba7a2/image4.png" />
          </figure><p><sup><i>Figure 3: I2C diagram showing I2C interconnection of the server’s memory modules (also known as DIMMs) with the BMC </i></sup></p><p><a href="https://www.techtarget.com/searchstorage/definition/DIMM"><u>DIMM</u></a> in Figure 3 refers to <a href="https://www.techtarget.com/searchstorage/definition/DIMM"><u>Dual Inline Memory Module</u></a>, which is the type of memory module used in servers.</p><p><b><i>Thermal telemetry:</i></b> During the boot-up process of some of our servers, some temperature devices, such as the temperature sensors of the memory modules, would show up as failed, thereby causing some of the fans to enter a fail-safe <a href="https://en.wikipedia.org/wiki/Pulse-width_modulation"><u>Pulse Width Modulation (PWM)</u></a> mode. <a href="https://en.wikipedia.org/wiki/Pulse-width_modulation"><u>PWM</u></a> is a technique to encode information delivered to electronic devices by adjusting the frequency of the waveform signal to the device. It is used in this case to control fan speed by adjusting the frequency of the power signal delivered to the fan. When a fan enters a fail-safe mode, PWM is used to set the fan speeds to a preset value, irrespective of what the optimized PWM setting of the fans should be, and this could negatively affect the cooling of the server and power consumption.</p>
    <div>
      <h2>Implementing host ACPI state on OpenBMC</h2>
      <a href="#implementing-host-acpi-state-on-openbmc">
        
      </a>
    </div>
    <p>In the process of studying the issues we faced relating to the boot-up process of the host, we learned how the power state of the subsystems within the chassis changes. Part of our learnings led us to investigate the Advanced Configuration and Power Interface (ACPI) and how the ACPI state of the host changed during the boot process.</p><p>Advanced Configuration and Power Interface (ACPI) is an open industry specification for power management used in desktop, mobile, workstation, and server systems. The <a href="https://uefi.org/sites/default/files/resources/ACPI_Spec_6_5_Aug29.pdf"><u>ACPI Specification</u></a> replaces previous power management methodologies such as <a href="https://en.wikipedia.org/wiki/Advanced_Power_Management"><u>Advanced Power Management (APM)</u></a>. ACPI provides the advantages of:</p><ul><li><p>Allowing OS-directed power management (OSPM).</p></li><li><p>Having a standardized and robust interface for power management.</p></li><li><p>Sending system-level events such as when the server power/sleep buttons are pressed </p></li><li><p>Hardware and software support, such as a real-time clock (RTC) to schedule the server to wake up from sleep or to reduce the functionality of the CPU based on RTC ticks when there is a loss of power.</p></li></ul><p>From the perspective of power management, ACPI enables an OS-driven conservation of energy by transitioning components which are not in active use to a lower power state, thereby reducing power consumption and contributing to more efficient power management.</p><p>The ACPI Specification defines four global “Gx” states, six sleeping “Sx” states, and four “Dx” device power states. These states are defined as follows:</p><div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td>
                        <p><span><span><strong>Gx</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Name</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Sx</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Description</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>G0</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Working</span></span></p>
                    </td>
                    <td>
                        <p><span><span>S0</span></span></p>
                    </td>
                    <td>
                        <p><span><span>The run state. In this state the machine is fully running</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>G1</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Sleeping</span></span></p>
                    </td>
                    <td>
                        <p><span><span>S1</span></span></p>
                    </td>
                    <td>
                        <p><span><span>A sleep state where the CPU will suspend activity but retain its contexts.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>S2</span></span></p>
                    </td>
                    <td>
                        <p><span><span>A sleep state where memory contexts are held, but CPU contexts are lost. CPU re-initialization is done by firmware.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>S3</span></span></p>
                    </td>
                    <td>
                        <p><span><span>A logically deeper sleep state than S2 where CPU re-initialization is done by device. Equates to Suspend to RAM.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>S4</span></span></p>
                    </td>
                    <td>
                        <p><span><span>A logically deeper sleep state than S3 in which DRAM is context is not maintained and contexts are saved to disk. Can be implemented by either OS or firmware. </span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>G2</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Soft off but PSU still supplies power</span></span></p>
                    </td>
                    <td>
                        <p><span><span>S5</span></span></p>
                    </td>
                    <td>
                        <p><span><span>The soft off state. All activity will stop, and all contexts are lost. The Complex Programmable Logic Device (CPLD) responsible for power-up and power-down sequences of various components e.g. CPU, BMC is on standby power, but the CPU/host is off.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>G3</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Mechanical off</span></span></p>
                    </td>
                    <td> </td>
                    <td>
                        <p><span><span>PSU does not supply power. The system is safe for disassembly.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Dx</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Name</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Description</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>D0</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Fully powered on</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Hardware device is fully functional and operational </span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>D1</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Hardware device is partially powered down</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Reduced functionality and can be quickly powered back to D0</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>D2</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Hardware device is in a deeper lower power than D1</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Much more limited functionality and can only be slowly powered back to D0.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>D3</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Hardware device is significantly powered down or off</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Device is inactive with perhaps only the ability to be powered back on</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div><p>The states that matter to us are:</p><ul><li><p><b>S0_G0_D0:</b> often referred to as the working state. Here we know our host system is running just fine.</p></li><li><p><b>S2_D2: </b>Memory contexts are held, but CPU context is lost. We usually use this state to know when the host’s UEFI is performing platform firmware initialization.</p></li><li><p><b>S5_G2:</b> Often referred to as the soft off state. Here we still have power going into the chassis, however, processor and DRAM context are not maintained, and the operating system power management of the host has no context.</p></li></ul><p>Since the issues we were experiencing were related to the power state changes of the host — when we asked the host to reboot or power on — we needed a way to track the various power state changes of the host as it went from power off to a complete working state. This would give us better management capabilities over the devices that were on the same power domain of the host during the boot process. Fortunately, the OpenBMC community already implemented an <a href="https://github.com/openbmc/google-misc/tree/master/subprojects/acpi-power-state-daemon"><u>ACPI daemon</u></a>, which we extended to serve our needs. We added an ACPI S2_D2 power state, in which memory contexts are held, but CPU context is lost, to the ACPI daemon running on the BMC to enable us to know when the host’s UEFI is performing firmware initialization, and also set up various management tasks for the different ACPI power states.</p><p>An example of a power management task we carry out using the S0_G0_D0 state is to re-export our Voltage Regulator (VR) sensors on S0_G0_D0 state, as shown with the service file below:</p>
            <pre><code>cat /lib/systemd/system/Re-export-VR-device.service 
[Unit]
Description=RE Export VR Device Process
Wants=xyz.openbmc_project.EntityManager.service
After=xyz.openbmc_project.EntityManager.service
Conflicts=host-s2-state.target

[Service]
Type=simple
ExecStart=/bin/bash -c 'set -a &amp;&amp; source /usr/bin/Re-export-VR-device.sh on'
SyslogIdentifier=Re-export-VR-device.service

[Install]
WantedBy=host-s0-state.target
</code></pre>
            <p>Having set this up, OpenBMC has a Net Function (ipmiSetACPIState) in <a href="https://github.com/openbmc/phosphor-host-ipmid/tree/master"><u>phosphor-host-ipmid</u></a> that is responsible for setting the ACPIState of the host on the BMC. This command is called by the host using the standard ipmi command with the corresponding NetFn=0x06 and Cmd=0x06.</p><p>In the event of an immediate power cycle (i.e. host reboots without operating system shutdown), the host is unable to send its S5_G2 state to the BMC. For this case, we created a patch to OpenBMC’s <a href="https://github.com/openbmc/x86-power-control/tree/master"><u>x86-power-control</u></a> to let the BMC become aware that the host has entered the ACPI S5_G2 state (i.e. soft-off). When the host comes out of the power off state, the UEFI performs the Power On Self Test (POST) and sends the S2_D2 to the BMC, and after the UEFI has loaded the OS on the host, it notifies the BMC by sending the ACPI S0_G0_D0 state.</p>
    <div>
      <h2>Fixing the issues</h2>
      <a href="#fixing-the-issues">
        
      </a>
    </div>
    <p>Going back to the boot-up issues we faced, we discovered that they were mostly caused by devices which were in the same power domain of the CPU, interfering with the UEFI/platform firmware initialization phase. Below is a high level description of the fixes we applied.</p><p><b><i>Servers not booting</i></b><b>:</b> After identifying the devices that were interfering with the POST stage of the firmware initialization, we used the host ACPI state to control when we set the appropriate power mode state for those devices so as not to cause POST to fail.</p><p><b><i>Memory modules missing</i></b><b>:</b> During the boot-up process, memory modules (DIMMs) are powered and initialized in S2_D2 ACPI state. During this initialization process, UEFI firmware sends read commands to the Serial Presence Detect (SPD) on the DIMM to retrieve information for DIMM enumeration. At the same time, the BMC could be sending commands to read DIMM temperature sensors. This can cause SMBUS collisions, which could either cause DIMM temperature reading to fail or UEFI DIMM enumeration to fail. The latter case would cause the system to boot up with reduced DIMM capacity, which could be mistaken as a failing DIMM scenario. After we had discovered the race condition issue, we disabled the BMC from reading the DIMM temperature sensors during S2_D2 ACPI state and set a fixed speed for the corresponding fans. This solution allows our UEFI to retrieve all the necessary DIMM subsystems information for enumeration, and our servers now boot up with the correct size of memory.</p><p><b>Thermal telemetry:</b> In S0_G0 power state, when sensors are not reporting values back to the BMC, the BMC assumes that devices may be overheating and puts the fan controller into fail-safe mode where fan speeds are ramped up to maximum speed. However, in S5_G2 state, some thermal sensors like CPU temperature, NIC temperature, etc. are not powered and not available. Our solution is to set these thermal sensors as non-functional in their exported configuration when in S5_G2 state and during the transition from S5_G2 state to S2_D2 state. Setting the affected devices as non-functional in their configuration, instead of waiting for thermal sensor read commands to error out, prevents the controller from entering the fail-safe mode.</p>
    <div>
      <h2>Moving forward</h2>
      <a href="#moving-forward">
        
      </a>
    </div>
    <p>Aside from resolving issues, we have seen other benefits from implementing ACPI Power State on our BMC firmware. An example is in the area of our automated firmware regression testing. Various parts of our tests require rebooting/power cycling the servers over a hundred times, during which we monitor the ACPI power state changes of our servers as against using a boolean (running or not running, pingable or not pingable) to assert the status of our servers.</p><p>Also, it has given us the opportunity to learn more about the complex subsystems in a server system, and the various power modes of the different subsystems. This is an aspect that we are still actively learning about as we look to further optimize various aspects of the boot sequence of our servers.</p><p>In the course of time, implementing ACPI states is helping us achieve the following:</p><ul><li><p>All components are enabled by end of boot sequence,</p></li><li><p>BIOS and BMC are able to retrieve component information,</p></li><li><p>And the BMC is aware when thermal sensors are in a non-functional state.
</p></li></ul><p>For better observability of the boot progress and “last state” of our systems, we have also started the process of adding the BootProgress object of the <a href="https://redfish.dmtf.org/schemas/v1/ComputerSystem.v1_13_0.json"><u>Redfish ComputerSystem Schema</u></a> into our systems. This will give us an opportunity for pre-operating system (OS) boot observability and an easier debug starting point when the UEFI has issues (such as when the server isn’t coming on) during the server platform initialization.</p><p>With each passing day, Cloudflare’s OpenBMC team, which is made up of folks from different embedded backgrounds, learns about, experiments with, and deploys OpenBMC across our global fleet. This has been made possible by relying on the OpenBMC community’s contribution (as well as upstreaming some of our own contributions), and our interaction with our various vendors, thereby giving us the opportunity to make our systems more reliable, and giving us the ownership and responsibility of the firmware that powers the BMCs that manage our servers. If you are thinking of embracing open-source firmware in your BMC, we hope this blog post written by a team which started deploying OpenBMC less than 18 months ago has inspired you to give it a try. </p><p>For those who are interested in considering making the jump to open-source firmware, check it out <a href="https://github.com/openbmc/openbmc"><u>here</u></a>!</p> ]]></content:encoded>
            <category><![CDATA[Infrastructure]]></category>
            <category><![CDATA[Open Source]]></category>
            <category><![CDATA[OpenBMC]]></category>
            <category><![CDATA[Servers]]></category>
            <category><![CDATA[Firmware]]></category>
            <guid isPermaLink="false">2hySj1JFTXmlofjA6IRijm</guid>
            <dc:creator>Nnamdi Ajah</dc:creator>
            <dc:creator>Ryan Chow</dc:creator>
            <dc:creator>Giovanni Pereira Zantedeschi</dc:creator>
        </item>
        <item>
            <title><![CDATA[How we used OpenBMC to support AI inference on GPUs around the world]]></title>
            <link>https://blog.cloudflare.com/how-we-used-openbmc-to-support-ai-inference-on-gpus-around-the-world/</link>
            <pubDate>Wed, 06 Dec 2023 14:00:34 GMT</pubDate>
            <description><![CDATA[ This is what Cloudflare has been able to do so far with OpenBMC with respect to our GPU-equipped servers ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3JeLifbB3Vdk6jqpeUpVRc/1647ed581b63f4f196194655e8c286d1/2148-HERO.png" />
            
            </figure><p>Cloudflare recently announced <a href="/workers-ai/">Workers AI</a>, giving developers the ability to run serverless GPU-powered AI inference on Cloudflare’s global network. One key area of focus in enabling this across our network was updating our Baseboard Management Controllers (BMCs). The BMC is an embedded microprocessor that sits on most servers and is responsible for remote power management, sensors, serial console, and other features such as virtual media.</p><p>To efficiently manage our BMCs, Cloudflare leverages OpenBMC, an open-source firmware stack from the Open Compute Project (OCP). For Cloudflare, OpenBMC provides transparent, auditable firmware. Below describes some of what Cloudflare has been able to do so far with OpenBMC with respect to our GPU-equipped servers.</p>
    <div>
      <h2>Ouch! That’s HOT!</h2>
      <a href="#ouch-thats-hot">
        
      </a>
    </div>
    <p>For this project, we needed a way to adjust our BMC firmware to accommodate new GPUs, while maintaining the operational efficiency with respect to thermals and power consumption. OpenBMC was a powerful tool in meeting this objective.</p><p>OpenBMC allows us to change the hardware of our existing servers without the dependency of our Original Design Manufacturers (ODMs), consequently allowing our product teams to get started on products quickly. To physically support this effort, our servers need to be able to supply enough power and keep the GPU and the rest of the chassis within operating temperatures. Our servers had power supplies that had sufficient power to support new GPUs as well as the rest of the server’s chassis, so we were primarily concerned with ensuring they had sufficient cooling.</p><p>With OpenBMC, our first approach to enabling our product teams to start working with the GPUs was to simply blast fans directly in line with the GPU, assuming the GPU was running at Thermal Design Power (TDP, the maximum heat from a given source). Unfortunately, because of the heat given off by these new GPUs, we could not keep them below 95˚C when they were fully stressed. This prompted us to install another fan to help keep the GPU cool and helped us bring a fully stressed GPU down to 65˚C. This served as our baseline before we began the process of fine-tuning the fan Peripheral Integral Derivative (PID) controller to handle variation in temperature in a more nuanced manner. Below shows a graph of the baseline described above:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1r06acJOE7ZIuVP4jrCnqz/543e4e015d4a7de22f35800a9b4a80f4/2148-1.png" />
            
            </figure><p>With this baseline in place, tuning becomes a tedious iteration of PID constants. For those unfamiliar with PID controllers, we use the following equation to describe the control output given the error as input.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5Ooby3NUPSj7MFRmkYpesl/8d63ee010e49d6f350a76b23d50862dc/Screenshot-2023-12-05-at-15.31.01.png" />
            
            </figure><p>To break this down, u(t) represents our control output, e(t) is the error signal, and Kp, Ki, and Kd are the proportional gain, integral gain, and derivative gain constants, respectively. To briefly describe how each of these components work, I will isolate each of the components. Our error, or e(t), is simply the difference between the target temperature and the current temperature, so if our target temperature is 50 ˚C and my current is 60 ˚C, the e(t) for the proportional component is 10 ˚C. If u(t) = Kp⋅e(t), we can see that u(t) is = Kp⋅10. Any given Kp could drastically affect the control output u(t) and is responsible for how quickly the controller adjusts to approaching the target. The Ki⋅∫e(t)dt accumulates the error over time. The scenario where the controller reaches steady state but does not hit the target setpoint is called steady-state error. The integral component accumulating that error is intended for resolving this scenario but can also cause oscillations if the integral gain is too large. Lastly, the derivative portion, Kd⋅∂e(t)/∂t, can be seen as Kd⋅(the slope at the given point in time). You can imagine that the more quickly the controller approaches the target, the greater the slope, and the slower the approach, the less slope. Another way to look at it is that with faster oscillations, the greater the derivative portion, and slower oscillations, the lesser the derivative portion.</p><p>With this in mind, the following points are taken into consideration when we manually tune the controller:</p><ol><li><p>Avoid oscillations at the target setpoint, i.e. avoid letting the temperature fluctuate above or below the specified temperature. Oscillations — specifically variations of fan speed and pulse width modulation (generally the power supplied to the fan), increase mechanical wear on components. We want these servers to last the entire five-year lifecycle while also not costing us capital expenses for replacing components or operating expenses in terms of the electricity we expend.</p></li><li><p>Approach the target setpoint as quickly as possible — with the above graph, we see the temperature settle somewhere between 63 ˚C and 65 ˚C quickly, but that’s because the fans are currently at 100% load. Settling at the target setpoint quickly means our fans are able to quickly adjust to the heat expended by the GPU or any component.</p></li><li><p>The proportional gain affects how quickly the controller approaches the setpoints</p></li><li><p>The integral gain is used to remove steady-state errors.</p></li><li><p>The derivative gain is based of the rate of change and is used to remove oscillations</p></li></ol><p>With a better understanding of the PID controller theory, we can see how we can iterate toward our final product. Our initial trial from a full load fan had some difficulties finding the setpoints, as shown by the oscillations on the left side of the graph. As we learned above, by adjusting our integral and derivative gains we were able to help reduce the oscillations. We can see the controller trying to lock in around the 70C, but our intended target was 65 ˚C (if it were to lock in at 70 ˚C, this would be a clear example of steady-state error). The last point we worked to resolve was to improve the speed at which it approaches the setpoint, which we were able to tune with by adjusting proportional gain.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/MX23CfxcUPHg4l72ITUVn/2961f3ef72cd07e21d780e90af5436a6/2148-3.png" />
            
            </figure><p>OpenBMC fan configurations are easily configurable JSON files to manually tune PID settings. The graphs presented come from comma-separated-value (CSV) files generated from OpenBMC’s PID controller application and allow us to easily iterate and improve our configuration. Several iterations later, we got our final product. We had a tad bit of overshoot in the beginning, but this is a strong enough result for us to leave the PID controller for now.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5n47tnZ8vZqTD2fQsIX33W/44690423f9ce2053ea99a875065cfc7c/2148-4.png" />
            
            </figure>
    <div>
      <h2>Talk to me GPU</h2>
      <a href="#talk-to-me-gpu">
        
      </a>
    </div>
    <p>In order to source the temperature data for the PID tuning above, we had to establish communication with the GPU. The first thing we did was identify the route from the BMC to the GPU and Peripheral Component Interconnect Express (PCIe) slot. Looking at our ODM’s schematics for the BMC and motherboard, we found a System Management Bus (SMBus) line to a mux or switch connecting to the PCIe slot. For embedded developers out there, the SMBus protocol is similar to Inter-Integrated Circuit (I2C) bus protocol, with minor differences in electrical and clock speed requirements. With a physical path to communication established, we next needed to communicate with the GPU in software.</p><p>OpenBMC applications, Linux kernel drivers, and the software tools we can add for development make the configuration and operation of devices such as fans, analog-to-digital converters (ADC), and power supplies as simple as possible. The first thing we try as a test is to get some temperature sensor data from the GPU’s onboard temperature sensor and inventory information from the Electrically-Erasable Programmable Read-Only Memory (EEPROM). We can verify the temperature sensor data with tooling provided by our GPU vendor, and the inventory information can be verified against the asset sheet provided to us when the device was delivered. Building the eerpog tool, we can try communicating with the eeprom:</p>
            <pre><code>~$ eeprog -f -16 /dev/i2c-23 0x50 -r 0x00:200
eeprog 0.7.5, a 24Cxx EEPROM reader/writer
Copyright (c) 2003 by Stefano Barbato - All rights reserved.
  Bus: /dev/i2c-23, Address: 0x50, Mode: 16bit
  Reading 200 bytes from 0x0
&lt;redacted&gt; Ver 0.02</code></pre>
            <p>This tool will produce block read requests over SMBus and dump the returned information. For temperature, the TMP75 temperature sensor is commonly used for many temperature sensors in server commodity components. We can manually bind the temperature sensor in sysfs like this:</p><p><code>~$echo "tmp75 0x4F &gt; /sys/bus/i2c/devices/i2c-23/new_device"</code></p><p>This will bind the tmp75 driver to address 0x4F on I2C bus 23, and we can verify the successful binding and sysfs information as seen below:</p><p><code>~$ cat /sys/bus/i2c/devices/i2c-23/23-004f/name tmp75</code></p><p>With our temperature sensor and inventory information, we can now leverage OpenBMC’s applications for simple configuration to make this information available via the Intelligent Platform Management Interface (IPMI) or Redfish, a REST based protocol for communicating with the BMC. For adding these components, we will focus on Entity-Manager.</p><p>Entity-Manager is OpenBMC’s means of making physical components available to the BMC’s software via JSON configuration files. OpenBMC applications refer to information made available with these configurations to make sensor data and inventory data available over BMC interfaces and raise alerts when going out of bounds of critically configured settings. The following is the configuration we use as a result of our discoveries above:</p>
            <pre><code>{
    "Exposes": [
        {
            "Address": "0x4F",
            "Bus": "23",
            "Name": "GPU_TEMP",
            "Thresholds": [
                {
                    "Direction": "greater than",
                    "Name": "upper critical",
                    "Severity": 1,
                    "Value": 92
                },
                {
                    "Direction": "less than",
                    "Name": "lower non critical",
                    "Severity": 0,
                    "Value": 30
                }
            ],
            "Type": "TMP75"
        }
    ],
    "Name": "****************",
    "Probe": "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': *********})",
    "Type": "NVMe",
    "xyz.openbmc_project.Inventory.Decorator.Asset": {
        "Manufacturer": "$BOARD_MANUFACTURER",
        "Model": "$BOARD_PRODUCT_NAME",
        "PartNumber": "$BOARD_PART_NUMBER",
        "SerialNumber": "$BOARD_SERIAL_NUMBER"
    }
}</code></pre>
            <p>Entity-Manager probes the I2C buses for all the EEPROMs for inventory information, possibly detailing what’s available on the buses. It will then try to match the information with a given JSON configuration’s “Probe” member, and if there is a match, it will take the configuration and configure the configurations as part of what is exposed. The end result is the FRU and GPU_TEMP available on IPMI.</p>
            <pre><code>$~ ipmi 517m206 sdr |grep GPU_TEMP
GPU_TEMP         | 39 degrees C      | ok
$~ ipmi 517m206 fru print 151
FRU Device Description : &lt;redacted&gt; (ID 151)
 Board Mfg Date        : Mon Mar 27 18:13:00 2023 UTC
 Board Mfg             : &lt;redacted&gt;
 Board Product         : &lt;redacted&gt;
 Board Serial          : &lt;redacted&gt;
 Board Part Number     : &lt;redacted&gt;</code></pre>
            
    <div>
      <h2>Open-Source firmware moving forward</h2>
      <a href="#open-source-firmware-moving-forward">
        
      </a>
    </div>
    <p>Cloudflare has been able to leverage OpenBMC to gain more control and flexibility with our server configurations, without sacrificing the efficiency at the core of our network. While we continue to work closely with our ODM partners, our ongoing GPU deployment has underscored the importance of being able to modify server firmware without being locked to traditional device update cycles.For those who are interested in considering making the jump to open-source firmware, check out OpenBMC <a href="https://github.com/openbmc/openbmc">here</a>!</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Workers AI]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Deep Dive]]></category>
            <guid isPermaLink="false">2M0H6i0QI1A4pXsAM6PrWI</guid>
            <dc:creator>Ryan Chow</dc:creator>
            <dc:creator>Giovanni Pereira Zantedeschi</dc:creator>
            <dc:creator>Nnamdi Ajah</dc:creator>
        </item>
        <item>
            <title><![CDATA[Armed to Boot: an enhancement to Arm's Secure Boot chain]]></title>
            <link>https://blog.cloudflare.com/armed-to-boot/</link>
            <pubDate>Wed, 25 Jan 2023 14:00:00 GMT</pubDate>
            <description><![CDATA[ Enhancing the Arm Secure Boot chain to improve platform security on modern systems. ]]></description>
            <content:encoded><![CDATA[ <p></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6DXRZwWpgxoNOs7LL87gEw/26d5483a74be3dcbe2a5c56c65c5986c/image1-45.png" />
            
            </figure><p>Over the last few years, there has been a rise in the number of attacks that affect how a computer boots. Most modern computers use a specification called Unified Extensible Firmware Interface (<a href="https://en.wikipedia.org/wiki/UEFI">UEFI</a>) that defines a software interface between an operating system (e.g. Windows) and platform firmware (e.g. disk drives, video cards). There are security mechanisms built into UEFI that ensure that platform firmware can be cryptographically validated and boot securely through an application called a bootloader. This firmware is stored in non-volatile <a href="https://en.wikipedia.org/wiki/Serial_Peripheral_Interface">SPI</a> flash memory on the motherboard, so it persists on the system even if the operating system is reinstalled and drives are replaced.</p><p>This creates a ‘trust anchor’ used to validate each stage of the boot process, but, unfortunately, this trust anchor is also a target for attack. In these UEFI attacks, malicious actions are loaded onto a compromised device early in the boot process. This means that malware can change configuration data, establish persistence by ‘<a href="https://www.zdnet.com/article/chinese-apt-deploy-moonbounce-malware-in-uefi-firmware/">implanting</a>’ itself, and can bypass security measures that are only loaded at the operating system stage. So, while UEFI-anchored secure boot protects the bootloader from bootloader attacks, it does not protect the UEFI firmware itself.</p><p>Because of this growing trend of attacks, we began the process of <a href="/anchoring-trust-a-hardware-secure-boot-story/">cryptographically signing our UEFI firmware</a> as a mitigation step. While our existing solution is platform specific to our x86 AMD server fleet, we did not have a similar solution to UEFI firmware signing for Arm. To determine what was missing, we had to take a deep dive into the Arm secure boot process.</p><p>Read on to learn about the world of Arm Trusted Firmware Secure Boot.</p>
    <div>
      <h2>Arm Trusted Firmware Secure Boot</h2>
      <a href="#arm-trusted-firmware-secure-boot">
        
      </a>
    </div>
    <p>Arm defines a trusted boot process through an architecture called <a href="https://developer.arm.com/documentation/den0006/d">Trusted Board Boot Requirements</a> (TBBR), or Arm Trusted Firmware (ATF) Secure Boot. TBBR works by authenticating a series of cryptographically signed binary images each containing a different stage or element in the system boot process to be loaded and executed. Every bootloader (BL) stage accomplishes a different stage in the initialization process:</p>
    <div>
      <h3>BL1</h3>
      <a href="#bl1">
        
      </a>
    </div>
    <p>BL1 defines the boot path (is this a cold boot or warm boot), initializes the architectures (exception vectors, CPU initialization, and control register setup), and initializes the platform (enables watchdog processes, MMU, and DDR initialization).</p>
    <div>
      <h3>BL2</h3>
      <a href="#bl2">
        
      </a>
    </div>
    <p>BL2 prepares initialization of the Arm Trusted Firmware (ATF), the stack responsible for setting up the secure boot process. After ATF setup, the console is initialized, memory is mapped for the MMU, and message buffers are set for the next bootloader.</p>
    <div>
      <h3>BL3</h3>
      <a href="#bl3">
        
      </a>
    </div>
    <p>The BL3 stage has multiple parts, the first being initialization of runtime services that are used in detecting system topology. After initialization, there is a handoff between the ATF ‘secure world’ boot stage to the ‘normal world’ boot stage that includes setup of UEFI firmware. Context is set up to ensure that no secure state information finds its way into the normal world execution state.</p><p>Each image is authenticated by a public key, which is stored in a signed certificate and can be traced back to a root key stored on the SoC in one time programmable (OTP) memory or ROM.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1UdHJVQqnXX9gZ6uaglVa4/83e7065007376d4f774fc6d9d6ee867b/image9.png" />
            
            </figure><p>TBBR was originally designed for cell phones. This established a reference architecture on how to build a “Chain of Trust” from the first ROM executed (BL1) to the handoff to “normal world” firmware (BL3). While this creates a validated firmware signing chain, it has caveats:</p><ol><li><p>SoC manufacturers are heavily involved in the secure boot chain, while the customer has little involvement.</p></li><li><p>A unique SoC SKU is required per customer. With one customer this could be easy, but most manufacturers have thousands of SKUs</p></li><li><p>The SoC manufacturer is primarily responsible for end-to-end signing and maintenance of the PKI chain. This adds complexity to the process  requiring USB key fobs for signing.</p></li><li><p>Doesn’t scale outside the manufacturer.</p></li></ol><p>What this tells us is what was built for cell phones doesn’t scale for servers.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3ycPPB81rgzRIuCGSu0KE7/6ed984097e839782f83ecbc28c25212a/image3-27.png" />
            
            </figure><p>If we were involved 100% in the manufacturing process, then this wouldn’t be as much of an issue, but we are a customer and consumer. As a customer, we have a lot of control of our server and block design, so we looked at design partners that would take some of the concepts we were able to implement with AMD Platform Secure Boot and refine them to fit Arm CPUs.</p>
    <div>
      <h2>Amping it up</h2>
      <a href="#amping-it-up">
        
      </a>
    </div>
    <p>We partnered with Ampere and tested their Altra Max <a href="/arms-race-ampere-altra-takes-on-aws-graviton2/">single socket rack server CPU</a> (code named Mystique) that provides high performance with incredible power efficiency per core, much of what we were looking for in reducing power consumption. These are only a small subset of specs, but Ampere backported various features into the Altra Max notably, speculative attack mitigations that include Meltdown and Spectre (variants 1 and 2) from the Armv8.5 instruction set architecture, giving Altra the “+” designation in their ISA.</p><p>Ampere does implement a signed boot process similar to the ATF signing process mentioned above, but with some slight variations. We’ll explain it a bit to help set context for the modifications that we made.</p>
    <div>
      <h2>Ampere Secure Boot</h2>
      <a href="#ampere-secure-boot">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3z02FzpTwAjg8aK9VdC2Ro/6ab22618c187ff09fcc1b7d177d165db/image4-21.png" />
            
            </figure><p>The diagram above shows the Arm processor boot sequence as implemented by Ampere. System Control Processors (SCP) are comprised of the System Management Processor (SMpro) and the Power Management Processor (PMpro). The SMpro is responsible for features such as secure boot and bmc communication while the PMpro is responsible for power features such as Dynamic Frequency Scaling and on-die thermal monitoring.</p><p>At power-on-reset, the SCP runs the system management bootloader from ROM and loads the SMpro firmware. After initialization, the SMpro spawns the power management stack on the PMpro and ATF threads. The ATF BL2 and BL31 bring up processor resources such as DRAM, and PCIe. After this, control is passed to BL33 BIOS.</p>
    <div>
      <h3>Authentication flow</h3>
      <a href="#authentication-flow">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1uctsORF4iINvxIpkpAMCM/34e931a29cc21a6b0e9d3549e81abcf8/image7-5.png" />
            
            </figure><p>At power on, the SMpro firmware reads Ampere’s public key (ROTPK) from the SMpro key certificate in SCP EEPROM, computes a hash and compares this to Ampere’s public key hash stored in eFuse. Once authenticated, Ampere’s public key is used to decrypt key and content certificates for SMpro, PMpro, and ATF firmware, which are launched in the order described above.</p><p>The SMpro public key will be used to authenticate the SMpro and PMpro images and ATF keys which in turn will authenticate ATF images. This cascading set of authentication that originates with the Ampere root key and stored in chip called an electronic fuse, or eFuse.  An eFuse can be programmed only once, setting the content to be read-only and can not be tampered with nor modified.</p><p>This is the original hardware root of trust used for signing system, secure world firmware. When we looked at this, after referencing the signing process we had with AMD PSB and knowing there was a large enough one-time-programmable (OTP) region within the SoC, we thought: why can’t we insert our key hash in here?</p>
    <div>
      <h2>Single Domain Secure Boot</h2>
      <a href="#single-domain-secure-boot">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6FQq6V32FKRBNJ8z0efGuP/e718f9c9cf5e8b754b4e2ce5018f904a/image11-2.png" />
            
            </figure><p>Single Domain Secure Boot takes the same authentication flow and adds a hash of the customer public key (Cloudflare firmware signing key in this case) to the eFuse domain. This enables the verification of UEFI firmware by a hardware root of trust. This process is performed in the already validated ATF firmware by BL2. Our public key (dbb) is read from UEFI secure variable storage, a hash is computed and compared to the public key hash stored in eFuse. If they match, the validated public key is used to decrypt the BL33 content certificate, validating and launching the BIOS, and remaining boot items. This is the key feature added by SDSB. It validates the entire software boot chain with a single eFuse root of trust on the processor.</p>
    <div>
      <h2>Building blocks</h2>
      <a href="#building-blocks">
        
      </a>
    </div>
    <p>With a basic understanding of how Single Domain Secure Boot works, the next logical question is “How does it get implemented?”. We ensure that all UEFI firmware is signed at build time, but this process can be better understood if broken down into steps.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7JbZYTpQmAzs85jK66urgj/dd5cf1128921938209c0ea090372eab4/Building-Blocks-1.png" />
            
            </figure><p>Ampere, our original device manufacturer (ODM), and we play a role in execution of SDSB. First, we generate certificates for a public-private key pair using our internal, secure PKI. The public key side is provided to the ODM as dbb.auth and dbu.auth in UEFI secure variable format. Ampere provides a reference Software Release Package (SRP) including the baseboard management controller, system control processor, UEFI, and complex programmable logic device (CPLD) firmware to the ODM, who customizes it for their platform. The ODM generates a board file describing the hardware configuration, and also customizes the UEFI to enroll dbb and dbu to secure variable storage on first boot.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3AtHZs6bsQ0VgTHkNDskFD/6ef31e083683fa462cf1f0f9e0860501/Building-Blocks-2.png" />
            
            </figure><p>Once this is done, we generate a UEFI.slim file using the ODM’s UEFI ROM image, Arm Trusted Firmware (ATF) and Board File. (Note: This differs from AMD PSB insofar as the entire image and ATF files are signed; with AMD PSB, only the first block of boot code is signed.) The entire .SLIM file is signed with our private key, producing a signature hash in the file. This can only be authenticated by the correct public key. Finally, the ODM packages the UEFI into .HPM format compatible with their platform BMC.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/74fFXKUQ6ao22MbxnLRTOZ/8ee373903359790a543c2907280069ec/Security-Provisioning-Firmware.png" />
            
            </figure><p>In parallel, we provide the debug fuse selection and hash of our DER-formatted public key. Ampere uses this information to create a special version of the SCP firmware known as Security Provisioning (SECPROV) .slim format. This firmware is run one time only, to program the debug fuse settings and public key hash into the SoC eFuses. Ampere delivers the SECPROV .slim file to the ODM, who packages it into a .hpm file compatible with the BMC firmware update tooling.</p>
    <div>
      <h2>Fusing the keys</h2>
      <a href="#fusing-the-keys">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5PcDXfMPCbyZHbW06S9TQK/a1fbf46b9176e2291172387cda350829/eFuse-Key-Provisioning.png" />
            
            </figure><p>During system manufacturing, firmware is pre-programmed into storage ICs before placement on the motherboard. Note that the SCP EEPROM contains the SECPROV image, not standard SCP firmware. After a system is first powered on, an IPMI command is sent to the BMC which releases the Ampere processor from reset. This allows SECPROV firmware to run, burning the SoC eFuse with our public key hash and debug fuse settings.</p>
    <div>
      <h2>Final manufacturing flow</h2>
      <a href="#final-manufacturing-flow">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5APB65geJdVYfsHYJDeU5W/b9ce5c4abbf565525110c79852d53e87/Final-manufacturing-flow.png" />
            
            </figure><p>Once our public key has been provisioned, manufacturing proceeds by re-programming the SCP EEPROM with its regular firmware. Once the system powers on, ATF detects there are no keys present in secure variable storage and allows UEFI firmware to boot, regardless of signature. Since this is the first UEFI boot, it programs our public key into secure variable storage and reboots. ATF is validated by Ampere’s public key hash as usual. Since our public key is present in dbb, it is validated against our public key hash in eFuse and allows UEFI to boot.</p>
    <div>
      <h2>Validation</h2>
      <a href="#validation">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/QqpZGCJe52609SFewuSK0/bc0514db4f993630e9ec8b735c38d91e/Validation.png" />
            
            </figure><p>The first part of validation requires observing successful destruction of the eFuses. This imprints our public key hash into a dedicated, immutable memory region, not allowing the hash to be overwritten. Upon automatic or manual issue of an IPMI OEM command to the BMC, the BMC observes a signal from the SECPROV firmware, denoting eFuse programming completion. This can be probed with BMC commands.</p><p>When the eFuses have been blown, validation continues by observing the boot chain of the other firmware. Corruption of the SCP, ATF, or UEFI firmware obstructs boot flow and boot authentication and will cause the machine to fail booting to the OS. Once firmware is in place, happy path validation begins with booting the machine.</p><p>Upon first boot, firmware boots in the following order: BMC, SCP, ATF, and UEFI. The BMC, SCP, and ATF firmware can be observed via their respective serial consoles. The UEFI will automatically enroll the dbb and dbu files to the secure variable storage and trigger a reset of the system.</p><p>After observing the reset, the machine should successfully boot to the OS if the feature is executed correctly. For further validation, we can use the UEFI shell environment to extract the dbb file and compare the hash against the hash submitted to Ampere. After successfully validating the keys, we flash an unsigned UEFI image. An unsigned UEFI image causes authentication failure at bootloader stage BL3-2. The ATF firmware undergoes a boot loop as a result. Similar results will occur for a UEFI image signed with incorrect keys.</p>
    <div>
      <h2>Updated authentication flow</h2>
      <a href="#updated-authentication-flow">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6AsINoXMVNcl9qeYT3mwgz/04850535a1613572e174fec5f40003a0/UEFI-Authentication.png" />
            
            </figure><p>On all subsequent boot cycles, the ATF will read secure variable dbb (our public key), compute a hash of the key, and compare it to the read-only Cloudflare public key hash in eFuse. If the computed and eFuse hashes match, our public key variable can be trusted and is used to authenticate the signed UEFI. After this, the system boots to the OS.</p>
    <div>
      <h2>Let’s boot!</h2>
      <a href="#lets-boot">
        
      </a>
    </div>
    <div></div>
<p></p><p>We were unable to get a machine without the feature enabled to demonstrate the set-up of the feature since we have the eFuse set at build time, but we can demonstrate what it looks like to go between an unsigned BIOS and a signed BIOS. What we would have observed with the set-up of the feature is a custom BMC command to instruct the SCP to burn the ROTPK into the SOC’s OTP fuses. From there, we would observe feedback to the BMC detailing whether burning the fuses was successful. Upon booting the UEFI image for the first time, the UEFI will write the dbb and dbu into secure storage.</p><p>As you can see, after flashing the unsigned BIOS, the machine fails to boot.</p><p>Despite the lack of visibility in failure to boot, there are a few things going on underneath the hood. The SCP (System Control Processor) still boots.</p><ol><li><p>The SCP image holds a key certificate with Ampere’s generated ROTPK and the SCP key hash. SCP will calculate the ROTPK hash and compare it against the burned OTP fuses. In the failure case, where the hash does not match, you will observe a failure as you saw earlier. If successful, the SCP firmware will proceed to boot the PMpro and SMpro. Both the PMpro and SMpro firmware will be verified and proceed with the ATF authentication flow.</p></li><li><p>The conclusion of the SCP authentication is the passing of the BL1 key to the first stage bootloader via the SCP HOB(hand-off-block) to proceed with the standard three stage bootloader ATF authentication mentioned previously.</p></li><li><p>At BL2, the dbb is read out of the secure variable storage and used to authenticate the BL33 certificate and complete the boot process by booting the BL33 UEFI image.</p></li></ol><div></div>
<p></p>
    <div>
      <h2>Still more to do</h2>
      <a href="#still-more-to-do">
        
      </a>
    </div>
    <p>In recent years, management interfaces on servers, like the BMC, have been the target of cyber attacks including ransomware, implants, and disruptive operations. Access to the BMC can be local or remote. With remote vectors open, there is potential for malware to be installed on the BMC via network interfaces. With compromised software on the BMC, malware or spyware could maintain persistence on the server. An attacker might be able to update the BMC directly using flashing tools such as flashrom or socflash without the same level of firmware resilience established at the UEFI level.</p><p>The future state involves using host CPU-agnostic infrastructure to enable a cryptographically secure host prior to boot time. We will look to incorporate a modular approach that has been proposed by the Open Compute Project’s Data Center Secure Control Module Specification (DC-SCM) 2.0 <a href="https://drive.google.com/file/d/13BxuseSrKo647hjIXjp087ei8l5QQVb0/view">specification</a>. This will allow us to standardize our Root of Trust, sign our BMC, and assign physically unclonable function (PUF) based identity keys to components and peripherals to limit the use of OTP fusing. OTP fusing creates a problem with trying to “e-cycle” or reuse machines as you cannot truly remove a machine identity.</p> ]]></content:encoded>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Encryption]]></category>
            <category><![CDATA[Cloudflare Network]]></category>
            <guid isPermaLink="false">1N9Xj1EVgCAmk3Sv1HVHQR</guid>
            <dc:creator>Derek Chamorro</dc:creator>
            <dc:creator>Ryan Chow</dc:creator>
        </item>
        <item>
            <title><![CDATA[Anchoring Trust: A Hardware Secure Boot Story]]></title>
            <link>https://blog.cloudflare.com/anchoring-trust-a-hardware-secure-boot-story/</link>
            <pubDate>Tue, 17 Nov 2020 12:00:00 GMT</pubDate>
            <description><![CDATA[ As a security company, we pride ourselves on finding innovative ways to protect our platform to, in turn, protect the data of our customers. Part of this approach is implementing progressive methods in protecting our hardware at scale. ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/15nAX8kXKg4gz7jDCecogD/f2340b560358c5d4c25f5ff7fbb77325/anchor2-2-1.png" />
            
            </figure><p>As a security company, we pride ourselves on finding innovative ways to protect our platform to, in turn, protect the data of our customers. Part of this approach is implementing progressive methods in protecting our hardware at scale. While we have blogged about how we address security threats from <a href="/mitigating-spectre-and-other-security-threats-the-cloudflare-workers-security-model/">application</a> to <a href="/securing-memory-at-epyc-scale/">memory</a>, the attacks on hardware, as well as firmware, have increased substantially. The data cataloged in the <a href="https://nvd.nist.gov/">National Vulnerability Database (NVD)</a> has shown the frequency of hardware and firmware-level vulnerabilities rising year after year.</p><p>Technologies like <a href="https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-secure-boot">secure boot</a>, common in desktops and laptops, have been ported over to the server industry as a method to combat firmware-level attacks and protect a device’s boot integrity. These technologies require that you create a trust ‘anchor’, an authoritative entity for which trust is assumed and not derived. A common trust anchor is the system <a href="https://en.wikipedia.org/wiki/BIOS">Basic Input/Output System (BIOS)</a> or the <a href="https://www.uefi.org/">Unified Extensible Firmware Interface (UEFI</a>) firmware.</p><p>While this ensures that the device boots only signed firmware and operating system bootloaders, does it protect the entire boot process? What protects the BIOS/UEFI firmware from attacks?</p>
    <div>
      <h2>The Boot Process</h2>
      <a href="#the-boot-process">
        
      </a>
    </div>
    <p>Before we discuss how we secure our boot process, we will first go over how we boot our machines.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3ubWFPurTNwYnbXL8EnVpl/bd8c93e0e7acedf04b2787816be51e6d/image1-7.png" />
            
            </figure><p>The above image shows the following sequence of events:</p><ul><li><p>After powering on the system (through a <a href="https://www.gigabyte.com/Glossary/bmc">baseboard management controller (BMC)</a> or physically pushing a button on the system), the system unconditionally executes the UEFI firmware residing on a flash chip on the motherboard.</p></li><li><p>UEFI performs some hardware and peripheral initialization and executes the <a href="https://wiki.debian.org/PXEBootInstall">Preboot Execution Environment (PXE)</a> code, which is a small program that boots an image over the network and usually resides on a flash chip on the network card.</p></li><li><p>PXE sets up the network card, and downloads and executes a small program bootloader through an open source boot firmware called <a href="https://ipxe.org/">iPXE</a>.</p></li><li><p>iPXE loads a script that automates a sequence of commands for the bootloader to know how to boot a specific operating system (sometimes several of them). In our case, it loads our Linux kernel, <code>initrd</code> (this contains device drivers which are not directly compiled into the kernel), and a standard Linux root filesystem. After loading these components, the bootloader executes and hands off the control to the kernel.</p></li><li><p>Finally, the Linux kernel loads any additional drivers it needs and starts applications and services.</p></li></ul>
    <div>
      <h2>UEFI Secure Boot</h2>
      <a href="#uefi-secure-boot">
        
      </a>
    </div>
    <p>Our UEFI secure boot process is fairly straightforward, albeit customized for our environments. After loading the UEFI firmware from the bootloader, an initialization script defines the following variables:</p><p><b>Platform Key (PK):</b> It serves as the cryptographic root of trust for secure boot, giving capabilities to manipulate and/or validate the other components of the <a href="https://blog.hansenpartnership.com/the-meaning-of-all-the-uefi-keys/">secure boot framework</a>.</p><p><b>Trusted Database (DB):</b> Contains a signed (by platform key) list of hashes of all PCI option ROMs, as well as a public key, which is used to verify the signature of the bootloader and the kernel on boot.</p><p>These variables are respectively the master platform public key, which is used to sign all other resources, and an allow list database, containing other certificates, binary file hashes, etc. In default secure boot scenarios, Microsoft keys are used by default. At Cloudflare we use our own, which makes us the root of trust for UEFI:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/12zsC1QVrT8uIGMG0K6ss8/92c1d1cdaf9348b03794be40943c81f8/image7.png" />
            
            </figure><p>But, by setting our trust anchor in the UEFI firmware, what attack vectors still exist?</p>
    <div>
      <h2>UEFI Attacks</h2>
      <a href="#uefi-attacks">
        
      </a>
    </div>
    <p>As stated previously, firmware and hardware attacks are on the rise. It is clear from the figure below that firmware-related vulnerabilities have increased significantly over the last 10 years, especially since 2017, when the hacker community started attacking the firmware on different platforms:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7gyyxjhnApSBYfZEdqglcS/d863b610573c1ca0b497b1b3e1ebf2cc/image14.png" />
            
            </figure><p>This upward trend, coupled with <a href="https://arstechnica.com/information-technology/2020/10/custom-made-uefi-bootkit-found-lurking-in-the-wild/">recent malware findings in UEFI</a>, shows that trusting firmware is becoming increasingly problematic.</p><p>By tainting the UEFI firmware image, you poison the entire boot trust chain. The ability to trust firmware integrity is important beyond secure boot. For example, if you can't trust the firmware not to be compromised, you can't trust things like <a href="https://docs.microsoft.com/en-us/windows/security/information-protection/tpm/trusted-platform-module-overview">trusted platform module (TPM) measurements</a> to be accurate, because the firmware is itself responsible for doing these measurements (e.g a TPM is not an on-path security mechanism, but instead it requires firmware to interact and cooperate with). Firmware may be crafted to extend measurements that are accepted by a remote attestor, but that don't represent what's being locally loaded. This could cause firmware to have a questionable measured boot and remote attestation procedure.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3hTmUFGH3CZwcPD6CXmASh/4a26d01153fb10cd9b11d461be513005/image11.png" />
            
            </figure><p>If we can’t trust firmware, then hardware becomes our last line of defense.</p>
    <div>
      <h2>Hardware Root of Trust</h2>
      <a href="#hardware-root-of-trust">
        
      </a>
    </div>
    <p>Early this year, we made a series of blog posts on <a href="/technical-details-of-why-cloudflare-chose-amd-epyc-for-gen-x-servers/">why we chose AMD EPYC processors</a> for our Gen X servers. With security in mind, we started <a href="/securing-memory-at-epyc-scale/">turning on</a> features that were available to us and set forth the plan of using AMD silicon as a Hardware Root of Trust (HRoT).</p><p><a href="https://www.amd.com/system/files/2017-06/Trusting-in-the-CPU.pdf">Platform Secure Boot</a> (PSB) is AMD’s implementation of hardware-rooted boot integrity. Why is it better than UEFI firmware-based root of trust? Because it is intended to assert, by a root of trust anchored in the hardware, the integrity and authenticity of the System ROM image before it can execute. It does so by performing the following actions:</p><ul><li><p>Authenticates the first block of BIOS/UEFI prior to releasing x86 CPUs from reset.</p></li><li><p>Authenticates the System Read-Only Memory (ROM) contents on each boot, not just during updates.</p></li><li><p>Moves the UEFI Secure Boot trust chain to immutable hardware.</p></li></ul><p>This is accomplished by the AMD Platform Security Processor (PSP), an ARM Cortex-A5 microcontroller that is an immutable part of the system on chip (SoC). The PSB consists of two components:</p><p><b><b><b>On-chip Boot ROM</b></b></b></p><ul><li><p>Embeds a SHA384 hash of an AMD root signing key</p></li><li><p>Verifies and then loads the off-chip PSP bootloader located in the boot flash</p></li></ul><p><b><b><b>Off-chip Boot</b></b></b><b><b>**l</b></b>oader******</p><ul><li><p>Locates the PSP directory table that allows the PSP to find and load various images</p></li><li><p>Authenticates first block of BIOS/UEFI code</p></li><li><p>Releases CPUs after successful authentication</p></li></ul>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5ABw5l5aHps4VcM0wHACDq/e0eaaf60f0ffee8317d88d049f3c594c/image4.gif" />
            
            </figure><ol><li><p>The PSP secures the On-chip Boot ROM code, loads the off-chip PSP firmware into PSP static random access memory (SRAM) after authenticating the firmware, and passes control to it.</p></li><li><p>The Off-chip Bootloader (BL) loads and specifies applications in a specific order (whether or not the system goes into a debug state and then a secure EFI application binary interface to the BL)</p></li><li><p>The system continues initialization through each bootloader stage.</p></li><li><p>If each stage passes, then the UEFI image is loaded and the x86 cores are released.</p></li></ol><p>Now that we know the booting steps, let’s build an image.</p>
    <div>
      <h2>Build Process</h2>
      <a href="#build-process">
        
      </a>
    </div>
    
    <div>
      <h3></h3>
      <a href="#">
        
      </a>
    </div>
    <p>Public Key Infrastructure</p><p>Before the image gets built, a public key infrastructure (PKI) is created to generate the key pairs involved for signing and validating signatures:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7CGqAcYMPxBE9kv0ZcjGwL/0ffb73c3d6b1353b0291b1736ff0f599/image10.png" />
            
            </figure><p>Our original device manufacturer (ODM), as a trust extension, creates a key pair (public and private) that is used to sign the first segment of the BIOS (private key) and validates that segment on boot (public key).</p><p>On AMD’s side, they have a key pair that is used to sign (the AMD root signing private key) and certify the public key created by the ODM. This is validated by AMD’s root signing public key, which is stored as a hash value (<a href="https://tools.ietf.org/html/rfc5756">RSASSA-PSS</a>: SHA-384 with 4096-bit key is used as the hashing algorithm for both message and mask generation) in <a href="https://en.wikipedia.org/wiki/Serial_Peripheral_Interface">SPI-ROM</a>.</p><p>Private keys (both AMD and ODM) are stored in <a href="https://en.wikipedia.org/wiki/Hardware_security_module">hardware security modules</a>.</p><p>Because of the way the PKI mechanisms are built, the system cannot be compromised if only one of the keys is leaked. This is an important piece of the trust hierarchy that is used for image signing.</p>
    <div>
      <h3>Certificate Signing Request</h3>
      <a href="#certificate-signing-request">
        
      </a>
    </div>
    <p>Once the PKI infrastructure is established, a BIOS signing key pair is created, together with a certificate signing request (CSR). Creating the CSR uses known common name (CN) fields that many are familiar with:</p><ul><li><p><code>countryName</code></p></li><li><p><code>stateOrProvinceName</code></p></li><li><p><code>localityName</code></p></li><li><p><code>organizationName</code></p></li></ul><p>In addition to the fields above, the CSR will contain a <code>serialNumber</code> field, a 32-bit integer value represented in ASCII HEX format that encodes the following values:</p><ul><li><p><code>PLATFORM_VENDOR_ID</code>: An 8-bit integer value assigned by AMD for each ODM.</p></li><li><p><code>PLATFORM_MODEL_ID</code>: A 4-bit integer value assigned to a platform by the ODM.</p></li><li><p><code>BIOS_KEY_REVISION_ID</code>: is set by the ODM encoding a 4-bit key revision as unary counter value.</p></li><li><p><code>DISABLE_SECURE_DEBUG</code>: Fuse bit that controls whether secure debug unlock feature is disabled permanently.</p></li><li><p><code>DISABLE_AMD_BIOS_KEY_USE</code>: Fuse bit that controls if the BIOS, signed by an AMD key, (with <code>vendor ID == 0</code>) is permitted to boot on a CPU with non-zero Vendor ID.</p></li><li><p><code>DISABLE_BIOS_KEY_ANTI_ROLLBACK</code>: Fuse bit that controls whether BIOS key anti-rollback feature is enabled.</p></li></ul>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7jqoVoEKDiRSoVt9MbdY0W/0f4d2d505e12ecef65a6b31648f223d1/image3-3.png" />
            
            </figure><p>Remember these values, as we’ll show how we use them in a bit. Any of the <code>DISABLE</code> values are optional, but recommended based on your security posture/comfort level.</p><p>AMD, upon processing the CSR, provides the public part of the BIOS signing key signed and certified by the AMD signing root key as a RSA Public Key Token file (<code>.stkn</code>) format.</p>
    <div>
      <h2>Putting It All Together</h2>
      <a href="#putting-it-all-together">
        
      </a>
    </div>
    <p>The following is a step-by-step illustration of how signed UEFI firmware is built:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/48teEpwD6WwiJEVvSql73e/203673a7e6265f4d799c2b31ec9f492a/image8.gif" />
            
            </figure><ol><li><p>The ODM submits their public key used for signing Cloudflare images to AMD.</p></li><li><p>AMD signs this key using their RSA private key and passes it back to ODM.</p></li><li><p>The AMD public key and the signed ODM public key are part of the final BIOS SPI image.</p></li><li><p>The BIOS source code is compiled and various BIOS components (PEI Volume, Driver eXecution Environment (DXE) volume, NVRAM storage, etc.) are <a href="https://edk2-docs.gitbook.io/edk-ii-build-specification/2_design_discussion/23_boot_sequence">built as usual.</a></p></li><li><p>The PSP directory and BIOS directory are built next. PSP directory and BIOS directory table points to the location of various firmware entities.</p></li><li><p>The ODM builds the signed BIOS Root of Trust Measurement (RTM) signature based on the blob of BIOS PEI volume concatenated with BIOS Directory header, and generates the digital signature of this using the private portion of ODM signing key. The SPI location for signed BIOS RTM code is finally updated with this signature blob.</p></li><li><p>Finally, the BIOS binaries, PSP directory, BIOS directory and various firmware binaries are combined to build the SPI BIOS image.</p></li></ol>
    <div>
      <h2>Enabling Platform Secure Boot</h2>
      <a href="#enabling-platform-secure-boot">
        
      </a>
    </div>
    <p>Platform Secure Boot is enabled at boot time with a PSB-ready firmware image. PSB is configured using a region of one-time programmable (OTP) fuses, specified for the customer. OTP fuses are on-chip non-volatile memory (NVM) that permits data to be written to memory only once. There is <b>NO</b> way to roll the fused CPU back to an unfused one.</p><p>Enabling PSB in the field will go through two steps: fusing and validating.</p><ul><li><p>Fusing: Fuse the values assigned in the <code>serialNumber</code> field that was generated in the CSR</p></li><li><p>Validating: Validate the fused values and the status code registers</p></li></ul><p>If validation is successful, the BIOS RTM signature is validated using the ODM BIOS signing key, PSB-specific registers (<code>MP0_C2P_MSG_37</code> and <code>MP0_C2P_MSG_38</code>) are updated with the PSB status and fuse values, and the x86 cores are released</p><p>If validation fails, the registers above are updated with the PSB error status and fuse values, and the x86 cores stay in a locked state.</p>
    <div>
      <h2>Let’s Boot!</h2>
      <a href="#lets-boot">
        
      </a>
    </div>
    <p>With a signed image in hand, we are ready to enable PSB on a machine. We chose to deploy this on a few machines that had an updated, unsigned <a href="https://ami.com/en/support/bios-uefi-firmware-support/">AMI UEFI</a> firmware image, in this case version <code>2.16</code>. We use a couple of different firmware <a href="https://github.com/Zibri/afulnx/releases">update</a> <a href="https://downloadcenter.intel.com/download/29977?v=t">tools</a>, so, after a quick script, we ran an update to change the firmware version from <code>2.16</code> to <code>2.18C</code> (the signed image):</p>
            <pre><code>. $sudo ./UpdateAll.sh
Bin file name is ****.218C

BEGIN

+---------------------------------------------------------------------------+
|                 AMI Firmware Update Utility v5.11.03.1778                 |      
|                 Copyright (C)2018 American Megatrends Inc.                |                       
|                         All Rights Reserved.                              |
+---------------------------------------------------------------------------+
Reading flash ............... done
FFS checksums ......... ok
Check RomLayout ........ ok.
Erasing Boot Block .......... done
Updating Boot Block ......... done
Verifying Boot Block ........ done
Erasing Main Block .......... done
Updating Main Block ......... done
Verifying Main Block ........ done
Erasing NVRAM Block ......... done
Updating NVRAM Block ........ done
Verifying NVRAM Block ....... done
Erasing NCB Block ........... done
Updating NCB Block .......... done
Verifying NCB Block ......... done

Process completed.</code></pre>
            <p>After the update completed, we rebooted:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2ZW4E36XqbrlpgvXyjR34t/21625b6e4691951b840d4d0d7bb91c5b/image2-6.png" />
            
            </figure><p>After a successful install, we validated that the image was correct via the <a href="https://man7.org/linux/man-pages/man5/sysfs.5.html">sysfs</a> information provided in the <a href="https://linux.die.net/man/8/dmidecode">dmidecode</a> output:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1gIi4xRxwq4PfpxAjc2nnA/6262739c2730a1c85865a59dd168ada7/image12.gif" />
            
            </figure>
    <div>
      <h3>Testing</h3>
      <a href="#testing">
        
      </a>
    </div>
    <p>With a signed image installed, we wanted to test that it worked, meaning: what if an unauthorized user installed their own firmware image? We did this by downgrading the image back to an unsigned image, <code>2.16</code>. In theory, the machine shouldn’t boot as the x86 cores should stay in a locked state. After downgrading, we rebooted and got the following:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7HQqHnKOTSHg1YQOyZq35A/2209455a149759a90c474970bb9bf6ad/image13-1.jpg" />
            
            </figure><p>This isn’t a powered down machine, but the result of booting with an unsigned image.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/y9RGO5UGzOEG1lxRyPJa2/818ecd62bc892f61097cf369d1b599a2/image9.jpg" />
            
            </figure><p>Flashing back to a signed image is done by running the same flashing utility through the BMC, so we weren’t bricked. Nonetheless, the results were successful.</p>
    <div>
      <h2>Naming Convention</h2>
      <a href="#naming-convention">
        
      </a>
    </div>
    <p>Our standard UEFI firmware images are alphanumeric, making it difficult to distinguish (by name) the difference between a signed and unsigned image (<code>v2.16A</code> vs <code>v2.18C</code>), for example. There isn’t a remote attestation capability (yet) to probe the PSB status registers or to store these values by means of a signature (e.g. <a href="https://linux.die.net/man/8/tpm_quote_tools">TPM quote</a>). As we transitioned to PSB, we wanted to make this easier to determine by adding a specific suffix: <code>-sig</code>  that we could query in userspace. This would allow us to query this information via <a href="https://prometheus.io/">Prometheus</a>. Changing the file name alone wouldn’t do it, so we had to make the following changes to reflect a new naming convention for signed images:</p><ul><li><p>Update filename</p></li><li><p>Update BIOS version for setup menu</p></li><li><p>Update post message</p></li><li><p>Update <a href="https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf">SMBIOS type 0</a> (BIOS version string identifier)</p></li></ul><p>Signed images now have a <code>-sig</code> suffix:</p>
            <pre><code>~$ sudo dmidecode -t0
# dmidecode 3.2
Getting SMBIOS data from sysfs.
SMBIOS 3.3.0 present.
# SMBIOS implementations newer than version 3.2.0 are not
# fully supported by this version of dmidecode.

Handle 0x0000, DMI type 0, 26 bytes
BIOS Information
	Vendor: American Megatrends Inc.
	Version: V2.20-sig
	Release Date: 09/29/2020
	Address: 0xF0000
	Runtime Size: 64 kB
	ROM Size: 16 MB</code></pre>
            
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Finding weaknesses in firmware is a challenge that many attackers have taken on. Attacks that physically manipulate the firmware used for performing hardware initialization during the booting process can invalidate many of the common secure boot features that are considered industry standard. By implementing a hardware root of trust that is used for code signing critical boot entities, your hardware becomes a 'first line of defense' in ensuring that your server hardware and software integrity can derive trust through cryptographic means.</p>
    <div>
      <h2>What’s Next?</h2>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>While this post discussed our current, AMD-based hardware platform, how will this affect our future hardware generations? One of the benefits of working with diverse vendors like AMD and <a href="https://amperecomputing.com/">Ampere</a> (ARM) is that we can ensure they are baking in our desired platform security by default (which we’ll speak about in a future post), making our hardware security outlook that much brighter ?.</p> ]]></content:encoded>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Encryption]]></category>
            <category><![CDATA[Data Center]]></category>
            <category><![CDATA[Cloudflare Network]]></category>
            <guid isPermaLink="false">m0jUp84VV1cK5dqLgVh32</guid>
            <dc:creator>Derek Chamorro</dc:creator>
            <dc:creator>Ryan Chow</dc:creator>
        </item>
    </channel>
</rss>