blob: 911fbd0d6783cbb883dc19f008cf423479ad41e9 [file] [log] [blame]
/*
* Copyright (c) 2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <debug.h>
#include <pcie.h>
#include <pcie_doe.h>
#include <spdm.h>
void pcie_init(void)
{
static bool is_init;
/* Create PCIe table and enumeration */
if (!is_init) {
pcie_create_info_table();
is_init = true;
}
}
/*
* @brief Returns the BDF Table pointer
*
* @param None
*
* @return BDF Table pointer
*/
pcie_device_bdf_table_t *get_pcie_bdf_table(void)
{
return pcie_get_bdf_table();
}
int find_doe_device(uint32_t *bdf_ptr, uint32_t *cap_base_ptr)
{
pcie_device_bdf_table_t *bdf_table_ptr = pcie_get_bdf_table();
uint32_t num_bdf = bdf_table_ptr->num_entries;
INFO("PCI BDF table entries: %u\n", num_bdf);
/* If no entries in BDF table return error */
if (num_bdf == 0) {
ERROR("No BDFs entries found\n");
return -ENODEV;
}
INFO("PCI BDF table 0x%lx\n", (uintptr_t)bdf_table_ptr);
while (num_bdf-- != 0) {
uint32_t bdf = bdf_table_ptr->device[num_bdf].bdf;
uint32_t status, doe_cap_base;
/* Check for DOE capability */
status = pcie_find_capability(bdf, PCIE_ECAP, DOE_CAP_ID, &doe_cap_base);
if (status == PCIE_SUCCESS) {
INFO("PCIe DOE capability: bdf 0x%x cap_base 0x%x\n", bdf, doe_cap_base);
*bdf_ptr = bdf;
*cap_base_ptr = doe_cap_base;
return 0;
}
}
ERROR("No PCIe DOE capability found\n");
return -ENODEV;
}
int get_spdm_version(uint32_t bdf, uint32_t doe_cap_base)
{
uint32_t response[SPDM_GET_VERS_RESP_LEN], resp_len;
spdm_version_response_t *ver_resp;
spdm_version_number_t *ver_ptr;
uint8_t entry_count;
int ret;
const spdm_get_version_request_t ver_req = {
{ SPDM_MESSAGE_VERSION, SPDM_GET_VERSION, }
};
ret = pcie_doe_send_req(DOE_HEADER_1, bdf, doe_cap_base,
(uint32_t *)&ver_req,
sizeof(spdm_get_version_request_t));
if (ret != 0) {
return ret;
}
ret = pcie_doe_recv_resp(bdf, doe_cap_base, response, &resp_len);
if (ret != 0) {
return ret;
}
ver_resp = (spdm_version_response_t *)response;
if (ver_resp->header.spdm_version != SPDM_MESSAGE_VERSION) {
ERROR("SPDM response v.%u doesn't match requested %u\n",
ver_resp->header.spdm_version,
SPDM_MESSAGE_VERSION);
return -EPROGMISMATCH;
}
if (ver_resp->header.request_response_code != SPDM_VERSION) {
ERROR("SPDM response code %u doesn't match expected %u\n",
ver_resp->header.request_response_code,
SPDM_VERSION);
return -EBADMSG;
}
entry_count = ver_resp->version_number_entry_count;
INFO("SPDM version entries: %u\n", entry_count);
ver_ptr = (spdm_version_number_t *)(
(uintptr_t)&ver_resp->version_number_entry_count +
sizeof(ver_resp->version_number_entry_count));
while (entry_count-- != 0) {
spdm_version_number_t ver __unused = *ver_ptr++;
INFO("SPDM v%llu.%llu.%llu.%llu\n",
EXTRACT(SPDM_VER_MAJOR, ver),
EXTRACT(SPDM_VER_MINOR, ver),
EXTRACT(SPDM_VER_UPDATE, ver),
EXTRACT(SPDM_VER_ALPHA, ver));
}
return ret;
}
int doe_discovery(uint32_t bdf, uint32_t doe_cap_base)
{
pcie_doe_disc_req_t request = { 0, };
pcie_doe_disc_resp_t response;
uint32_t resp_len;
int ret;
do {
ret = pcie_doe_send_req(DOE_HEADER_0, bdf, doe_cap_base,
(uint32_t *)&request,
sizeof(pcie_doe_disc_req_t));
if (ret != 0) {
return ret;
}
ret = pcie_doe_recv_resp(bdf, doe_cap_base,
(uint32_t *)&response, &resp_len);
if (ret != 0) {
return ret;
}
print_doe_disc(&response);
request.index = response.next_index;
} while (response.next_index != 0);
return 0;
}