groupextcommands: Add SBMR send boot progress command
Add send boot progress command for postcode recording.
NetFn: 0x2C, Cmd: 0x02, Group: 0xAE (SBMR)
Tested Result:
```
root@bmc:~# ipmitool raw 0x2C 0x02 0xAE 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09
ae
root@bmc:~# ipmitool raw 0x2C 0x02 0xAE 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19
ae
root@bmc:~# ipmitool raw 0x2C 0x02 0xAE 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29
ae
root@bmc:~# busctl call xyz.openbmc_project.State.Boot.PostCode0 /xyz/openbmc_project/State/Boot/PostCode0 xyz.openbmc_project.State.Boot.PostCode GetPostCodes q 1 -j
{
"type" : "a(tay)",
"data" : [
[
[
72623859790382856,
[
1,
2,
3,
4,
5,
6,
7,
8,
9
]
],
[
1230066625199609624,
[
17,
18,
19,
20,
21,
22,
23,
24,
25
]
],
[
2387509390608836392,
[
33,
34,
35,
36,
37,
38,
39,
40,
41
]
]
]
]
}
```
Change-Id: If064fe1300c63e334022a54054958a000200d9d8
Signed-off-by: Potin Lai <potin.lai@quantatw.com>
diff --git a/src/groupextcommands.cpp b/src/groupextcommands.cpp
new file mode 100644
index 0000000..54a3fc5
--- /dev/null
+++ b/src/groupextcommands.cpp
@@ -0,0 +1,76 @@
+#include <commandutils.hpp>
+#include <groupextcommands.hpp>
+#include <ipmid/api-types.hpp>
+#include <ipmid/api.hpp>
+#include <phosphor-logging/lg2.hpp>
+
+namespace ipmi
+{
+
+PHOSPHOR_LOG2_USING;
+
+uint64_t bigEndianToHost(uint64_t bigEndianValue)
+{
+ if (std::endian::native == std::endian::little)
+ {
+ return std::byteswap(bigEndianValue);
+ }
+
+ return bigEndianValue;
+}
+
+void registerSBMRFunctions() __attribute__((constructor));
+
+ipmi::RspType<> ipmiSBMRSendBootProgress(ipmi::Context::ptr ctx,
+ std::vector<uint8_t> data)
+{
+ using postcode_t = std::tuple<uint64_t, std::vector<uint8_t>>;
+
+ std::optional<size_t> hostId = findHost(ctx->hostIdx);
+
+ if (!hostId)
+ {
+ error("Invalid Host Id received");
+ return ipmi::responseInvalidCommand();
+ }
+
+ if (data.size() != 9)
+ {
+ error("Invalid request of boot progress length received: {LENGTH}",
+ "LENGTH", data.size());
+ return ipmi::responseReqDataLenInvalid();
+ }
+
+ try
+ {
+ auto primaryPostCode = reinterpret_cast<const uint64_t*>(data.data());
+ auto postCode = postcode_t(bigEndianToHost(*primaryPostCode), data);
+ auto conn = getSdBus();
+ auto hostbootRawObj = std::string(bootRawObjPrefix) +
+ std::to_string(*hostId);
+ auto method =
+ conn->new_method_call(bootRawBusName, hostbootRawObj.data(),
+ "org.freedesktop.DBus.Properties", "Set");
+
+ method.append(bootRawIntf, "Value", std::variant<postcode_t>(postCode));
+
+ conn->call_noreply(method);
+ }
+ catch (std::exception& e)
+ {
+ error("postcode handler error: {ERROR}", "ERROR", e);
+ return ipmi::responseResponseError();
+ }
+
+ return ipmi::responseSuccess();
+}
+
+void registerSBMRFunctions()
+{
+ ipmi::registerGroupHandler(
+ ipmi::prioOemBase, ipmi::groupSBMR, ipmi::sbmr::cmdSendBootProgress,
+ ipmi::Privilege::Admin, ipmiSBMRSendBootProgress);
+ return;
+}
+
+} // end of namespace ipmi