1d96e2701SPotin Lai #include <commandutils.hpp>
2d96e2701SPotin Lai #include <groupextcommands.hpp>
3d96e2701SPotin Lai #include <ipmid/api-types.hpp>
4d96e2701SPotin Lai #include <ipmid/api.hpp>
5d96e2701SPotin Lai #include <phosphor-logging/lg2.hpp>
6d96e2701SPotin Lai 
7d96e2701SPotin Lai namespace ipmi
8d96e2701SPotin Lai {
9d96e2701SPotin Lai 
10d96e2701SPotin Lai PHOSPHOR_LOG2_USING;
11d96e2701SPotin Lai 
bigEndianToHost(uint64_t bigEndianValue)12d96e2701SPotin Lai uint64_t bigEndianToHost(uint64_t bigEndianValue)
13d96e2701SPotin Lai {
14d96e2701SPotin Lai     if (std::endian::native == std::endian::little)
15d96e2701SPotin Lai     {
16d96e2701SPotin Lai         return std::byteswap(bigEndianValue);
17d96e2701SPotin Lai     }
18d96e2701SPotin Lai 
19d96e2701SPotin Lai     return bigEndianValue;
20d96e2701SPotin Lai }
21d96e2701SPotin Lai 
22d96e2701SPotin Lai void registerSBMRFunctions() __attribute__((constructor));
23d96e2701SPotin Lai 
ipmiSBMRSendBootProgress(ipmi::Context::ptr ctx,std::vector<uint8_t> data)24d96e2701SPotin Lai ipmi::RspType<> ipmiSBMRSendBootProgress(ipmi::Context::ptr ctx,
25d96e2701SPotin Lai                                          std::vector<uint8_t> data)
26d96e2701SPotin Lai {
27d96e2701SPotin Lai     using postcode_t = std::tuple<uint64_t, std::vector<uint8_t>>;
28d96e2701SPotin Lai 
29d96e2701SPotin Lai     std::optional<size_t> hostId = findHost(ctx->hostIdx);
30d96e2701SPotin Lai 
31d96e2701SPotin Lai     if (!hostId)
32d96e2701SPotin Lai     {
33d96e2701SPotin Lai         error("Invalid Host Id received");
34d96e2701SPotin Lai         return ipmi::responseInvalidCommand();
35d96e2701SPotin Lai     }
36d96e2701SPotin Lai 
37d96e2701SPotin Lai     if (data.size() != 9)
38d96e2701SPotin Lai     {
39d96e2701SPotin Lai         error("Invalid request of boot progress length received: {LENGTH}",
40d96e2701SPotin Lai               "LENGTH", data.size());
41d96e2701SPotin Lai         return ipmi::responseReqDataLenInvalid();
42d96e2701SPotin Lai     }
43d96e2701SPotin Lai 
44d96e2701SPotin Lai     try
45d96e2701SPotin Lai     {
46d96e2701SPotin Lai         auto primaryPostCode = reinterpret_cast<const uint64_t*>(data.data());
47*979fca29SPotin Lai         auto secondaryPostCode =
48*979fca29SPotin Lai             std::vector<uint8_t>(data.begin() + 8, data.end());
49*979fca29SPotin Lai         auto postCode =
50*979fca29SPotin Lai             postcode_t(bigEndianToHost(*primaryPostCode), secondaryPostCode);
51d96e2701SPotin Lai         auto conn = getSdBus();
5233803b4dSPatrick Williams         auto hostbootRawObj =
5333803b4dSPatrick Williams             std::string(bootRawObjPrefix) + std::to_string(*hostId);
54d96e2701SPotin Lai         auto method =
55d96e2701SPotin Lai             conn->new_method_call(bootRawBusName, hostbootRawObj.data(),
56d96e2701SPotin Lai                                   "org.freedesktop.DBus.Properties", "Set");
57d96e2701SPotin Lai 
58d96e2701SPotin Lai         method.append(bootRawIntf, "Value", std::variant<postcode_t>(postCode));
59d96e2701SPotin Lai 
60d96e2701SPotin Lai         conn->call_noreply(method);
61d96e2701SPotin Lai     }
62d96e2701SPotin Lai     catch (std::exception& e)
63d96e2701SPotin Lai     {
64d96e2701SPotin Lai         error("postcode handler error: {ERROR}", "ERROR", e);
65d96e2701SPotin Lai         return ipmi::responseResponseError();
66d96e2701SPotin Lai     }
67d96e2701SPotin Lai 
68d96e2701SPotin Lai     return ipmi::responseSuccess();
69d96e2701SPotin Lai }
70d96e2701SPotin Lai 
registerSBMRFunctions()71d96e2701SPotin Lai void registerSBMRFunctions()
72d96e2701SPotin Lai {
73d96e2701SPotin Lai     ipmi::registerGroupHandler(
74d96e2701SPotin Lai         ipmi::prioOemBase, ipmi::groupSBMR, ipmi::sbmr::cmdSendBootProgress,
75d96e2701SPotin Lai         ipmi::Privilege::Admin, ipmiSBMRSendBootProgress);
76d96e2701SPotin Lai     return;
77d96e2701SPotin Lai }
78d96e2701SPotin Lai 
79d96e2701SPotin Lai } // end of namespace ipmi
80