AlexeiFedorov | 9f2de63 | 2024-09-10 11:48:22 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2024, Arm Limited. All rights reserved. |
| 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
| 6 | |
| 7 | #include <errno.h> |
| 8 | #include <stdbool.h> |
| 9 | #include <stdlib.h> |
| 10 | |
| 11 | #include <debug.h> |
| 12 | #include <pcie.h> |
| 13 | #include <pcie_doe.h> |
| 14 | #include <spdm.h> |
| 15 | |
| 16 | #include <platform_pcie.h> |
| 17 | |
| 18 | void pcie_init(void) |
| 19 | { |
| 20 | /* Create PCIe table and enumeration */ |
| 21 | pcie_create_info_table(); |
| 22 | } |
| 23 | |
| 24 | /* |
| 25 | * @brief Returns the BDF Table pointer |
| 26 | * |
| 27 | * @param None |
| 28 | * |
| 29 | * @return BDF Table pointer |
| 30 | */ |
| 31 | pcie_device_bdf_table_t *get_pcie_bdf_table(void) |
| 32 | { |
| 33 | return pcie_get_bdf_table(); |
| 34 | } |
| 35 | |
| 36 | int find_doe_device(uint32_t *bdf_ptr, uint32_t *cap_base_ptr) |
| 37 | { |
| 38 | pcie_device_bdf_table_t *bdf_table_ptr = pcie_get_bdf_table(); |
| 39 | uint32_t num_bdf = bdf_table_ptr->num_entries; |
| 40 | |
| 41 | INFO("PCI BDF table entries: %u\n", num_bdf); |
| 42 | |
| 43 | /* If no entries in BDF table return error */ |
| 44 | if (num_bdf == 0) { |
| 45 | ERROR("No BDFs entries found\n"); |
| 46 | return -ENODEV; |
| 47 | } |
| 48 | |
| 49 | INFO("PCI BDF table 0x%lx\n", (uintptr_t)bdf_table_ptr); |
| 50 | |
| 51 | while (num_bdf-- != 0) { |
| 52 | uint32_t bdf = bdf_table_ptr->device[num_bdf].bdf; |
| 53 | uint32_t status, doe_cap_base; |
| 54 | |
| 55 | /* Check for DOE capability */ |
| 56 | status = pcie_find_capability(bdf, PCIE_ECAP, DOE_CAP_ID, &doe_cap_base); |
| 57 | if (status == PCIE_SUCCESS) { |
| 58 | INFO("PCIe DOE capability: bdf 0x%x cap_base 0x%x\n", bdf, doe_cap_base); |
| 59 | *bdf_ptr = bdf; |
| 60 | *cap_base_ptr = doe_cap_base; |
| 61 | return 0; |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | ERROR("No PCIe DOE capability found\n"); |
| 66 | return -ENODEV; |
| 67 | } |
| 68 | |
| 69 | int get_spdm_version(uint32_t bdf, uint32_t doe_cap_base) |
| 70 | { |
| 71 | uint32_t response[SPDM_GET_VERS_RESP_LEN], resp_len; |
| 72 | spdm_version_response_t *ver_resp; |
| 73 | spdm_version_number_t *ver_ptr; |
| 74 | uint8_t entry_count; |
| 75 | int ret; |
| 76 | const spdm_get_version_request_t ver_req = { |
| 77 | { SPDM_MESSAGE_VERSION, SPDM_GET_VERSION, } |
| 78 | }; |
| 79 | |
| 80 | ret = pcie_doe_send_req(DOE_HEADER_1, bdf, doe_cap_base, |
| 81 | (uint32_t *)&ver_req, |
| 82 | sizeof(spdm_get_version_request_t)); |
| 83 | if (ret != 0) { |
| 84 | return ret; |
| 85 | } |
| 86 | |
| 87 | ret = pcie_doe_recv_resp(bdf, doe_cap_base, response, &resp_len); |
| 88 | if (ret != 0) { |
| 89 | return ret; |
| 90 | } |
| 91 | |
| 92 | ver_resp = (spdm_version_response_t *)response; |
| 93 | |
| 94 | if (ver_resp->header.spdm_version != SPDM_MESSAGE_VERSION) { |
| 95 | ERROR("SPDM response v.%u doesn't match requested %u\n", |
| 96 | ver_resp->header.spdm_version, |
| 97 | SPDM_MESSAGE_VERSION); |
| 98 | return -EPROGMISMATCH; |
| 99 | } |
| 100 | |
| 101 | if (ver_resp->header.request_response_code != SPDM_VERSION) { |
| 102 | ERROR("SPDM response code %u doesn't match expected %u\n", |
| 103 | ver_resp->header.request_response_code, |
| 104 | SPDM_VERSION); |
| 105 | return -EBADMSG; |
| 106 | } |
| 107 | |
| 108 | entry_count = ver_resp->version_number_entry_count; |
| 109 | INFO("SPDM version entries: %u\n", entry_count); |
| 110 | |
| 111 | ver_ptr = (spdm_version_number_t *)( |
| 112 | (uintptr_t)&ver_resp->version_number_entry_count + |
| 113 | sizeof(ver_resp->version_number_entry_count)); |
| 114 | |
| 115 | while (entry_count-- != 0) { |
| 116 | spdm_version_number_t ver = *ver_ptr++; |
| 117 | |
| 118 | INFO("SPDM v%llu.%llu.%llu.%llu\n", |
| 119 | EXTRACT(SPDM_VER_MAJOR, ver), |
| 120 | EXTRACT(SPDM_VER_MINOR, ver), |
| 121 | EXTRACT(SPDM_VER_UPDATE, ver), |
| 122 | EXTRACT(SPDM_VER_ALPHA, ver)); |
| 123 | } |
| 124 | return ret; |
| 125 | } |
| 126 | |
| 127 | int doe_discovery(uint32_t bdf, uint32_t doe_cap_base) |
| 128 | { |
| 129 | pcie_doe_disc_req_t request = { 0, }; |
| 130 | pcie_doe_disc_resp_t response; |
| 131 | uint32_t resp_len; |
| 132 | int ret; |
| 133 | |
| 134 | do { |
| 135 | ret = pcie_doe_send_req(DOE_HEADER_0, bdf, doe_cap_base, |
| 136 | (uint32_t *)&request, |
| 137 | sizeof(pcie_doe_disc_req_t)); |
| 138 | if (ret != 0) { |
| 139 | return ret; |
| 140 | } |
| 141 | |
| 142 | ret = pcie_doe_recv_resp(bdf, doe_cap_base, |
| 143 | (uint32_t *)&response, &resp_len); |
| 144 | if (ret != 0) { |
| 145 | return ret; |
| 146 | } |
| 147 | |
| 148 | print_doe_disc(&response); |
| 149 | request.index = response.next_index; |
| 150 | |
| 151 | } while (response.next_index != 0); |
| 152 | |
| 153 | return 0; |
| 154 | } |