oemcommands: add https boot commands
1. netfn 0x30, cmd 0x57: GET_HTTPS_BOOT_DATA:
for BIOS to read cert data during POST
2. netfn 0x30, cmd 0x58: GET_HTTPS_BOOT_ATTR:
for BIOS to read cert info during POST
param 0: cert size
param 1: CRC32 of the cert
Change-Id: I258072916061f7859d101f2b4f8cdda018314b0c
Signed-off-by: Cosmo Chou <cosmo.chou@quantatw.com>
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index 21d10ae..3893bdf 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -49,6 +49,8 @@
CMD_OEM_GET_80PORT_RECORD = 0x49,
CMD_OEM_SET_BOOT_ORDER = 0x52,
CMD_OEM_GET_BOOT_ORDER = 0x53,
+ CMD_OEM_GET_HTTPS_BOOT_DATA = 0x57,
+ CMD_OEM_GET_HTTPS_BOOT_ATTR = 0x58,
CMD_OEM_SET_MACHINE_CONFIG_INFO = 0x6A,
CMD_OEM_LEGACY_SET_PPR = 0x6E,
CMD_OEM_LEGACY_GET_PPR = 0x6F,
@@ -243,6 +245,12 @@
uint8_t data[];
} qDriveInfo_t;
+enum class HttpsBootAttr : uint8_t
+{
+ certSize = 0x00,
+ certCrc = 0x01
+};
+
enum class BankType : uint8_t
{
mca = 0x01,
@@ -283,6 +291,12 @@
#pragma pack(push, 1)
+struct HttpsDataReq
+{
+ uint16_t offset;
+ uint8_t length;
+};
+
struct CrdCmdHdr
{
uint8_t version;
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index c721f0d..6d9af87 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -17,6 +17,7 @@
#include "xyz/openbmc_project/Common/error.hpp"
+#include <boost/crc.hpp>
#include <commandutils.hpp>
#include <ipmid/api-types.hpp>
#include <ipmid/api.hpp>
@@ -71,6 +72,8 @@
nlohmann::json oemData __attribute__((init_priority(101)));
+constexpr const char* certPath = "/mnt/data/host/bios-rootcert";
+
static constexpr size_t GUID_SIZE = 16;
// TODO Make offset and location runtime configurable to ensure we
// can make each define their own locations.
@@ -2098,6 +2101,84 @@
return sendDCMICmd(ctx, ipmi::dcmi::cmdActDeactivatePwrLimit, reqData);
}
+// Https Boot related functions
+ipmi::RspType<std::vector<uint8_t>>
+ ipmiOemGetHttpsData([[maybe_unused]] ipmi::Context::ptr ctx,
+ std::vector<uint8_t> reqData)
+{
+ if (reqData.size() < sizeof(HttpsDataReq))
+ return ipmi::responseReqDataLenInvalid();
+
+ const auto* pReq = reinterpret_cast<const HttpsDataReq*>(reqData.data());
+ std::error_code ec;
+ auto fileSize = std::filesystem::file_size(certPath, ec);
+ if (ec)
+ return ipmi::responseUnspecifiedError();
+
+ if (pReq->offset >= fileSize)
+ return ipmi::responseInvalidFieldRequest();
+
+ std::ifstream file(certPath, std::ios::binary);
+ if (!file)
+ return ipmi::responseUnspecifiedError();
+
+ auto readLen = std::min<uint16_t>(pReq->length, fileSize - pReq->offset);
+ std::vector<uint8_t> resData(readLen + 1);
+ resData[0] = readLen;
+ file.seekg(pReq->offset);
+ file.read(reinterpret_cast<char*>(resData.data() + 1), readLen);
+
+ return ipmi::responseSuccess(resData);
+}
+
+ipmi::RspType<std::vector<uint8_t>>
+ ipmiOemGetHttpsAttr([[maybe_unused]] ipmi::Context::ptr ctx,
+ std::vector<uint8_t> reqData)
+{
+ if (reqData.size() < sizeof(HttpsBootAttr))
+ return ipmi::responseReqDataLenInvalid();
+
+ std::vector<uint8_t> resData;
+
+ switch (static_cast<HttpsBootAttr>(reqData[0]))
+ {
+ case HttpsBootAttr::certSize:
+ {
+ std::error_code ec;
+ auto fileSize = std::filesystem::file_size(certPath, ec);
+ if (ec || fileSize > std::numeric_limits<uint16_t>::max())
+ return ipmi::responseUnspecifiedError();
+
+ uint16_t size = static_cast<uint16_t>(fileSize);
+ resData.resize(sizeof(uint16_t));
+ std::memcpy(resData.data(), &size, sizeof(uint16_t));
+ break;
+ }
+ case HttpsBootAttr::certCrc:
+ {
+ std::ifstream file(certPath, std::ios::binary);
+ if (!file)
+ return ipmi::responseUnspecifiedError();
+
+ boost::crc_32_type result;
+ char data[1024];
+ while (file.read(data, sizeof(data)))
+ result.process_bytes(data, file.gcount());
+ if (file.gcount() > 0)
+ result.process_bytes(data, file.gcount());
+
+ uint32_t crc = result.checksum();
+ resData.resize(sizeof(uint32_t));
+ std::memcpy(resData.data(), &crc, sizeof(uint32_t));
+ break;
+ }
+ default:
+ return ipmi::responseInvalidFieldRequest();
+ }
+
+ return ipmi::responseSuccess(resData);
+}
+
// OEM Crashdump related functions
static ipmi_ret_t setDumpState(CrdState& currState, CrdState newState)
{
@@ -2641,6 +2722,14 @@
ipmiOemSetBootOrder); // Set Boot Order
ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
+ CMD_OEM_GET_HTTPS_BOOT_DATA, ipmi::Privilege::User,
+ ipmiOemGetHttpsData);
+
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
+ CMD_OEM_GET_HTTPS_BOOT_ATTR, ipmi::Privilege::User,
+ ipmiOemGetHttpsAttr);
+
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
CMD_OEM_CRASHDUMP, ipmi::Privilege::User,
ipmiOemCrashdump);