From 040477a4da869330ce95ca40b07af70e4d6c50fd Mon Sep 17 00:00:00 2001 From: Sridevi Ramesh Date: Fri, 16 Jul 2021 04:22:02 -0500 Subject: [PATCH 1/5] OEM-IBM: Implement encode response & decode request API for FileAckWithMetadata This commit implements requester and responder flow for FileAckWithMetadata. PLDM SPEC: PLDM File IO Table 15 Tested: Unit tests passed Signed-off-by: Sridevi Ramesh Change-Id: I6bf5fba7030e42a5501165530a3ffc23a9ff7b8b --- oem/ibm/libpldm/file_io.c | 103 +++++++++++ oem/ibm/libpldm/file_io.h | 87 ++++++++++ oem/ibm/test/libpldm_fileio_test.cpp | 244 +++++++++++++++++++++++++++ 3 files changed, 434 insertions(+) diff --git a/oem/ibm/libpldm/file_io.c b/oem/ibm/libpldm/file_io.c index 262af4704..6c045a959 100644 --- a/oem/ibm/libpldm/file_io.c +++ b/oem/ibm/libpldm/file_io.c @@ -839,3 +839,106 @@ int decode_file_ack_resp(const struct pldm_msg *msg, size_t payload_length, return PLDM_SUCCESS; } + +int encode_file_ack_with_meta_data_req( + uint8_t instance_id, uint16_t file_type, uint32_t file_handle, + uint8_t file_status, uint32_t file_meta_data_1, uint32_t file_meta_data_2, + uint32_t file_meta_data_3, uint32_t file_meta_data_4, struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_REQUEST; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_FILE_ACK_WITH_META_DATA; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_file_ack_with_meta_data_req *req = + (struct pldm_file_ack_with_meta_data_req *)msg->payload; + req->file_type = htole16(file_type); + req->file_handle = htole32(file_handle); + req->file_status = file_status; + req->file_meta_data_1 = htole32(file_meta_data_1); + req->file_meta_data_2 = htole32(file_meta_data_2); + req->file_meta_data_3 = htole32(file_meta_data_3); + req->file_meta_data_4 = htole32(file_meta_data_4); + + return PLDM_SUCCESS; +} + +int decode_file_ack_with_meta_data_resp(const struct pldm_msg *msg, + size_t payload_length, + uint8_t *completion_code) +{ + if (msg == NULL || completion_code == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_FILE_ACK_WITH_META_DATA_RESP_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_file_ack_with_meta_data_resp *response = + (struct pldm_file_ack_with_meta_data_resp *)msg->payload; + *completion_code = response->completion_code; + + return PLDM_SUCCESS; +} + +int decode_file_ack_with_meta_data_req( + const struct pldm_msg *msg, size_t payload_length, uint16_t *file_type, + uint32_t *file_handle, uint8_t *file_status, uint32_t *file_meta_data_1, + uint32_t *file_meta_data_2, uint32_t *file_meta_data_3, + uint32_t *file_meta_data_4) +{ + if (msg == NULL || file_type == NULL || file_handle == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_FILE_ACK_WITH_META_DATA_REQ_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_file_ack_with_meta_data_req *request = + (struct pldm_file_ack_with_meta_data_req *)msg->payload; + *file_type = le16toh(request->file_type); + *file_handle = le32toh(request->file_handle); + *file_status = request->file_status; + *file_meta_data_1 = le32toh(request->file_meta_data_1); + *file_meta_data_2 = le32toh(request->file_meta_data_2); + *file_meta_data_3 = le32toh(request->file_meta_data_3); + *file_meta_data_4 = le32toh(request->file_meta_data_4); + + return PLDM_SUCCESS; +} + +int encode_file_ack_with_meta_data_resp(uint8_t instance_id, + uint8_t completion_code, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_RESPONSE; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_FILE_ACK_WITH_META_DATA; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_file_ack_with_meta_data_resp *response = + (struct pldm_file_ack_with_meta_data_resp *)msg->payload; + response->completion_code = completion_code; + + return PLDM_SUCCESS; +} diff --git a/oem/ibm/libpldm/file_io.h b/oem/ibm/libpldm/file_io.h index 07db4ed0f..ed3c0be2f 100644 --- a/oem/ibm/libpldm/file_io.h +++ b/oem/ibm/libpldm/file_io.h @@ -24,6 +24,8 @@ enum pldm_fileio_commands { PLDM_READ_FILE_BY_TYPE = 0xB, PLDM_WRITE_FILE_BY_TYPE = 0xC, PLDM_FILE_ACK = 0xD, + PLDM_NEW_FILE_AVAILABLE_WITH_META_DATA = 0xE, + PLDM_FILE_ACK_WITH_META_DATA = 0xF, }; /** @brief PLDM Command specific codes @@ -75,6 +77,8 @@ enum pldm_fileio_file_type { #define PLDM_RW_FILE_BY_TYPE_RESP_BYTES 5 #define PLDM_FILE_ACK_REQ_BYTES 7 #define PLDM_FILE_ACK_RESP_BYTES 1 +#define PLDM_FILE_ACK_WITH_META_DATA_REQ_BYTES 26 +#define PLDM_FILE_ACK_WITH_META_DATA_RESP_BYTES 1 /** @struct pldm_read_write_file_memory_req * @@ -718,6 +722,89 @@ int encode_file_ack_req(uint8_t instance_id, uint16_t file_type, int decode_file_ack_resp(const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code); +/* FileAckWithMetadata */ + +/** @struct pldm_file_ack_with_meta_data_req + * + * Structure representing FileAckWithMetadata request + */ +struct pldm_file_ack_with_meta_data_req { + uint16_t file_type; //!< Type of file + uint32_t file_handle; //!< Handle to file + uint8_t file_status; //!< Status of file processing + uint32_t file_meta_data_1; //!< Meta data specific to file type 1 + uint32_t file_meta_data_2; //!< Meta data specific to file type 2 + uint32_t file_meta_data_3; //!< Meta data specific to file type 3 + uint32_t file_meta_data_4; //!< meta data specific to file type 4 +} __attribute__((packed)); + +/** @struct pldm_file_ack_with_meta_data_resp + * + * Structure representing FileAckWithMetadata response + */ +struct pldm_file_ack_with_meta_data_resp { + uint8_t completion_code; //!< Completion code +} __attribute__((packed)); + +/** @brief Encode FileAckWithMetadata request data + * + * @param[in] instance_id - Message's instance id + * @param[in] file_type - Type of the file + * @param[in] file_handle - A handle to the file + * @param[in] file_status - Status of file processing + * @param[in] file_meta_data_1 - meta data specific to file type 1 + * @param[in] file_meta_data_2 - meta data specific to file type 2 + * @param[in] file_meta_data_3 - meta data specific to file type 3 + * @param[in] file_meta_data_4 - Meta data specific to file type 4 + * @param[out] msg - Message will be written to this + * @return pldm_completion_codes + */ +int encode_file_ack_with_meta_data_req( + uint8_t instance_id, uint16_t file_type, uint32_t file_handle, + uint8_t file_status, uint32_t file_meta_data_1, uint32_t file_meta_data_2, + uint32_t file_meta_data_3, uint32_t file_meta_data_4, struct pldm_msg *msg); + +/** @brief Decode FileAckWithMetadata command response data + * + * @param[in] msg - pointer to PLDM response message + * @param[in] payload_length - Length of response payload + * @param[out] completion_code - PLDM completion code + * @return pldm_completion_codes + */ +int decode_file_ack_with_meta_data_resp(const struct pldm_msg *msg, + size_t payload_length, + uint8_t *completion_code); + +/** @brief Decode FileAckWithMetadata request data + * + * @param[in] msg - Pointer to PLDM request message + * @param[in] payload_length - Length of request payload + * @param[out] file_type - Type of the file + * @param[out] file_handle - A handle to the file + * @param[out] file_status - Status of file processing + * @param[out] file_meta_data_1 - meta data specific to file type 1 + * @param[out] file_meta_data_2 - meta data specific to file type 2 + * @param[out] file_meta_data_3 - meta data specific to file type 3 + * @param[out] file_meta_data_4 - Meta data specific to file type 4 + * @return pldm_completion_codes + */ +int decode_file_ack_with_meta_data_req( + const struct pldm_msg *msg, size_t payload_length, uint16_t *file_type, + uint32_t *file_handle, uint8_t *file_status, uint32_t *file_meta_data_1, + uint32_t *file_meta_data_2, uint32_t *file_meta_data_3, + uint32_t *file_meta_data_4); + +/** @brief Create a PLDM response message for FileAckWithMetadata + * + * @param[in] instance_id - Message's instance id + * @param[in] completion_code - PLDM completion code + * @param[in,out] msg - Message will be written to this + * @return pldm_completion_codes + */ +int encode_file_ack_with_meta_data_resp(uint8_t instance_id, + uint8_t completion_code, + struct pldm_msg *msg); + #ifdef __cplusplus } #endif diff --git a/oem/ibm/test/libpldm_fileio_test.cpp b/oem/ibm/test/libpldm_fileio_test.cpp index 94b7e1da3..fcdbbf03f 100644 --- a/oem/ibm/test/libpldm_fileio_test.cpp +++ b/oem/ibm/test/libpldm_fileio_test.cpp @@ -1628,3 +1628,247 @@ TEST(FileAck, testBadEncodeRequest) ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA); } + +TEST(FileAckWithMetadata, testGoodEncodeResponse) +{ + std::array + responseMsg{}; + + uint8_t completionCode = 0x0; + + pldm_msg* response = reinterpret_cast(responseMsg.data()); + + auto rc = encode_file_ack_with_meta_data_resp(0, completionCode, response); + + ASSERT_EQ(rc, PLDM_SUCCESS); + ASSERT_EQ(response->hdr.request, PLDM_RESPONSE); + ASSERT_EQ(response->hdr.instance_id, 0); + ASSERT_EQ(response->hdr.type, PLDM_OEM); + ASSERT_EQ(response->hdr.command, PLDM_FILE_ACK_WITH_META_DATA); + ASSERT_EQ( + 0, memcmp(response->payload, &completionCode, sizeof(completionCode))); +} + +TEST(FileAckWithMetadata, testBadEncodeResponse) +{ + std::array + responseMsg{}; + pldm_msg* response = reinterpret_cast(responseMsg.data()); + + // completion code is PLDM_ERROR + auto rc = encode_file_ack_with_meta_data_resp(0, PLDM_ERROR, response); + + ASSERT_EQ(rc, PLDM_SUCCESS); + ASSERT_EQ(response->hdr.request, PLDM_RESPONSE); + ASSERT_EQ(response->hdr.instance_id, 0); + ASSERT_EQ(response->hdr.type, PLDM_OEM); + ASSERT_EQ(response->hdr.command, PLDM_FILE_ACK_WITH_META_DATA); + ASSERT_EQ(response->payload[0], PLDM_ERROR); + + // response is NULL pointer + rc = encode_file_ack_with_meta_data_resp(0, PLDM_SUCCESS, NULL); + + ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA); +} + +TEST(FileAckWithMetadata, testGoodDecodeResponse) +{ + std::array + responseMsg{}; + + auto responsePtr = reinterpret_cast(responseMsg.data()); + size_t payload_length = responseMsg.size() - sizeof(pldm_msg_hdr); + auto response = reinterpret_cast( + responsePtr->payload); + + // Random value for completion code + uint8_t completionCode = 0x0; + + response->completion_code = completionCode; + + uint8_t retCompletionCode = PLDM_SUCCESS; + + // Invoke decode the read/write file response + auto rc = decode_file_ack_with_meta_data_resp(responsePtr, payload_length, + &retCompletionCode); + + ASSERT_EQ(rc, PLDM_SUCCESS); + ASSERT_EQ(completionCode, retCompletionCode); +} + +TEST(FileAckWithMetadata, testBadDecodeResponse) +{ + uint8_t completionCode = 0; + + // Request payload message is missing + auto rc = decode_file_ack_with_meta_data_resp(NULL, 0, &completionCode); + ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA); + + std::array + responseMsg{}; + + auto responsePtr = reinterpret_cast(responseMsg.data()); + + // Payload length is invalid + rc = decode_file_ack_with_meta_data_resp(responsePtr, 0, &completionCode); + ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); +} + +TEST(FileAckWithMetadata, testGoodEncodeRequest) +{ + std::array + requestMsg{}; + + uint16_t fileType = 0xFFFF; + uint32_t fileHandle = 0x12345678; + uint8_t fileStatus = 0xFF; + uint32_t fileMetaData1 = 0xFFFFFFFF; + uint32_t fileMetaData2 = 0xFFFFFFFF; + uint32_t fileMetaData3 = 0xFFFFFFFF; + uint32_t fileMetaData4 = 0xFFFFFFFF; + + uint16_t fileTypeLe = htole16(fileType); + uint32_t fileHandleLe = htole32(fileHandle); + uint32_t fileMetaData1Le = htole32(fileMetaData1); + uint32_t fileMetaData2Le = htole32(fileMetaData2); + uint32_t fileMetaData3Le = htole32(fileMetaData3); + uint32_t fileMetaData4Le = htole32(fileMetaData4); + + pldm_msg* request = reinterpret_cast(requestMsg.data()); + + auto rc = encode_file_ack_with_meta_data_req( + 0, fileType, fileHandle, fileStatus, fileMetaData1, fileMetaData2, + fileMetaData3, fileMetaData4, request); + + ASSERT_EQ(rc, PLDM_SUCCESS); + ASSERT_EQ(request->hdr.request, PLDM_REQUEST); + ASSERT_EQ(request->hdr.instance_id, 0); + ASSERT_EQ(request->hdr.type, PLDM_OEM); + ASSERT_EQ(request->hdr.command, PLDM_FILE_ACK_WITH_META_DATA); + ASSERT_EQ(0, memcmp(request->payload, &fileTypeLe, sizeof(fileTypeLe))); + ASSERT_EQ(0, memcmp(request->payload + sizeof(fileTypeLe), &fileHandleLe, + sizeof(fileHandleLe))); + ASSERT_EQ( + 0, memcmp(request->payload + sizeof(fileTypeLe) + sizeof(fileHandleLe), + &fileStatus, sizeof(fileStatus))); + ASSERT_EQ(0, memcmp(request->payload + sizeof(fileTypeLe) + + sizeof(fileHandleLe) + sizeof(fileStatus), + &fileMetaData1Le, sizeof(fileMetaData1Le))); + ASSERT_EQ(0, memcmp(request->payload + sizeof(fileTypeLe) + + sizeof(fileHandleLe) + sizeof(fileStatus) + + sizeof(fileMetaData1Le), + &fileMetaData2Le, sizeof(fileMetaData2Le))); + + ASSERT_EQ(0, memcmp(request->payload + sizeof(fileTypeLe) + + sizeof(fileHandleLe) + sizeof(fileStatus) + + sizeof(fileMetaData1Le) + sizeof(fileMetaData2Le), + &fileMetaData3Le, sizeof(fileMetaData3Le))); + + ASSERT_EQ(0, memcmp(request->payload + sizeof(fileTypeLe) + + sizeof(fileHandleLe) + sizeof(fileStatus) + + sizeof(fileMetaData1Le) + sizeof(fileMetaData2Le) + + sizeof(fileMetaData3Le), + &fileMetaData4Le, sizeof(fileMetaData4Le))); +} + +TEST(FileAckWithMetadata, testBadEncodeRequest) +{ + uint8_t fileType = 0xFF; + uint32_t fileHandle = 0; + uint8_t fileStatus = 0; + uint32_t fileMetaData1 = 0; + uint32_t fileMetaData2 = 0; + uint32_t fileMetaData3 = 0; + uint32_t fileMetaData4 = 0; + + // request is NULL pointer + auto rc = encode_file_ack_with_meta_data_req( + 0, fileType, fileHandle, fileStatus, fileMetaData1, fileMetaData2, + fileMetaData3, fileMetaData4, nullptr); + + ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA); +} + +TEST(FileAckWithMetadata, testGoodDecodeRequest) +{ + std::array + requestMsg{}; + + auto requestPtr = reinterpret_cast(requestMsg.data()); + size_t payload_length = requestMsg.size() - sizeof(pldm_msg_hdr); + auto request = reinterpret_cast( + requestPtr->payload); + + uint16_t fileType = 0xFFFF; + uint32_t fileHandle = 0x12345678; + uint8_t fileStatus = 0xFF; + uint32_t fileMetaData1 = 0x12345678; + uint32_t fileMetaData2 = 0x87654321; + uint32_t fileMetaData3 = 0x22121117; + uint32_t fileMetaData4 = 0x12334345; + + request->file_type = htole16(fileType); + request->file_handle = htole32(fileHandle); + request->file_status = fileStatus; + request->file_meta_data_1 = htole32(fileMetaData1); + request->file_meta_data_2 = htole32(fileMetaData2); + request->file_meta_data_3 = htole32(fileMetaData3); + request->file_meta_data_4 = htole32(fileMetaData4); + + uint16_t retFileType = 0xFFFF; + uint32_t retFileHandle = 0; + uint8_t retFileStatus = 0; + uint32_t retFileMetaData1 = 0; + uint32_t retFileMetaData2 = 0; + uint32_t retFileMetaData3 = 0; + uint32_t retFileMetaData4 = 0; + + auto rc = decode_file_ack_with_meta_data_req( + requestPtr, payload_length, &retFileType, &retFileHandle, + &retFileStatus, &retFileMetaData1, &retFileMetaData2, &retFileMetaData3, + &retFileMetaData4); + ASSERT_EQ(rc, PLDM_SUCCESS); + ASSERT_EQ(fileType, retFileType); + ASSERT_EQ(fileHandle, retFileHandle); + ASSERT_EQ(fileStatus, retFileStatus); + ASSERT_EQ(fileMetaData1, retFileMetaData1); + ASSERT_EQ(fileMetaData2, retFileMetaData2); + ASSERT_EQ(fileMetaData3, retFileMetaData3); + ASSERT_EQ(fileMetaData4, retFileMetaData4); +} + +TEST(FileAckWithMetadata, testBadDecodeRequest) +{ + uint16_t fileType = 0; + uint32_t fileHandle = 0; + uint8_t fileStatus = 0; + uint32_t fileMetaData1 = 0; + uint32_t fileMetaData2 = 0; + uint32_t fileMetaData3 = 0; + uint32_t fileMetaData4 = 0; + + // Request payload message is missing + auto rc = decode_file_ack_with_meta_data_req( + NULL, 0, &fileType, &fileHandle, &fileStatus, &fileMetaData1, + &fileMetaData2, &fileMetaData3, &fileMetaData4); + + ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA); + + std::array + requestMsg{}; + + auto requestPtr = reinterpret_cast(requestMsg.data()); + + // Payload length is invalid + rc = decode_file_ack_with_meta_data_req( + requestPtr, 0, &fileType, &fileHandle, &fileStatus, &fileMetaData1, + &fileMetaData2, &fileMetaData3, &fileMetaData4); + ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); +} From da540ec18eda5a7ad4662b7a1b552aff6be900bc Mon Sep 17 00:00:00 2001 From: Varsha Kaverappa Date: Tue, 27 Jul 2021 00:20:06 -0500 Subject: [PATCH 2/5] OEM: Create a new file in oem-ibm file io to serve COD This commit introduces a new LicenseHandler class that is inherits the FileHandler class. This class contains functions to read the the license and create a new license file in path /var/lib/ibm/cod that will be read and sent to the phyp. Signed-off-by: Varsha Kaverappa Change-Id: Ibabeb812795fad1be2e12cd3bb9b740f1f3112b6 --- oem/ibm/libpldm/file_io.h | 1 + oem/ibm/libpldmresponder/file_io_type_lic.cpp | 39 ++++++++++++++++ oem/ibm/libpldmresponder/file_io_type_lic.hpp | 44 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 oem/ibm/libpldmresponder/file_io_type_lic.cpp create mode 100644 oem/ibm/libpldmresponder/file_io_type_lic.hpp diff --git a/oem/ibm/libpldm/file_io.h b/oem/ibm/libpldm/file_io.h index ed3c0be2f..6712d705b 100644 --- a/oem/ibm/libpldm/file_io.h +++ b/oem/ibm/libpldm/file_io.h @@ -59,6 +59,7 @@ enum pldm_fileio_file_type { PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS = 0x8, PLDM_FILE_TYPE_RESOURCE_DUMP = 0x9, PLDM_FILE_TYPE_PROGRESS_SRC = 0xA, + PLDM_FILE_TYPE_COD_LICENSE_KEY = 0xB, }; #define PLDM_RW_FILE_MEM_REQ_BYTES 20 diff --git a/oem/ibm/libpldmresponder/file_io_type_lic.cpp b/oem/ibm/libpldmresponder/file_io_type_lic.cpp new file mode 100644 index 000000000..425da0470 --- /dev/null +++ b/oem/ibm/libpldmresponder/file_io_type_lic.cpp @@ -0,0 +1,39 @@ +#include "file_io_type_lic.hpp" + +#include "libpldm/base.h" +#include "oem/ibm/libpldm/file_io.h" + +#include "common/utils.hpp" + +#include + +#include + +namespace pldm +{ +namespace responder +{ + +static constexpr auto codFilePath = "/var/lib/ibm/cod/"; + +int LicenseHandler::read(uint32_t offset, uint32_t& length, Response& response, + oem_platform::Handler* /*oemPlatformHandler*/) +{ + std::string filePath = codFilePath; + filePath += "licFile" + + if (licType != PLDM_FILE_TYPE_COD_LICENSE_KEY) + { + return PLDM_ERROR_INVALID_DATA; + } + auto rc = readFile(filePath.c_str(), offset, length, response); + fs::remove(filePath); + if (rc) + { + return PLDM_ERROR; + } + return PLDM_SUCCESS; +} + +} // namespace responder +} // namespace pldm diff --git a/oem/ibm/libpldmresponder/file_io_type_lic.hpp b/oem/ibm/libpldmresponder/file_io_type_lic.hpp new file mode 100644 index 000000000..32beadb57 --- /dev/null +++ b/oem/ibm/libpldmresponder/file_io_type_lic.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include "file_io_by_type.hpp" + +#include + +namespace pldm +{ +namespace responder +{ + +using LicType = uint16_t; + +/** @class LicenseHandler + * + * @brief Inherits and implements FileHandler. This class is used + * to read license + */ +class LicenseHandler : public FileHandler +{ + public: + /** @brief Handler constructor + */ + LicenseHandler(uint32_t fileHandle, uint16_t fileType) : + FileHandler(fileHandle), licType(fileType) + {} + + virtual int readIntoMemory(uint32_t offset, uint32_t& length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/); + virtual int read(uint32_t offset, uint32_t& length, Response& response, + oem_platform::Handler* /*oemPlatformHandler*/); + + /** @brief CertHandler destructor + */ + ~LicenseHandler() + {} + + private: + uint16_t licType; //!< type of the certificate +}; +} // namespace responder +} // namespace pldm +~ From bf619a76dd15d506637d17e6b0b60f9dc8733c0d Mon Sep 17 00:00:00 2001 From: Varsha Kaverappa Date: Wed, 8 Sep 2021 01:44:04 -0500 Subject: [PATCH 3/5] OEM-IBM: COD: pass license activation key to Phyp In this commit, property change signal is monitored for a license string added to the COD dbus interface. Once property change signal is detected, anew file available command is sent to Host and subsequently the string is passed by an inband readFileByType command Signed-off-by: Varsha Kaverappa Change-Id: I6f9147a7b3b944d3ca02cd17a5adf338460fffa9 --- oem/ibm/libpldmresponder/file_io.hpp | 32 +++++++++++++++++ oem/ibm/requester/dbus_to_file_handler.cpp | 42 +++++++++++++++++++--- oem/ibm/requester/dbus_to_file_handler.hpp | 5 +++ 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/oem/ibm/libpldmresponder/file_io.hpp b/oem/ibm/libpldmresponder/file_io.hpp index 10c6d479e..59547e39d 100644 --- a/oem/ibm/libpldmresponder/file_io.hpp +++ b/oem/ibm/libpldmresponder/file_io.hpp @@ -163,6 +163,9 @@ static constexpr auto resDumpEntry = "com.ibm.Dump.Entry.Resource"; static constexpr auto certObjPath = "/xyz/openbmc_project/certs/ca/"; static constexpr auto certAuthority = "xyz.openbmc_project.PLDM.Provider.Certs.Authority.CSR"; + +static constexpr auto codLicObjPath = "/com/ibm/license"; +static constexpr auto codLicInterface = "com.ibm.License.LicenseManager"; class Handler : public CmdHandler { public: @@ -313,6 +316,32 @@ class Handler : public CmdHandler } } }); + codLicensesubs = std::make_unique( + pldm::utils::DBusHandler::getBus(), + sdbusplus::bus::match::rules::propertiesChanged(codLicObjPath, + codLicInterface), + [this, hostSockFd, hostEid, dbusImplReqester, + &handler](sdbusplus::message::message& msg) { + sdbusplus::message::object_path path; + std::map props; + std::string iface; + msg.read(iface, props); + std::string licenseStr; + + for (auto& prop : props) + { + if (prop.first == "LicenseString") + { + pldm::utils::PropertyValue licStrVal{prop.second}; + licenseStr = std::get(licStrVal); + } + } + dbusToFileHandlers + .emplace_back(std::make_unique< + pldm::requester::oem_ibm::DbusToFileHandler>( + hostSockFd, hostEid, dbusImplReqester, path, handler)) + ->newLicFileAvailable(licenseStr); + }); } /** @brief Handler for readFileIntoMemory command @@ -428,6 +457,9 @@ class Handler : public CmdHandler std::unique_ptr vmiCertMatcher; //!< Pointer to capture the interface added signal //!< for new csr string + std::unique_ptr + codLicensesubs; //!< Pointer to capture the property changed signal + //!< for new license string /** @brief PLDM request handler */ pldm::requester::Handler* handler; std::vector> diff --git a/oem/ibm/requester/dbus_to_file_handler.cpp b/oem/ibm/requester/dbus_to_file_handler.cpp index ee23bce03..cd6c9c62f 100644 --- a/oem/ibm/requester/dbus_to_file_handler.cpp +++ b/oem/ibm/requester/dbus_to_file_handler.cpp @@ -220,13 +220,46 @@ void DbusToFileHandler::newCsrFileAvailable(const std::string& csr, PLDM_FILE_TYPE_CERT_SIGNING_REQUEST); } +void DbusToFileHandler::newLicFileAvailable(const std::string& licenseStr) +{ + namespace fs = std::filesystem; + std::string dirPath = "/var/lib/ibm/cod"; + const fs::path licDirPath = dirPath; + + if (!fs::exists(licDirPath)) + { + fs::create_directories(licDirPath); + fs::permissions(licDirPath, + fs::perms::others_read | fs::perms::owner_write); + } + + fs::path licFilePath = licDirPath / "licFile"; + std::ofstream licFile; + + licFile.open(licFilePath, std::ios::out | std::ofstream::binary); + + if (!licFile) + { + std::cerr << "License file open error: " << licFilePath << "\n"; + return; + } + + // Add csr to file + licFile << licenseStr << std::endl; + + licFile.close(); + uint32_t fileSize = fs::file_size(licFilePath); + + newFileAvailableSendToHost(fileSize, 0, PLDM_FILE_TYPE_COD_LICENSE_KEY); +} + void DbusToFileHandler::newFileAvailableSendToHost(const uint32_t fileSize, const uint32_t fileHandle, const uint16_t type) { if (requester == NULL) { - std::cerr << "Failed to send csr to host."; + std::cerr << "Failed to send file to host."; pldm::utils::reportError( "xyz.openbmc_project.bmc.pldm.InternalFailure"); return; @@ -252,14 +285,14 @@ void DbusToFileHandler::newFileAvailableSendToHost(const uint32_t fileSize, if (response == nullptr || !respMsgLen) { std::cerr << "Failed to receive response for NewFileAvailable " - "command for vmi \n"; + "command\n"; return; } uint8_t completionCode{}; auto rc = decode_new_file_resp(response, respMsgLen, &completionCode); if (rc || completionCode) { - std::cerr << "Failed to decode_new_file_resp for vmi, or" + std::cerr << "Failed to decode_new_file_resp for file, or" << " Host returned error for new_file_available" << " rc=" << rc << ", cc=" << static_cast(completionCode) @@ -273,8 +306,7 @@ void DbusToFileHandler::newFileAvailableSendToHost(const uint32_t fileSize, std::move(requestMsg), std::move(newFileAvailableRespHandler)); if (rc) { - std::cerr - << "Failed to send NewFileAvailable Request to Host for vmi \n"; + std::cerr << "Failed to send NewFileAvailable Request to Host\n"; pldm::utils::reportError( "xyz.openbmc_project.bmc.pldm.InternalFailure"); } diff --git a/oem/ibm/requester/dbus_to_file_handler.hpp b/oem/ibm/requester/dbus_to_file_handler.hpp index d415d1dec..bc5bd8448 100644 --- a/oem/ibm/requester/dbus_to_file_handler.hpp +++ b/oem/ibm/requester/dbus_to_file_handler.hpp @@ -56,6 +56,11 @@ class DbusToFileHandler void newCsrFileAvailable(const std::string& csr, const std::string fileHandle); + /** @brief Process the new license file available + * @param[in] licenseStr - License string + */ + void newLicFileAvailable(const std::string& licenseStr); + private: /** @brief Send the new file available command request to hypervisor * @param[in] fileSize - size of the file From 9f6d2eb1db002fde00da87b0e36d8d4f37536b00 Mon Sep 17 00:00:00 2001 From: Varsha Kaverappa Date: Wed, 15 Sep 2021 01:08:51 -0500 Subject: [PATCH 4/5] OEM IBM: Set status property once file ack for license string is received from phyp This commit receives the ack response with meta data from host and set the dbus status property with the enum value to indicate if the COD_ACTIVATION_KEY was accepted by the host. Signed-off-by: Varsha Kaverappa Change-Id: Ibcbdab6aa34a9259277590ccc9d4f010c202b6a0 --- oem/ibm/libpldmresponder/file_io.cpp | 45 +++++ oem/ibm/libpldmresponder/file_io.hpp | 9 + oem/ibm/libpldmresponder/file_io_by_type.cpp | 5 + oem/ibm/libpldmresponder/file_io_by_type.hpp | 9 + .../libpldmresponder/file_io_type_cert.hpp | 5 + .../libpldmresponder/file_io_type_dump.hpp | 5 + oem/ibm/libpldmresponder/file_io_type_lic.cpp | 156 +++++++++++++++++- oem/ibm/libpldmresponder/file_io_type_lic.hpp | 52 +++++- oem/ibm/libpldmresponder/file_io_type_lid.hpp | 5 + oem/ibm/libpldmresponder/file_io_type_pel.hpp | 5 + .../file_io_type_progress_src.hpp | 5 + 11 files changed, 292 insertions(+), 9 deletions(-) diff --git a/oem/ibm/libpldmresponder/file_io.cpp b/oem/ibm/libpldmresponder/file_io.cpp index 1192510ca..abb4f140f 100644 --- a/oem/ibm/libpldmresponder/file_io.cpp +++ b/oem/ibm/libpldmresponder/file_io.cpp @@ -892,6 +892,51 @@ Response Handler::newFileAvailable(const pldm_msg* request, return response; } +Response Handler::fileAckWithMetaData(const pldm_msg* request, + size_t payloadLength) +{ + Response response(sizeof(pldm_msg_hdr) + + PLDM_FILE_ACK_WITH_META_DATA_RESP_BYTES); + + if (payloadLength != PLDM_FILE_ACK_WITH_META_DATA_RESP_BYTES) + { + return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); + } + uint16_t fileType{}; + uint32_t fileHandle{}; + uint8_t fileStatus{}; + uint32_t fileMetaData1{}; + uint32_t fileMetaData2{}; + uint32_t fileMetaData3{}; + uint32_t fileMetaData4{}; + + auto rc = decode_file_ack_with_meta_data_req( + request, payloadLength, &fileType, &fileHandle, &fileStatus, + &fileMetaData1, &fileMetaData2, &fileMetaData3, &fileMetaData4); + + if (rc != PLDM_SUCCESS) + { + return CmdHandler::ccOnlyResponse(request, rc); + } + + std::unique_ptr handler{}; + try + { + handler = getHandlerByType(fileType, fileHandle); + } + catch (const InternalFailure& e) + { + std::cerr << "unknown file type, TYPE=" << fileType << "\n"; + return CmdHandler::ccOnlyResponse(request, PLDM_INVALID_FILE_TYPE); + } + + rc = handler->fileAckWithMetaData(fileMetaData1); + auto responsePtr = reinterpret_cast(response.data()); + encode_file_ack_with_meta_data_resp(request->hdr.instance_id, rc, + responsePtr); + return response; +} + } // namespace oem_ibm } // namespace responder } // namespace pldm diff --git a/oem/ibm/libpldmresponder/file_io.hpp b/oem/ibm/libpldmresponder/file_io.hpp index 59547e39d..c5a997f6f 100644 --- a/oem/ibm/libpldmresponder/file_io.hpp +++ b/oem/ibm/libpldmresponder/file_io.hpp @@ -441,6 +441,15 @@ class Handler : public CmdHandler */ Response newFileAvailable(const pldm_msg* request, size_t payloadLength); + /** @brief Handler for fileAckWithMetaData command + * + * @param[in] request - PLDM request msg + * @param[in] payloadLength - length of the message payload + * + * @return PLDM response message + */ + Response fileAckWithMetaData(const pldm_msg* request, size_t payloadLength); + private: oem_platform::Handler* oemPlatformHandler; int hostSockFd; diff --git a/oem/ibm/libpldmresponder/file_io_by_type.cpp b/oem/ibm/libpldmresponder/file_io_by_type.cpp index 9bd5e7482..602f258b2 100644 --- a/oem/ibm/libpldmresponder/file_io_by_type.cpp +++ b/oem/ibm/libpldmresponder/file_io_by_type.cpp @@ -8,6 +8,7 @@ #include "common/utils.hpp" #include "file_io_type_cert.hpp" #include "file_io_type_dump.hpp" +#include "file_io_type_lic.hpp" #include "file_io_type_lid.hpp" #include "file_io_type_pel.hpp" #include "file_io_type_progress_src.hpp" @@ -157,6 +158,10 @@ std::unique_ptr getHandlerByType(uint16_t fileType, { return std::make_unique(fileHandle, fileType); } + case PLDM_FILE_TYPE_COD_LICENSE_KEY: + { + return std::make_unique(fileHandle, fileType); + } case PLDM_FILE_TYPE_PROGRESS_SRC: { return std::make_unique(fileHandle); diff --git a/oem/ibm/libpldmresponder/file_io_by_type.hpp b/oem/ibm/libpldmresponder/file_io_by_type.hpp index 1aed02b1a..10fee0e1b 100644 --- a/oem/ibm/libpldmresponder/file_io_by_type.hpp +++ b/oem/ibm/libpldmresponder/file_io_by_type.hpp @@ -79,6 +79,15 @@ class FileHandler */ virtual int newFileAvailable(uint64_t length) = 0; + /** @brief Method to process a file ack with meta data notification from the + * host. The bmc can chose to do different actions based on the file type. + * + * @param[in] metaDataValue - value of meta datat sent by host + * + * @return PLDM status code + */ + virtual int fileAckWithMetaData(uint32_t metaDataValue) = 0; + /** @brief Method to read an oem file type's content into the PLDM response. * @param[in] filePath - file to read from * @param[in] offset - offset to read diff --git a/oem/ibm/libpldmresponder/file_io_type_cert.hpp b/oem/ibm/libpldmresponder/file_io_type_cert.hpp index ee3457566..879355cbe 100644 --- a/oem/ibm/libpldmresponder/file_io_type_cert.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_cert.hpp @@ -48,6 +48,11 @@ class CertHandler : public FileHandler virtual int newFileAvailable(uint64_t length); + virtual int fileAckWithMetaData(uint32_t /*metaDataValue*/) + { + return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + } + /** @brief CertHandler destructor */ ~CertHandler() diff --git a/oem/ibm/libpldmresponder/file_io_type_dump.hpp b/oem/ibm/libpldmresponder/file_io_type_dump.hpp index 2c425d1bc..571ea66fb 100644 --- a/oem/ibm/libpldmresponder/file_io_type_dump.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_dump.hpp @@ -39,6 +39,11 @@ class DumpHandler : public FileHandler virtual int fileAck(uint8_t fileStatus); + virtual int fileAckWithMetaData(uint32_t /*metaDataValue*/) + { + return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + } + std::string findDumpObjPath(uint32_t fileHandle); std::string getOffloadUri(uint32_t fileHandle); diff --git a/oem/ibm/libpldmresponder/file_io_type_lic.cpp b/oem/ibm/libpldmresponder/file_io_type_lic.cpp index 425da0470..63b0413b7 100644 --- a/oem/ibm/libpldmresponder/file_io_type_lic.cpp +++ b/oem/ibm/libpldmresponder/file_io_type_lic.cpp @@ -11,6 +11,8 @@ namespace pldm { +using namespace utils; + namespace responder { @@ -20,9 +22,9 @@ int LicenseHandler::read(uint32_t offset, uint32_t& length, Response& response, oem_platform::Handler* /*oemPlatformHandler*/) { std::string filePath = codFilePath; - filePath += "licFile" + filePath += "licFile"; - if (licType != PLDM_FILE_TYPE_COD_LICENSE_KEY) + if (licType != PLDM_FILE_TYPE_COD_LICENSE_KEY) { return PLDM_ERROR_INVALID_DATA; } @@ -35,5 +37,155 @@ int LicenseHandler::read(uint32_t offset, uint32_t& length, Response& response, return PLDM_SUCCESS; } +int LicenseHandler::fileAckWithMetaData(uint32_t metaDataValue) +{ + constexpr auto codLicInterface = "com.ibm.License.LicenseManager"; + constexpr auto codLicObjPath = "/com/ibm/license"; + + Status status = static_cast(metaDataValue); + + if (status == Status::InvalidLicense) + { + PropertyValue valueStatus{ + "com.ibm.License.LicenseManager.Status.InvalidLicense"}; + DBusMapping dbusMappingStatus{codLicObjPath, codLicInterface, "Status", + "string"}; + + try + { + pldm::utils::DBusHandler().setDbusProperty(dbusMappingStatus, + valueStatus); + } + catch (const std::exception& e) + { + std::cerr << "failed to set status property of license manager, " + "ERROR=" + << e.what() << "\n"; + return PLDM_ERROR; + } + } + else if (status == Status::Activated) + { + PropertyValue valueStatus{ + "com.ibm.License.LicenseManager.Status.Activated"}; + DBusMapping dbusMappingStatus{codLicObjPath, codLicInterface, "Status", + "string"}; + + try + { + pldm::utils::DBusHandler().setDbusProperty(dbusMappingStatus, + valueStatus); + } + catch (const std::exception& e) + { + std::cerr << "failed to set status property of license manager, " + "ERROR=" + << e.what() << "\n"; + return PLDM_ERROR; + } + } + else if (status == Status::Pending) + { + PropertyValue valueStatus{ + "com.ibm.License.LicenseManager.Status.Pending"}; + DBusMapping dbusMappingStatus{codLicObjPath, codLicInterface, "Status", + "string"}; + + try + { + pldm::utils::DBusHandler().setDbusProperty(dbusMappingStatus, + valueStatus); + } + catch (const std::exception& e) + { + std::cerr << "failed to set status property of license manager, " + "ERROR=" + << e.what() << "\n"; + return PLDM_ERROR; + } + } + else if (status == Status::ActivationFailed) + { + PropertyValue valueStatus{ + "com.ibm.License.LicenseManager.Status.ActivationFailed"}; + DBusMapping dbusMappingStatus{codLicObjPath, codLicInterface, "Status", + "string"}; + + try + { + pldm::utils::DBusHandler().setDbusProperty(dbusMappingStatus, + valueStatus); + } + catch (const std::exception& e) + { + std::cerr << "failed to set status property of license manager, " + "ERROR=" + << e.what() << "\n"; + return PLDM_ERROR; + } + } + else if (status == Status::IncorrectSystem) + { + PropertyValue valueStatus{ + "com.ibm.License.LicenseManager.Status.IncorrectSystem"}; + DBusMapping dbusMappingStatus{codLicObjPath, codLicInterface, "Status", + "string"}; + + try + { + pldm::utils::DBusHandler().setDbusProperty(dbusMappingStatus, + valueStatus); + } + catch (const std::exception& e) + { + std::cerr << "failed to set status property of license manager, " + "ERROR=" + << e.what() << "\n"; + return PLDM_ERROR; + } + } + else if (status == Status::InvalidHostState) + { + PropertyValue valueStatus{ + "com.ibm.License.LicenseManager.Status.InvalidHostState"}; + DBusMapping dbusMappingStatus{codLicObjPath, codLicInterface, "Status", + "string"}; + + try + { + pldm::utils::DBusHandler().setDbusProperty(dbusMappingStatus, + valueStatus); + } + catch (const std::exception& e) + { + std::cerr << "failed to set status property of license manager, " + "ERROR=" + << e.what() << "\n"; + return PLDM_ERROR; + } + } + else if (status == Status::IncorrectSequence) + { + PropertyValue valueStatus{ + "com.ibm.License.LicenseManager.Status.IncorrectSequence"}; + DBusMapping dbusMappingStatus{codLicObjPath, codLicInterface, "Status", + "string"}; + + try + { + pldm::utils::DBusHandler().setDbusProperty(dbusMappingStatus, + valueStatus); + } + catch (const std::exception& e) + { + std::cerr << "failed to set status property of license manager, " + "ERROR=" + << e.what() << "\n"; + return PLDM_ERROR; + } + } + return PLDM_SUCCESS; +} + } // namespace responder } // namespace pldm diff --git a/oem/ibm/libpldmresponder/file_io_type_lic.hpp b/oem/ibm/libpldmresponder/file_io_type_lic.hpp index 32beadb57..98c4e2440 100644 --- a/oem/ibm/libpldmresponder/file_io_type_lic.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_lic.hpp @@ -2,8 +2,6 @@ #include "file_io_by_type.hpp" -#include - namespace pldm { namespace responder @@ -25,20 +23,60 @@ class LicenseHandler : public FileHandler FileHandler(fileHandle), licType(fileType) {} - virtual int readIntoMemory(uint32_t offset, uint32_t& length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/); + virtual int writeFromMemory(uint32_t /*offset*/, uint32_t /*length*/, + uint64_t /*address*/, + oem_platform::Handler* /*oemPlatformHandler*/) + { + return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + } + + virtual int readIntoMemory(uint32_t /*offset*/, uint32_t& /*length*/, + uint64_t /*address*/, + oem_platform::Handler* /*oemPlatformHandler*/) + { + return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + } + virtual int read(uint32_t offset, uint32_t& length, Response& response, oem_platform::Handler* /*oemPlatformHandler*/); - /** @brief CertHandler destructor + virtual int write(const char* /*buffer*/, uint32_t /*offset*/, + uint32_t& /*length*/, + oem_platform::Handler* /*oemPlatformHandler*/) + { + return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + } + + virtual int fileAck(uint8_t /*fileStatus*/) + { + return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + } + + virtual int newFileAvailable(uint64_t /*length*/) + { + return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + } + + virtual int fileAckWithMetaData(uint32_t metaDataValue); + + /** @brief LicenseHandler destructor */ ~LicenseHandler() {} private: uint16_t licType; //!< type of the certificate + + enum class Status + { + InvalidLicense, + Activated, + Pending, + ActivationFailed, + IncorrectSystem, + InvalidHostState, + IncorrectSequence + }; }; } // namespace responder } // namespace pldm -~ diff --git a/oem/ibm/libpldmresponder/file_io_type_lid.hpp b/oem/ibm/libpldmresponder/file_io_type_lid.hpp index 0853d48a7..9682ff2c7 100644 --- a/oem/ibm/libpldmresponder/file_io_type_lid.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_lid.hpp @@ -300,6 +300,11 @@ class LidHandler : public FileHandler return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; } + virtual int fileAckWithMetaData(uint32_t /*metaDataValue*/) + { + return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + } + /** @brief LidHandler destructor */ ~LidHandler() diff --git a/oem/ibm/libpldmresponder/file_io_type_pel.hpp b/oem/ibm/libpldmresponder/file_io_type_pel.hpp index 043454dc9..d4a47a054 100644 --- a/oem/ibm/libpldmresponder/file_io_type_pel.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_pel.hpp @@ -49,6 +49,11 @@ class PelHandler : public FileHandler return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; } + virtual int fileAckWithMetaData(uint32_t /*metaDataValue*/) + { + return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + } + /** @brief PelHandler destructor */ ~PelHandler() diff --git a/oem/ibm/libpldmresponder/file_io_type_progress_src.hpp b/oem/ibm/libpldmresponder/file_io_type_progress_src.hpp index a223f1a63..ae9f1b4e2 100644 --- a/oem/ibm/libpldmresponder/file_io_type_progress_src.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_progress_src.hpp @@ -54,6 +54,11 @@ class ProgressCodeHandler : public FileHandler return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; } + virtual int fileAckWithMetaData(uint32_t /*metaDataValue*/) + { + return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + } + /** @brief method to set the dbus Raw value Property with * the obtained progress code from the host. * From c017a4a7bc6bde2d8a2e92122619afa6cad4433e Mon Sep 17 00:00:00 2001 From: Jayashankar Padath Date: Thu, 16 Sep 2021 03:37:11 -0500 Subject: [PATCH 5/5] oem-ibm : Capacity on demand licensing support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit supports: 1. Creation or update of new license interfaces and properties supplied by host 2. Clearing of license status to Unknown, during host power off transition 3. Restoration of license interfaces during reset reload and setting the license status to Unknown Test Output: busctl tree xyz.openbmc_project.PLDM └─/xyz └─/xyz/openbmc_project ├─/xyz/openbmc_project/inventory ├─/xyz/openbmc_project/license │ └─/xyz/openbmc_project/license/entry │ ├─/xyz/openbmc_project/license/entry/AIX │ ├─/xyz/openbmc_project/license/entry/PermProcs │ └─/xyz/openbmc_project/license/entry/RPAHosting └─/xyz/openbmc_project/pldm Signed-off-by: Jayashankar Padath Change-Id: I66e283600de628872bdeb40c0cf56859ce7730ea --- host-bmc/custom_dbus.cpp | 35 ++ host-bmc/custom_dbus.hpp | 45 +++ libpldmresponder/meson.build | 1 + oem/ibm/libpldm/file_io.h | 5 +- oem/ibm/libpldmresponder/file_io_by_type.cpp | 3 +- oem/ibm/libpldmresponder/file_io_type_lic.cpp | 117 ++++++- oem/ibm/libpldmresponder/file_io_type_lic.hpp | 27 +- oem/ibm/libpldmresponder/oem_ibm_handler.hpp | 3 + oem/ibm/libpldmresponder/utils.cpp | 321 ++++++++++++++++++ oem/ibm/libpldmresponder/utils.hpp | 79 +++++ oem/ibm/requester/dbus_to_file_handler.cpp | 2 +- pldmd/pldmd.cpp | 2 + 12 files changed, 619 insertions(+), 21 deletions(-) diff --git a/host-bmc/custom_dbus.cpp b/host-bmc/custom_dbus.cpp index 6197fcf7a..4f799ebb4 100644 --- a/host-bmc/custom_dbus.cpp +++ b/host-bmc/custom_dbus.cpp @@ -97,5 +97,40 @@ void CustomDBus::implementObjectEnableIface(const std::string& path) } } +void CustomDBus::implementLicInterfaces( + const std::string& path, const uint32_t& authdevno, const std::string& name, + const std::string& serialno, const uint64_t& exptime, + const sdbusplus::com::ibm::License::Entry::server::LicenseEntry::Type& type, + const sdbusplus::com::ibm::License::Entry::server::LicenseEntry:: + AuthorizationType& authtype) +{ + if (codLic.find(path) == codLic.end()) + { + codLic.emplace( + path, std::make_unique(pldm::utils::DBusHandler::getBus(), + path.c_str())); + } + + codLic.at(path)->authDeviceNumber(authdevno); + codLic.at(path)->name(name); + codLic.at(path)->serialNumber(serialno); + codLic.at(path)->expirationTime(exptime); + codLic.at(path)->type(type); + codLic.at(path)->authorizationType(authtype); +} + +void CustomDBus::setAvailabilityState(const std::string& path, + const bool& state) +{ + if (availabilityState.find(path) == availabilityState.end()) + { + availabilityState.emplace( + path, std::make_unique( + pldm::utils::DBusHandler::getBus(), path.c_str())); + } + + availabilityState.at(path)->available(state); +} + } // namespace dbus } // namespace pldm diff --git a/host-bmc/custom_dbus.hpp b/host-bmc/custom_dbus.hpp index f2ad57371..a34e34ffc 100644 --- a/host-bmc/custom_dbus.hpp +++ b/host-bmc/custom_dbus.hpp @@ -1,5 +1,6 @@ #pragma once +#include "com/ibm/License/Entry/LicenseEntry/server.hpp" #include "common/utils.hpp" #include @@ -7,6 +8,7 @@ #include #include #include +#include #include #include @@ -32,6 +34,10 @@ using CoreIntf = sdbusplus::server::object::object< sdbusplus::xyz::openbmc_project::Inventory::Item::server::CpuCore>; using EnableIface = sdbusplus::server::object::object< sdbusplus::xyz::openbmc_project::Object::server::Enable>; +using LicIntf = sdbusplus::server::object::object< + sdbusplus::com::ibm::License::Entry::server::LicenseEntry>; +using AvailabilityIntf = sdbusplus::server::object::object< + sdbusplus::xyz::openbmc_project::State::Decorator::server::Availability>; /** @class CustomDBus * @brief This is a custom D-Bus object, used to add D-Bus interface and @@ -113,14 +119,53 @@ class CustomDBus */ void implementObjectEnableIface(const std::string& path); + /** @brief Implement the license interface properties + * + * @param[in] path - The object path + * + * @param[in] authdevno - License name + * + * @param[in] name - License name + * + * @param[in] serialno - License serial number + * + * @param[in] exptime - License expiration time + * + * @param[in] type - License type + * + * @param[in] authtype - License authorization type + * + * @note This API implements the following interface + * com.ibm.License.Entry.LicenseEntry and associated + * dbus properties. + */ + void implementLicInterfaces( + const std::string& path, const uint32_t& authdevno, + const std::string& name, const std::string& serialno, + const uint64_t& exptime, + const sdbusplus::com::ibm::License::Entry::server::LicenseEntry::Type& + type, + const sdbusplus::com::ibm::License::Entry::server::LicenseEntry:: + AuthorizationType& authtype); + + /** @brief Set the availability state property + * + * @param[in] path - The object path + * + * @param[in] state - Availability state + */ + void setAvailabilityState(const std::string& path, const bool& state); + private: std::map> location; std::map> operationalStatus; + std::map> availabilityState; std::unordered_map> presentStatus; std::unordered_map> cpuCore; + std::unordered_map> codLic; /** @brief Used to hold the objects which will contain EnableIface */ std::unordered_map> _enabledStatus; diff --git a/libpldmresponder/meson.build b/libpldmresponder/meson.build index 129376171..b5db9392c 100644 --- a/libpldmresponder/meson.build +++ b/libpldmresponder/meson.build @@ -44,6 +44,7 @@ if get_option('oem-ibm').enabled() '../oem/ibm/libpldmresponder/inband_code_update.cpp', '../oem/ibm/requester/dbus_to_file_handler.cpp', '../oem/ibm/libpldmresponder/file_io_type_progress_src.cpp', + '../oem/ibm/libpldmresponder/file_io_type_lic.cpp', ] endif diff --git a/oem/ibm/libpldm/file_io.h b/oem/ibm/libpldm/file_io.h index 6712d705b..5a92f6e2e 100644 --- a/oem/ibm/libpldm/file_io.h +++ b/oem/ibm/libpldm/file_io.h @@ -59,7 +59,10 @@ enum pldm_fileio_file_type { PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS = 0x8, PLDM_FILE_TYPE_RESOURCE_DUMP = 0x9, PLDM_FILE_TYPE_PROGRESS_SRC = 0xA, - PLDM_FILE_TYPE_COD_LICENSE_KEY = 0xB, + PLDM_FILE_TYPE_ADJUNCT_DUMP = 0xB, + PLDM_FILE_TYPE_DEVICE_DUMP = 0xC, + PLDM_FILE_TYPE_COD_LICENSE_KEY = 0xD, + PLDM_FILE_TYPE_COD_LICENSED_RESOURCES = 0xE, }; #define PLDM_RW_FILE_MEM_REQ_BYTES 20 diff --git a/oem/ibm/libpldmresponder/file_io_by_type.cpp b/oem/ibm/libpldmresponder/file_io_by_type.cpp index 602f258b2..d682cd624 100644 --- a/oem/ibm/libpldmresponder/file_io_by_type.cpp +++ b/oem/ibm/libpldmresponder/file_io_by_type.cpp @@ -119,7 +119,7 @@ int FileHandler::transferFileData(const fs::path& path, bool upstream, ; return PLDM_ERROR; } - utils::CustomFD fd(file); + pldm::utils::CustomFD fd(file); return transferFileData(fd(), upstream, offset, length, address); } @@ -159,6 +159,7 @@ std::unique_ptr getHandlerByType(uint16_t fileType, return std::make_unique(fileHandle, fileType); } case PLDM_FILE_TYPE_COD_LICENSE_KEY: + case PLDM_FILE_TYPE_COD_LICENSED_RESOURCES: { return std::make_unique(fileHandle, fileType); } diff --git a/oem/ibm/libpldmresponder/file_io_type_lic.cpp b/oem/ibm/libpldmresponder/file_io_type_lic.cpp index 63b0413b7..fde0b30a4 100644 --- a/oem/ibm/libpldmresponder/file_io_type_lic.cpp +++ b/oem/ibm/libpldmresponder/file_io_type_lic.cpp @@ -11,12 +11,127 @@ namespace pldm { -using namespace utils; +using namespace pldm::responder::utils; +using namespace pldm::utils; +using Json = nlohmann::json; +const Json emptyJson{}; +const std::vector emptyJsonList{}; namespace responder { static constexpr auto codFilePath = "/var/lib/ibm/cod/"; +static constexpr auto licFilePath = "/var/lib/pldm/license/"; +constexpr auto newLicenseFile = "new_license.bin"; +constexpr auto newLicenseJsonFile = "new_license.json"; + +int LicenseHandler::updateBinFileAndLicObjs(const fs::path& newLicJsonFilePath) +{ + int rc = PLDM_SUCCESS; + fs::path newLicFilePath(fs::path(licFilePath) / newLicenseFile); + std::ifstream jsonFileNew(newLicJsonFilePath); + + auto dataNew = Json::parse(jsonFileNew, nullptr, false); + if (dataNew.is_discarded()) + { + std::cerr << "Parsing the new license json file failed, FILE=" + << newLicJsonFilePath << "\n"; + throw InternalFailure(); + } + + // Store the json data in a file with binary format + convertJsonToBinaryFile(dataNew, newLicFilePath); + + // Create or update the license objects + rc = createOrUpdateLicenseObjs(); + if (rc != PLDM_SUCCESS) + { + std::cerr << "createOrUpdateLicenseObjs failed with rc= " << rc + << " \n"; + return rc; + } + return PLDM_SUCCESS; +} + +int LicenseHandler::writeFromMemory( + uint32_t offset, uint32_t length, uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/) +{ + namespace fs = std::filesystem; + if (!fs::exists(licFilePath)) + { + fs::create_directories(licFilePath); + fs::permissions(licFilePath, + fs::perms::others_read | fs::perms::owner_write); + } + fs::path newLicJsonFilePath(fs::path(licFilePath) / newLicenseJsonFile); + std::ofstream licJsonFile(newLicJsonFilePath, + std::ios::out | std::ios::binary); + if (!licJsonFile) + { + std::cerr << "license json file create error: " << newLicJsonFilePath + << std::endl; + return -1; + } + + auto rc = + transferFileData(newLicJsonFilePath, false, offset, length, address); + if (rc != PLDM_SUCCESS) + { + std::cerr << "transferFileData failed with rc= " << rc << " \n"; + return rc; + } + + if (length == licLength) + { + rc = updateBinFileAndLicObjs(newLicJsonFilePath); + if (rc != PLDM_SUCCESS) + { + std::cerr << "updateBinFileAndLicObjs failed with rc= " << rc + << " \n"; + return rc; + } + } + + return PLDM_SUCCESS; +} + +int LicenseHandler::write(const char* buffer, uint32_t offset, uint32_t& length, + oem_platform::Handler* /*oemPlatformHandler*/) +{ + int rc = PLDM_SUCCESS; + + fs::path newLicJsonFilePath(fs::path(licFilePath) / newLicenseJsonFile); + std::ofstream licJsonFile(newLicJsonFilePath, + std::ios::out | std::ios::binary | std::ios::app); + if (!licJsonFile) + { + std::cerr << "license json file create error: " << newLicJsonFilePath + << std::endl; + return -1; + } + + if (buffer != nullptr) + { + licJsonFile.write(buffer, length); + } + licJsonFile.close(); + + updateBinFileAndLicObjs(newLicJsonFilePath); + if (rc != PLDM_SUCCESS) + { + std::cerr << "updateBinFileAndLicObjs failed with rc= " << rc << " \n"; + return rc; + } + + return rc; +} + +int LicenseHandler::newFileAvailable(uint64_t length) +{ + licLength = length; + return PLDM_SUCCESS; +} int LicenseHandler::read(uint32_t offset, uint32_t& length, Response& response, oem_platform::Handler* /*oemPlatformHandler*/) diff --git a/oem/ibm/libpldmresponder/file_io_type_lic.hpp b/oem/ibm/libpldmresponder/file_io_type_lic.hpp index 98c4e2440..345cc000c 100644 --- a/oem/ibm/libpldmresponder/file_io_type_lic.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_lic.hpp @@ -23,12 +23,9 @@ class LicenseHandler : public FileHandler FileHandler(fileHandle), licType(fileType) {} - virtual int writeFromMemory(uint32_t /*offset*/, uint32_t /*length*/, - uint64_t /*address*/, - oem_platform::Handler* /*oemPlatformHandler*/) - { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; - } + virtual int writeFromMemory(uint32_t offset, uint32_t length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/); virtual int readIntoMemory(uint32_t /*offset*/, uint32_t& /*length*/, uint64_t /*address*/, @@ -40,32 +37,28 @@ class LicenseHandler : public FileHandler virtual int read(uint32_t offset, uint32_t& length, Response& response, oem_platform::Handler* /*oemPlatformHandler*/); - virtual int write(const char* /*buffer*/, uint32_t /*offset*/, - uint32_t& /*length*/, - oem_platform::Handler* /*oemPlatformHandler*/) - { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; - } + virtual int write(const char* buffer, uint32_t offset, uint32_t& length, + oem_platform::Handler* /*oemPlatformHandler*/); virtual int fileAck(uint8_t /*fileStatus*/) { return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; } - virtual int newFileAvailable(uint64_t /*length*/) - { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; - } + virtual int newFileAvailable(uint64_t length); virtual int fileAckWithMetaData(uint32_t metaDataValue); + int updateBinFileAndLicObjs(const fs::path& newLicFilePath); + /** @brief LicenseHandler destructor */ ~LicenseHandler() {} private: - uint16_t licType; //!< type of the certificate + uint16_t licType; //!< type of the license + uint64_t licLength; //!< length of the full license data enum class Status { diff --git a/oem/ibm/libpldmresponder/oem_ibm_handler.hpp b/oem/ibm/libpldmresponder/oem_ibm_handler.hpp index 3ff76922e..26750a6ad 100644 --- a/oem/ibm/libpldmresponder/oem_ibm_handler.hpp +++ b/oem/ibm/libpldmresponder/oem_ibm_handler.hpp @@ -7,6 +7,7 @@ #include "libpldmresponder/pdr_utils.hpp" #include "libpldmresponder/platform.hpp" #include "requester/handler.hpp" +#include "utils.hpp" namespace pldm { @@ -60,6 +61,7 @@ class Handler : public oem_platform::Handler mctp_eid(mctp_eid), requester(requester), event(event), handler(handler) { codeUpdate->setVersions(); + pldm::responder::utils::clearLicenseStatus(); setEventReceiverCnt = 0; using namespace sdbusplus::bus::match::rules; @@ -82,6 +84,7 @@ class Handler : public oem_platform::Handler hostOff = true; setEventReceiverCnt = 0; disableWatchDogTimer(); + pldm::responder::utils::clearLicenseStatus(); } else if (propVal == "xyz.openbmc_project.State.Host.HostState.Running") diff --git a/oem/ibm/libpldmresponder/utils.cpp b/oem/ibm/libpldmresponder/utils.cpp index 370e8b583..8035ee3c4 100644 --- a/oem/ibm/libpldmresponder/utils.cpp +++ b/oem/ibm/libpldmresponder/utils.cpp @@ -2,20 +2,42 @@ #include "libpldm/base.h" +#include "common/utils.hpp" +#include "host-bmc/custom_dbus.hpp" + #include #include #include #include +#include + +#include +#include #include namespace pldm { + +using namespace pldm::dbus; namespace responder { namespace utils { +static constexpr auto curLicFilePath = + "/var/lib/pldm/license/current_license.bin"; +static constexpr auto newLicFilePath = "/var/lib/pldm/license/new_license.bin"; +static constexpr auto licEntryPath = "/xyz/openbmc_project/license/entry"; +static constexpr uint8_t createLic = 1; +static constexpr uint8_t clearLicStatus = 2; + +using InternalFailure = + sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; + +using LicJsonObjMap = std::map; +LicJsonObjMap licJsonMap; + int setupUnixSocket(const std::string& socketInterface) { int sock; @@ -141,6 +163,305 @@ int writeToUnixSocket(const int sock, const char* buf, const uint64_t blockSize) return 0; } +Json convertBinFileToJson(const fs::path& path) +{ + std::ifstream file(path, std::ios::in | std::ios::binary); + std::streampos fileSize; + + // Get the file size + file.seekg(0, std::ios::end); + fileSize = file.tellg(); + file.seekg(0, std::ios::beg); + + // Read the data into vector from file and convert to json object + std::vector vJson(fileSize); + file.read((char*)&vJson[0], fileSize); + return Json::from_bson(vJson); +} + +void convertJsonToBinaryFile(const Json& jsonData, const fs::path& path) +{ + // Covert the json data to binary format and copy to vector + std::vector vJson = {}; + vJson = Json::to_bson(jsonData); + + // Copy the vector to file + std::ofstream licout(path, std::ios::out | std::ios::binary); + size_t size = vJson.size(); + licout.write(reinterpret_cast(&vJson[0]), size * sizeof(vJson[0])); +} + +void clearLicenseStatus() +{ + if (!fs::exists(curLicFilePath)) + { + return; + } + + auto data = convertBinFileToJson(curLicFilePath); + + const Json empty{}; + const std::vector emptyList{}; + + auto entries = data.value("Licenses", emptyList); + fs::path path{licEntryPath}; + + for (const auto& entry : entries) + { + auto licId = entry.value("Id", empty); + fs::path l_path = path / licId; + licJsonMap.emplace(l_path, entry); + } + + createOrUpdateLicenseDbusPaths(clearLicStatus); +} + +int createOrUpdateLicenseDbusPaths(const uint8_t& flag) +{ + const Json empty{}; + std::string authTypeAsNoOfDev = "NumberOfDevice"; + struct tm tm; + time_t licTimeSinceEpoch; + + sdbusplus::com::ibm::License::Entry::server::LicenseEntry::Type licType = + sdbusplus::com::ibm::License::Entry::server::LicenseEntry::Type:: + Prototype; + sdbusplus::com::ibm::License::Entry::server::LicenseEntry::AuthorizationType + licAuthType = sdbusplus::com::ibm::License::Entry::server:: + LicenseEntry::AuthorizationType::Device; + for (auto const& [key, licJson] : licJsonMap) + { + auto licName = licJson.value("Name", empty); + + auto type = licJson.value("Type", empty); + if (type == "Trial") + { + licType = sdbusplus::com::ibm::License::Entry::server:: + LicenseEntry::Type::Trial; + } + else if (type == "Commercial") + { + licType = sdbusplus::com::ibm::License::Entry::server:: + LicenseEntry::Type::Purchased; + } + else + { + licType = sdbusplus::com::ibm::License::Entry::server:: + LicenseEntry::Type::Prototype; + } + + auto authType = licJson.value("AuthType", empty); + if (authType == "NumberOfDevice") + { + licAuthType = sdbusplus::com::ibm::License::Entry::server:: + LicenseEntry::AuthorizationType::Capacity; + } + else if (authType == "Unlimited") + { + licAuthType = sdbusplus::com::ibm::License::Entry::server:: + LicenseEntry::AuthorizationType::Unlimited; + } + else + { + licAuthType = sdbusplus::com::ibm::License::Entry::server:: + LicenseEntry::AuthorizationType::Device; + } + + uint32_t licAuthDevNo = 0; + if (authType == authTypeAsNoOfDev) + { + licAuthDevNo = licJson.value("AuthDeviceNumber", 0); + } + + auto licSerialNo = licJson.value("SerialNum", ""); + + auto expTime = licJson.value("ExpirationTime", ""); + if (!expTime.empty()) + { + memset(&tm, 0, sizeof(tm)); + strptime(expTime.c_str(), "%Y-%m-%dT%H:%M:%SZ", &tm); + licTimeSinceEpoch = mktime(&tm); + } + + CustomDBus::getCustomDBus().implementLicInterfaces( + key, licAuthDevNo, licName, licSerialNo, licTimeSinceEpoch, licType, + licAuthType); + + auto status = licJson.value("Status", empty); + + // License status is a single entry which needs to be mapped to + // OperationalStatus and Availability dbus interfaces + auto licOpStatus = false; + auto licAvailState = false; + if ((flag == clearLicStatus) || (status == "Unknown")) + { + licOpStatus = false; + licAvailState = false; + } + else if (status == "Enabled") + { + licOpStatus = true; + licAvailState = true; + } + else if (status == "Disabled") + { + licOpStatus = false; + licAvailState = true; + } + + CustomDBus::getCustomDBus().setOperationalStatus(key, licOpStatus); + CustomDBus::getCustomDBus().setAvailabilityState(key, licAvailState); + } + + return PLDM_SUCCESS; +} + +int createOrUpdateLicenseObjs() +{ + bool l_curFilePresent = true; + const Json empty{}; + const std::vector emptyList{}; + std::ifstream jsonFileCurrent; + Json dataCurrent; + Json entries; + + if (!fs::exists(curLicFilePath)) + { + l_curFilePresent = false; + } + + if (l_curFilePresent == true) + { + dataCurrent = convertBinFileToJson(curLicFilePath); + } + + auto dataNew = convertBinFileToJson(newLicFilePath); + + if (l_curFilePresent == true) + { + dataCurrent.merge_patch(dataNew); + convertJsonToBinaryFile(dataCurrent, curLicFilePath); + entries = dataCurrent.value("Licenses", emptyList); + } + else + { + convertJsonToBinaryFile(dataNew, curLicFilePath); + entries = dataNew.value("Licenses", emptyList); + } + + fs::path path{licEntryPath}; + + for (const auto& entry : entries) + { + auto licId = entry.value("Id", empty); + fs::path l_path = path / licId; + licJsonMap.emplace(l_path, entry); + } + + int rc = createOrUpdateLicenseDbusPaths(createLic); + if (rc == PLDM_SUCCESS) + { + fs::copy_file(newLicFilePath, curLicFilePath, + fs::copy_options::overwrite_existing); + if (fs::exists(newLicFilePath)) + { + fs::remove_all(newLicFilePath); + } + } + + return rc; +} + +bool checkIfIBMCableCard(const std::string& objPath) +{ + constexpr auto pcieAdapterModelInterface = + "xyz.openbmc_project.Inventory.Decorator.Asset"; + constexpr auto modelProperty = "Model"; + + try + { + auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant( + objPath.c_str(), modelProperty, pcieAdapterModelInterface); + const auto& model = std::get(propVal); + if (!model.empty()) + { + return true; + } + } + catch (const sdbusplus::exception::SdBusError& e) + { + return false; + } + return false; +} + +void findPortObjects(const std::string& cardObjPath, + std::vector& portObjects) +{ + static constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; + static constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; + static constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; + static constexpr auto portInterface = + "xyz.openbmc_project.Inventory.Item.Connector"; + + auto& bus = pldm::utils::DBusHandler::getBus(); + try + { + auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, + MAPPER_INTERFACE, "GetSubTreePaths"); + method.append(cardObjPath); + method.append(0); + method.append(std::vector({portInterface})); + auto reply = bus.call(method); + reply.read(portObjects); + } + catch (const std::exception& e) + { + std::cerr << "no ports under card " << cardObjPath << "\n"; + } +} + +bool checkFruPresence(const char* objPath) +{ + // if we enter here with port objects then we need to find the parent + // and see if the card is present. if so then the port is considered as + // present. this is so because the ports do not have "Present" property + std::string nvme("nvme"); + std::string pcieAdapter("pcie_card"); + std::string portStr("cxp_"); + std::string newObjPath = objPath; + bool isPresent = true; + if (newObjPath.find(nvme) != std::string::npos) + { + return true; + } + else if ((newObjPath.find(pcieAdapter) != std::string::npos) && + !checkIfIBMCableCard(newObjPath)) + { + return true; // industry std cards + } + else if (newObjPath.find(portStr) != std::string::npos) + { + newObjPath = pldm::utils::findParent(objPath); + } + + // Phyp expects the FRU records for nvme and industry std cards to be always + // built, irrespective of presence + + static constexpr auto presentInterface = + "xyz.openbmc_project.Inventory.Item"; + static constexpr auto presentProperty = "Present"; + try + { + auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant( + newObjPath.c_str(), presentProperty, presentInterface); + isPresent = std::get(propVal); + } + catch (const sdbusplus::exception::SdBusError& e) + {} + return isPresent; +} + } // namespace utils } // namespace responder } // namespace pldm diff --git a/oem/ibm/libpldmresponder/utils.hpp b/oem/ibm/libpldmresponder/utils.hpp index 8f9ac4748..44ec3cd08 100644 --- a/oem/ibm/libpldmresponder/utils.hpp +++ b/oem/ibm/libpldmresponder/utils.hpp @@ -1,6 +1,10 @@ #pragma once +#include + +#include #include +#include namespace pldm { @@ -8,6 +12,8 @@ namespace responder { namespace utils { +namespace fs = std::filesystem; +using Json = nlohmann::json; /** @brief Setup UNIX socket * This function creates listening socket in non-blocking mode and allows only @@ -34,6 +40,79 @@ int setupUnixSocket(const std::string& socketInterface); */ int writeToUnixSocket(const int sock, const char* buf, const uint64_t blockSize); + +/** @brief Converts a binary file to json data + * This function converts bson data stored in a binary file to + * nlohmann json data + * + * @param[in] path - binary file path to fetch the bson data + * + * @return on success returns nlohmann::json object + */ +Json convertBinFileToJson(const fs::path& path); + +/** @brief Converts a json data in to a binary file + * This function converts the json data to a binary json(bson) + * format and copies it to specified destination file. + * + * @param[in] jsonData - nlohmann json data + * @param[in] path - destination path to store the bson data + * + * @return None + */ +void convertJsonToBinaryFile(const Json& jsonData, const fs::path& path); + +/** @brief Clear License Status + * This function clears all the license status to "Unknown" during + * reset reload operation or when host is coming down to off state. + * During the genesis mode, it skips the license status update. + * + * @return None + */ +void clearLicenseStatus(); + +/** @brief Create or update the d-bus license data + * This function creates or updates the d-bus license details. If the input + * input flag is 1, then new license data will be created and if the the input + * flag is 2 license status will be cleared. + * + * @param[in] flag - input flag, 1 : create and 2 : clear + * + * @return on success returns PLDM_SUCCESS + * on failure returns -1 + */ +int createOrUpdateLicenseDbusPaths(const uint8_t& flag); + +/** @brief Create or update the license bjects + * This function creates or updates the license objects as per the data passed + * from host. + * + * @return on success returns PLDM_SUCCESS + * on failure returns -1 + */ +int createOrUpdateLicenseObjs(); + +/** @brief checks if a pcie adapter is IBM specific + * cable card + * @param[in] objPath - FRU object path + * + * @return bool - true if IBM specific card + */ +bool checkIfIBMCableCard(const std::string& objPath); + +/** @brief checks whether the fru is actually present + * @param[in] objPath - the fru object path + * + * @return bool to indicate presence or absence + */ +bool checkFruPresence(const char* objPath); + +/** @brief finds the ports under an adapter + * @param[in] cardObjPath - D-Bus object path for the adapter + * @param[out] portObjects - the ports under the adapter + */ +void findPortObjects(const std::string& cardObjPath, + std::vector& portObjects); } // namespace utils } // namespace responder } // namespace pldm diff --git a/oem/ibm/requester/dbus_to_file_handler.cpp b/oem/ibm/requester/dbus_to_file_handler.cpp index cd6c9c62f..4c8fcd95f 100644 --- a/oem/ibm/requester/dbus_to_file_handler.cpp +++ b/oem/ibm/requester/dbus_to_file_handler.cpp @@ -277,7 +277,7 @@ void DbusToFileHandler::newFileAvailableSendToHost(const uint32_t fileSize, std::cerr << "Failed to encode_new_file_req, rc = " << rc << std::endl; return; } - std::cout << "Sending Sign CSR request to Host for fileHandle: " + std::cout << "Sending new file available request to Host with fileHandle: " << fileHandle << std::endl; auto newFileAvailableRespHandler = [](mctp_eid_t /*eid*/, const pldm_msg* response, diff --git a/pldmd/pldmd.cpp b/pldmd/pldmd.cpp index 375078bcc..eb155e517 100644 --- a/pldmd/pldmd.cpp +++ b/pldmd/pldmd.cpp @@ -183,6 +183,8 @@ int main(int argc, char** argv) auto& bus = pldm::utils::DBusHandler::getBus(); sdbusplus::server::manager::manager objManager( bus, "/xyz/openbmc_project/inventory"); + sdbusplus::server::manager::manager licObjManager( + bus, "/xyz/openbmc_project/license"); dbus_api::Requester dbusImplReq(bus, "/xyz/openbmc_project/pldm"); Invoker invoker{};