support OEM Crashdump
Supports OEM Crashdump command, BIOS sends crashdump data during POST.
Change-Id: Ie3eaee7c14ae52623b8e150e7ef9aa453fe26820
Signed-off-by: Cosmo Chou <cosmo.chou@quantatw.com>
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index ac31949..21d10ae 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -74,7 +74,7 @@
CMD_OEM_SET_IPMB_OFFONLINE = 0xE6,
CMD_OEM_RISER_SENSOR_MON_CRL = 0xE7,
CMD_OEM_BBV_POWER_CYCLE = 0xE9,
- CMD_OEM_ADD_CPER_LOG = 0x70,
+ CMD_OEM_CRASHDUMP = 0x70,
};
@@ -243,6 +243,197 @@
uint8_t data[];
} qDriveInfo_t;
+enum class BankType : uint8_t
+{
+ mca = 0x01,
+ virt = 0x02,
+ cpuWdt = 0x03,
+ tcdx = 0x06,
+ cake = 0x07,
+ pie0 = 0x08,
+ iom = 0x09,
+ ccix = 0x0a,
+ cs = 0x0b,
+ pcieAer = 0x0c,
+ wdtReg = 0x0d,
+ ctrl = 0x80,
+ crdHdr = 0x81
+};
+
+enum class CrdState
+{
+ free = 0x01,
+ waitData = 0x02,
+ packing = 0x03
+};
+
+enum class CrdCtrl
+{
+ getState = 0x01,
+ finish = 0x02
+};
+
+constexpr uint8_t ccmNum = 8;
+constexpr uint8_t tcdxNum = 12;
+constexpr uint8_t cakeNum = 6;
+constexpr uint8_t pie0Num = 1;
+constexpr uint8_t iomNum = 4;
+constexpr uint8_t ccixNum = 4;
+constexpr uint8_t csNum = 8;
+
+#pragma pack(push, 1)
+
+struct CrdCmdHdr
+{
+ uint8_t version;
+ uint8_t reserved[3];
+};
+
+struct CrdBankHdr
+{
+ BankType bankType;
+ uint8_t version;
+ union
+ {
+ struct
+ {
+ uint8_t bankId;
+ uint8_t coreId;
+ };
+ uint8_t reserved[2];
+ };
+};
+
+struct CrashDumpHdr
+{
+ CrdCmdHdr cmdHdr;
+ CrdBankHdr bankHdr;
+};
+
+// Type 0x01: MCA Bank
+struct CrdMcaBank
+{
+ uint64_t mcaCtrl;
+ uint64_t mcaSts;
+ uint64_t mcaAddr;
+ uint64_t mcaMisc0;
+ uint64_t mcaCtrlMask;
+ uint64_t mcaConfig;
+ uint64_t mcaIpid;
+ uint64_t mcaSynd;
+ uint64_t mcaDestat;
+ uint64_t mcaDeaddr;
+ uint64_t mcaMisc1;
+};
+
+struct BankCorePair
+{
+ uint8_t bankId;
+ uint8_t coreId;
+};
+
+// Type 0x02: Virtual/Global Bank
+struct CrdVirtualBankV2
+{
+ uint32_t s5ResetSts;
+ uint32_t breakevent;
+ uint16_t mcaCount;
+ uint16_t procNum;
+ uint32_t apicId;
+ uint32_t eax;
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ struct BankCorePair mcaList[];
+};
+
+struct CrdVirtualBankV3
+{
+ uint32_t s5ResetSts;
+ uint32_t breakevent;
+ uint32_t rstSts;
+ uint16_t mcaCount;
+ uint16_t procNum;
+ uint32_t apicId;
+ uint32_t eax;
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ struct BankCorePair mcaList[];
+};
+
+// Type 0x03: CPU/Data Fabric Watchdog Timer Bank
+struct CrdCpuWdtBank
+{
+ uint32_t hwAssertStsHi[ccmNum];
+ uint32_t hwAssertStsLo[ccmNum];
+ uint32_t origWdtAddrLogHi[ccmNum];
+ uint32_t origWdtAddrLogLo[ccmNum];
+ uint32_t hwAssertMskHi[ccmNum];
+ uint32_t hwAssertMskLo[ccmNum];
+ uint32_t origWdtAddrLogStat[ccmNum];
+};
+
+template <size_t N>
+struct CrdHwAssertBank
+{
+ uint32_t hwAssertStsHi[N];
+ uint32_t hwAssertStsLo[N];
+ uint32_t hwAssertMskHi[N];
+ uint32_t hwAssertMskLo[N];
+};
+
+// Type 0x0C: PCIe AER Bank
+struct CrdPcieAerBank
+{
+ uint8_t bus;
+ uint8_t dev;
+ uint8_t fun;
+ uint16_t cmd;
+ uint16_t sts;
+ uint16_t slot;
+ uint8_t secondBus;
+ uint16_t vendorId;
+ uint16_t devId;
+ uint16_t classCodeLo; // Class Code 3 byte
+ uint8_t classCodeHi;
+ uint16_t secondSts;
+ uint16_t ctrl;
+ uint32_t uncorrErrSts;
+ uint32_t uncorrErrMsk;
+ uint32_t uncorrErrSeverity;
+ uint32_t corrErrSts;
+ uint32_t corrErrMsk;
+ uint32_t hdrLogDw0;
+ uint32_t hdrLogDw1;
+ uint32_t hdrLogDw2;
+ uint32_t hdrLogDw3;
+ uint32_t rootErrSts;
+ uint16_t corrErrSrcId;
+ uint16_t errSrcId;
+ uint32_t laneErrSts;
+};
+
+// Type 0x0D: SMU/PSP/PTDMA Watchdog Timers Register Bank
+struct CrdWdtRegBank
+{
+ uint8_t nbio;
+ char name[32];
+ uint32_t addr;
+ uint8_t count;
+ uint32_t data[];
+};
+
+// Type 0x81: Crashdump Header
+struct CrdHdrBank
+{
+ uint64_t ppin;
+ uint32_t ucodeVer;
+ uint32_t pmio;
+};
+
+#pragma pack(pop)
+
const char* cpuInfoKey[] = {"", "product_name", "basic_info",
"type", "micro_code", "turbo_mode"};
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index ba2b6e0..8516e54 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -55,6 +55,8 @@
constexpr uint8_t cmdSetQDimmInfo = 0x12;
constexpr uint8_t cmdGetQDimmInfo = 0x13;
+constexpr ipmi_ret_t ccInvalidParam = 0x80;
+
int plat_udbg_get_post_desc(uint8_t, uint8_t*, uint8_t, uint8_t*, uint8_t*,
uint8_t*);
int plat_udbg_get_gpio_desc(uint8_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*,
@@ -2096,6 +2098,424 @@
return sendDCMICmd(ctx, ipmi::dcmi::cmdActDeactivatePwrLimit, reqData);
}
+// OEM Crashdump related functions
+static ipmi_ret_t setDumpState(CrdState& currState, CrdState newState)
+{
+ switch (newState)
+ {
+ case CrdState::waitData:
+ if (currState == CrdState::packing)
+ return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
+ break;
+ case CrdState::packing:
+ if (currState != CrdState::waitData)
+ return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
+ break;
+ case CrdState::free:
+ break;
+ default:
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+ currState = newState;
+
+ return IPMI_CC_OK;
+}
+
+static ipmi_ret_t handleMcaBank(const CrashDumpHdr& hdr,
+ std::span<const uint8_t> data,
+ CrdState& currState, std::stringstream& ss)
+{
+ if (data.size() < sizeof(CrdMcaBank))
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+
+ ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
+ if (res)
+ return res;
+
+ const auto* pBank = reinterpret_cast<const CrdMcaBank*>(data.data());
+ ss << std::format(" Bank ID : 0x{:02X}, Core ID : 0x{:02X}\n",
+ hdr.bankHdr.bankId, hdr.bankHdr.coreId);
+ ss << std::format(" MCA_CTRL : 0x{:016X}\n", pBank->mcaCtrl);
+ ss << std::format(" MCA_STATUS : 0x{:016X}\n", pBank->mcaSts);
+ ss << std::format(" MCA_ADDR : 0x{:016X}\n", pBank->mcaAddr);
+ ss << std::format(" MCA_MISC0 : 0x{:016X}\n", pBank->mcaMisc0);
+ ss << std::format(" MCA_CTRL_MASK : 0x{:016X}\n", pBank->mcaCtrlMask);
+ ss << std::format(" MCA_CONFIG : 0x{:016X}\n", pBank->mcaConfig);
+ ss << std::format(" MCA_IPID : 0x{:016X}\n", pBank->mcaIpid);
+ ss << std::format(" MCA_SYND : 0x{:016X}\n", pBank->mcaSynd);
+ ss << std::format(" MCA_DESTAT : 0x{:016X}\n", pBank->mcaDestat);
+ ss << std::format(" MCA_DEADDR : 0x{:016X}\n", pBank->mcaDeaddr);
+ ss << std::format(" MCA_MISC1 : 0x{:016X}\n", pBank->mcaMisc1);
+ ss << "\n";
+
+ return IPMI_CC_OK;
+}
+
+template <typename T>
+static ipmi_ret_t handleVirtualBank(std::span<const uint8_t> data,
+ CrdState& currState, std::stringstream& ss)
+{
+ if (data.size() < sizeof(T))
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+
+ const auto* pBank = reinterpret_cast<const T*>(data.data());
+
+ if (data.size() < sizeof(T) + sizeof(BankCorePair) * pBank->mcaCount)
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+
+ ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
+ if (res)
+ return res;
+
+ ss << " Virtual Bank\n";
+ ss << std::format(" S5_RESET_STATUS : 0x{:08X}\n", pBank->s5ResetSts);
+ ss << std::format(" PM_BREAKEVENT : 0x{:08X}\n", pBank->breakevent);
+ if constexpr (std::is_same_v<T, CrdVirtualBankV3>)
+ {
+ ss << std::format(" WARMCOLDRSTSTATUS : 0x{:08X}\n", pBank->rstSts);
+ }
+ ss << std::format(" PROCESSOR NUMBER : 0x{:04X}\n", pBank->procNum);
+ ss << std::format(" APIC ID : 0x{:08X}\n", pBank->apicId);
+ ss << std::format(" EAX : 0x{:08X}\n", pBank->eax);
+ ss << std::format(" EBX : 0x{:08X}\n", pBank->ebx);
+ ss << std::format(" ECX : 0x{:08X}\n", pBank->ecx);
+ ss << std::format(" EDX : 0x{:08X}\n", pBank->edx);
+ ss << " VALID LIST : ";
+ for (size_t i = 0; i < pBank->mcaCount; i++)
+ {
+ ss << std::format("(0x{:02X},0x{:02X}) ", pBank->mcaList[i].bankId,
+ pBank->mcaList[i].coreId);
+ }
+ ss << "\n\n";
+
+ return IPMI_CC_OK;
+}
+
+static ipmi_ret_t handleCpuWdtBank(std::span<const uint8_t> data,
+ CrdState& currState, std::stringstream& ss)
+{
+ if (data.size() < sizeof(CrdCpuWdtBank))
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+
+ ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
+ if (res)
+ return res;
+
+ const auto* pBank = reinterpret_cast<const CrdCpuWdtBank*>(data.data());
+ for (size_t i = 0; i < ccmNum; i++)
+ {
+ ss << std::format(" [CCM{}]\n", i);
+ ss << std::format(" HwAssertStsHi : 0x{:08X}\n",
+ pBank->hwAssertStsHi[i]);
+ ss << std::format(" HwAssertStsLo : 0x{:08X}\n",
+ pBank->hwAssertStsLo[i]);
+ ss << std::format(" OrigWdtAddrLogHi : 0x{:08X}\n",
+ pBank->origWdtAddrLogHi[i]);
+ ss << std::format(" OrigWdtAddrLogLo : 0x{:08X}\n",
+ pBank->origWdtAddrLogLo[i]);
+ ss << std::format(" HwAssertMskHi : 0x{:08X}\n",
+ pBank->hwAssertMskHi[i]);
+ ss << std::format(" HwAssertMskLo : 0x{:08X}\n",
+ pBank->hwAssertMskLo[i]);
+ ss << std::format(" OrigWdtAddrLogStat : 0x{:08X}\n",
+ pBank->origWdtAddrLogStat[i]);
+ }
+ ss << "\n";
+
+ return IPMI_CC_OK;
+}
+
+template <size_t N>
+static ipmi_ret_t handleHwAssertBank(const char* name,
+ std::span<const uint8_t> data,
+ CrdState& currState, std::stringstream& ss)
+{
+ if (data.size() < sizeof(CrdHwAssertBank<N>))
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+
+ ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
+ if (res)
+ return res;
+
+ const CrdHwAssertBank<N>* pBank =
+ reinterpret_cast<const CrdHwAssertBank<N>*>(data.data());
+
+ for (size_t i = 0; i < N; i++)
+ {
+ ss << std::format(" [{}{}]\n", name, i);
+ ss << std::format(" HwAssertStsHi : 0x{:08X}\n",
+ pBank->hwAssertStsHi[i]);
+ ss << std::format(" HwAssertStsLo : 0x{:08X}\n",
+ pBank->hwAssertStsLo[i]);
+ ss << std::format(" HwAssertMskHi : 0x{:08X}\n",
+ pBank->hwAssertMskHi[i]);
+ ss << std::format(" HwAssertMskLo : 0x{:08X}\n",
+ pBank->hwAssertMskLo[i]);
+ }
+ ss << "\n";
+
+ return IPMI_CC_OK;
+}
+
+static ipmi_ret_t handlePcieAerBank(std::span<const uint8_t> data,
+ CrdState& currState, std::stringstream& ss)
+{
+ if (data.size() < sizeof(CrdPcieAerBank))
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+
+ ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
+ if (res)
+ return res;
+
+ const auto* pBank = reinterpret_cast<const CrdPcieAerBank*>(data.data());
+ ss << std::format(" [Bus{} Dev{} Fun{}]\n", pBank->bus, pBank->dev,
+ pBank->fun);
+ ss << std::format(" Command : 0x{:04X}\n",
+ pBank->cmd);
+ ss << std::format(" Status : 0x{:04X}\n",
+ pBank->sts);
+ ss << std::format(" Slot : 0x{:04X}\n",
+ pBank->slot);
+ ss << std::format(" Secondary Bus : 0x{:02X}\n",
+ pBank->secondBus);
+ ss << std::format(" Vendor ID : 0x{:04X}\n",
+ pBank->vendorId);
+ ss << std::format(" Device ID : 0x{:04X}\n",
+ pBank->devId);
+ ss << std::format(" Class Code : 0x{:02X}{:04X}\n",
+ pBank->classCodeHi, pBank->classCodeLo);
+ ss << std::format(" Bridge: Secondary Status : 0x{:04X}\n",
+ pBank->secondSts);
+ ss << std::format(" Bridge: Control : 0x{:04X}\n",
+ pBank->ctrl);
+ ss << std::format(" Uncorrectable Error Status : 0x{:08X}\n",
+ pBank->uncorrErrSts);
+ ss << std::format(" Uncorrectable Error Mask : 0x{:08X}\n",
+ pBank->uncorrErrMsk);
+ ss << std::format(" Uncorrectable Error Severity : 0x{:08X}\n",
+ pBank->uncorrErrSeverity);
+ ss << std::format(" Correctable Error Status : 0x{:08X}\n",
+ pBank->corrErrSts);
+ ss << std::format(" Correctable Error Mask : 0x{:08X}\n",
+ pBank->corrErrMsk);
+ ss << std::format(" Header Log DW0 : 0x{:08X}\n",
+ pBank->hdrLogDw0);
+ ss << std::format(" Header Log DW1 : 0x{:08X}\n",
+ pBank->hdrLogDw1);
+ ss << std::format(" Header Log DW2 : 0x{:08X}\n",
+ pBank->hdrLogDw2);
+ ss << std::format(" Header Log DW3 : 0x{:08X}\n",
+ pBank->hdrLogDw3);
+ ss << std::format(" Root Error Status : 0x{:08X}\n",
+ pBank->rootErrSts);
+ ss << std::format(" Correctable Error Source ID : 0x{:04X}\n",
+ pBank->corrErrSrcId);
+ ss << std::format(" Error Source ID : 0x{:04X}\n",
+ pBank->errSrcId);
+ ss << std::format(" Lane Error Status : 0x{:08X}\n",
+ pBank->laneErrSts);
+ ss << "\n";
+
+ return IPMI_CC_OK;
+}
+
+static ipmi_ret_t handleWdtRegBank(std::span<const uint8_t> data,
+ CrdState& currState, std::stringstream& ss)
+{
+ if (data.size() < sizeof(CrdWdtRegBank))
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+
+ const auto* pBank = reinterpret_cast<const CrdWdtRegBank*>(data.data());
+ if (data.size() < sizeof(CrdWdtRegBank) + sizeof(uint32_t) * pBank->count)
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+
+ ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
+ if (res)
+ return res;
+
+ ss << std::format(" [NBIO{}] {}\n", pBank->nbio, pBank->name);
+ ss << std::format(" Address: 0x{:08X}\n", pBank->addr);
+ ss << std::format(" Data Count: {}\n", pBank->count);
+ ss << " Data:\n";
+ for (size_t i = 0; i < pBank->count; i++)
+ {
+ ss << std::format(" {}: 0x{:08X}\n", i, pBank->data[i]);
+ }
+ ss << "\n";
+
+ return IPMI_CC_OK;
+}
+
+static ipmi_ret_t handleCrdHdrBank(std::span<const uint8_t> data,
+ CrdState& currState, std::stringstream& ss)
+{
+ if (data.size() < sizeof(CrdHdrBank))
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+
+ ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
+ if (res)
+ return res;
+
+ const auto* pBank = reinterpret_cast<const CrdHdrBank*>(data.data());
+ ss << " Crashdump Header\n";
+ ss << std::format(" CPU PPIN : 0x{:016X}\n", pBank->ppin);
+ ss << std::format(" UCODE VERSION : 0x{:08X}\n", pBank->ucodeVer);
+ ss << std::format(" PMIO 80h : 0x{:08X}\n", pBank->pmio);
+ ss << std::format(
+ " BIT0 - SMN Parity/SMN Timeouts PSP/SMU Parity and ECC/SMN On-Package Link Error : {}\n",
+ pBank->pmio & 0x1);
+ ss << std::format(" BIT2 - PSP Parity and ECC : {}\n",
+ (pBank->pmio & 0x4) >> 2);
+ ss << std::format(" BIT3 - SMN Timeouts SMU : {}\n",
+ (pBank->pmio & 0x8) >> 3);
+ ss << std::format(" BIT4 - SMN Off-Package Link Packet Error : {}\n",
+ (pBank->pmio & 0x10) >> 4);
+ ss << "\n";
+
+ return IPMI_CC_OK;
+}
+
+static std::string getFilename(const std::filesystem::path& dir,
+ const std::string& prefix)
+{
+ std::vector<int> indices;
+ std::regex pattern(prefix + "(\\d+)\\.txt");
+
+ for (const auto& entry : std::filesystem::directory_iterator(dir))
+ {
+ std::string filename = entry.path().filename().string();
+ std::smatch match;
+ if (std::regex_match(filename, match, pattern))
+ indices.push_back(std::stoi(match[1]));
+ }
+
+ std::sort(indices.rbegin(), indices.rend());
+ while (indices.size() > 2) // keep 3 files, so remove if more than 2
+ {
+ std::filesystem::remove(
+ dir / (prefix + std::to_string(indices.back()) + ".txt"));
+ indices.pop_back();
+ }
+
+ int nextIndex = indices.empty() ? 1 : indices.front() + 1;
+ return prefix + std::to_string(nextIndex) + ".txt";
+}
+
+static ipmi_ret_t handleCtrlBank(std::span<const uint8_t> data,
+ CrdState& currState, std::stringstream& ss)
+{
+ if (data.empty())
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+
+ switch (static_cast<CrdCtrl>(data[0]))
+ {
+ case CrdCtrl::getState:
+ break;
+ case CrdCtrl::finish:
+ {
+ ipmi_ret_t res = setDumpState(currState, CrdState::packing);
+ if (res)
+ return res;
+
+ const std::filesystem::path dumpDir = "/var/lib/fb-ipmi-oem";
+ std::string filename = getFilename(dumpDir, "crashdump_");
+ std::ofstream outFile(dumpDir / filename);
+ if (!outFile.is_open())
+ return IPMI_CC_UNSPECIFIED_ERROR;
+
+ auto now = std::chrono::system_clock::to_time_t(
+ std::chrono::system_clock::now());
+ outFile << "Crash Dump generated at: "
+ << std::put_time(std::localtime(&now), "%Y-%m-%d %H:%M:%S")
+ << "\n\n";
+ outFile << ss.str();
+ outFile.close();
+ ss.str("");
+ ss.clear();
+ setDumpState(currState, CrdState::free);
+ break;
+ }
+ default:
+ return ccInvalidParam;
+ }
+
+ return IPMI_CC_OK;
+}
+
+ipmi::RspType<std::vector<uint8_t>>
+ ipmiOemCrashdump([[maybe_unused]] ipmi::Context::ptr ctx,
+ std::vector<uint8_t> reqData)
+{
+ static CrdState dumpState = CrdState::free;
+ static std::stringstream ss;
+
+ if (reqData.size() < sizeof(CrashDumpHdr))
+ return ipmi::responseReqDataLenInvalid();
+
+ const auto* pHdr = reinterpret_cast<const CrashDumpHdr*>(reqData.data());
+ std::span<const uint8_t> bData{reqData.data() + sizeof(CrashDumpHdr),
+ reqData.size() - sizeof(CrashDumpHdr)};
+ ipmi_ret_t res;
+
+ switch (pHdr->bankHdr.bankType)
+ {
+ case BankType::mca:
+ res = handleMcaBank(*pHdr, bData, dumpState, ss);
+ break;
+ case BankType::virt:
+ if (pHdr->bankHdr.version >= 3)
+ {
+ res = handleVirtualBank<CrdVirtualBankV3>(bData, dumpState, ss);
+ break;
+ }
+ res = handleVirtualBank<CrdVirtualBankV2>(bData, dumpState, ss);
+ break;
+ case BankType::cpuWdt:
+ res = handleCpuWdtBank(bData, dumpState, ss);
+ break;
+ case BankType::tcdx:
+ res = handleHwAssertBank<tcdxNum>("TCDX", bData, dumpState, ss);
+ break;
+ case BankType::cake:
+ res = handleHwAssertBank<cakeNum>("CAKE", bData, dumpState, ss);
+ break;
+ case BankType::pie0:
+ res = handleHwAssertBank<pie0Num>("PIE", bData, dumpState, ss);
+ break;
+ case BankType::iom:
+ res = handleHwAssertBank<iomNum>("IOM", bData, dumpState, ss);
+ break;
+ case BankType::ccix:
+ res = handleHwAssertBank<ccixNum>("CCIX", bData, dumpState, ss);
+ break;
+ case BankType::cs:
+ res = handleHwAssertBank<csNum>("CS", bData, dumpState, ss);
+ break;
+ case BankType::pcieAer:
+ res = handlePcieAerBank(bData, dumpState, ss);
+ break;
+ case BankType::wdtReg:
+ res = handleWdtRegBank(bData, dumpState, ss);
+ break;
+ case BankType::ctrl:
+ res = handleCtrlBank(bData, dumpState, ss);
+ if (res == IPMI_CC_OK &&
+ static_cast<CrdCtrl>(bData[0]) == CrdCtrl::getState)
+ {
+ return ipmi::responseSuccess(
+ std::vector<uint8_t>{static_cast<uint8_t>(dumpState)});
+ }
+ break;
+ case BankType::crdHdr:
+ res = handleCrdHdrBank(bData, dumpState, ss);
+ break;
+ default:
+ return ipmi::responseInvalidFieldRequest();
+ }
+
+ return ipmi::response(res);
+}
+
static void registerOEMFunctions(void)
{
/* Get OEM data from json file */
@@ -2220,6 +2640,10 @@
CMD_OEM_SET_BOOT_ORDER, ipmi::Privilege::User,
ipmiOemSetBootOrder); // Set Boot Order
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
+ CMD_OEM_CRASHDUMP, ipmi::Privilege::User,
+ ipmiOemCrashdump);
+
return;
}