core/manifest/pcd/pcd.h (114 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. #ifndef PCD_H_ #define PCD_H_ #include <stdbool.h> #include <stddef.h> #include <stdint.h> #include "cmd_interface/device_manager.h" #include "manifest/manifest.h" #include "status/rot_status.h" /** * Container for RoT info. */ struct pcd_rot_info { bool is_pa_rot; /**< Flag indicating if RoT is a PA-RoT */ uint8_t port_count; /**< Number of ports directly protected by RoT */ uint8_t components_count; /**< Number of components attested by RoT */ uint8_t i2c_slave_addr; /**< I2C slave address */ uint8_t eid; /**< MCTP EID */ uint8_t bridge_i2c_addr; /**< MCTP bridge I2C address */ uint8_t bridge_eid; /**< MCTP bridge EID */ uint32_t attestation_success_retry; /**< Wait time before reattesting after device succeeds attestation, in ms. */ uint32_t attestation_fail_retry; /**< Wait time before reattesting after device fails attestation, in ms. */ uint32_t discovery_fail_retry; /**< Wait time before retrying after device fails discovery, in ms. */ uint32_t mctp_ctrl_timeout; /**< MCTP control protocol response timeout period, in ms. */ uint32_t mctp_bridge_get_table_wait; /**< Wait time after RoT boots to send MCTP get table request, in ms. If 0, RoT only waits for EID assignment. */ uint32_t mctp_bridge_additional_timeout; /**< Additional time for timeout period due to MCTP bridge, in ms. */ uint32_t attestation_rsp_not_ready_max_duration; /**< Maximum duration to wait before retrying after receiving SPDM ResponseNotReady error, in ms. */ uint8_t attestation_rsp_not_ready_max_retry; /**< Maximum number of SPDM ResponseNotReady retries permitted by device. */ }; /** * Flags for host reset action setting. */ enum pcd_port_host_reset_action { PCD_PORT_HOST_RESET_ACTION_NONE = 0x0, /**< No action on host reset. */ PCD_PORT_HOST_RESET_ACTION_RESET_FLASH = 0x1, /**< Reset flash on host reset. */ }; /** * Flags for port watchdog monitoring setting. */ enum pcd_port_watchdog_monitoring { PCD_PORT_WATCHDOG_MONITORING_DISABLED = 0x0, /**< Watchdog monitoring disabled. */ PCD_PORT_WATCHDOG_MONITORING_ENABLED = 0x1, /**< Watchdog monitoring enabled. */ }; /** * Flags for port runtime verification setting. */ enum pcd_port_runtime_verification { PCD_PORT_RUNTIME_VERIFICATION_DISABLED = 0x0, /**< Runtime verification disabled. */ PCD_PORT_RUNTIME_VERIFICATION_ENABLED = 0x1, /**< Runtime verification enabled. */ }; /** * Flags for port flash mode. */ enum pcd_port_flash_mode { PCD_PORT_FLASH_MODE_DUAL = 0x0, /**< Dual flash mode. */ PCD_PORT_FLASH_MODE_SINGLE = 0x1, /**< Single flash mode. */ PCD_PORT_FLASH_MODE_DUAL_FILTERED_BYPASS = 0x2, /**< Dual flash mode with filtered bypass. */ PCD_PORT_FLASH_MODE_SINGLE_FILTERED_BYPASS = 0x3, /**< Single flash mode with filtered bypass. */ PCD_PORT_FLASH_MODE_RESERVED, /**< Reserved value. */ }; /** * Flags for port reset control. */ enum pcd_port_reset_control { PCD_PORT_RESET_CTRL_NOTIFY = 0x0, /**< Notify when port reset pin toggled. */ PCD_PORT_RESET_CTRL_RESET = 0x1, /**< Reset port when port reset pin toggled. */ PCD_PORT_RESET_CTRL_PULSE = 0x2, /**< Reset is pulsed after validation. */ PCD_PORT_RESET_CTRL_RESERVED, /**< Reserved value. */ }; /** * Container for RoT port info. */ struct pcd_port_info { uint32_t spi_freq; /**< Port SPI frequency */ enum pcd_port_flash_mode flash_mode; /**< Port flash mode */ enum pcd_port_reset_control reset_ctrl; /**< Port reset control */ uint8_t policy; /**< Port attestation policy */ enum pcd_port_runtime_verification runtime_verification; /**< Runtime verification setting */ enum pcd_port_watchdog_monitoring watchdog_monitoring; /**< Watchdog monitoring setting */ enum pcd_port_host_reset_action host_reset_action; /**< Host reset action setting */ uint8_t pulse_interval; /**< Pulse interval in multiples of 10ms */ }; /** * Flags for I2C mode. */ enum pcd_i2c_mode { PCD_I2C_MODE_MULTIMASTER = 0x0, /**< MultiMaster I2C communication scheme. */ PCD_I2C_MODE_MASTER_SLAVE = 0x1, /**< Master/Slave I2C communication scheme. */ PCD_I2C_MODE_RESERVED, /**< Reserved value. */ }; /** * Container for power controller info. */ struct pcd_power_controller_info { uint8_t mux_count; /**< Number of muxes to reach power controller */ enum pcd_i2c_mode i2c_mode; /**< Power controller I2C mode */ uint8_t bus; /**< Bus power controller is on */ uint8_t address; /**< Power controller address */ uint8_t eid; /**< MCTP EID used by power controller if any */ }; /** * Container for mux info. */ struct pcd_mux_info { uint8_t address; /**< Mux address */ uint8_t channel; /**< Mux channel to utilize */ }; /** * Container for MCTP bridge components info. */ struct pcd_mctp_bridge_components_info { void *context; /**< Implementation context. */ uint32_t component_id; /**< Unique identifier for component type connected to bridge */ uint16_t pci_vid; /**< PCI Vendor ID */ uint16_t pci_device_id; /**< PCI Device ID */ uint16_t pci_subsystem_vid; /**< PCI Subsystem Vendor ID */ uint16_t pci_subsystem_id; /**< PCI Subsystem ID */ uint8_t components_count; /**< Number of identical components this element describes. */ }; #pragma pack(push, 1) /** * Details for a single component type supported by a PCD. */ struct pcd_supported_component { uint32_t component_id; /**< Unique identifier for component type supported by PCD. */ uint8_t component_count; /**< Number of identical components this element describes. */ }; #pragma pack(pop) /** * The API for interfacing with a PCD file. */ struct pcd { struct manifest base; /**< Manifest interface */ /** * Get list of supported component IDs from PCD. * * @param pcd The PCD to query. * @param offset The byte offset within the overall list of supported component IDs that should * be returned. * @param length The maximum length of component ID information that should be returned, in * bytes. * @param component_ids Output buffer for the list of supported component IDs. This information * will be stored as a list of {@link struct pcd_supported_component} entries. However, depending * on offset and length parameters, it may not contain complete entries at the beginning or end * of the list. * * @return The number of bytes written to the output buffer or an error code. Use ROT_IS_ERROR * to check the return value. */ int (*buffer_supported_components) (const struct pcd *pcd, size_t offset, size_t length, uint8_t *pcd_component_ids); /** * Get next MCTP bridge component from PCD. * * @param pcd The PCD to query. * @param component A container to be updated with the component information. If first is not * true, then same container that was passed previously needs to be passed in. Instances never * passed to this function need to have first set to true. * @param first Fetch first MCTP bridge component from PCD, or next MCTP component since last * call. * * @return 0 if a component was found or an error code. */ int (*get_next_mctp_bridge_component) (const struct pcd *pcd, struct pcd_mctp_bridge_components_info *component, bool first); /* TODO Implement a similar function to get_next_mctp_bridge_component for direct connection components */ /** * Get RoT info. * * @param pcd The PCD to query. * @param info Container with RoT info. * * @return 0 if the RoT info was retrieved successfully or an error code. */ int (*get_rot_info) (const struct pcd *pcd, struct pcd_rot_info *info); /** * Get RoT port info. * * @param pcd The PCD to query. * @param port_id ID of requested port. * @param info Info for requested port. * * @return 0 if the port info was retrieved successfully or an error code. */ int (*get_port_info) (const struct pcd *pcd, uint8_t port_id, struct pcd_port_info *info); /** * Get power controller info. * * @param pcd The PCD to query. * @param info Container with power controller info. * * @return 0 if the power controller info was retrieved successfully or an error code. */ int (*get_power_controller_info) (const struct pcd *pcd, struct pcd_power_controller_info *info); }; #define PCD_ERROR(code) ROT_ERROR (ROT_MODULE_PCD, code) /** * Error codes that can be generated by a PCD. */ enum { PCD_INVALID_ARGUMENT = PCD_ERROR (0x00), /**< Input parameter is null or not valid. */ PCD_NO_MEMORY = PCD_ERROR (0x01), /**< Memory allocation failed. */ PCD_INVALID_PORT = PCD_ERROR (0x02), /**< Port not found in PCD. */ PCD_UNKNOWN_COMPONENT = PCD_ERROR (0x03), /**< The component identifier is not present in the PCD. */ PCD_MALFORMED_ROT_ELEMENT = PCD_ERROR (0x04), /**< PCD RoT element too short. */ PCD_MALFORMED_DIRECT_I2C_COMPONENT_ELEMENT = PCD_ERROR (0x05), /**< PCD direct i2c component element too short. */ PCD_MALFORMED_BRIDGE_COMPONENT_ELEMENT = PCD_ERROR (0x06), /**< PCD bridge component element too short. */ PCD_MALFORMED_PORT_ELEMENT = PCD_ERROR (0x07), /**< PCD port element too short. */ }; #endif /* PCD_H_ */