# BIOS->BMC SMM Error Logging Queue Daemon Author: - Brandon Kim / brandonkim@google.com / @brandonk Other contributors: - Marco Cruz-Heredia / mcruzheredia@google.com Created: Mar 15, 2022 ## Problem Description We've identified use cases where the BIOS will go into System Management Mode (SMM) to provide error logs to the BMC, requiring messages to be sent as quickly as possible without a handshake / ack back from the BMC due to the time constraint that it's under. The goal of this daemon we are proposing is to implement a circular buffer over a shared BIOS->BMC buffer that the BIOS can fire-and-forget. ## Background and References There are various ways of communicating between the BMC and the BIOS, but there are only a few that don't require a handshake and lets the data persist in shared memory. These will be listed in the "Alternatives Considered" section. Different BMC vendors support different methods such as Shared Memory (SHM, via LPC / eSPI) and P2A or PCI Mailbox, but the existing daemon that utilizes them do it over IPMI blob to communicate where and how much data has been transferred (see [phosphor-ipmi-flash](https://github.com/openbmc/phosphor-ipmi-flash) and [libmctp/astlpc](https://github.com/openbmc/libmctp/blob/master/docs/bindings/vendor-ibm-astlpc.md)) ## Requirements The fundamental requirements for this daemon are listed as follows: 1. The BMC shall initialize the shared buffer in a way that the BIOS can recognize when it can write to the buffer 2. After initialization, the BIOS shall not have to wait for an ack back from the BMC before any writes to the shared buffer (**no synchronization**) 3. The BIOS shall be the main writer to the shared buffer, with the BMC mainly reading the payloads, only writing to the buffer to update the header 4. The BMC shall read new payloads from the shared buffer for further processing 5. The BIOS must be able to write a payload (~1KB) to the buffer within 50µs The shared buffer will be as big as the protocol allows for a given BMC platform (for Nuvoton's PCI Mailbox for NPCM 7xx as an example, 16KB) and each of the payloads is estimated to be less than 1KB. This daemon assumes that no other traffic will communicate through the given protocol. The circular buffer and its header will provide some protection against corruption, but it should not be relied upon. ## Proposed Design The implementation of interfacing with the shared buffer will very closely follow [phosphor-ipmi-flash](https://github.com/openbmc/phosphor-ipmi-flash). In the future, it may be wise to extract out the PCI Mailbox, P2A and LPC as separate libraries shared between `phosphor-ipmi-flash` and this daemon to reduce duplication of code. Taken from Marco's (mcruzheredia@google.com) internal design document for the circular buffer, the data structure of its header will look like the following: | Name | Size | Offset | Written by | Description | | ----------------------------------- | -------------------------------- | ----------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | BMC Interface Version | 4 bytes | 0x0 | BMC at init | Allows the BIOS to determine if it is compatible with the BMC | | BIOS Interface Version | 4 bytes | 0x4 | BIOS at init | Allows the BMC to determine if it is compatible with the BIOS | | Magic Number | 16 bytes | 0x8 | BMC at init | Magic number to set the state of the queue as described below. Written by BMC once the memory region is ready to be used. Must be checked by BIOS before logging. BMC can change this number when it suspects data corruption to prevent BIOS from writing anything during reinitialization | | Queue size | 3 bytes | 0x18 | BMC at init | Indicates the size of the region allocated for the circular queue. Written by BMC on init only, should not change during runtime. **This includes the size of the header and UE region size** | | Uncorrectable Error region size | 2 bytes | 0x1b | BMC at init | Indicates the size of the region reserved for Uncorrectable Error (UE) logs. Written by BMC on init only, should not change during runtime | | BMC flags | 4 bytes | 0x1d | BMC |