Merged PR 1626: support v2 pcds
support v2 pcds Related work items: #499, #840, #863, #885
This commit is contained in:
Родитель
de051b8c0d
Коммит
6306b55da5
|
@ -11,4 +11,4 @@ build
|
|||
*~
|
||||
*.bin
|
||||
*.pyc
|
||||
|
||||
tools/manifest_visualizer/manifest_visualizor
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
#define PFM_V2_MAGIC_NUM 0x706D
|
||||
#define CFM_MAGIC_NUM 0xA592
|
||||
#define CFM_V2_MAGIC_NUM MANIFEST_NOT_SUPPORTED
|
||||
#define PCD_MAGIC_NUM 0x8EBC
|
||||
#define PCD_V2_MAGIC_NUM MANIFEST_NOT_SUPPORTED
|
||||
#define PCD_MAGIC_NUM MANIFEST_NOT_SUPPORTED
|
||||
#define PCD_V2_MAGIC_NUM 0x1029
|
||||
|
||||
/**
|
||||
* Identifier for the hash algorithm used for signatures and other verificitaion hashes in
|
||||
|
@ -58,6 +58,7 @@ enum manifest_key_type {
|
|||
*/
|
||||
#define manifest_get_key_type(sig_type) ((enum manifest_key_type) ((sig_type) & 0xf8))
|
||||
|
||||
#pragma pack(push, 1)
|
||||
/**
|
||||
* The header information on a manifest.
|
||||
*/
|
||||
|
@ -138,6 +139,7 @@ struct manifest_platform_id {
|
|||
uint8_t id_length; /**< Length of the platform ID string. */
|
||||
uint8_t reserved[3]; /**< Unused. */
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
#endif /* MANIFEST_FORMAT_H_ */
|
||||
|
|
|
@ -13,28 +13,45 @@
|
|||
|
||||
|
||||
/**
|
||||
* I2C interface modes
|
||||
*/
|
||||
enum {
|
||||
PCD_I2C_MULTIMASTER = 0,
|
||||
PCD_I2C_MASTER_SLAVE,
|
||||
NUM_PCD_I2C_MODES
|
||||
};
|
||||
|
||||
/**
|
||||
* Container for a RoT info.
|
||||
* 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 componenets attested by RoT */
|
||||
uint8_t i2c_slave_addr; /**< I2C slave address */
|
||||
uint8_t bmc_i2c_addr; /**< BMC I2C address */
|
||||
uint8_t eid; /**< MCTP EID */
|
||||
uint8_t bridge_i2c_addr; /**< MCTP bridge I2C address */
|
||||
uint8_t bridge_eid; /**< MCTP bridge EID */
|
||||
};
|
||||
|
||||
/**
|
||||
* Container for an RoT port info.
|
||||
* Container for RoT port info.
|
||||
*/
|
||||
struct pcd_port_info {
|
||||
uint32_t spi_freq; /**< Port SPI frequency */
|
||||
uint8_t flash_mode; /**< Port flash mode */
|
||||
uint8_t reset_ctrl; /**< Port reset control */
|
||||
uint8_t policy; /**< Port attestation policy */
|
||||
};
|
||||
|
||||
/**
|
||||
* Container for power controller info.
|
||||
*/
|
||||
struct pcd_power_controller_info {
|
||||
uint8_t mux_count; /**< Number of muxes to reach power controller */
|
||||
uint8_t 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 */
|
||||
};
|
||||
|
||||
/**
|
||||
* Containter for mux info.
|
||||
*/
|
||||
struct pcd_mux_info {
|
||||
uint8_t address; /**< Mux address */
|
||||
uint8_t channel; /**< Mux channel to utilize */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -76,6 +93,16 @@ struct pcd {
|
|||
* @return 0 if the port info was retrieved successfully or an error code.
|
||||
*/
|
||||
int (*get_port_info) (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) (struct pcd *pcd, struct pcd_power_controller_info *info);
|
||||
};
|
||||
|
||||
|
||||
|
@ -85,13 +112,13 @@ struct pcd {
|
|||
* 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_BUF_TOO_SMALL = PCD_ERROR (0x02), /**< The buffer provided is too small for requested contents. */
|
||||
PCD_UNKNOWN_COMPONENT = PCD_ERROR (0x03), /**< The component identifier is not present in the PCD. */
|
||||
PCD_INVALID_SEG_LEN = PCD_ERROR (0x04), /**< Segment in PCD has invalid length. */
|
||||
PCD_INVALID_SEG_HDR_LEN = PCD_ERROR (0x05), /**< Segment header in PCD has invalid length. */
|
||||
PCD_INVALID_PORT = PCD_ERROR (0x06), /**< Port not found in PCD. */
|
||||
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. */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -16,176 +16,13 @@ static int pcd_flash_verify (struct manifest *pcd, struct hash_engine *hash,
|
|||
struct signature_verification *verification, uint8_t *hash_out, size_t hash_length)
|
||||
{
|
||||
struct pcd_flash *pcd_flash = (struct pcd_flash*) pcd;
|
||||
struct flash *flash_device;
|
||||
struct pcd_header pcd_header;
|
||||
struct pcd_rot_header pcd_rot_header;
|
||||
struct pcd_port_header pcd_port_header;
|
||||
struct pcd_components_header pcd_components_header;
|
||||
struct pcd_component_header pcd_component_header;
|
||||
struct pcd_mux_header pcd_mux_header;
|
||||
struct pcd_platform_header pcd_platform_header;
|
||||
uint32_t pcd_addr;
|
||||
uint16_t pcd_len;
|
||||
uint16_t pcd_rot_len;
|
||||
uint16_t pcd_components_len;
|
||||
uint16_t pcd_component_len;
|
||||
uint8_t index;
|
||||
uint8_t index2;
|
||||
int status;
|
||||
|
||||
if ((pcd_flash == NULL) || (hash == NULL) || (verification == NULL)) {
|
||||
if (pcd_flash == NULL) {
|
||||
return PCD_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
status = manifest_flash_verify (&pcd_flash->base_flash, hash, verification, hash_out,
|
||||
return manifest_flash_verify (&pcd_flash->base_flash, hash, verification, hash_out,
|
||||
hash_length);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
pcd_len = pcd_flash->base_flash.header.length -
|
||||
(pcd_flash->base_flash.header.sig_length + sizeof (struct manifest_header));
|
||||
pcd_addr = pcd_flash->base_flash.addr + sizeof (struct manifest_header);
|
||||
|
||||
flash_device = pcd_flash->base_flash.flash;
|
||||
status = flash_device->read (flash_device, pcd_addr, (uint8_t*) &pcd_header,
|
||||
sizeof (struct pcd_header));
|
||||
if (status != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (pcd_len != pcd_header.length) {
|
||||
status = PCD_INVALID_SEG_LEN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_len -= pcd_header.header_len;
|
||||
pcd_addr += pcd_header.header_len;
|
||||
|
||||
status = flash_device->read (flash_device, pcd_addr, (uint8_t*) &pcd_rot_header,
|
||||
sizeof (struct pcd_rot_header));
|
||||
if (status != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (pcd_len < pcd_rot_header.length) {
|
||||
status = PCD_INVALID_SEG_LEN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_rot_len = pcd_rot_header.length - pcd_rot_header.header_len;
|
||||
pcd_addr += pcd_rot_header.header_len;
|
||||
|
||||
for (index = 0; index < pcd_rot_header.num_ports; ++index) {
|
||||
status = flash_device->read (flash_device, pcd_addr, (uint8_t*) &pcd_port_header,
|
||||
sizeof (struct pcd_port_header));
|
||||
if (status != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_addr += pcd_port_header.length;
|
||||
pcd_rot_len -= pcd_port_header.length;
|
||||
}
|
||||
|
||||
if (pcd_rot_len != 0) {
|
||||
status = PCD_INVALID_SEG_LEN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_len -= pcd_rot_header.length;
|
||||
|
||||
status = flash_device->read (flash_device, pcd_addr, (uint8_t*) &pcd_components_header,
|
||||
sizeof (struct pcd_components_header));
|
||||
if (status != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (pcd_len < pcd_components_header.length) {
|
||||
status = PCD_INVALID_SEG_LEN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_addr += pcd_components_header.header_len;
|
||||
pcd_components_len = pcd_components_header.length - pcd_components_header.header_len;
|
||||
|
||||
for (index = 0; index < pcd_components_header.num_components; ++index) {
|
||||
status = flash_device->read (flash_device, pcd_addr, (uint8_t*) &pcd_component_header,
|
||||
sizeof (struct pcd_component_header));
|
||||
if (status != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_component_len = pcd_component_header.length - pcd_component_header.header_len;
|
||||
if (pcd_components_len < pcd_component_len) {
|
||||
status = PCD_INVALID_SEG_LEN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_addr += pcd_component_header.header_len;
|
||||
|
||||
for (index2 = 0; index2 < pcd_component_header.num_muxes; ++index2) {
|
||||
status = flash_device->read (flash_device, pcd_addr, (uint8_t*) &pcd_mux_header,
|
||||
sizeof (struct pcd_mux_header));
|
||||
if (status != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_addr += pcd_mux_header.length;
|
||||
pcd_component_len -= pcd_mux_header.length;
|
||||
}
|
||||
|
||||
if (pcd_component_len != 0) {
|
||||
status = PCD_INVALID_SEG_LEN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_components_len -= pcd_component_header.length;
|
||||
}
|
||||
|
||||
if (pcd_components_len != 0) {
|
||||
status = PCD_INVALID_SEG_LEN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_len -= pcd_components_header.length;
|
||||
|
||||
status = flash_device->read (flash_device, pcd_addr, (uint8_t*) &pcd_platform_header,
|
||||
sizeof (struct pcd_platform_header));
|
||||
if (status != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (pcd_len != pcd_platform_header.length) {
|
||||
status = PCD_INVALID_SEG_LEN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (pcd_platform_header.length !=
|
||||
(pcd_platform_header.header_len + pcd_platform_header.id_len)) {
|
||||
status = PCD_INVALID_SEG_HDR_LEN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (pcd_platform_header.length >= pcd_flash->base_flash.max_platform_id) {
|
||||
status = MANIFEST_PLAT_ID_BUFFER_TOO_SMALL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_addr += sizeof (struct pcd_platform_header);
|
||||
status = flash_device->read (flash_device, pcd_addr,
|
||||
(uint8_t*) pcd_flash->base_flash.platform_id, pcd_platform_header.id_len);
|
||||
if (status != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
pcd_flash->base_flash.platform_id[pcd_platform_header.id_len] = '\0';
|
||||
return 0;
|
||||
|
||||
error:
|
||||
/* Clearing this flag in validation error cases is not tested but is only temporary as v1 PCDs
|
||||
* will be unsupported with the move to v2. */
|
||||
pcd_flash->base_flash.manifest_valid = false;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int pcd_flash_get_id (struct manifest *pcd, uint32_t *id)
|
||||
|
@ -241,12 +78,9 @@ static int pcd_flash_get_signature (struct manifest *pcd, uint8_t *signature, si
|
|||
static int pcd_flash_get_port_info (struct pcd *pcd, uint8_t port_id, struct pcd_port_info *info)
|
||||
{
|
||||
struct pcd_flash *pcd_flash = (struct pcd_flash*) pcd;
|
||||
struct pcd_header pcd_header;
|
||||
struct pcd_rot_header rot_header;
|
||||
struct pcd_port_header port_header;
|
||||
struct flash *flash_device;
|
||||
uint32_t next_addr;
|
||||
size_t i_port;
|
||||
struct pcd_rot_element *rot_element = NULL;
|
||||
struct pcd_port *port_element;
|
||||
int i_port;
|
||||
int status;
|
||||
|
||||
if ((pcd_flash == NULL) || (info == NULL)) {
|
||||
|
@ -257,49 +91,55 @@ static int pcd_flash_get_port_info (struct pcd *pcd, uint8_t port_id, struct pcd
|
|||
return MANIFEST_NO_MANIFEST;
|
||||
}
|
||||
|
||||
flash_device = pcd_flash->base_flash.flash;
|
||||
|
||||
status = flash_device->read (flash_device, pcd_flash->base_flash.addr +
|
||||
sizeof (struct manifest_header), (uint8_t*) &pcd_header, sizeof (struct pcd_header));
|
||||
if (status != 0) {
|
||||
status = manifest_flash_read_element_data (&pcd_flash->base_flash, pcd_flash->base_flash.hash,
|
||||
PCD_ROT, 0, MANIFEST_NO_PARENT, 0, NULL, NULL, NULL, (uint8_t**) &rot_element, 0);
|
||||
if (ROT_IS_ERROR (status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
next_addr = pcd_flash->base_flash.addr + sizeof (struct manifest_header) +
|
||||
pcd_header.header_len;
|
||||
status = flash_device->read (flash_device, next_addr, (uint8_t*) &rot_header,
|
||||
sizeof (struct pcd_rot_header));
|
||||
if (status != 0) {
|
||||
return status;
|
||||
if (status < (int) (sizeof (struct pcd_rot_element))) {
|
||||
status = PCD_MALFORMED_ROT_ELEMENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
next_addr += sizeof (struct pcd_rot_header);
|
||||
|
||||
for (i_port = 0; i_port < rot_header.num_ports; ++i_port) {
|
||||
status = flash_device->read (flash_device, next_addr, (uint8_t*) &port_header,
|
||||
sizeof (struct pcd_port_header));
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (port_header.id == port_id) {
|
||||
info->spi_freq = port_header.frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
next_addr += sizeof (struct pcd_port_header);
|
||||
if (rot_element->port_count == 0) {
|
||||
goto port_not_found;
|
||||
}
|
||||
|
||||
return PCD_INVALID_PORT;
|
||||
if (status < (int) (sizeof (struct pcd_rot_element) +
|
||||
sizeof (struct pcd_port) * rot_element->port_count)) {
|
||||
status = PCD_MALFORMED_ROT_ELEMENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
port_element = (struct pcd_port*) (((uint8_t*) rot_element) + sizeof (struct pcd_rot_element));
|
||||
|
||||
for (i_port = 0; i_port < rot_element->port_count; ++i_port, ++port_element) {
|
||||
if (port_element->port_id == port_id) {
|
||||
info->spi_freq = port_element->spi_frequency_hz;
|
||||
info->flash_mode = pcd_get_port_flash_mode (port_element);
|
||||
info->reset_ctrl = pcd_get_port_reset_control (port_element);
|
||||
info->policy = port_element->policy;
|
||||
|
||||
status = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
port_not_found:
|
||||
status = PCD_INVALID_PORT;
|
||||
|
||||
done:
|
||||
platform_free (rot_element);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int pcd_flash_get_rot_info (struct pcd *pcd, struct pcd_rot_info *info)
|
||||
{
|
||||
struct pcd_flash *pcd_flash = (struct pcd_flash*) pcd;
|
||||
struct pcd_header pcd_header;
|
||||
struct pcd_rot_header rot_header;
|
||||
struct flash *flash_device;
|
||||
uint32_t next_addr;
|
||||
struct pcd_rot_element rot_element;
|
||||
uint8_t *rot_element_ptr = (uint8_t*) &rot_element;
|
||||
int status;
|
||||
|
||||
if ((pcd_flash == NULL) || (info == NULL)) {
|
||||
|
@ -310,25 +150,56 @@ static int pcd_flash_get_rot_info (struct pcd *pcd, struct pcd_rot_info *info)
|
|||
return MANIFEST_NO_MANIFEST;
|
||||
}
|
||||
|
||||
flash_device = pcd_flash->base_flash.flash;
|
||||
|
||||
status = flash_device->read (flash_device, pcd_flash->base_flash.addr +
|
||||
sizeof (struct manifest_header), (uint8_t*) &pcd_header, sizeof (struct pcd_header));
|
||||
if (status != 0) {
|
||||
status = manifest_flash_read_element_data (&pcd_flash->base_flash, pcd_flash->base_flash.hash,
|
||||
PCD_ROT, 0, MANIFEST_NO_PARENT, 0, NULL, NULL, NULL, &rot_element_ptr,
|
||||
sizeof (struct pcd_rot_element));
|
||||
if (ROT_IS_ERROR (status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
next_addr = pcd_flash->base_flash.addr + sizeof (struct manifest_header) +
|
||||
pcd_header.header_len;
|
||||
status = flash_device->read (flash_device, next_addr, (uint8_t*) &rot_header,
|
||||
sizeof (struct pcd_rot_header));
|
||||
if (status != 0) {
|
||||
if (status < (int) sizeof (struct pcd_rot_element)) {
|
||||
return PCD_MALFORMED_ROT_ELEMENT;
|
||||
}
|
||||
|
||||
info->is_pa_rot = (pcd_get_rot_type (&rot_element) == PCD_ROT_TYPE_PA_ROT);
|
||||
info->port_count = rot_element.port_count;
|
||||
info->components_count = rot_element.components_count;
|
||||
info->i2c_slave_addr = rot_element.rot_address;
|
||||
info->eid = rot_element.rot_eid;
|
||||
info->bridge_i2c_addr = rot_element.bridge_address;
|
||||
info->bridge_eid = rot_element.bridge_eid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcd_flash_get_power_controller_info (struct pcd *pcd,
|
||||
struct pcd_power_controller_info *info)
|
||||
{
|
||||
struct pcd_flash *pcd_flash = (struct pcd_flash*) pcd;
|
||||
struct pcd_power_controller_element power_controller_element;
|
||||
uint8_t *power_controller_element_ptr = (uint8_t*) &power_controller_element;
|
||||
int status;
|
||||
|
||||
if ((pcd_flash == NULL) || (info == NULL)) {
|
||||
return PCD_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (!pcd_flash->base_flash.manifest_valid) {
|
||||
return MANIFEST_NO_MANIFEST;
|
||||
}
|
||||
|
||||
status = manifest_flash_read_element_data (&pcd_flash->base_flash, pcd_flash->base_flash.hash,
|
||||
PCD_POWER_CONTROLLER, 0, MANIFEST_NO_PARENT, 0, NULL, NULL, NULL,
|
||||
&power_controller_element_ptr, sizeof (struct pcd_power_controller_element));
|
||||
if (ROT_IS_ERROR (status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
info->is_pa_rot = (rot_header.flags & PCD_ROT_HDR_IS_PA_ROT_SET_MASK);
|
||||
info->i2c_slave_addr = rot_header.addr;
|
||||
info->bmc_i2c_addr = rot_header.bmc_i2c_addr;
|
||||
info->mux_count = power_controller_element.i2c.mux_count;
|
||||
info->i2c_mode = pcd_get_i2c_interface_i2c_mode (&power_controller_element.i2c);
|
||||
info->bus = power_controller_element.i2c.bus;
|
||||
info->address = power_controller_element.i2c.address;
|
||||
info->eid = power_controller_element.i2c.eid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -337,23 +208,22 @@ static int pcd_flash_get_devices_info (struct pcd *pcd, struct device_manager_in
|
|||
size_t *num_devices)
|
||||
{
|
||||
struct pcd_flash *pcd_flash = (struct pcd_flash*) pcd;
|
||||
struct pcd_header pcd_header;
|
||||
struct pcd_rot_header rot_header;
|
||||
struct pcd_components_header components_header;
|
||||
struct pcd_component_header component_header;
|
||||
struct flash *flash_device;
|
||||
uint32_t next_addr;
|
||||
size_t i_component;
|
||||
struct device_manager_info *device_ptr;
|
||||
struct pcd_i2c_interface *interface;
|
||||
struct pcd_mctp_bridge_component_connection *connection;
|
||||
union {
|
||||
struct pcd_rot_info rot_info;
|
||||
struct pcd_direct_i2c_component_element direct_component;
|
||||
struct pcd_mctp_bridge_component_element bridge_component;
|
||||
} buffer;
|
||||
uint8_t *element_ptr;
|
||||
uint8_t i_component;
|
||||
uint8_t found;
|
||||
size_t type_len;
|
||||
int start = 0;
|
||||
int status;
|
||||
|
||||
if ((devices == NULL) || (num_devices == NULL)) {
|
||||
return PCD_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*devices = NULL;
|
||||
*num_devices = 0;
|
||||
|
||||
if (pcd_flash == NULL) {
|
||||
if ((pcd_flash == NULL) || (devices == NULL) || (num_devices == NULL)) {
|
||||
return PCD_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
|
@ -361,57 +231,83 @@ static int pcd_flash_get_devices_info (struct pcd *pcd, struct device_manager_in
|
|||
return MANIFEST_NO_MANIFEST;
|
||||
}
|
||||
|
||||
flash_device = pcd_flash->base_flash.flash;
|
||||
|
||||
status = flash_device->read (flash_device, pcd_flash->base_flash.addr +
|
||||
sizeof (struct manifest_header), (uint8_t*) &pcd_header, sizeof (struct pcd_header));
|
||||
status = pcd_flash_get_rot_info (pcd, &buffer.rot_info);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
next_addr = pcd_flash->base_flash.addr + sizeof (struct manifest_header) +
|
||||
pcd_header.header_len;
|
||||
status = flash_device->read (flash_device, next_addr, (uint8_t*) &rot_header,
|
||||
sizeof (struct pcd_rot_header));
|
||||
if (status != 0) {
|
||||
return status;
|
||||
if (buffer.rot_info.components_count == 0) {
|
||||
*num_devices = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
next_addr += rot_header.length;
|
||||
status = flash_device->read (flash_device, next_addr, (uint8_t*) &components_header,
|
||||
sizeof (struct pcd_components_header));
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
*devices = platform_calloc (components_header.num_components,
|
||||
sizeof (struct device_manager_info));
|
||||
*num_devices = buffer.rot_info.components_count;
|
||||
|
||||
*devices = platform_calloc (*num_devices, sizeof (struct device_manager_info));
|
||||
if (*devices == NULL) {
|
||||
return PCD_NO_MEMORY;
|
||||
}
|
||||
|
||||
*num_devices = components_header.num_components;
|
||||
next_addr += sizeof (struct pcd_components_header);
|
||||
device_ptr = *devices;
|
||||
element_ptr = (uint8_t*) &buffer.direct_component;
|
||||
|
||||
for (i_component = 0; i_component < components_header.num_components; ++i_component) {
|
||||
status = flash_device->read (flash_device, next_addr, (uint8_t*) &component_header,
|
||||
sizeof (struct pcd_component_header));
|
||||
if (status != 0) {
|
||||
platform_free ((void*) *devices);
|
||||
*num_devices = 0;
|
||||
*devices = NULL;
|
||||
|
||||
return status;
|
||||
for (i_component = 0; i_component < *num_devices; ++i_component) {
|
||||
status = manifest_flash_read_element_data (&pcd_flash->base_flash,
|
||||
pcd_flash->base_flash.hash, PCD_COMPONENT_DIRECT, start, MANIFEST_NO_PARENT, 0, &found,
|
||||
NULL, NULL, &element_ptr, sizeof (struct pcd_direct_i2c_component_element));
|
||||
if (status == MANIFEST_ELEMENT_NOT_FOUND) {
|
||||
break;
|
||||
}
|
||||
if (ROT_IS_ERROR (status)) {
|
||||
goto fail;
|
||||
}
|
||||
if (((size_t) status) <
|
||||
(sizeof (struct pcd_direct_i2c_component_element) - MANIFEST_MAX_STRING)) {
|
||||
status = PCD_MALFORMED_DIRECT_I2C_COMPONENT_ELEMENT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
next_addr += sizeof (struct pcd_component_header);
|
||||
type_len = ((buffer.direct_component.component.type_len + 3) & ~((size_t) 3));
|
||||
interface = (struct pcd_i2c_interface*) (element_ptr +
|
||||
(sizeof (struct pcd_component_common) - MANIFEST_MAX_STRING + type_len));
|
||||
|
||||
(*devices)[i_component].smbus_addr = component_header.addr;
|
||||
(*devices)[i_component].eid = component_header.eid;
|
||||
device_ptr->eid = interface->eid;
|
||||
device_ptr->smbus_addr = interface->address;
|
||||
|
||||
start = found + 1;
|
||||
++device_ptr;
|
||||
}
|
||||
|
||||
start = 0;
|
||||
element_ptr = (uint8_t*) &buffer.bridge_component;
|
||||
|
||||
for (; i_component < *num_devices; ++i_component) {
|
||||
status = manifest_flash_read_element_data (&pcd_flash->base_flash,
|
||||
pcd_flash->base_flash.hash, PCD_COMPONENT_MCTP_BRIDGE, start, MANIFEST_NO_PARENT, 0,
|
||||
&found, NULL, NULL, &element_ptr, sizeof (struct pcd_mctp_bridge_component_element));
|
||||
if (ROT_IS_ERROR (status)) {
|
||||
goto fail;
|
||||
}
|
||||
if ((size_t) status <
|
||||
(sizeof (struct pcd_mctp_bridge_component_element) - MANIFEST_MAX_STRING)) {
|
||||
status = PCD_MALFORMED_BRIDGE_COMPONENT_ELEMENT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
connection = pcd_get_mctp_bridge_component_connection (element_ptr, status);
|
||||
|
||||
device_ptr->eid = connection->eid;
|
||||
|
||||
start = found + 1;
|
||||
++device_ptr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
platform_free (*devices);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -419,6 +315,9 @@ static int pcd_flash_get_devices_info (struct pcd *pcd, struct device_manager_in
|
|||
*
|
||||
* @param pcd The PCD instance to initialize.
|
||||
* @param flash The flash device that contains the PCD.
|
||||
* @param hash A hash engine to use for validating run-time access to PCD information. If it is
|
||||
* possible for any PCD information to be requested concurrently by different threads, this hash
|
||||
* engine MUST be thread-safe. There is no internal synchronization around the hashing operations.
|
||||
* @param base_addr The starting address of the PCD storage location.
|
||||
* @param signature_cache Buffer to hold the manifest signature.
|
||||
* @param max_signature The maximum supported length for a manifest signature.
|
||||
|
@ -427,8 +326,8 @@ static int pcd_flash_get_devices_info (struct pcd *pcd, struct device_manager_in
|
|||
*
|
||||
* @return 0 if the PCD instance was initialized successfully or an error code.
|
||||
*/
|
||||
int pcd_flash_init (struct pcd_flash *pcd, struct flash *flash, uint32_t base_addr,
|
||||
uint8_t *signature_cache, size_t max_signature, uint8_t *platform_id_cache,
|
||||
int pcd_flash_init (struct pcd_flash *pcd, struct flash *flash, struct hash_engine *hash,
|
||||
uint32_t base_addr, uint8_t *signature_cache, size_t max_signature, uint8_t *platform_id_cache,
|
||||
size_t max_platform_id)
|
||||
{
|
||||
int status;
|
||||
|
@ -439,7 +338,7 @@ int pcd_flash_init (struct pcd_flash *pcd, struct flash *flash, uint32_t base_ad
|
|||
|
||||
memset (pcd, 0, sizeof (struct pcd_flash));
|
||||
|
||||
status = manifest_flash_v2_init (&pcd->base_flash, flash, NULL, base_addr, PCD_MAGIC_NUM,
|
||||
status = manifest_flash_v2_init (&pcd->base_flash, flash, hash, base_addr, PCD_MAGIC_NUM,
|
||||
PCD_V2_MAGIC_NUM, signature_cache, max_signature, platform_id_cache, max_platform_id);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
|
@ -455,6 +354,7 @@ int pcd_flash_init (struct pcd_flash *pcd, struct flash *flash, uint32_t base_ad
|
|||
pcd->base.get_port_info = pcd_flash_get_port_info;
|
||||
pcd->base.get_rot_info = pcd_flash_get_rot_info;
|
||||
pcd->base.get_devices_info = pcd_flash_get_devices_info;
|
||||
pcd->base.get_power_controller_info = pcd_flash_get_power_controller_info;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ struct pcd_flash {
|
|||
};
|
||||
|
||||
|
||||
int pcd_flash_init (struct pcd_flash *pcd, struct flash *flash, uint32_t base_addr,
|
||||
uint8_t *signature_cache, size_t max_signature, uint8_t *platform_id_cache,
|
||||
int pcd_flash_init (struct pcd_flash *pcd, struct flash *flash, struct hash_engine *hash,
|
||||
uint32_t base_addr, uint8_t *signature_cache, size_t max_signature, uint8_t *platform_id_cache,
|
||||
size_t max_platform_id);
|
||||
void pcd_flash_release (struct pcd_flash *pcd);
|
||||
|
||||
|
|
|
@ -8,135 +8,200 @@
|
|||
#include "manifest/manifest_format.h"
|
||||
|
||||
|
||||
#define PCD_ROT_HDR_IS_PA_ROT_SHIFT 0
|
||||
#define PCD_ROT_HDR_IS_PA_ROT_SET_MASK (1U << PCD_ROT_HDR_IS_PA_ROT_SHIFT)
|
||||
#define PCD_ROT_HDR_IS_PA_ROT_CLR_MASK (~PCD_ROT_HDR_IS_PA_ROT_SET_MASK)
|
||||
|
||||
#define PCD_COMPONENT_HDR_I2C_MODE_SHIFT 0
|
||||
#define PCD_COMPONENT_HDR_I2C_MODE_SET_MASK (1U << PCD_COMPONENT_HDR_I2C_MODE_SHIFT)
|
||||
#define PCD_COMPONENT_HDR_I2C_MODE_CLR_MASK (~PCD_COMPONENT_HDR_I2C_MODE_SET_MASK)
|
||||
|
||||
/**
|
||||
* Type identifiers for PCD v2 elements.
|
||||
*/
|
||||
enum pcd_element_type {
|
||||
PCD_ROT = 0x40, /**< Information about the RoT configuration. */
|
||||
PCD_POWER_CONTROLLER = 0x41, /**< Information about power controller utilized by RoT. */
|
||||
PCD_COMPONENT_DIRECT = 0x42, /**< A single component connected directly to RoT. */
|
||||
PCD_COMPONENT_MCTP_BRIDGE = 0x43, /**< A components connected to RoT through an MCTP bridge. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The PCD is a variable length structure that has the following format:
|
||||
* Flags for policy failure action.
|
||||
*/
|
||||
enum pcd_policy_failure_action {
|
||||
PCD_POLICY_FAILURE_ACTION_PASSIVE = 0x0, /**< Report policy failure through attestation. */
|
||||
PCD_POLICY_FAILURE_ACTION_ACTIVE = 0x1, /**< Prevent failed device from booting. */
|
||||
};
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct pcd_rot_element {
|
||||
uint8_t rot_flags; /**< Flags pertaining to RoT configuration. */
|
||||
uint8_t port_count; /**< The number of ports protected by RoT. */
|
||||
uint8_t components_count; /**< The number of components attested by RoT. */
|
||||
uint8_t rot_address; /**< RoT slave address to utilize. */
|
||||
uint8_t rot_eid; /**< Default RoT MCTP EID to utilize. */
|
||||
uint8_t bridge_address; /**< MCTP bridge slave address. */
|
||||
uint8_t bridge_eid; /**< MCTP bridge EID. */
|
||||
uint8_t reserved; /**< Unused. */
|
||||
};
|
||||
|
||||
#define PCD_ROT_FLAGS_ROT_TYPE_SHIFT 0
|
||||
#define PCD_ROT_FLAGS_ROT_TYPE_SET_MASK (1 << PCD_ROT_FLAGS_ROT_TYPE_SHIFT)
|
||||
|
||||
/**
|
||||
* Flags for RoT configuration.
|
||||
*/
|
||||
enum pcd_rot_type_flags {
|
||||
PCD_ROT_TYPE_PA_ROT = 0x0, /**< PA-ROT. */
|
||||
PCD_ROT_TYPE_AC_ROT = 0x1, /**< AC-ROT. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Get RoT type.
|
||||
*
|
||||
* struct {
|
||||
* struct manifest_header
|
||||
* struct pcd_header
|
||||
* struct pcd_rot_header
|
||||
* <struct pcd_port_header> [pcd_rot_header.num_ports]
|
||||
* struct pcd_components_header
|
||||
* <components> [pcd_components_header.num_components]
|
||||
* struct pcd_platform_header
|
||||
* char platform_id[pcd_platform_header.id_len]
|
||||
* uint8_t signature[manifest_header.sig_length]
|
||||
* }
|
||||
* @param rot Pointer to a pcd_rot element.
|
||||
*/
|
||||
#define pcd_get_rot_type(rot) (enum pcd_rot_type_flags) (((rot)->rot_flags) & \
|
||||
PCD_ROT_FLAGS_ROT_TYPE_SET_MASK)
|
||||
|
||||
/**
|
||||
* A port section defined in PCD as part of RoT element.
|
||||
*/
|
||||
struct pcd_port {
|
||||
uint8_t port_id; /**< Port ID. */
|
||||
uint8_t port_flags; /**< Flags with port configuration. */
|
||||
uint8_t policy; /**< Port attestation policy. */
|
||||
uint8_t reserved; /**< Unused. */
|
||||
uint32_t spi_frequency_hz; /**< Flash SPI frequency in Hz. */
|
||||
};
|
||||
|
||||
#define PCD_PORT_FLAGS_FLASH_MODE_SHIFT 2
|
||||
#define PCD_PORT_FLAGS_FLASH_MODE_SET_MASK (3 << PCD_PORT_FLAGS_FLASH_MODE_SHIFT)
|
||||
|
||||
#define PCD_PORT_FLAGS_RESET_CTRL_SHIFT 0
|
||||
#define PCD_PORT_FLAGS_RESET_CTRL_SET_MASK (3 << PCD_PORT_FLAGS_RESET_CTRL_SHIFT)
|
||||
|
||||
/**
|
||||
* 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. */
|
||||
};
|
||||
|
||||
/**
|
||||
* 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. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Get port flash mode.
|
||||
*
|
||||
* Each component is a variable length structure that has the following format:
|
||||
* @param port Pointer to a pcd_port element.
|
||||
*/
|
||||
#define pcd_get_port_flash_mode(port) (enum pcd_port_flash_mode) ((((port)->port_flags) & \
|
||||
PCD_PORT_FLAGS_FLASH_MODE_SET_MASK) >> PCD_PORT_FLAGS_FLASH_MODE_SHIFT)
|
||||
|
||||
/**
|
||||
* Get port reset control setting.
|
||||
*
|
||||
* struct {
|
||||
* struct pcd_component_header
|
||||
* <struct pcd_mux_header> [pcd_component_header.num_muxes]
|
||||
* }
|
||||
* @param port Pointer to a pcd_port element.
|
||||
*/
|
||||
#define pcd_get_port_reset_control(port) (enum pcd_port_reset_control) (((port)->port_flags) & \
|
||||
PCD_PORT_FLAGS_RESET_CTRL_SET_MASK)
|
||||
|
||||
/**
|
||||
* The header information for the PCD.
|
||||
* A single I2C mux section.
|
||||
*/
|
||||
struct pcd_header {
|
||||
uint16_t length; /**< Total length of PCD without manifest header and signature. */
|
||||
uint16_t header_len; /**< PCD header length. */
|
||||
uint8_t format_id; /**< PCD format ID. */
|
||||
uint8_t reserved1; /**< Reserved. */
|
||||
uint8_t reserved2; /**< Reserved. */
|
||||
uint8_t reserved3; /**< Reserved. */
|
||||
struct pcd_mux {
|
||||
uint8_t mux_address; /**< I2C slave address of mux. */
|
||||
uint8_t mux_channel; /**< Channel to activate on mux. */
|
||||
uint16_t reserved; /**< Unused. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The header information for the PCD RoT.
|
||||
* Container for fields common to I2C interface sections in elements.
|
||||
*/
|
||||
struct pcd_rot_header {
|
||||
uint16_t length; /**< Total length of PCD RoT section including header. */
|
||||
uint16_t header_len; /**< Length of PCD RoT header. */
|
||||
uint8_t format_id; /**< PCD RoT format ID. */
|
||||
uint8_t num_ports; /**< Number of ports in RoT. */
|
||||
uint8_t addr; /**< I2C slave address */
|
||||
uint8_t bmc_i2c_addr; /**< BMC I2C address */
|
||||
uint8_t cpld_addr; /**< CPLD I2C slave address */
|
||||
uint8_t cpld_channel; /**< CPLD I2C bus channel */
|
||||
uint8_t active; /**< Policy active */
|
||||
uint8_t default_failure_action; /**< Default action on attestation failure */
|
||||
uint8_t flags; /**< Field for flags */
|
||||
uint8_t reserved1; /**< Reserved. */
|
||||
uint8_t reserved2; /**< Reserved. */
|
||||
uint8_t reserved3; /**< Reserved. */
|
||||
struct pcd_i2c_interface {
|
||||
uint8_t mux_count:4; /**< Number of muxes in I2C path from RoT to device. */
|
||||
uint8_t i2c_flags:4; /**< Flags with I2C configuration. */
|
||||
uint8_t bus; /**< I2C bus device is on. */
|
||||
uint8_t address; /**< Device I2C slave address. */
|
||||
uint8_t eid; /**< Device MCTP EID, 0x00 if not utilizing MCTP. */
|
||||
};
|
||||
|
||||
#define PCD_I2C_FLAGS_I2C_MODE_SHIFT 0
|
||||
#define PCD_I2C_FLAGS_I2C_MODE_SET_MASK (3 << PCD_I2C_FLAGS_I2C_MODE_SHIFT)
|
||||
|
||||
/**
|
||||
* 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. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The header information for a RoT port section.
|
||||
* Get i2c mode for i2c interface.
|
||||
*
|
||||
* @param i2c Pointer to a pcd_i2c_interface element.
|
||||
*/
|
||||
struct pcd_port_header {
|
||||
uint16_t length; /**< Total length of RoT ports section. */
|
||||
uint16_t header_len; /**< Length of PCD port header. */
|
||||
uint8_t format_id; /**< RoT ports format ID. */
|
||||
uint8_t id; /**< Port ID */
|
||||
uint8_t reserverd1; /**< Reserved. */
|
||||
uint8_t reserverd2; /**< Reserved. */
|
||||
uint32_t frequency; /**< Bus frequency */
|
||||
#define pcd_get_i2c_interface_i2c_mode(i2c) (enum pcd_i2c_mode) (((i2c)->i2c_flags) & \
|
||||
PCD_I2C_FLAGS_I2C_MODE_SET_MASK)
|
||||
|
||||
/**
|
||||
* An I2C power controller element.
|
||||
*/
|
||||
struct pcd_power_controller_element {
|
||||
struct pcd_i2c_interface i2c; /**< Power controller I2C interface. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The header information for the PCD components section.
|
||||
* Container for fields common to component elements.
|
||||
*/
|
||||
struct pcd_components_header {
|
||||
uint16_t length; /**< Total length of PCD components section. */
|
||||
uint16_t header_len; /**< Length of PCD components header. */
|
||||
uint8_t format_id; /**< PCD components format ID. */
|
||||
uint8_t num_components; /**< Number of components in PCD. */
|
||||
uint8_t reserved1; /**< Reserved. */
|
||||
uint8_t reserved2; /**< Reserved. */
|
||||
struct pcd_component_common {
|
||||
uint8_t policy; /**< Component attestation policy. */
|
||||
uint8_t power_ctrl_reg; /**< Power control register. */
|
||||
uint8_t power_ctrl_mask; /**< Power control mask. */
|
||||
uint8_t type_len; /**< Component type length. */
|
||||
uint8_t type[MANIFEST_MAX_STRING]; /**< Component type. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The header information for a PCD component.
|
||||
* Element for a component with direct I2C connection to RoT.
|
||||
*/
|
||||
struct pcd_component_header {
|
||||
uint16_t length; /**< Total length of PCD component. */
|
||||
uint16_t header_len; /**< Length of PCD component header. */
|
||||
uint8_t format_id; /**< PCD component format ID. */
|
||||
uint8_t num_muxes; /**< Number of muxes in component. */
|
||||
uint8_t addr; /**< I2C slave address */
|
||||
uint8_t channel; /**< I2C bus channel */
|
||||
uint8_t flags; /**< Field for flags */
|
||||
uint8_t eid; /**< MCTP EID */
|
||||
uint8_t power_ctrl_reg; /**< Power control register */
|
||||
uint8_t power_ctrl_mask; /**< Power control bitmask */
|
||||
uint32_t id; /**< Component ID. */
|
||||
struct pcd_direct_i2c_component_element {
|
||||
struct pcd_component_common component; /**< Common component configuration. */
|
||||
struct pcd_i2c_interface i2c; /**< Component I2C interface. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The header information for a mux section.
|
||||
* Container for connection information for a component with connection to RoT through MCTP bridge.
|
||||
*/
|
||||
struct pcd_mux_header {
|
||||
uint16_t length; /**< Total length of component mux section. */
|
||||
uint16_t header_len; /**< Length of PCD mux header */
|
||||
uint8_t format_id; /**< Component mux format ID. */
|
||||
uint8_t addr; /**< I2C slave address */
|
||||
uint8_t channel; /**< I2C bus channel */
|
||||
uint8_t mux_level; /**< Mux level */
|
||||
struct pcd_mctp_bridge_component_connection {
|
||||
uint16_t device_id; /**< Device ID. */
|
||||
uint16_t vendor_id; /**< Vendor ID. */
|
||||
uint16_t subsystem_device_id; /**< Subsystem device ID. */
|
||||
uint16_t subsystem_vendor_id; /**< Subsystem vendor ID. */
|
||||
uint8_t components_count; /**< Number of identical components this element describes. */
|
||||
uint8_t eid; /**< Default EID to use if cannot retrieve EID table from MCTP bridge. */
|
||||
uint16_t reserved; /**< Unused. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The header information for the platform information.
|
||||
* Element for a component with connection to RoT through MCTP bridge.
|
||||
*/
|
||||
struct pcd_platform_header {
|
||||
uint16_t length; /**< The total length of the platform descriptor. */
|
||||
uint16_t header_len; /**< Length of PCD platform header. */
|
||||
uint8_t format_id; /**< PCD platform header format ID. */
|
||||
uint8_t id_len; /**< Platform ID length. */
|
||||
uint8_t reserved1; /**< Reserved. */
|
||||
uint8_t reserved2; /**< Reserved. */
|
||||
struct pcd_mctp_bridge_component_element {
|
||||
struct pcd_component_common component; /**< Common component configuration. */
|
||||
struct pcd_mctp_bridge_component_connection connection; /**< Component connection information. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Get component connection portion from a MCTP bridge component element container.
|
||||
*
|
||||
* @param component Pointer to a buffer containing a pcd_mctp_bridge_component_element element.
|
||||
* @param len Length of buffer
|
||||
*/
|
||||
#define pcd_get_mctp_bridge_component_connection(component, len) ((struct pcd_mctp_bridge_component_connection*) \
|
||||
((component) + len - sizeof (struct pcd_mctp_bridge_component_connection)))
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
#endif /* PCD_FORMAT_H_ */
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -5,6 +5,31 @@
|
|||
#define PCD_TESTING_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "manifest_v2_testing.h"
|
||||
|
||||
|
||||
/**
|
||||
* Describe a test PFM structure.
|
||||
*/
|
||||
struct pcd_testing_data {
|
||||
struct manifest_v2_testing_data manifest; /**< Common manifest components. */
|
||||
size_t rot_len; /**< RoT element data length. */
|
||||
uint32_t rot_offset; /**< Offset of the RoT element. */
|
||||
int rot_entry; /**< TOC entry for the RoT element. */
|
||||
int rot_hash; /**< TOC hash for the RoT element. */
|
||||
size_t power_ctrl_len; /**< Power controller element data length. */
|
||||
uint32_t power_ctrl_offset; /**< Offset of a power controller element. */
|
||||
int power_ctrl_entry; /**< TOC entry for a power controller element. */
|
||||
int power_ctrl_hash; /**< TOC hash for a power controller element. */
|
||||
size_t bridge_component_len; /**< Bridge component element data length. */
|
||||
uint32_t bridge_component_offset; /**< Offset of a bridge component element. */
|
||||
int bridge_component_entry; /**< TOC entry for a bridge component element. */
|
||||
int bridge_component_hash; /**< TOC hash for a bridge component element. */
|
||||
size_t direct_component_len; /**< Direct component element data length. */
|
||||
uint32_t direct_component_offset; /**< Offset of a direct component element. */
|
||||
int direct_component_entry; /**< TOC entry for a direct component element. */
|
||||
int direct_component_hash; /**< TOC hash for a direct component element. */
|
||||
};
|
||||
|
||||
|
||||
extern const uint8_t PCD_DATA[];
|
||||
|
@ -32,10 +57,9 @@ extern const uint32_t PCD_PLATFORM_ID_OFFSET;
|
|||
extern const char PCD_PLATFORM_ID[];
|
||||
extern const size_t PCD_PLATFORM_ID_LEN;
|
||||
|
||||
/*
|
||||
* Constant PCD sizes.
|
||||
*/
|
||||
#define PCD_HEADER_SIZE 12
|
||||
extern const uint8_t PCD_TOC_HASH[];
|
||||
|
||||
extern const struct pcd_testing_data PCD_TESTING;
|
||||
|
||||
|
||||
#endif /* PCD_TESTING_H_ */
|
||||
|
|
|
@ -34,7 +34,7 @@ PFM_V2_FW_TYPE_ID = int ("0x11", 16)
|
|||
PFM_V2_FW_VERSION_TYPE_ID = int ("0x12", 16)
|
||||
|
||||
PCD_V2_ROT_TYPE_ID = int ("0x40", 16)
|
||||
PCD_V2_I2C_CPLD_TYPE_ID = int ("0x41", 16)
|
||||
PCD_V2_I2C_POWER_CONTROLLER_TYPE_ID = int ("0x41", 16)
|
||||
PCD_V2_DIRECT_COMPONENT_TYPE_ID = int ("0x42", 16)
|
||||
PCD_V2_MCTP_BRIDGE_COMPONENT_TYPE_ID = int ("0x43", 16)
|
||||
|
||||
|
@ -519,14 +519,14 @@ def generate_toc (hash_engine, hash_type, toc_list, hash_list):
|
|||
hash_len = hash_engine.digest_size
|
||||
|
||||
toc_len = ctypes.sizeof (manifest_toc_header) + \
|
||||
(ctypes.sizeof (manifest_toc_entry) * num_entries) + ((num_entries + 1) * hash_len)
|
||||
(ctypes.sizeof (manifest_toc_entry) + hash_len) * num_entries
|
||||
toc = (ctypes.c_ubyte * toc_len) ()
|
||||
|
||||
toc_header_len = ctypes.sizeof (manifest_toc_header)
|
||||
toc_header = manifest_toc_header (num_entries, num_entries, hash_type, 0)
|
||||
ctypes.memmove (ctypes.addressof (toc), ctypes.addressof (toc_header), toc_header_len)
|
||||
|
||||
offset = ctypes.sizeof (manifest_header) + toc_len
|
||||
offset = ctypes.sizeof (manifest_header) + toc_len + hash_len
|
||||
hash_id = 0
|
||||
toc_entry_len = ctypes.sizeof (manifest_toc_entry)
|
||||
toc_offset = toc_header_len
|
||||
|
@ -548,6 +548,11 @@ def generate_toc (hash_engine, hash_type, toc_list, hash_list):
|
|||
toc_offset += hash_len
|
||||
|
||||
table_hash = generate_hash (toc, hash_engine)
|
||||
ctypes.memmove (ctypes.addressof (toc) + toc_offset, ctypes.addressof (table_hash), hash_len)
|
||||
|
||||
return toc
|
||||
toc_w_hash = (ctypes.c_ubyte * (toc_len + hash_len)) ()
|
||||
|
||||
ctypes.memmove (ctypes.addressof (toc_w_hash), ctypes.addressof (toc), toc_len)
|
||||
ctypes.memmove (ctypes.addressof (toc_w_hash) + toc_offset, ctypes.addressof (table_hash),
|
||||
hash_len)
|
||||
|
||||
return toc_w_hash
|
||||
|
|
|
@ -44,7 +44,7 @@ XML_ROT_EID_TAG = "RoTEID"
|
|||
XML_BRIDGE_EID_TAG = "BridgeEID"
|
||||
XML_BRIDGE_ADDRESS_TAG = "BridgeAddress"
|
||||
XML_EID_TAG = "EID"
|
||||
XML_CPLD_TAG = "CPLD"
|
||||
XML_POWER_CONTROLLER_TAG = "PowerController"
|
||||
XML_CHANNEL_TAG = "Channel"
|
||||
XML_COMPONENTS_TAG = "Components"
|
||||
XML_COMPONENT_TAG = "Component"
|
||||
|
@ -508,15 +508,15 @@ def process_pcd (root):
|
|||
|
||||
xml["rot"]["interface"].update (result)
|
||||
|
||||
cpld = xml_find_single_tag (root, XML_CPLD_TAG, False)
|
||||
if cpld is not None:
|
||||
xml["cpld"] = {}
|
||||
power_controller = xml_find_single_tag (root, XML_POWER_CONTROLLER_TAG, False)
|
||||
if power_controller is not None:
|
||||
xml["power_controller"] = {}
|
||||
|
||||
interface = xml_find_single_tag (cpld, XML_INTERFACE_TAG)
|
||||
interface = xml_find_single_tag (power_controller, XML_INTERFACE_TAG)
|
||||
if interface is None:
|
||||
return None, None
|
||||
|
||||
xml["cpld"]["interface"] = {}
|
||||
xml["power_controller"]["interface"] = {}
|
||||
|
||||
interface_type = xml_extract_attrib (interface, XML_TYPE_ATTRIB, True)
|
||||
if interface_type is None:
|
||||
|
@ -524,9 +524,9 @@ def process_pcd (root):
|
|||
if interface_type == PCD_INTERFACE_TYPE_I2C:
|
||||
interface_type = 0
|
||||
else:
|
||||
print ("Unknown CPLD interface type: {0}".format (interface_type))
|
||||
print ("Unknown PowerController interface type: {0}".format (interface_type))
|
||||
|
||||
xml["cpld"]["interface"].update ({"type":interface_type})
|
||||
xml["power_controller"]["interface"].update ({"type":interface_type})
|
||||
|
||||
result = xml_extract_single_value (interface, {"bus": XML_BUS_TAG,
|
||||
"eid": XML_EID_TAG, "address": XML_ADDRESS_TAG, "i2cmode": XML_I2CMODE_TAG})
|
||||
|
@ -543,13 +543,13 @@ def process_pcd (root):
|
|||
elif result["i2cmode"] == PCD_INTERFACE_I2C_MODE_MS:
|
||||
result["i2cmode"] = 1
|
||||
else:
|
||||
print ("Unknown CPLD interface I2C mode: {0}".format (result["i2cmode"]))
|
||||
print ("Unknown PowerController interface I2C mode: {0}".format (result["i2cmode"]))
|
||||
|
||||
xml["cpld"]["interface"].update (result)
|
||||
xml["power_controller"]["interface"].update (result)
|
||||
|
||||
muxes = xml_find_single_tag (interface, XML_MUXES_TAG, False)
|
||||
if muxes is not None:
|
||||
xml["cpld"]["interface"]["muxes"] = {}
|
||||
xml["power_controller"]["interface"]["muxes"] = {}
|
||||
|
||||
for mux in muxes.findall (XML_MUX_TAG):
|
||||
level = xml_extract_attrib (mux, XML_LEVEL_ATTRIB, False)
|
||||
|
@ -563,7 +563,7 @@ def process_pcd (root):
|
|||
|
||||
result["address"] = int (result["address"], 16)
|
||||
|
||||
xml["cpld"]["interface"]["muxes"].update ({level:result})
|
||||
xml["power_controller"]["interface"]["muxes"].update ({level:result})
|
||||
|
||||
components = xml_find_single_tag (root, XML_COMPONENTS_TAG, False)
|
||||
if components is not None:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<PCD sku="C2030" version="0x1A">
|
||||
<PCD sku="SKU1" version="0x1A">
|
||||
<RoT type="PA-RoT">
|
||||
<Ports>
|
||||
<Port id="0">
|
||||
|
@ -21,7 +21,7 @@
|
|||
<BridgeAddress>0x10</BridgeAddress>
|
||||
</Interface>
|
||||
</RoT>
|
||||
<CPLD>
|
||||
<PowerController>
|
||||
<Interface type="I2C">
|
||||
<Bus>2</Bus>
|
||||
<EID>0x14</EID>
|
||||
|
@ -38,9 +38,9 @@
|
|||
</Mux>
|
||||
</Muxes>
|
||||
</Interface>
|
||||
</CPLD>
|
||||
</PowerController>
|
||||
<Components>
|
||||
<Component type="Corsica" connection="Direct">
|
||||
<Component type="Alpha" connection="Direct">
|
||||
<Policy>Passive</Policy>
|
||||
<Interface type="I2C">
|
||||
<Bus>3</Bus>
|
||||
|
@ -59,7 +59,7 @@
|
|||
<Mask>0xe0</Mask>
|
||||
</PwrCtrl>
|
||||
</Component>
|
||||
<Component type="Overlake" connection="MCTPBridge" count="2">
|
||||
<Component type="Beta" connection="MCTPBridge" count="2">
|
||||
<Policy>Passive</Policy>
|
||||
<DeviceID>0x0a</DeviceID>
|
||||
<VendorID>0x0b</VendorID>
|
||||
|
|
|
@ -144,38 +144,42 @@ def generate_muxes_buf (xml_muxes):
|
|||
|
||||
return muxes_buf, muxes_len, num_muxes
|
||||
|
||||
def generate_cpld (xml_cpld, hash_engine):
|
||||
def generate_power_controller (xml_power_controller, hash_engine):
|
||||
"""
|
||||
Create a CPLD object from parsed XML list
|
||||
Create a power_controller object from parsed XML list
|
||||
|
||||
:param xml_cpld: List of parsed XML of CPLD to be included in CPLD object
|
||||
:param xml_power_controller: List of parsed XML of power_controller to be included in
|
||||
power_controller object
|
||||
:param hash_engine: Hashing engine
|
||||
|
||||
:return Instance of a CPLD object, CPLD's TOC entry, hash of CPLD object
|
||||
:return Instance of a power_controller object, power_controller's TOC entry,
|
||||
hash of power_controller object
|
||||
"""
|
||||
|
||||
if xml_cpld["interface"]["type"] is not 0:
|
||||
raise ValueError ("Unsupported CPLD interface type: {0}".format (
|
||||
xml_cpld["interface"]["type"]))
|
||||
if xml_power_controller["interface"]["type"] is not 0:
|
||||
raise ValueError ("Unsupported power_controller interface type: {0}".format (
|
||||
xml_power_controller["interface"]["type"]))
|
||||
|
||||
if "muxes" in xml_cpld["interface"]:
|
||||
muxes, muxes_len, num_muxes = generate_muxes_buf (xml_cpld["interface"]["muxes"])
|
||||
if "muxes" in xml_power_controller["interface"]:
|
||||
muxes, muxes_len, num_muxes = generate_muxes_buf (
|
||||
xml_power_controller["interface"]["muxes"])
|
||||
else:
|
||||
muxes = (ctypes.c_ubyte * 0)()
|
||||
muxes_len = 0
|
||||
num_muxes = 0
|
||||
|
||||
bus = int (manifest_common.get_key_from_dict (xml_cpld["interface"], "bus", "CPLD interface"))
|
||||
address = int (manifest_common.get_key_from_dict (xml_cpld["interface"], "address",
|
||||
"CPLD interface"))
|
||||
eid = int (manifest_common.get_key_from_dict (xml_cpld["interface"], "eid",
|
||||
"CPLD interface"))
|
||||
i2cmode = int (manifest_common.get_key_from_dict (xml_cpld["interface"], "i2cmode",
|
||||
"CPLD interface"))
|
||||
bus = int (manifest_common.get_key_from_dict (xml_power_controller["interface"], "bus",
|
||||
"Power controller interface"))
|
||||
address = int (manifest_common.get_key_from_dict (xml_power_controller["interface"], "address",
|
||||
"Power controller interface"))
|
||||
eid = int (manifest_common.get_key_from_dict (xml_power_controller["interface"], "eid",
|
||||
"Power controller interface"))
|
||||
i2cmode = int (manifest_common.get_key_from_dict (xml_power_controller["interface"], "i2cmode",
|
||||
"Power controller interface"))
|
||||
|
||||
i2c_flags = i2cmode
|
||||
|
||||
class pcd_cpld_element (ctypes.LittleEndianStructure):
|
||||
class pcd_power_controller_element (ctypes.LittleEndianStructure):
|
||||
_pack_ = 1
|
||||
_fields_ = [('mux_count', ctypes.c_ubyte, 4),
|
||||
('i2c_flags', ctypes.c_ubyte, 4),
|
||||
|
@ -184,14 +188,15 @@ def generate_cpld (xml_cpld, hash_engine):
|
|||
('eid', ctypes.c_ubyte),
|
||||
('muxes', ctypes.c_ubyte * muxes_len)]
|
||||
|
||||
cpld = pcd_cpld_element (num_muxes, i2c_flags, bus, address, eid, muxes)
|
||||
cpld_len = ctypes.sizeof (cpld)
|
||||
cpld_toc_entry = manifest_common.manifest_toc_entry (manifest_common.PCD_V2_I2C_CPLD_TYPE_ID,
|
||||
manifest_common.V2_BASE_TYPE_ID, 1, 0, 0, cpld_len)
|
||||
power_controller = pcd_power_controller_element (num_muxes, i2c_flags, bus, address, eid, muxes)
|
||||
power_controller_len = ctypes.sizeof (power_controller)
|
||||
power_controller_toc_entry = manifest_common.manifest_toc_entry (
|
||||
manifest_common.PCD_V2_I2C_POWER_CONTROLLER_TYPE_ID, manifest_common.V2_BASE_TYPE_ID, 1, 0,
|
||||
0, power_controller_len)
|
||||
|
||||
cpld_hash = manifest_common.generate_hash (cpld, hash_engine)
|
||||
power_controller_hash = manifest_common.generate_hash (power_controller, hash_engine)
|
||||
|
||||
return cpld, cpld_toc_entry, cpld_hash
|
||||
return power_controller, power_controller_toc_entry, power_controller_hash
|
||||
|
||||
def generate_direct_component_buf (xml_component):
|
||||
"""
|
||||
|
@ -414,13 +419,14 @@ elements_list.append (platform_id)
|
|||
toc_list.append (platform_id_toc_entry)
|
||||
hash_list.append (platform_id_hash)
|
||||
|
||||
if "cpld" in processed_xml:
|
||||
cpld, cpld_toc_entry, cpld_hash = generate_cpld (processed_xml["cpld"], hash_engine)
|
||||
if "power_controller" in processed_xml:
|
||||
power_controller, power_controller_toc_entry, power_controller_hash = \
|
||||
generate_power_controller (processed_xml["power_controller"], hash_engine)
|
||||
|
||||
pcd_len += ctypes.sizeof (cpld)
|
||||
elements_list.append (cpld)
|
||||
toc_list.append (cpld_toc_entry)
|
||||
hash_list.append (cpld_hash)
|
||||
pcd_len += ctypes.sizeof (power_controller)
|
||||
elements_list.append (power_controller)
|
||||
toc_list.append (power_controller_toc_entry)
|
||||
hash_list.append (power_controller_hash)
|
||||
|
||||
if "components" in processed_xml:
|
||||
components, num_components, components_toc_list, components_hash_list = generate_components (
|
||||
|
|
|
@ -487,25 +487,26 @@ int32_t visualize_pcd_rot_element (uint8_t *start, const char* prefix)
|
|||
return (pointer - start);
|
||||
}
|
||||
|
||||
int32_t visualize_pcd_cpld_element (uint8_t *start, const char* prefix)
|
||||
int32_t visualize_pcd_power_controller_element (uint8_t *start, const char* prefix)
|
||||
{
|
||||
uint8_t *pointer = start;
|
||||
struct pcd_cpld_element *cpld = (struct pcd_cpld_element*) pointer;
|
||||
struct pcd_power_controller_element *power_controller =
|
||||
(struct pcd_power_controller_element*) pointer;
|
||||
|
||||
pointer += sizeof (struct pcd_cpld_element);
|
||||
pointer += sizeof (struct pcd_power_controller_element);
|
||||
|
||||
printf ("%spcd_cpld_element\n", prefix);
|
||||
printf ("%spcd_power_controller_element\n", prefix);
|
||||
printf ("%s{\n", prefix);
|
||||
printf ("%s\tmux_count: %i\n", prefix, cpld->interface.mux_count);
|
||||
printf ("%s\ti2c_flags: 0x%x\n", prefix, cpld->interface.i2c_flags);
|
||||
printf ("%s\tbus: %i\n", prefix, cpld->interface.bus);
|
||||
printf ("%s\taddress: 0x%x\n", prefix, cpld->interface.address);
|
||||
printf ("%s\teid: 0x%x\n", prefix, cpld->interface.eid);
|
||||
printf ("%s\tmux_count: %i\n", prefix, power_controller->i2c.mux_count);
|
||||
printf ("%s\ti2c_flags: 0x%x\n", prefix, power_controller->i2c.i2c_flags);
|
||||
printf ("%s\tbus: %i\n", prefix, power_controller->i2c.bus);
|
||||
printf ("%s\taddress: 0x%x\n", prefix, power_controller->i2c.address);
|
||||
printf ("%s\teid: 0x%x\n", prefix, power_controller->i2c.eid);
|
||||
|
||||
printf ("%s\tMuxes\n", prefix);
|
||||
printf ("%s\t[\n", prefix);
|
||||
|
||||
for (int i = 0; i < cpld->interface.mux_count; ++i) {
|
||||
for (int i = 0; i < power_controller->i2c.mux_count; ++i) {
|
||||
struct pcd_mux *mux = (struct pcd_mux*) pointer;
|
||||
pointer += sizeof (struct pcd_mux);
|
||||
|
||||
|
@ -698,8 +699,8 @@ int32_t visualize_pcd (uint8_t *start)
|
|||
case PCD_ROT:
|
||||
offset = visualize_pcd_rot_element (pointer, "");
|
||||
break;
|
||||
case PCD_CPLD:
|
||||
offset = visualize_pcd_cpld_element (pointer, "");
|
||||
case PCD_POWER_CONTROLLER:
|
||||
offset = visualize_pcd_power_controller_element (pointer, "");
|
||||
break;
|
||||
case PCD_COMPONENT_DIRECT:
|
||||
offset = visualize_pcd_direct_i2c_component_element (pointer, "");
|
||||
|
|
Загрузка…
Ссылка в новой задаче