oem-meta: Add file IO handler for getting Http boot certification
Support parsing read file IO for Http Boot command (type: 0x03) and
returning the Http boot certification stored in BMC.
Tested: Verified in yosemite4 platform.
- The HTTP boot certificate is parsed correctly if the file exists.
Change-Id: I4f35b408ac7547347f837620a0039c429a573e0f
Signed-off-by: Lora Lin <lora.lin.wiwynn@gmail.com>
Signed-off-by: Sora Su <baxiche@gmail.com>
diff --git a/oem/meta/libpldmresponder/file_io.cpp b/oem/meta/libpldmresponder/file_io.cpp
index ec82856..2293d43 100644
--- a/oem/meta/libpldmresponder/file_io.cpp
+++ b/oem/meta/libpldmresponder/file_io.cpp
@@ -1,6 +1,7 @@
#include "file_io.hpp"
#include "file_io_type_bios_version.hpp"
+#include "file_io_type_http_boot.hpp"
#include "file_io_type_post_code.hpp"
#include "file_io_type_power_control.hpp"
@@ -23,6 +24,8 @@
case FileIOType::POWER_CONTROL:
return std::make_unique<PowerControlHandler>(messageTid,
dBusHandler);
+ case FileIOType::HTTP_BOOT:
+ return std::make_unique<HttpBootHandler>();
default:
error("Get invalid file io type {FILEIOTYPE}", "FILEIOTYPE",
fileIOType);
diff --git a/oem/meta/libpldmresponder/file_io_by_type.hpp b/oem/meta/libpldmresponder/file_io_by_type.hpp
index 1724514..7fee086 100644
--- a/oem/meta/libpldmresponder/file_io_by_type.hpp
+++ b/oem/meta/libpldmresponder/file_io_by_type.hpp
@@ -14,7 +14,8 @@
{
POST_CODE = 0x00,
BIOS_VERSION = 0x01,
- POWER_CONTROL = 0x02
+ POWER_CONTROL = 0x02,
+ HTTP_BOOT = 0x03
};
/**
diff --git a/oem/meta/libpldmresponder/file_io_type_http_boot.cpp b/oem/meta/libpldmresponder/file_io_type_http_boot.cpp
new file mode 100644
index 0000000..bd988c9
--- /dev/null
+++ b/oem/meta/libpldmresponder/file_io_type_http_boot.cpp
@@ -0,0 +1,182 @@
+#include "file_io_type_http_boot.hpp"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <phosphor-logging/lg2.hpp>
+
+#include <cstring>
+#include <fstream>
+#include <utility>
+
+PHOSPHOR_LOG2_USING;
+
+namespace pldm::responder::oem_meta
+{
+
+constexpr uint8_t HTTP_BOOT_ATTR_REQ_DATA_LEN = 0;
+
+static constexpr auto certificationfilepath = "/mnt/data/host/bios-rootcert";
+
+int HttpBootHandler::read(struct pldm_oem_meta_file_io_read_resp* data)
+{
+ if (data == nullptr)
+ {
+ error("Input data pointer is NULL");
+ return PLDM_ERROR;
+ }
+
+ int fd = -1;
+ struct stat sb;
+
+ if (access(certificationfilepath, F_OK) == -1)
+ {
+ error("Failed to find Http boot certification file");
+ goto noCertificationFile;
+ }
+
+ fd = open(certificationfilepath, O_RDONLY);
+ if (fd < 0)
+ {
+ error("Failed to open Http boot certification file");
+ goto noCertificationFile;
+ }
+
+ if (fstat(fd, &sb) == -1)
+ {
+ error("Failed to get Http boot certification file size");
+ goto noCertificationFile;
+ }
+
+ switch (data->option)
+ {
+ case PLDM_OEM_META_FILE_IO_READ_ATTR:
+ {
+ if (data->length != HTTP_BOOT_ATTR_REQ_DATA_LEN)
+ {
+ error(
+ "Invalid request data length for http boot attribute, option={OPTION}, data size={SIZE}",
+ "OPTION", data->option, "SIZE", data->length);
+ close(fd);
+ return PLDM_ERROR;
+ }
+
+ if (sb.st_size == 0)
+ {
+ data->info.attr.size = 0;
+ data->info.attr.crc32 = 0;
+ close(fd);
+ return PLDM_SUCCESS;
+ }
+
+ uint8_t* buffer = (uint8_t*)malloc(sb.st_size);
+ if (buffer == nullptr)
+ {
+ error(
+ "Failed to allocate buffer for http boot, length={LENGTH}",
+ "LENGTH", sb.st_size);
+ close(fd);
+ return PLDM_ERROR;
+ }
+
+ int ret = ::read(fd, buffer, sb.st_size);
+ if (ret < 0)
+ {
+ error("Failed to read all Http boot certification file");
+ free(buffer);
+ close(fd);
+ return PLDM_ERROR;
+ }
+
+ uint32_t checksum = pldm_edac_crc32(buffer, sb.st_size);
+ free(buffer);
+
+ data->info.attr.size = sb.st_size;
+ data->info.attr.crc32 = checksum;
+ close(fd);
+ return PLDM_SUCCESS;
+ }
+ break;
+ case PLDM_OEM_META_FILE_IO_READ_DATA:
+ {
+ if (sb.st_size == 0)
+ {
+ data->length = 0;
+ data->info.data.transferFlag = PLDM_END;
+ data->info.data.offset = 0;
+ close(fd);
+ return PLDM_SUCCESS;
+ }
+
+ uint8_t transferFlag = data->info.data.transferFlag;
+ uint16_t offset = data->info.data.offset;
+
+ int ret = lseek(fd, offset, SEEK_SET);
+ if (ret < 0)
+ {
+ error(
+ "Failed to lseek at offset={OFFSET} of length={LENGTH} on Http boot certification file",
+ "OFFSET", offset, "LENGTH", data->length);
+ close(fd);
+ return PLDM_ERROR;
+ }
+
+ if (offset + data->length >= sb.st_size)
+ {
+ transferFlag = PLDM_END;
+ data->length = sb.st_size - offset; // Revise length
+ }
+ else
+ {
+ transferFlag = PLDM_MIDDLE;
+ }
+
+ uint8_t* buffer = (uint8_t*)malloc(data->length);
+ if (buffer == nullptr)
+ {
+ error(
+ "Failed to allocate buffer for http boot, length={LENGTH}",
+ "LENGTH", data->length);
+ close(fd);
+ return PLDM_ERROR;
+ }
+
+ ret = ::read(fd, buffer, data->length);
+ if (ret < 0)
+ {
+ error(
+ "Failed to read file content at offset={OFFSET} of length={LENGTH} on Http boot certification file",
+ "OFFSET", offset, "LENGTH", data->length);
+ free(buffer);
+ close(fd);
+ return PLDM_ERROR;
+ }
+
+ memcpy(pldm_oem_meta_file_io_read_resp_data(data), buffer,
+ data->length);
+ free(buffer);
+
+ offset = offset + data->length;
+
+ data->info.data.transferFlag = transferFlag;
+ data->info.data.offset = offset;
+
+ close(fd);
+ return PLDM_SUCCESS;
+ }
+ break;
+ default:
+ error("Get invalid http boot option, option={OPTION}", "OPTION",
+ data->option);
+ close(fd);
+ return PLDM_ERROR;
+ }
+
+noCertificationFile:
+ close(fd);
+ data->length = 0;
+ return PLDM_SUCCESS;
+}
+
+} // namespace pldm::responder::oem_meta
diff --git a/oem/meta/libpldmresponder/file_io_type_http_boot.hpp b/oem/meta/libpldmresponder/file_io_type_http_boot.hpp
new file mode 100644
index 0000000..cc908bd
--- /dev/null
+++ b/oem/meta/libpldmresponder/file_io_type_http_boot.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "file_io_by_type.hpp"
+
+#include <libpldm/oem/meta/file_io.h>
+
+namespace pldm::responder::oem_meta
+{
+/** @class PostCodeHandler
+ *
+ * @brief Inherits and implements FileHandler. This class is used
+ * to store incoming postcode
+ */
+class HttpBootHandler : public FileHandler
+{
+ public:
+ HttpBootHandler() = default;
+ HttpBootHandler(const HttpBootHandler&) = delete;
+ HttpBootHandler(HttpBootHandler&&) = delete;
+ HttpBootHandler& operator=(const HttpBootHandler&) = delete;
+ HttpBootHandler& operator=(HttpBootHandler&&) = delete;
+
+ ~HttpBootHandler() = default;
+
+ /** @brief Method to parse read file IO for Http Boot command (type: 0x03)
+ * and returning the Http boot certification stored in BMC.
+ * @param[in] data - eventData
+ * @return PLDM status code
+ */
+ int read(struct pldm_oem_meta_file_io_read_resp* data) override;
+};
+
+} // namespace pldm::responder::oem_meta
diff --git a/oem/meta/libpldmresponder/meson.build b/oem/meta/libpldmresponder/meson.build
index 33e2bc9..265f6f3 100644
--- a/oem/meta/libpldmresponder/meson.build
+++ b/oem/meta/libpldmresponder/meson.build
@@ -1,6 +1,7 @@
oem_files += files(
'file_io.cpp',
'file_io_type_bios_version.cpp',
+ 'file_io_type_http_boot.cpp',
'file_io_type_post_code.cpp',
'file_io_type_power_control.cpp',
)