15d214202SPotin Lai #include "config.h"
25d214202SPotin Lai
30b02be92SPatrick Venture #include <arpa/inet.h>
484bf9be5SRichard Marian Thomaiyar #include <fcntl.h>
587651333SXo Wang #include <limits.h>
684bf9be5SRichard Marian Thomaiyar #include <linux/i2c-dev.h>
784bf9be5SRichard Marian Thomaiyar #include <linux/i2c.h>
884bf9be5SRichard Marian Thomaiyar #include <sys/ioctl.h>
984bf9be5SRichard Marian Thomaiyar #include <sys/stat.h>
1084bf9be5SRichard Marian Thomaiyar #include <sys/types.h>
110b02be92SPatrick Venture #include <systemd/sd-bus.h>
1287651333SXo Wang #include <unistd.h>
130b02be92SPatrick Venture
140120b680SVernon Mauery #include <app/channel.hpp>
150120b680SVernon Mauery #include <app/watchdog.hpp>
160120b680SVernon Mauery #include <apphandler.hpp>
17fbc6c9d7SPatrick Williams #include <ipmid/api.hpp>
18fbc6c9d7SPatrick Williams #include <ipmid/sessiondef.hpp>
19fbc6c9d7SPatrick Williams #include <ipmid/sessionhelper.hpp>
20fbc6c9d7SPatrick Williams #include <ipmid/types.hpp>
21fbc6c9d7SPatrick Williams #include <ipmid/utils.hpp>
22fbc6c9d7SPatrick Williams #include <nlohmann/json.hpp>
23fbc6c9d7SPatrick Williams #include <phosphor-logging/elog-errors.hpp>
2424fffdc8SGeorge Liu #include <phosphor-logging/lg2.hpp>
25fbc6c9d7SPatrick Williams #include <sdbusplus/message/types.hpp>
26fbc6c9d7SPatrick Williams #include <sys_info_param.hpp>
27fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Common/error.hpp>
28fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Control/Power/ACPIPowerState/server.hpp>
29fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Software/Activation/server.hpp>
30fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Software/Version/server.hpp>
31fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/State/BMC/server.hpp>
32fbc6c9d7SPatrick Williams
33fbc6c9d7SPatrick Williams #include <algorithm>
343a5071a9SPatrick Venture #include <array>
35886d6840SWilly Tu #include <charconv>
363a5071a9SPatrick Venture #include <cstddef>
370120b680SVernon Mauery #include <cstdint>
38bdda8008SVernon Mauery #include <filesystem>
393a5071a9SPatrick Venture #include <fstream>
403a5071a9SPatrick Venture #include <memory>
415d214202SPotin Lai #include <regex>
423a5071a9SPatrick Venture #include <string>
43886d6840SWilly Tu #include <string_view>
443a5071a9SPatrick Venture #include <tuple>
453a5071a9SPatrick Venture #include <vector>
46b8e9955dSRatan Gupta
4798a23840SMatthew Barth extern sd_bus* bus;
4898a23840SMatthew Barth
49ba19c184SAlexander Amelkin constexpr auto bmc_state_interface = "xyz.openbmc_project.State.BMC";
50ba19c184SAlexander Amelkin constexpr auto bmc_state_property = "CurrentBMCState";
51a809fa55SThang Tran constexpr auto versionPurposeHostEnd = ".Host";
525e007a5dSMarri Devender Rao
53744398dcSNagaraju Goruganti static constexpr auto redundancyIntf =
54744398dcSNagaraju Goruganti "xyz.openbmc_project.Software.RedundancyPriority";
550b02be92SPatrick Venture static constexpr auto versionIntf = "xyz.openbmc_project.Software.Version";
56744398dcSNagaraju Goruganti static constexpr auto activationIntf =
57744398dcSNagaraju Goruganti "xyz.openbmc_project.Software.Activation";
58744398dcSNagaraju Goruganti static constexpr auto softwareRoot = "/xyz/openbmc_project/software";
59744398dcSNagaraju Goruganti
605087b075SGeorge Liu void registerNetFnAppFunctions() __attribute__((constructor));
6198a23840SMatthew Barth
62b8e9955dSRatan Gupta using namespace phosphor::logging;
63523e2d1bSWilly Tu using namespace sdbusplus::error::xyz::openbmc_project::common;
64523e2d1bSWilly Tu using Version = sdbusplus::server::xyz::openbmc_project::software::Version;
65744398dcSNagaraju Goruganti using Activation =
66523e2d1bSWilly Tu sdbusplus::server::xyz::openbmc_project::software::Activation;
67523e2d1bSWilly Tu using BMC = sdbusplus::server::xyz::openbmc_project::state::BMC;
68185b9f8bSVernon Mauery namespace fs = std::filesystem;
69b8e9955dSRatan Gupta
70bd0503a7SYong Li #ifdef ENABLE_I2C_WHITELIST_CHECK
7184bf9be5SRichard Marian Thomaiyar typedef struct
7284bf9be5SRichard Marian Thomaiyar {
7384bf9be5SRichard Marian Thomaiyar uint8_t busId;
7468d9d405SMatt Simmering uint8_t targetAddr;
7568d9d405SMatt Simmering uint8_t targetAddrMask;
7684bf9be5SRichard Marian Thomaiyar std::vector<uint8_t> data;
7784bf9be5SRichard Marian Thomaiyar std::vector<uint8_t> dataMask;
7868d9d405SMatt Simmering } i2cControllerWRAllowlist;
7984bf9be5SRichard Marian Thomaiyar
getWRAllowlist()8068d9d405SMatt Simmering static std::vector<i2cControllerWRAllowlist>& getWRAllowlist()
8184bf9be5SRichard Marian Thomaiyar {
8268d9d405SMatt Simmering static std::vector<i2cControllerWRAllowlist> wrAllowlist;
8368d9d405SMatt Simmering return wrAllowlist;
8484bf9be5SRichard Marian Thomaiyar }
8584bf9be5SRichard Marian Thomaiyar
8668d9d405SMatt Simmering static constexpr const char* i2cControllerWRAllowlistFile =
8784bf9be5SRichard Marian Thomaiyar "/usr/share/ipmi-providers/master_write_read_white_list.json";
8884bf9be5SRichard Marian Thomaiyar
8984bf9be5SRichard Marian Thomaiyar static constexpr const char* filtersStr = "filters";
9084bf9be5SRichard Marian Thomaiyar static constexpr const char* busIdStr = "busId";
9168d9d405SMatt Simmering static constexpr const char* targetAddrStr = "slaveAddr";
9268d9d405SMatt Simmering static constexpr const char* targetAddrMaskStr = "slaveAddrMask";
9384bf9be5SRichard Marian Thomaiyar static constexpr const char* cmdStr = "command";
9484bf9be5SRichard Marian Thomaiyar static constexpr const char* cmdMaskStr = "commandMask";
9584bf9be5SRichard Marian Thomaiyar static constexpr int base_16 = 16;
96bd0503a7SYong Li #endif // ENABLE_I2C_WHITELIST_CHECK
973c5e413bSjayaprakash Mutyala static constexpr uint8_t oemCmdStart = 192;
983c5e413bSjayaprakash Mutyala static constexpr uint8_t invalidParamSelectorStart = 8;
993c5e413bSjayaprakash Mutyala static constexpr uint8_t invalidParamSelectorEnd = 191;
10084bf9be5SRichard Marian Thomaiyar
101744398dcSNagaraju Goruganti /**
102744398dcSNagaraju Goruganti * @brief Returns the Version info from primary s/w object
103744398dcSNagaraju Goruganti *
104744398dcSNagaraju Goruganti * Get the Version info from the active s/w object which is having high
105744398dcSNagaraju Goruganti * "Priority" value(a smaller number is a higher priority) and "Purpose"
106744398dcSNagaraju Goruganti * is "BMC" from the list of all s/w objects those are implementing
107744398dcSNagaraju Goruganti * RedundancyPriority interface from the given softwareRoot path.
108744398dcSNagaraju Goruganti *
109744398dcSNagaraju Goruganti * @return On success returns the Version info from primary s/w object.
110744398dcSNagaraju Goruganti *
111744398dcSNagaraju Goruganti */
getActiveSoftwareVersionInfo(ipmi::Context::ptr ctx)112ea1c401cSVernon Mauery std::string getActiveSoftwareVersionInfo(ipmi::Context::ptr ctx)
113744398dcSNagaraju Goruganti {
114744398dcSNagaraju Goruganti std::string revision{};
11586a5082fSVernon Mauery ipmi::ObjectTree objectTree;
11686a5082fSVernon Mauery try
117744398dcSNagaraju Goruganti {
1181318a5edSPatrick Williams objectTree =
1191318a5edSPatrick Williams ipmi::getAllDbusObjects(*ctx->bus, softwareRoot, redundancyIntf);
12086a5082fSVernon Mauery }
1215d82f474SPatrick Williams catch (const sdbusplus::exception_t& e)
12286a5082fSVernon Mauery {
12324fffdc8SGeorge Liu lg2::error("Failed to fetch redundancy object from dbus, "
12424fffdc8SGeorge Liu "interface: {INTERFACE}, error: {ERROR}",
12524fffdc8SGeorge Liu "INTERFACE", redundancyIntf, "ERROR", e);
126744398dcSNagaraju Goruganti elog<InternalFailure>();
127744398dcSNagaraju Goruganti }
128744398dcSNagaraju Goruganti
129744398dcSNagaraju Goruganti auto objectFound = false;
130744398dcSNagaraju Goruganti for (auto& softObject : objectTree)
131744398dcSNagaraju Goruganti {
1321318a5edSPatrick Williams auto service =
1331318a5edSPatrick Williams ipmi::getService(*ctx->bus, redundancyIntf, softObject.first);
1341318a5edSPatrick Williams auto objValueTree =
1351318a5edSPatrick Williams ipmi::getManagedObjects(*ctx->bus, service, softwareRoot);
136744398dcSNagaraju Goruganti
137744398dcSNagaraju Goruganti auto minPriority = 0xFF;
138744398dcSNagaraju Goruganti for (const auto& objIter : objValueTree)
139744398dcSNagaraju Goruganti {
140744398dcSNagaraju Goruganti try
141744398dcSNagaraju Goruganti {
142744398dcSNagaraju Goruganti auto& intfMap = objIter.second;
143744398dcSNagaraju Goruganti auto& redundancyPriorityProps = intfMap.at(redundancyIntf);
144744398dcSNagaraju Goruganti auto& versionProps = intfMap.at(versionIntf);
145744398dcSNagaraju Goruganti auto& activationProps = intfMap.at(activationIntf);
146f442e119SVernon Mauery auto priority =
147f442e119SVernon Mauery std::get<uint8_t>(redundancyPriorityProps.at("Priority"));
1484c008028SWilliam A. Kennington III auto purpose =
149f442e119SVernon Mauery std::get<std::string>(versionProps.at("Purpose"));
150f442e119SVernon Mauery auto activation =
151f442e119SVernon Mauery std::get<std::string>(activationProps.at("Activation"));
1524c008028SWilliam A. Kennington III auto version =
153f442e119SVernon Mauery std::get<std::string>(versionProps.at("Version"));
154744398dcSNagaraju Goruganti if ((Version::convertVersionPurposeFromString(purpose) ==
155744398dcSNagaraju Goruganti Version::VersionPurpose::BMC) &&
156744398dcSNagaraju Goruganti (Activation::convertActivationsFromString(activation) ==
157744398dcSNagaraju Goruganti Activation::Activations::Active))
158744398dcSNagaraju Goruganti {
159744398dcSNagaraju Goruganti if (priority < minPriority)
160744398dcSNagaraju Goruganti {
161744398dcSNagaraju Goruganti minPriority = priority;
162744398dcSNagaraju Goruganti objectFound = true;
163744398dcSNagaraju Goruganti revision = std::move(version);
164744398dcSNagaraju Goruganti }
165744398dcSNagaraju Goruganti }
166744398dcSNagaraju Goruganti }
167744398dcSNagaraju Goruganti catch (const std::exception& e)
168744398dcSNagaraju Goruganti {
16924fffdc8SGeorge Liu lg2::error("error message: {ERROR}", "ERROR", e);
170744398dcSNagaraju Goruganti }
171744398dcSNagaraju Goruganti }
172744398dcSNagaraju Goruganti }
173744398dcSNagaraju Goruganti
174744398dcSNagaraju Goruganti if (!objectFound)
175744398dcSNagaraju Goruganti {
17624fffdc8SGeorge Liu lg2::error("Could not found an BMC software Object");
177744398dcSNagaraju Goruganti elog<InternalFailure>();
178744398dcSNagaraju Goruganti }
179744398dcSNagaraju Goruganti
180744398dcSNagaraju Goruganti return revision;
181744398dcSNagaraju Goruganti }
182744398dcSNagaraju Goruganti
getCurrentBmcState()183ba19c184SAlexander Amelkin bool getCurrentBmcState()
184ba19c184SAlexander Amelkin {
1855d82f474SPatrick Williams sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
186ba19c184SAlexander Amelkin
187ba19c184SAlexander Amelkin // Get the Inventory object implementing the BMC interface
1881318a5edSPatrick Williams ipmi::DbusObjectInfo bmcObject =
1891318a5edSPatrick Williams ipmi::getDbusObject(bus, bmc_state_interface);
1901318a5edSPatrick Williams auto variant =
1911318a5edSPatrick Williams ipmi::getDbusProperty(bus, bmcObject.second, bmcObject.first,
1921318a5edSPatrick Williams bmc_state_interface, bmc_state_property);
193ba19c184SAlexander Amelkin
194f442e119SVernon Mauery return std::holds_alternative<std::string>(variant) &&
195f442e119SVernon Mauery BMC::convertBMCStateFromString(std::get<std::string>(variant)) ==
196f442e119SVernon Mauery BMC::BMCState::Ready;
197ba19c184SAlexander Amelkin }
198ba19c184SAlexander Amelkin
getCurrentBmcStateWithFallback(const bool fallbackAvailability)19994930a11SPatrick Venture bool getCurrentBmcStateWithFallback(const bool fallbackAvailability)
20094930a11SPatrick Venture {
20194930a11SPatrick Venture try
20294930a11SPatrick Venture {
20394930a11SPatrick Venture return getCurrentBmcState();
20494930a11SPatrick Venture }
20594930a11SPatrick Venture catch (...)
20694930a11SPatrick Venture {
20794930a11SPatrick Venture // Nothing provided the BMC interface, therefore return whatever was
20894930a11SPatrick Venture // configured as the default.
20994930a11SPatrick Venture return fallbackAvailability;
21094930a11SPatrick Venture }
21194930a11SPatrick Venture }
21294930a11SPatrick Venture
21318d77263SYong Li namespace acpi_state
21418d77263SYong Li {
215523e2d1bSWilly Tu using namespace sdbusplus::server::xyz::openbmc_project::control::power;
21618d77263SYong Li
21718d77263SYong Li const static constexpr char* acpiInterface =
21818d77263SYong Li "xyz.openbmc_project.Control.Power.ACPIPowerState";
21918d77263SYong Li const static constexpr char* sysACPIProp = "SysACPIStatus";
22018d77263SYong Li const static constexpr char* devACPIProp = "DevACPIStatus";
22118d77263SYong Li
22218d77263SYong Li enum class PowerStateType : uint8_t
22318d77263SYong Li {
22418d77263SYong Li sysPowerState = 0x00,
22518d77263SYong Li devPowerState = 0x01,
22618d77263SYong Li };
22718d77263SYong Li
22818d77263SYong Li // Defined in 20.6 of ipmi doc
22918d77263SYong Li enum class PowerState : uint8_t
23018d77263SYong Li {
23118d77263SYong Li s0G0D0 = 0x00,
23218d77263SYong Li s1D1 = 0x01,
23318d77263SYong Li s2D2 = 0x02,
23418d77263SYong Li s3D3 = 0x03,
23518d77263SYong Li s4 = 0x04,
23618d77263SYong Li s5G2 = 0x05,
23718d77263SYong Li s4S5 = 0x06,
23818d77263SYong Li g3 = 0x07,
23918d77263SYong Li sleep = 0x08,
24018d77263SYong Li g1Sleep = 0x09,
24118d77263SYong Li override = 0x0a,
24218d77263SYong Li legacyOn = 0x20,
24318d77263SYong Li legacyOff = 0x21,
24418d77263SYong Li unknown = 0x2a,
24518d77263SYong Li noChange = 0x7f,
24618d77263SYong Li };
24718d77263SYong Li
24818d77263SYong Li static constexpr uint8_t stateChanged = 0x80;
24918d77263SYong Li
25018d77263SYong Li std::map<ACPIPowerState::ACPI, PowerState> dbusToIPMI = {
25118d77263SYong Li {ACPIPowerState::ACPI::S0_G0_D0, PowerState::s0G0D0},
25218d77263SYong Li {ACPIPowerState::ACPI::S1_D1, PowerState::s1D1},
25318d77263SYong Li {ACPIPowerState::ACPI::S2_D2, PowerState::s2D2},
25418d77263SYong Li {ACPIPowerState::ACPI::S3_D3, PowerState::s3D3},
25518d77263SYong Li {ACPIPowerState::ACPI::S4, PowerState::s4},
25618d77263SYong Li {ACPIPowerState::ACPI::S5_G2, PowerState::s5G2},
25718d77263SYong Li {ACPIPowerState::ACPI::S4_S5, PowerState::s4S5},
25818d77263SYong Li {ACPIPowerState::ACPI::G3, PowerState::g3},
25918d77263SYong Li {ACPIPowerState::ACPI::SLEEP, PowerState::sleep},
26018d77263SYong Li {ACPIPowerState::ACPI::G1_SLEEP, PowerState::g1Sleep},
26118d77263SYong Li {ACPIPowerState::ACPI::OVERRIDE, PowerState::override},
26218d77263SYong Li {ACPIPowerState::ACPI::LEGACY_ON, PowerState::legacyOn},
26318d77263SYong Li {ACPIPowerState::ACPI::LEGACY_OFF, PowerState::legacyOff},
26418d77263SYong Li {ACPIPowerState::ACPI::Unknown, PowerState::unknown}};
26518d77263SYong Li
isValidACPIState(acpi_state::PowerStateType type,uint8_t state)26618d77263SYong Li bool isValidACPIState(acpi_state::PowerStateType type, uint8_t state)
26718d77263SYong Li {
26818d77263SYong Li if (type == acpi_state::PowerStateType::sysPowerState)
26918d77263SYong Li {
27018d77263SYong Li if ((state <= static_cast<uint8_t>(acpi_state::PowerState::override)) ||
27118d77263SYong Li (state == static_cast<uint8_t>(acpi_state::PowerState::legacyOn)) ||
27218d77263SYong Li (state ==
27318d77263SYong Li static_cast<uint8_t>(acpi_state::PowerState::legacyOff)) ||
27418d77263SYong Li (state == static_cast<uint8_t>(acpi_state::PowerState::unknown)) ||
27518d77263SYong Li (state == static_cast<uint8_t>(acpi_state::PowerState::noChange)))
27618d77263SYong Li {
27718d77263SYong Li return true;
27818d77263SYong Li }
27918d77263SYong Li else
28018d77263SYong Li {
28118d77263SYong Li return false;
28218d77263SYong Li }
28318d77263SYong Li }
28418d77263SYong Li else if (type == acpi_state::PowerStateType::devPowerState)
28518d77263SYong Li {
28618d77263SYong Li if ((state <= static_cast<uint8_t>(acpi_state::PowerState::s3D3)) ||
28718d77263SYong Li (state == static_cast<uint8_t>(acpi_state::PowerState::unknown)) ||
28818d77263SYong Li (state == static_cast<uint8_t>(acpi_state::PowerState::noChange)))
28918d77263SYong Li {
29018d77263SYong Li return true;
29118d77263SYong Li }
29218d77263SYong Li else
29318d77263SYong Li {
29418d77263SYong Li return false;
29518d77263SYong Li }
29618d77263SYong Li }
29718d77263SYong Li else
29818d77263SYong Li {
29918d77263SYong Li return false;
30018d77263SYong Li }
30118d77263SYong Li return false;
30218d77263SYong Li }
30318d77263SYong Li } // namespace acpi_state
30418d77263SYong Li
305520c1315SDeepak Kumar Sahu /** @brief implements Set ACPI Power State command
306520c1315SDeepak Kumar Sahu * @param sysAcpiState - ACPI system power state to set
307520c1315SDeepak Kumar Sahu * @param devAcpiState - ACPI device power state to set
308520c1315SDeepak Kumar Sahu *
309520c1315SDeepak Kumar Sahu * @return IPMI completion code on success
310520c1315SDeepak Kumar Sahu **/
ipmiSetAcpiPowerState(uint8_t sysAcpiState,uint8_t devAcpiState)311520c1315SDeepak Kumar Sahu ipmi::RspType<> ipmiSetAcpiPowerState(uint8_t sysAcpiState,
312520c1315SDeepak Kumar Sahu uint8_t devAcpiState)
31398a23840SMatthew Barth {
31418d77263SYong Li auto s = static_cast<uint8_t>(acpi_state::PowerState::unknown);
31518d77263SYong Li
3165d82f474SPatrick Williams sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
31718d77263SYong Li
31818d77263SYong Li auto value = acpi_state::ACPIPowerState::ACPI::Unknown;
31918d77263SYong Li
320520c1315SDeepak Kumar Sahu if (sysAcpiState & acpi_state::stateChanged)
32118d77263SYong Li {
32218d77263SYong Li // set system power state
323520c1315SDeepak Kumar Sahu s = sysAcpiState & ~acpi_state::stateChanged;
32418d77263SYong Li
32518d77263SYong Li if (!acpi_state::isValidACPIState(
32618d77263SYong Li acpi_state::PowerStateType::sysPowerState, s))
32718d77263SYong Li {
32824fffdc8SGeorge Liu lg2::error("set_acpi_power sys invalid input, S: {S}", "S", s);
329520c1315SDeepak Kumar Sahu return ipmi::responseParmOutOfRange();
33018d77263SYong Li }
33118d77263SYong Li
33218d77263SYong Li // valid input
33318d77263SYong Li if (s == static_cast<uint8_t>(acpi_state::PowerState::noChange))
33418d77263SYong Li {
33524fffdc8SGeorge Liu lg2::debug("No change for system power state");
33618d77263SYong Li }
33718d77263SYong Li else
33818d77263SYong Li {
3391318a5edSPatrick Williams auto found = std::find_if(
3401318a5edSPatrick Williams acpi_state::dbusToIPMI.begin(), acpi_state::dbusToIPMI.end(),
34118d77263SYong Li [&s](const auto& iter) {
34218d77263SYong Li return (static_cast<uint8_t>(iter.second) == s);
34318d77263SYong Li });
34418d77263SYong Li
34518d77263SYong Li value = found->first;
34618d77263SYong Li
34718d77263SYong Li try
34818d77263SYong Li {
34918d77263SYong Li auto acpiObject =
35018d77263SYong Li ipmi::getDbusObject(bus, acpi_state::acpiInterface);
35118d77263SYong Li ipmi::setDbusProperty(bus, acpiObject.second, acpiObject.first,
35218d77263SYong Li acpi_state::acpiInterface,
35318d77263SYong Li acpi_state::sysACPIProp,
35418d77263SYong Li convertForMessage(value));
35518d77263SYong Li }
35618d77263SYong Li catch (const InternalFailure& e)
35718d77263SYong Li {
35824fffdc8SGeorge Liu lg2::error("Failed in set ACPI system property: {ERROR}",
35924fffdc8SGeorge Liu "ERROR", e);
360520c1315SDeepak Kumar Sahu return ipmi::responseUnspecifiedError();
36118d77263SYong Li }
36218d77263SYong Li }
36318d77263SYong Li }
36418d77263SYong Li else
36518d77263SYong Li {
36624fffdc8SGeorge Liu lg2::debug("Do not change system power state");
36718d77263SYong Li }
36818d77263SYong Li
369520c1315SDeepak Kumar Sahu if (devAcpiState & acpi_state::stateChanged)
37018d77263SYong Li {
37118d77263SYong Li // set device power state
372520c1315SDeepak Kumar Sahu s = devAcpiState & ~acpi_state::stateChanged;
37318d77263SYong Li if (!acpi_state::isValidACPIState(
37418d77263SYong Li acpi_state::PowerStateType::devPowerState, s))
37518d77263SYong Li {
37624fffdc8SGeorge Liu lg2::error("set_acpi_power dev invalid input, S: {S}", "S", s);
377520c1315SDeepak Kumar Sahu return ipmi::responseParmOutOfRange();
37818d77263SYong Li }
37918d77263SYong Li
38018d77263SYong Li // valid input
38118d77263SYong Li if (s == static_cast<uint8_t>(acpi_state::PowerState::noChange))
38218d77263SYong Li {
38324fffdc8SGeorge Liu lg2::debug("No change for device power state");
38418d77263SYong Li }
38518d77263SYong Li else
38618d77263SYong Li {
3871318a5edSPatrick Williams auto found = std::find_if(
3881318a5edSPatrick Williams acpi_state::dbusToIPMI.begin(), acpi_state::dbusToIPMI.end(),
38918d77263SYong Li [&s](const auto& iter) {
39018d77263SYong Li return (static_cast<uint8_t>(iter.second) == s);
39118d77263SYong Li });
39218d77263SYong Li
39318d77263SYong Li value = found->first;
39418d77263SYong Li
39518d77263SYong Li try
39618d77263SYong Li {
39718d77263SYong Li auto acpiObject =
39818d77263SYong Li ipmi::getDbusObject(bus, acpi_state::acpiInterface);
39918d77263SYong Li ipmi::setDbusProperty(bus, acpiObject.second, acpiObject.first,
40018d77263SYong Li acpi_state::acpiInterface,
40118d77263SYong Li acpi_state::devACPIProp,
40218d77263SYong Li convertForMessage(value));
40318d77263SYong Li }
40418d77263SYong Li catch (const InternalFailure& e)
40518d77263SYong Li {
40624fffdc8SGeorge Liu lg2::error("Failed in set ACPI device property: {ERROR}",
40724fffdc8SGeorge Liu "ERROR", e);
408520c1315SDeepak Kumar Sahu return ipmi::responseUnspecifiedError();
40918d77263SYong Li }
41018d77263SYong Li }
41118d77263SYong Li }
41218d77263SYong Li else
41318d77263SYong Li {
41424fffdc8SGeorge Liu lg2::debug("Do not change device power state");
41518d77263SYong Li }
416520c1315SDeepak Kumar Sahu return ipmi::responseSuccess();
41718d77263SYong Li }
41818d77263SYong Li
4194e6d2571SDeepak Kumar Sahu /**
4204e6d2571SDeepak Kumar Sahu * @brief implements the get ACPI power state command
4214e6d2571SDeepak Kumar Sahu *
4224e6d2571SDeepak Kumar Sahu * @return IPMI completion code plus response data on success.
4234e6d2571SDeepak Kumar Sahu * - ACPI system power state
4244e6d2571SDeepak Kumar Sahu * - ACPI device power state
4254e6d2571SDeepak Kumar Sahu **/
4264e6d2571SDeepak Kumar Sahu ipmi::RspType<uint8_t, // acpiSystemPowerState
4274e6d2571SDeepak Kumar Sahu uint8_t // acpiDevicePowerState
4284e6d2571SDeepak Kumar Sahu >
ipmiGetAcpiPowerState()4294e6d2571SDeepak Kumar Sahu ipmiGetAcpiPowerState()
43018d77263SYong Li {
4314e6d2571SDeepak Kumar Sahu uint8_t sysAcpiState;
4324e6d2571SDeepak Kumar Sahu uint8_t devAcpiState;
43318d77263SYong Li
4345d82f474SPatrick Williams sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
43518d77263SYong Li
43618d77263SYong Li try
43718d77263SYong Li {
43818d77263SYong Li auto acpiObject = ipmi::getDbusObject(bus, acpi_state::acpiInterface);
43918d77263SYong Li
44018d77263SYong Li auto sysACPIVal = ipmi::getDbusProperty(
44118d77263SYong Li bus, acpiObject.second, acpiObject.first, acpi_state::acpiInterface,
44218d77263SYong Li acpi_state::sysACPIProp);
44318d77263SYong Li auto sysACPI = acpi_state::ACPIPowerState::convertACPIFromString(
444f442e119SVernon Mauery std::get<std::string>(sysACPIVal));
4454e6d2571SDeepak Kumar Sahu sysAcpiState = static_cast<uint8_t>(acpi_state::dbusToIPMI.at(sysACPI));
44618d77263SYong Li
44718d77263SYong Li auto devACPIVal = ipmi::getDbusProperty(
44818d77263SYong Li bus, acpiObject.second, acpiObject.first, acpi_state::acpiInterface,
44918d77263SYong Li acpi_state::devACPIProp);
45018d77263SYong Li auto devACPI = acpi_state::ACPIPowerState::convertACPIFromString(
451f442e119SVernon Mauery std::get<std::string>(devACPIVal));
4524e6d2571SDeepak Kumar Sahu devAcpiState = static_cast<uint8_t>(acpi_state::dbusToIPMI.at(devACPI));
45318d77263SYong Li }
45418d77263SYong Li catch (const InternalFailure& e)
45518d77263SYong Li {
4564e6d2571SDeepak Kumar Sahu return ipmi::responseUnspecifiedError();
45718d77263SYong Li }
4584e6d2571SDeepak Kumar Sahu
4594e6d2571SDeepak Kumar Sahu return ipmi::responseSuccess(sysAcpiState, devAcpiState);
46098a23840SMatthew Barth }
46198a23840SMatthew Barth
46298a23840SMatthew Barth typedef struct
46398a23840SMatthew Barth {
46498a23840SMatthew Barth char major;
46598a23840SMatthew Barth char minor;
466c7c55928SPotin Lai uint8_t aux[4];
46786a5082fSVernon Mauery } Revision;
46898a23840SMatthew Barth
4695d214202SPotin Lai /* Use regular expression searching matched pattern X.Y, and convert it to */
4705d214202SPotin Lai /* Major (X) and Minor (Y) version. */
4715d214202SPotin Lai /* Example: */
4725d214202SPotin Lai /* version = 2.14.0-dev */
4735d214202SPotin Lai /* ^ ^ */
47498a23840SMatthew Barth /* | |---------------- Minor */
47598a23840SMatthew Barth /* |------------------ Major */
4765d214202SPotin Lai /* */
477c7c55928SPotin Lai /* Default regex string only tries to match Major and Minor version. */
478c7c55928SPotin Lai /* */
479c7c55928SPotin Lai /* To match more firmware version info, platforms need to define it own */
480c7c55928SPotin Lai /* regex string to match more strings, and assign correct mapping index in */
481c7c55928SPotin Lai /* matches array. */
482c7c55928SPotin Lai /* */
483c7c55928SPotin Lai /* matches[0]: matched index for major ver */
484c7c55928SPotin Lai /* matches[1]: matched index for minor ver */
485c7c55928SPotin Lai /* matches[2]: matched index for aux[0] (set 0 to skip) */
486c7c55928SPotin Lai /* matches[3]: matched index for aux[1] (set 0 to skip) */
487c7c55928SPotin Lai /* matches[4]: matched index for aux[2] (set 0 to skip) */
488c7c55928SPotin Lai /* matches[5]: matched index for aux[3] (set 0 to skip) */
489c7c55928SPotin Lai /* Example: */
490c7c55928SPotin Lai /* regex = "([\d]+).([\d]+).([\d]+)-dev-([\d]+)-g([0-9a-fA-F]{2}) */
491c7c55928SPotin Lai /* ([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})" */
492c7c55928SPotin Lai /* matches = {1,2,5,6,7,8} */
493c7c55928SPotin Lai /* version = 2.14.0-dev-750-g37a7c5ad1-dirty */
494c7c55928SPotin Lai /* ^ ^ ^ ^ ^ ^ ^ ^ */
495c7c55928SPotin Lai /* | | | | | | | | */
496c7c55928SPotin Lai /* | | | | | | | |-- Aux byte 3 (0xAD), index 8 */
497c7c55928SPotin Lai /* | | | | | | |---- Aux byte 2 (0xC5), index 7 */
498c7c55928SPotin Lai /* | | | | | |------ Aux byte 1 (0xA7), index 6 */
499c7c55928SPotin Lai /* | | | | |-------- Aux byte 0 (0x37), index 5 */
500c7c55928SPotin Lai /* | | | |------------- Not used, index 4 */
501c7c55928SPotin Lai /* | | |------------------- Not used, index 3 */
502c7c55928SPotin Lai /* | |---------------------- Minor (14), index 2 */
503c7c55928SPotin Lai /* |------------------------ Major (2), index 1 */
convertVersion(std::string s,Revision & rev)5045d214202SPotin Lai int convertVersion(std::string s, Revision& rev)
50598a23840SMatthew Barth {
506c7c55928SPotin Lai static const std::vector<size_t> matches = {
507c7c55928SPotin Lai MAJOR_MATCH_INDEX, MINOR_MATCH_INDEX, AUX_0_MATCH_INDEX,
508c7c55928SPotin Lai AUX_1_MATCH_INDEX, AUX_2_MATCH_INDEX, AUX_3_MATCH_INDEX};
5095d214202SPotin Lai std::regex fw_regex(FW_VER_REGEX);
5105d214202SPotin Lai std::smatch m;
5115d214202SPotin Lai Revision r = {0};
5125d214202SPotin Lai size_t val;
51398a23840SMatthew Barth
514dcde04e0SPotin Lai if (std::regex_search(s, m, fw_regex))
5152b7e07d3SDinesh Chinari {
516c7c55928SPotin Lai if (m.size() < *std::max_element(matches.begin(), matches.end()))
517c7c55928SPotin Lai { // max index higher than match count
518dcde04e0SPotin Lai return -1;
519dcde04e0SPotin Lai }
520dcde04e0SPotin Lai
5215d214202SPotin Lai // convert major
5225d214202SPotin Lai {
523*a6c307a8SJayanth Othayoth std::string str = m[matches[0]].str();
524*a6c307a8SJayanth Othayoth const auto& [ptr, ec] =
525*a6c307a8SJayanth Othayoth std::from_chars(str.data(), str.data() + str.size(), val);
526*a6c307a8SJayanth Othayoth if (ec != std::errc() || ptr != str.data() + str.size())
5275d214202SPotin Lai { // failed to convert major string
528dcde04e0SPotin Lai return -1;
5295d214202SPotin Lai }
530058e291fSPotin Lai
531058e291fSPotin Lai if (val >= 2000)
532058e291fSPotin Lai { // For the platforms use year as major version, it would expect to
533058e291fSPotin Lai // have major version between 0 - 99. If the major version is
534058e291fSPotin Lai // greater than or equal to 2000, it is treated as a year and
535058e291fSPotin Lai // converted to 0 - 99.
536058e291fSPotin Lai r.major = val % 100;
537058e291fSPotin Lai }
538058e291fSPotin Lai else
539058e291fSPotin Lai {
5405d214202SPotin Lai r.major = val & 0x7F;
5412b7e07d3SDinesh Chinari }
542058e291fSPotin Lai }
54398a23840SMatthew Barth
5445d214202SPotin Lai // convert minor
5452b7e07d3SDinesh Chinari {
546*a6c307a8SJayanth Othayoth std::string str = m[matches[1]].str();
547*a6c307a8SJayanth Othayoth const auto& [ptr, ec] =
548*a6c307a8SJayanth Othayoth std::from_chars(str.data(), str.data() + str.size(), val);
549*a6c307a8SJayanth Othayoth if (ec != std::errc() || ptr != str.data() + str.size())
5505d214202SPotin Lai { // failed to convert minor string
551dcde04e0SPotin Lai return -1;
552886d6840SWilly Tu }
5535d214202SPotin Lai r.minor = val & 0xFF;
5542b7e07d3SDinesh Chinari }
55598a23840SMatthew Barth
556c7c55928SPotin Lai // convert aux bytes
557c7c55928SPotin Lai {
558c7c55928SPotin Lai size_t i;
559c7c55928SPotin Lai for (i = 0; i < 4; i++)
560c7c55928SPotin Lai {
561c7c55928SPotin Lai if (matches[i + 2] == 0)
562c7c55928SPotin Lai {
563c7c55928SPotin Lai continue;
564c7c55928SPotin Lai }
565c7c55928SPotin Lai
566*a6c307a8SJayanth Othayoth std::string str = m[matches[i + 2]].str();
567*a6c307a8SJayanth Othayoth const char* cstr = str.c_str();
568c7c55928SPotin Lai auto [ptr,
569*a6c307a8SJayanth Othayoth ec] = std::from_chars(cstr, cstr + str.size(), val, 16);
570*a6c307a8SJayanth Othayoth if (ec != std::errc() || ptr != cstr + str.size())
571c7c55928SPotin Lai { // failed to convert aux byte string
572c7c55928SPotin Lai break;
573c7c55928SPotin Lai }
574c7c55928SPotin Lai
575c7c55928SPotin Lai r.aux[i] = val & 0xFF;
576c7c55928SPotin Lai }
577c7c55928SPotin Lai
578c7c55928SPotin Lai if (i != 4)
579c7c55928SPotin Lai { // something wrong durign converting aux bytes
580c7c55928SPotin Lai return -1;
581c7c55928SPotin Lai }
582c7c55928SPotin Lai }
583c7c55928SPotin Lai
5845d214202SPotin Lai // all matched
5855d214202SPotin Lai rev = r;
58698a23840SMatthew Barth return 0;
58798a23840SMatthew Barth }
58898a23840SMatthew Barth
5895d214202SPotin Lai return -1;
5905d214202SPotin Lai }
5915d214202SPotin Lai
592ea1c401cSVernon Mauery /* @brief: Implement the Get Device ID IPMI command per the IPMI spec
593ea1c401cSVernon Mauery * @param[in] ctx - shared_ptr to an IPMI context struct
594ea1c401cSVernon Mauery *
595ea1c401cSVernon Mauery * @returns IPMI completion code plus response data
596ea1c401cSVernon Mauery * - Device ID (manufacturer defined)
597ea1c401cSVernon Mauery * - Device revision[4 bits]; reserved[3 bits]; SDR support[1 bit]
598ea1c401cSVernon Mauery * - FW revision major[7 bits] (binary encoded); available[1 bit]
599ea1c401cSVernon Mauery * - FW Revision minor (BCD encoded)
600ea1c401cSVernon Mauery * - IPMI version (0x02 for IPMI 2.0)
601ea1c401cSVernon Mauery * - device support (bitfield of supported options)
602ea1c401cSVernon Mauery * - MFG IANA ID (3 bytes)
603ea1c401cSVernon Mauery * - product ID (2 bytes)
604ea1c401cSVernon Mauery * - AUX info (4 bytes)
605ea1c401cSVernon Mauery */
606ea1c401cSVernon Mauery ipmi::RspType<uint8_t, // Device ID
60786a5082fSVernon Mauery uint8_t, // Device Revision
60886a5082fSVernon Mauery uint8_t, // Firmware Revision Major
60986a5082fSVernon Mauery uint8_t, // Firmware Revision minor
61086a5082fSVernon Mauery uint8_t, // IPMI version
61186a5082fSVernon Mauery uint8_t, // Additional device support
61286a5082fSVernon Mauery uint24_t, // MFG ID
61386a5082fSVernon Mauery uint16_t, // Product ID
61486a5082fSVernon Mauery uint32_t // AUX info
61586a5082fSVernon Mauery >
ipmiAppGetDeviceId(ipmi::Context::ptr ctx)61611d68897SWilly Tu ipmiAppGetDeviceId([[maybe_unused]] ipmi::Context::ptr ctx)
61798a23840SMatthew Barth {
61886a5082fSVernon Mauery static struct
61986a5082fSVernon Mauery {
62086a5082fSVernon Mauery uint8_t id;
62186a5082fSVernon Mauery uint8_t revision;
62286a5082fSVernon Mauery uint8_t fw[2];
62386a5082fSVernon Mauery uint8_t ipmiVer;
62486a5082fSVernon Mauery uint8_t addnDevSupport;
62586a5082fSVernon Mauery uint24_t manufId;
62686a5082fSVernon Mauery uint16_t prodId;
62786a5082fSVernon Mauery uint32_t aux;
62886a5082fSVernon Mauery } devId;
629a1adb077SDavid Cobbley static bool dev_id_initialized = false;
63094930a11SPatrick Venture static bool defaultActivationSetting = true;
631a1adb077SDavid Cobbley const char* filename = "/usr/share/ipmi-providers/dev_id.json";
632ba19c184SAlexander Amelkin constexpr auto ipmiDevIdStateShift = 7;
633ba19c184SAlexander Amelkin constexpr auto ipmiDevIdFw1Mask = ~(1 << ipmiDevIdStateShift);
634b78184e7SWilly Tu
635b78184e7SWilly Tu #ifdef GET_DBUS_ACTIVE_SOFTWARE
636b78184e7SWilly Tu static bool haveBMCVersion = false;
63727a62ecaSJeffLin if (!haveBMCVersion || !dev_id_initialized)
638a1adb077SDavid Cobbley {
639b78184e7SWilly Tu int r = -1;
640ceee811eSJayanth Othayoth Revision rev = {0, 0, {0, 0, 0, 0}};
641744398dcSNagaraju Goruganti try
642744398dcSNagaraju Goruganti {
643ea1c401cSVernon Mauery auto version = getActiveSoftwareVersionInfo(ctx);
64486a5082fSVernon Mauery r = convertVersion(version, rev);
645eb9b8144SSergey Solomin }
646744398dcSNagaraju Goruganti catch (const std::exception& e)
647744398dcSNagaraju Goruganti {
64824fffdc8SGeorge Liu lg2::error("error message: {ERROR}", "ERROR", e);
649744398dcSNagaraju Goruganti }
650744398dcSNagaraju Goruganti
6510b02be92SPatrick Venture if (r >= 0)
6520b02be92SPatrick Venture {
653a1adb077SDavid Cobbley // bit7 identifies if the device is available
654a1adb077SDavid Cobbley // 0=normal operation
655a1adb077SDavid Cobbley // 1=device firmware, SDR update,
656a1adb077SDavid Cobbley // or self-initialization in progress.
657ba19c184SAlexander Amelkin // The availability may change in run time, so mask here
658ba19c184SAlexander Amelkin // and initialize later.
65986a5082fSVernon Mauery devId.fw[0] = rev.major & ipmiDevIdFw1Mask;
66098a23840SMatthew Barth
66198a23840SMatthew Barth rev.minor = (rev.minor > 99 ? 99 : rev.minor);
66286a5082fSVernon Mauery devId.fw[1] = rev.minor % 10 + (rev.minor / 10) * 16;
663c7c55928SPotin Lai std::memcpy(&devId.aux, rev.aux, sizeof(rev.aux));
664c1f5aca0SBrandon Kim haveBMCVersion = true;
66598a23840SMatthew Barth }
66627a62ecaSJeffLin }
667b78184e7SWilly Tu #endif
66827a62ecaSJeffLin if (!dev_id_initialized)
66927a62ecaSJeffLin {
6708991dd62SGunnar Mills // IPMI Spec version 2.0
67186a5082fSVernon Mauery devId.ipmiVer = 2;
672ee0cb902SNan Li
67386a5082fSVernon Mauery std::ifstream devIdFile(filename);
67486a5082fSVernon Mauery if (devIdFile.is_open())
675a1adb077SDavid Cobbley {
67686a5082fSVernon Mauery auto data = nlohmann::json::parse(devIdFile, nullptr, false);
677a1adb077SDavid Cobbley if (!data.is_discarded())
678a1adb077SDavid Cobbley {
67986a5082fSVernon Mauery devId.id = data.value("id", 0);
68086a5082fSVernon Mauery devId.revision = data.value("revision", 0);
68186a5082fSVernon Mauery devId.addnDevSupport = data.value("addn_dev_support", 0);
68286a5082fSVernon Mauery devId.manufId = data.value("manuf_id", 0);
68386a5082fSVernon Mauery devId.prodId = data.value("prod_id", 0);
6849a686366SPotin Lai #ifdef GET_DBUS_ACTIVE_SOFTWARE
6859a686366SPotin Lai if (!(AUX_0_MATCH_INDEX || AUX_1_MATCH_INDEX ||
6869a686366SPotin Lai AUX_2_MATCH_INDEX || AUX_3_MATCH_INDEX))
6879a686366SPotin Lai #endif
6889a686366SPotin Lai {
68986a5082fSVernon Mauery devId.aux = data.value("aux", 0);
6909a686366SPotin Lai }
691ee0cb902SNan Li
692bfd3a17fSWilly Tu if (data.contains("firmware_revision"))
693bfd3a17fSWilly Tu {
694bfd3a17fSWilly Tu const auto& firmwareRevision = data.at("firmware_revision");
695bfd3a17fSWilly Tu if (firmwareRevision.contains("major"))
696bfd3a17fSWilly Tu {
697bfd3a17fSWilly Tu firmwareRevision.at("major").get_to(devId.fw[0]);
698bfd3a17fSWilly Tu }
699bfd3a17fSWilly Tu if (firmwareRevision.contains("minor"))
700bfd3a17fSWilly Tu {
701bfd3a17fSWilly Tu firmwareRevision.at("minor").get_to(devId.fw[1]);
702bfd3a17fSWilly Tu }
703bfd3a17fSWilly Tu }
704bfd3a17fSWilly Tu
70594930a11SPatrick Venture // Set the availablitity of the BMC.
70694930a11SPatrick Venture defaultActivationSetting = data.value("availability", true);
70794930a11SPatrick Venture
708a1adb077SDavid Cobbley // Don't read the file every time if successful
709a1adb077SDavid Cobbley dev_id_initialized = true;
710a1adb077SDavid Cobbley }
711a1adb077SDavid Cobbley else
712a1adb077SDavid Cobbley {
71324fffdc8SGeorge Liu lg2::error("Device ID JSON parser failure");
714f2587fceSVernon Mauery return ipmi::responseUnspecifiedError();
715a1adb077SDavid Cobbley }
716a1adb077SDavid Cobbley }
717a1adb077SDavid Cobbley else
718a1adb077SDavid Cobbley {
71924fffdc8SGeorge Liu lg2::error("Device ID file not found");
720f2587fceSVernon Mauery return ipmi::responseUnspecifiedError();
721a1adb077SDavid Cobbley }
722a1adb077SDavid Cobbley }
723ee0cb902SNan Li
724ba19c184SAlexander Amelkin // Set availability to the actual current BMC state
72586a5082fSVernon Mauery devId.fw[0] &= ipmiDevIdFw1Mask;
72694930a11SPatrick Venture if (!getCurrentBmcStateWithFallback(defaultActivationSetting))
727ba19c184SAlexander Amelkin {
72886a5082fSVernon Mauery devId.fw[0] |= (1 << ipmiDevIdStateShift);
729ba19c184SAlexander Amelkin }
730ba19c184SAlexander Amelkin
73186a5082fSVernon Mauery return ipmi::responseSuccess(
73286a5082fSVernon Mauery devId.id, devId.revision, devId.fw[0], devId.fw[1], devId.ipmiVer,
73386a5082fSVernon Mauery devId.addnDevSupport, devId.manufId, devId.prodId, devId.aux);
73498a23840SMatthew Barth }
73598a23840SMatthew Barth
ipmiAppGetSelfTestResults()736b84a5282SVernon Mauery auto ipmiAppGetSelfTestResults() -> ipmi::RspType<uint8_t, uint8_t>
73741fa24a1SNan Li {
73841fa24a1SNan Li // Byte 2:
73941fa24a1SNan Li // 55h - No error.
7408991dd62SGunnar Mills // 56h - Self Test function not implemented in this controller.
74141fa24a1SNan Li // 57h - Corrupted or inaccesssible data or devices.
74241fa24a1SNan Li // 58h - Fatal hardware error.
74341fa24a1SNan Li // FFh - reserved.
74441fa24a1SNan Li // all other: Device-specific 'internal failure'.
74541fa24a1SNan Li // Byte 3:
74641fa24a1SNan Li // For byte 2 = 55h, 56h, FFh: 00h
74741fa24a1SNan Li // For byte 2 = 58h, all other: Device-specific
74841fa24a1SNan Li // For byte 2 = 57h: self-test error bitfield.
74941fa24a1SNan Li // Note: returning 57h does not imply that all test were run.
75041fa24a1SNan Li // [7] 1b = Cannot access SEL device.
75141fa24a1SNan Li // [6] 1b = Cannot access SDR Repository.
75241fa24a1SNan Li // [5] 1b = Cannot access BMC FRU device.
75341fa24a1SNan Li // [4] 1b = IPMB signal lines do not respond.
75441fa24a1SNan Li // [3] 1b = SDR Repository empty.
75541fa24a1SNan Li // [2] 1b = Internal Use Area of BMC FRU corrupted.
75641fa24a1SNan Li // [1] 1b = controller update 'boot block' firmware corrupted.
75741fa24a1SNan Li // [0] 1b = controller operational firmware corrupted.
758b84a5282SVernon Mauery constexpr uint8_t notImplemented = 0x56;
759b84a5282SVernon Mauery constexpr uint8_t zero = 0;
760b84a5282SVernon Mauery return ipmi::responseSuccess(notImplemented, zero);
76141fa24a1SNan Li }
76241fa24a1SNan Li
7631554132bSVernon Mauery static constexpr size_t uuidBinaryLength = 16;
rfc4122ToIpmi(std::string rfc4122)7641554132bSVernon Mauery static std::array<uint8_t, uuidBinaryLength> rfc4122ToIpmi(std::string rfc4122)
76598a23840SMatthew Barth {
766523e2d1bSWilly Tu using Argument = xyz::openbmc_project::common::InvalidArgument;
76798a23840SMatthew Barth // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
768d211702bSPatrick Venture // Per IPMI Spec 2.0 need to convert to 16 hex bytes and reverse the byte
769d211702bSPatrick Venture // order
77098a23840SMatthew Barth // Ex: 0x2332fc2c40e66298e511f2782395a361
7711554132bSVernon Mauery constexpr size_t uuidHexLength = (2 * uuidBinaryLength);
7721554132bSVernon Mauery constexpr size_t uuidRfc4122Length = (uuidHexLength + 4);
7731554132bSVernon Mauery std::array<uint8_t, uuidBinaryLength> uuid;
7741554132bSVernon Mauery if (rfc4122.size() == uuidRfc4122Length)
7750b02be92SPatrick Venture {
7761554132bSVernon Mauery rfc4122.erase(std::remove(rfc4122.begin(), rfc4122.end(), '-'),
7771554132bSVernon Mauery rfc4122.end());
778eb9b8144SSergey Solomin }
7791554132bSVernon Mauery if (rfc4122.size() != uuidHexLength)
78098a23840SMatthew Barth {
7811554132bSVernon Mauery elog<InvalidArgument>(Argument::ARGUMENT_NAME("rfc4122"),
7821554132bSVernon Mauery Argument::ARGUMENT_VALUE(rfc4122.c_str()));
7831554132bSVernon Mauery }
7841554132bSVernon Mauery for (size_t ind = 0; ind < uuidHexLength; ind += 2)
7851554132bSVernon Mauery {
7861554132bSVernon Mauery char v[3];
7871554132bSVernon Mauery v[0] = rfc4122[ind];
7881554132bSVernon Mauery v[1] = rfc4122[ind + 1];
7891554132bSVernon Mauery v[2] = 0;
7901554132bSVernon Mauery size_t err;
7911554132bSVernon Mauery long b;
7921554132bSVernon Mauery try
7931554132bSVernon Mauery {
7941554132bSVernon Mauery b = std::stoul(v, &err, 16);
7951554132bSVernon Mauery }
796a2ad2da8SPatrick Williams catch (const std::exception& e)
7971554132bSVernon Mauery {
7981554132bSVernon Mauery elog<InvalidArgument>(Argument::ARGUMENT_NAME("rfc4122"),
7991554132bSVernon Mauery Argument::ARGUMENT_VALUE(rfc4122.c_str()));
8001554132bSVernon Mauery }
8011554132bSVernon Mauery // check that exactly two ascii bytes were converted
8021554132bSVernon Mauery if (err != 2)
8031554132bSVernon Mauery {
8041554132bSVernon Mauery elog<InvalidArgument>(Argument::ARGUMENT_NAME("rfc4122"),
8051554132bSVernon Mauery Argument::ARGUMENT_VALUE(rfc4122.c_str()));
8061554132bSVernon Mauery }
8071554132bSVernon Mauery uuid[uuidBinaryLength - (ind / 2) - 1] = static_cast<uint8_t>(b);
8081554132bSVernon Mauery }
8091554132bSVernon Mauery return uuid;
81098a23840SMatthew Barth }
81198a23840SMatthew Barth
ipmiAppGetDeviceGuid()8121554132bSVernon Mauery auto ipmiAppGetDeviceGuid()
8131554132bSVernon Mauery -> ipmi::RspType<std::array<uint8_t, uuidBinaryLength>>
81498a23840SMatthew Barth {
8151554132bSVernon Mauery // return a fixed GUID based on /etc/machine-id
8161554132bSVernon Mauery // This should match the /redfish/v1/Managers/bmc's UUID data
81798a23840SMatthew Barth
8181554132bSVernon Mauery // machine specific application ID (for BMC ID)
8191554132bSVernon Mauery // generated by systemd-id128 -p new as per man page
8201554132bSVernon Mauery static constexpr sd_id128_t bmcUuidAppId = SD_ID128_MAKE(
8211554132bSVernon Mauery e0, e1, 73, 76, 64, 61, 47, da, a5, 0c, d0, cc, 64, 12, 45, 78);
82298a23840SMatthew Barth
8231554132bSVernon Mauery sd_id128_t bmcUuid;
8241554132bSVernon Mauery // create the UUID from /etc/machine-id via the systemd API
8251554132bSVernon Mauery sd_id128_get_machine_app_specific(bmcUuidAppId, &bmcUuid);
82698a23840SMatthew Barth
8271554132bSVernon Mauery char bmcUuidCstr[SD_ID128_STRING_MAX];
8281554132bSVernon Mauery std::string systemUuid = sd_id128_to_string(bmcUuid, bmcUuidCstr);
82998a23840SMatthew Barth
8301554132bSVernon Mauery std::array<uint8_t, uuidBinaryLength> uuid = rfc4122ToIpmi(systemUuid);
8311554132bSVernon Mauery return ipmi::responseSuccess(uuid);
83298a23840SMatthew Barth }
83398a23840SMatthew Barth
ipmiAppGetBtCapabilities()834cc99ba43SVernon Mauery auto ipmiAppGetBtCapabilities()
835cc99ba43SVernon Mauery -> ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t>
83698a23840SMatthew Barth {
83788ad815dSAdriana Kobylak // Per IPMI 2.0 spec, the input and output buffer size must be the max
83888ad815dSAdriana Kobylak // buffer size minus one byte to allocate space for the length byte.
839cc99ba43SVernon Mauery constexpr uint8_t nrOutstanding = 0x01;
840cc99ba43SVernon Mauery constexpr uint8_t inputBufferSize = MAX_IPMI_BUFFER - 1;
841cc99ba43SVernon Mauery constexpr uint8_t outputBufferSize = MAX_IPMI_BUFFER - 1;
842cc99ba43SVernon Mauery constexpr uint8_t transactionTime = 0x0A;
843cc99ba43SVernon Mauery constexpr uint8_t nrRetries = 0x01;
84498a23840SMatthew Barth
845cc99ba43SVernon Mauery return ipmi::responseSuccess(nrOutstanding, inputBufferSize,
846cc99ba43SVernon Mauery outputBufferSize, transactionTime, nrRetries);
84798a23840SMatthew Barth }
84898a23840SMatthew Barth
ipmiAppGetSystemGuid(ipmi::Context::ptr & ctx)8496c44a94dSVernon Mauery auto ipmiAppGetSystemGuid(ipmi::Context::ptr& ctx)
8506c44a94dSVernon Mauery -> ipmi::RspType<std::array<uint8_t, 16>>
8515e007a5dSMarri Devender Rao {
852b90a5328SVernon Mauery static constexpr auto uuidInterface = "xyz.openbmc_project.Common.UUID";
853b90a5328SVernon Mauery static constexpr auto uuidProperty = "UUID";
8545e007a5dSMarri Devender Rao
8555e007a5dSMarri Devender Rao // Get the Inventory object implementing BMC interface
8566c44a94dSVernon Mauery ipmi::DbusObjectInfo objectInfo{};
857d386fba6SHieu Huynh boost::system::error_code ec = ipmi::getDbusObject(
858d386fba6SHieu Huynh ctx, uuidInterface, ipmi::sensor::inventoryRoot, objectInfo);
8596c44a94dSVernon Mauery if (ec.value())
8606c44a94dSVernon Mauery {
86124fffdc8SGeorge Liu lg2::error("Failed to locate System UUID object, "
86224fffdc8SGeorge Liu "interface: {INTERFACE}, error: {ERROR}",
86324fffdc8SGeorge Liu "INTERFACE", uuidInterface, "ERROR", ec.message());
8646c44a94dSVernon Mauery }
8655e007a5dSMarri Devender Rao
8665e007a5dSMarri Devender Rao // Read UUID property value from bmcObject
8675e007a5dSMarri Devender Rao // UUID is in RFC4122 format Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
8686c44a94dSVernon Mauery std::string rfc4122Uuid{};
8696c44a94dSVernon Mauery ec = ipmi::getDbusProperty(ctx, objectInfo.second, objectInfo.first,
8706c44a94dSVernon Mauery uuidInterface, uuidProperty, rfc4122Uuid);
8716c44a94dSVernon Mauery if (ec.value())
8725e007a5dSMarri Devender Rao {
87324fffdc8SGeorge Liu lg2::error("Failed to read System UUID property, "
87424fffdc8SGeorge Liu "interface: {INTERFACE}, property: {PROPERTY}, "
87524fffdc8SGeorge Liu "error: {ERROR}",
87624fffdc8SGeorge Liu "INTERFACE", uuidInterface, "PROPERTY", uuidProperty,
87724fffdc8SGeorge Liu "ERROR", ec.message());
878b90a5328SVernon Mauery return ipmi::responseUnspecifiedError();
8795e007a5dSMarri Devender Rao }
880b90a5328SVernon Mauery std::array<uint8_t, 16> uuid;
881b90a5328SVernon Mauery try
882b90a5328SVernon Mauery {
883b90a5328SVernon Mauery // convert to IPMI format
884b90a5328SVernon Mauery uuid = rfc4122ToIpmi(rfc4122Uuid);
885b90a5328SVernon Mauery }
886b90a5328SVernon Mauery catch (const InvalidArgument& e)
887b90a5328SVernon Mauery {
88824fffdc8SGeorge Liu lg2::error("Failed in parsing BMC UUID property, "
88924fffdc8SGeorge Liu "interface: {INTERFACE}, property: {PROPERTY}, "
89024fffdc8SGeorge Liu "value: {VALUE}, error: {ERROR}",
89124fffdc8SGeorge Liu "INTERFACE", uuidInterface, "PROPERTY", uuidProperty,
89224fffdc8SGeorge Liu "VALUE", rfc4122Uuid, "ERROR", e);
893b90a5328SVernon Mauery return ipmi::responseUnspecifiedError();
894b90a5328SVernon Mauery }
895b90a5328SVernon Mauery return ipmi::responseSuccess(uuid);
8965e007a5dSMarri Devender Rao }
8975e007a5dSMarri Devender Rao
898e7023926SRajashekar Gade Reddy /**
899e7023926SRajashekar Gade Reddy * @brief set the session state as teardown
900e7023926SRajashekar Gade Reddy *
901e7023926SRajashekar Gade Reddy * This function is to set the session state to tear down in progress if the
902e7023926SRajashekar Gade Reddy * state is active.
903e7023926SRajashekar Gade Reddy *
904e7023926SRajashekar Gade Reddy * @param[in] busp - Dbus obj
905e7023926SRajashekar Gade Reddy * @param[in] service - service name
906e7023926SRajashekar Gade Reddy * @param[in] obj - object path
907e7023926SRajashekar Gade Reddy *
908e7023926SRajashekar Gade Reddy * @return success completion code if it sets the session state to
909e7023926SRajashekar Gade Reddy * tearDownInProgress else return the corresponding error completion code.
910e7023926SRajashekar Gade Reddy **/
setSessionState(std::shared_ptr<sdbusplus::asio::connection> & busp,const std::string & service,const std::string & obj)911e7023926SRajashekar Gade Reddy uint8_t setSessionState(std::shared_ptr<sdbusplus::asio::connection>& busp,
912e7023926SRajashekar Gade Reddy const std::string& service, const std::string& obj)
913e7023926SRajashekar Gade Reddy {
914e7023926SRajashekar Gade Reddy try
915e7023926SRajashekar Gade Reddy {
916e7023926SRajashekar Gade Reddy uint8_t sessionState = std::get<uint8_t>(ipmi::getDbusProperty(
917e7023926SRajashekar Gade Reddy *busp, service, obj, session::sessionIntf, "State"));
918e7023926SRajashekar Gade Reddy
919e7023926SRajashekar Gade Reddy if (sessionState == static_cast<uint8_t>(session::State::active))
920e7023926SRajashekar Gade Reddy {
921e7023926SRajashekar Gade Reddy ipmi::setDbusProperty(
922e7023926SRajashekar Gade Reddy *busp, service, obj, session::sessionIntf, "State",
923e7023926SRajashekar Gade Reddy static_cast<uint8_t>(session::State::tearDownInProgress));
924e7023926SRajashekar Gade Reddy return ipmi::ccSuccess;
925e7023926SRajashekar Gade Reddy }
926e7023926SRajashekar Gade Reddy }
927a2ad2da8SPatrick Williams catch (const std::exception& e)
928e7023926SRajashekar Gade Reddy {
92924fffdc8SGeorge Liu lg2::error("Failed in getting session state property, "
93024fffdc8SGeorge Liu "service: {SERVICE}, object path: {OBJECT_PATH}, "
93124fffdc8SGeorge Liu "interface: {INTERFACE}, error: {ERROR}",
93224fffdc8SGeorge Liu "SERVICE", service, "OBJECT_PATH", obj, "INTERFACE",
93324fffdc8SGeorge Liu session::sessionIntf, "ERROR", e);
934e7023926SRajashekar Gade Reddy return ipmi::ccUnspecifiedError;
935e7023926SRajashekar Gade Reddy }
936e7023926SRajashekar Gade Reddy
937e7023926SRajashekar Gade Reddy return ipmi::ccInvalidFieldRequest;
938e7023926SRajashekar Gade Reddy }
939e7023926SRajashekar Gade Reddy
ipmiAppCloseSession(uint32_t reqSessionId,std::optional<uint8_t> requestSessionHandle)940e7023926SRajashekar Gade Reddy ipmi::RspType<> ipmiAppCloseSession(uint32_t reqSessionId,
941e7023926SRajashekar Gade Reddy std::optional<uint8_t> requestSessionHandle)
942e7023926SRajashekar Gade Reddy {
943e7023926SRajashekar Gade Reddy auto busp = getSdBus();
944e7023926SRajashekar Gade Reddy uint8_t reqSessionHandle =
945e7023926SRajashekar Gade Reddy requestSessionHandle.value_or(session::defaultSessionHandle);
946e7023926SRajashekar Gade Reddy
947e7023926SRajashekar Gade Reddy if (reqSessionId == session::sessionZero &&
948e7023926SRajashekar Gade Reddy reqSessionHandle == session::defaultSessionHandle)
949e7023926SRajashekar Gade Reddy {
950e7023926SRajashekar Gade Reddy return ipmi::response(session::ccInvalidSessionId);
951e7023926SRajashekar Gade Reddy }
952e7023926SRajashekar Gade Reddy
953e7023926SRajashekar Gade Reddy if (reqSessionId == session::sessionZero &&
954e7023926SRajashekar Gade Reddy reqSessionHandle == session::invalidSessionHandle)
955e7023926SRajashekar Gade Reddy {
956e7023926SRajashekar Gade Reddy return ipmi::response(session::ccInvalidSessionHandle);
957e7023926SRajashekar Gade Reddy }
958e7023926SRajashekar Gade Reddy
959e7023926SRajashekar Gade Reddy if (reqSessionId != session::sessionZero &&
960e7023926SRajashekar Gade Reddy reqSessionHandle != session::defaultSessionHandle)
961e7023926SRajashekar Gade Reddy {
962e7023926SRajashekar Gade Reddy return ipmi::response(ipmi::ccInvalidFieldRequest);
963e7023926SRajashekar Gade Reddy }
964e7023926SRajashekar Gade Reddy
965e7023926SRajashekar Gade Reddy try
966e7023926SRajashekar Gade Reddy {
967e7023926SRajashekar Gade Reddy ipmi::ObjectTree objectTree = ipmi::getAllDbusObjects(
968e7023926SRajashekar Gade Reddy *busp, session::sessionManagerRootPath, session::sessionIntf);
969e7023926SRajashekar Gade Reddy
970e7023926SRajashekar Gade Reddy for (auto& objectTreeItr : objectTree)
971e7023926SRajashekar Gade Reddy {
972e7023926SRajashekar Gade Reddy const std::string obj = objectTreeItr.first;
973e7023926SRajashekar Gade Reddy
974e7023926SRajashekar Gade Reddy if (isSessionObjectMatched(obj, reqSessionId, reqSessionHandle))
975e7023926SRajashekar Gade Reddy {
976e7023926SRajashekar Gade Reddy auto& serviceMap = objectTreeItr.second;
977e7023926SRajashekar Gade Reddy
978e7023926SRajashekar Gade Reddy // Session id and session handle are unique for each session.
979e7023926SRajashekar Gade Reddy // Session id and handler are retrived from the object path and
980e7023926SRajashekar Gade Reddy // object path will be unique for each session. Checking if
981e7023926SRajashekar Gade Reddy // multiple objects exist with same object path under multiple
982e7023926SRajashekar Gade Reddy // services.
983e7023926SRajashekar Gade Reddy if (serviceMap.size() != 1)
984e7023926SRajashekar Gade Reddy {
985e7023926SRajashekar Gade Reddy return ipmi::responseUnspecifiedError();
986e7023926SRajashekar Gade Reddy }
987e7023926SRajashekar Gade Reddy
988e7023926SRajashekar Gade Reddy auto itr = serviceMap.begin();
989e7023926SRajashekar Gade Reddy const std::string service = itr->first;
990e7023926SRajashekar Gade Reddy return ipmi::response(setSessionState(busp, service, obj));
991e7023926SRajashekar Gade Reddy }
992e7023926SRajashekar Gade Reddy }
993e7023926SRajashekar Gade Reddy }
9945d82f474SPatrick Williams catch (const sdbusplus::exception_t& e)
995e7023926SRajashekar Gade Reddy {
99624fffdc8SGeorge Liu lg2::error("Failed to fetch object from dbus, "
99724fffdc8SGeorge Liu "interface: {INTERFACE}, error: {ERROR}",
99824fffdc8SGeorge Liu "INTERFACE", session::sessionIntf, "ERROR", e);
999e7023926SRajashekar Gade Reddy return ipmi::responseUnspecifiedError();
1000e7023926SRajashekar Gade Reddy }
1001e7023926SRajashekar Gade Reddy
1002e7023926SRajashekar Gade Reddy return ipmi::responseInvalidFieldRequest();
1003e7023926SRajashekar Gade Reddy }
1004e7023926SRajashekar Gade Reddy
getTotalSessionCount()1005f71444daSRajashekar Gade Reddy uint8_t getTotalSessionCount()
1006f71444daSRajashekar Gade Reddy {
1007c178948eSMeera-Katta uint8_t count = 0, ch = 0;
1008f71444daSRajashekar Gade Reddy
1009f71444daSRajashekar Gade Reddy while (ch < ipmi::maxIpmiChannels &&
1010f71444daSRajashekar Gade Reddy count < session::maxNetworkInstanceSupported)
1011f71444daSRajashekar Gade Reddy {
101280207e62SJayaprakash Mutyala ipmi::ChannelInfo chInfo{};
1013f71444daSRajashekar Gade Reddy ipmi::getChannelInfo(ch, chInfo);
1014f71444daSRajashekar Gade Reddy if (static_cast<ipmi::EChannelMediumType>(chInfo.mediumType) ==
1015f71444daSRajashekar Gade Reddy ipmi::EChannelMediumType::lan8032)
1016f71444daSRajashekar Gade Reddy {
1017f71444daSRajashekar Gade Reddy count++;
1018f71444daSRajashekar Gade Reddy }
1019f71444daSRajashekar Gade Reddy ch++;
1020f71444daSRajashekar Gade Reddy }
1021f71444daSRajashekar Gade Reddy return count * session::maxSessionCountPerChannel;
1022f71444daSRajashekar Gade Reddy }
1023f71444daSRajashekar Gade Reddy
1024f71444daSRajashekar Gade Reddy /**
1025f71444daSRajashekar Gade Reddy * @brief get session info request data.
1026f71444daSRajashekar Gade Reddy *
1027f71444daSRajashekar Gade Reddy * This function validates the request data and retrive request session id,
1028f71444daSRajashekar Gade Reddy * session handle.
1029f71444daSRajashekar Gade Reddy *
10304d22640aSRajashekar Gade Reddy * @param[in] ctx - context of current session.
1031f71444daSRajashekar Gade Reddy * @param[in] sessionIndex - request session index
1032f71444daSRajashekar Gade Reddy * @param[in] payload - input payload
1033f71444daSRajashekar Gade Reddy * @param[in] reqSessionId - unpacked session Id will be asigned
1034f71444daSRajashekar Gade Reddy * @param[in] reqSessionHandle - unpacked session handle will be asigned
1035f71444daSRajashekar Gade Reddy *
1036f71444daSRajashekar Gade Reddy * @return success completion code if request data is valid
1037f71444daSRajashekar Gade Reddy * else return the correcponding error completion code.
1038f71444daSRajashekar Gade Reddy **/
getSessionInfoRequestData(const ipmi::Context::ptr ctx,const uint8_t sessionIndex,ipmi::message::Payload & payload,uint32_t & reqSessionId,uint8_t & reqSessionHandle)10391318a5edSPatrick Williams uint8_t getSessionInfoRequestData(
10401318a5edSPatrick Williams const ipmi::Context::ptr ctx, const uint8_t sessionIndex,
10411318a5edSPatrick Williams ipmi::message::Payload& payload, uint32_t& reqSessionId,
1042f71444daSRajashekar Gade Reddy uint8_t& reqSessionHandle)
1043f71444daSRajashekar Gade Reddy {
10444d22640aSRajashekar Gade Reddy if ((sessionIndex > session::maxSessionCountPerChannel) &&
10454d22640aSRajashekar Gade Reddy (sessionIndex < session::searchSessionByHandle))
1046f71444daSRajashekar Gade Reddy {
1047f71444daSRajashekar Gade Reddy return ipmi::ccInvalidFieldRequest;
1048f71444daSRajashekar Gade Reddy }
1049f71444daSRajashekar Gade Reddy
1050f71444daSRajashekar Gade Reddy switch (sessionIndex)
1051f71444daSRajashekar Gade Reddy {
10524d22640aSRajashekar Gade Reddy case session::searchCurrentSession:
10534d22640aSRajashekar Gade Reddy
10544d22640aSRajashekar Gade Reddy ipmi::ChannelInfo chInfo;
10554d22640aSRajashekar Gade Reddy ipmi::getChannelInfo(ctx->channel, chInfo);
10564d22640aSRajashekar Gade Reddy
10574d22640aSRajashekar Gade Reddy if (static_cast<ipmi::EChannelMediumType>(chInfo.mediumType) !=
10584d22640aSRajashekar Gade Reddy ipmi::EChannelMediumType::lan8032)
10594d22640aSRajashekar Gade Reddy {
10604d22640aSRajashekar Gade Reddy return ipmi::ccInvalidFieldRequest;
10614d22640aSRajashekar Gade Reddy }
10624d22640aSRajashekar Gade Reddy
10634d22640aSRajashekar Gade Reddy if (!payload.fullyUnpacked())
10644d22640aSRajashekar Gade Reddy {
10654d22640aSRajashekar Gade Reddy return ipmi::ccReqDataLenInvalid;
10664d22640aSRajashekar Gade Reddy }
10674d22640aSRajashekar Gade Reddy // Check if current sessionId is 0, sessionId 0 is reserved.
10684d22640aSRajashekar Gade Reddy if (ctx->sessionId == session::sessionZero)
10694d22640aSRajashekar Gade Reddy {
10704d22640aSRajashekar Gade Reddy return session::ccInvalidSessionId;
10714d22640aSRajashekar Gade Reddy }
10724d22640aSRajashekar Gade Reddy reqSessionId = ctx->sessionId;
10734d22640aSRajashekar Gade Reddy break;
10744d22640aSRajashekar Gade Reddy
1075f71444daSRajashekar Gade Reddy case session::searchSessionByHandle:
1076f71444daSRajashekar Gade Reddy
1077f71444daSRajashekar Gade Reddy if ((payload.unpack(reqSessionHandle)) ||
1078f71444daSRajashekar Gade Reddy (!payload.fullyUnpacked()))
1079f71444daSRajashekar Gade Reddy {
1080f71444daSRajashekar Gade Reddy return ipmi::ccReqDataLenInvalid;
1081f71444daSRajashekar Gade Reddy }
1082f71444daSRajashekar Gade Reddy
1083f71444daSRajashekar Gade Reddy if ((reqSessionHandle == session::sessionZero) ||
1084f71444daSRajashekar Gade Reddy ((reqSessionHandle & session::multiIntfaceSessionHandleMask) >
1085f71444daSRajashekar Gade Reddy session::maxSessionCountPerChannel))
1086f71444daSRajashekar Gade Reddy {
1087f71444daSRajashekar Gade Reddy return session::ccInvalidSessionHandle;
1088f71444daSRajashekar Gade Reddy }
1089f71444daSRajashekar Gade Reddy break;
1090f71444daSRajashekar Gade Reddy
1091f71444daSRajashekar Gade Reddy case session::searchSessionById:
1092f71444daSRajashekar Gade Reddy
1093f71444daSRajashekar Gade Reddy if ((payload.unpack(reqSessionId)) || (!payload.fullyUnpacked()))
1094f71444daSRajashekar Gade Reddy {
1095f71444daSRajashekar Gade Reddy return ipmi::ccReqDataLenInvalid;
1096f71444daSRajashekar Gade Reddy }
1097f71444daSRajashekar Gade Reddy
1098f71444daSRajashekar Gade Reddy if (reqSessionId == session::sessionZero)
1099f71444daSRajashekar Gade Reddy {
1100f71444daSRajashekar Gade Reddy return session::ccInvalidSessionId;
1101f71444daSRajashekar Gade Reddy }
1102f71444daSRajashekar Gade Reddy break;
1103f71444daSRajashekar Gade Reddy
1104f71444daSRajashekar Gade Reddy default:
1105f71444daSRajashekar Gade Reddy if (!payload.fullyUnpacked())
1106f71444daSRajashekar Gade Reddy {
1107f71444daSRajashekar Gade Reddy return ipmi::ccReqDataLenInvalid;
1108f71444daSRajashekar Gade Reddy }
1109f71444daSRajashekar Gade Reddy break;
1110f71444daSRajashekar Gade Reddy }
1111f71444daSRajashekar Gade Reddy return ipmi::ccSuccess;
1112f71444daSRajashekar Gade Reddy }
1113f71444daSRajashekar Gade Reddy
getSessionState(ipmi::Context::ptr ctx,const std::string & service,const std::string & objPath,uint8_t & sessionState)1114e7e8b816SVernon Mauery uint8_t getSessionState(ipmi::Context::ptr ctx, const std::string& service,
1115e7e8b816SVernon Mauery const std::string& objPath, uint8_t& sessionState)
1116f71444daSRajashekar Gade Reddy {
1117e7e8b816SVernon Mauery boost::system::error_code ec = ipmi::getDbusProperty(
1118e7e8b816SVernon Mauery ctx, service, objPath, session::sessionIntf, "State", sessionState);
1119e7e8b816SVernon Mauery if (ec)
1120f71444daSRajashekar Gade Reddy {
112124fffdc8SGeorge Liu lg2::error("Failed to fetch state property, service: {SERVICE}, "
112224fffdc8SGeorge Liu "object path: {OBJECTPATH}, interface: {INTERFACE}, "
112324fffdc8SGeorge Liu "error: {ERROR}",
112424fffdc8SGeorge Liu "SERVICE", service, "OBJECTPATH", objPath, "INTERFACE",
112524fffdc8SGeorge Liu session::sessionIntf, "ERROR", ec.message());
1126f71444daSRajashekar Gade Reddy return ipmi::ccUnspecifiedError;
1127f71444daSRajashekar Gade Reddy }
1128f71444daSRajashekar Gade Reddy return ipmi::ccSuccess;
1129f71444daSRajashekar Gade Reddy }
1130f71444daSRajashekar Gade Reddy
1131f71444daSRajashekar Gade Reddy static constexpr uint8_t macAddrLen = 6;
1132e7e8b816SVernon Mauery /** Alias SessionDetails - contain the optional information about an
1133e7e8b816SVernon Mauery * RMCP+ session.
1134e7e8b816SVernon Mauery *
1135e7e8b816SVernon Mauery * @param userID - uint6_t session user ID (0-63)
1136e7e8b816SVernon Mauery * @param reserved - uint2_t reserved
1137e7e8b816SVernon Mauery * @param privilege - uint4_t session privilege (0-5)
1138e7e8b816SVernon Mauery * @param reserved - uint4_t reserved
1139e7e8b816SVernon Mauery * @param channel - uint4_t session channel number
1140e7e8b816SVernon Mauery * @param protocol - uint4_t session protocol
1141e7e8b816SVernon Mauery * @param remoteIP - uint32_t remote IP address
1142e7e8b816SVernon Mauery * @param macAddr - std::array<uint8_t, 6> mac address
1143e7e8b816SVernon Mauery * @param port - uint16_t remote port
1144e7e8b816SVernon Mauery */
1145e7e8b816SVernon Mauery using SessionDetails =
1146e7e8b816SVernon Mauery std::tuple<uint2_t, uint6_t, uint4_t, uint4_t, uint4_t, uint4_t, uint32_t,
1147e7e8b816SVernon Mauery std::array<uint8_t, macAddrLen>, uint16_t>;
1148f71444daSRajashekar Gade Reddy
1149e7e8b816SVernon Mauery /** @brief get session details for a given session
1150e7e8b816SVernon Mauery *
1151e7e8b816SVernon Mauery * @param[in] ctx - ipmi::Context pointer for accessing D-Bus
1152e7e8b816SVernon Mauery * @param[in] service - D-Bus service name to fetch details from
1153e7e8b816SVernon Mauery * @param[in] objPath - D-Bus object path for session
1154e7e8b816SVernon Mauery * @param[out] sessionHandle - return session handle for session
1155e7e8b816SVernon Mauery * @param[out] sessionState - return session state for session
1156e7e8b816SVernon Mauery * @param[out] details - return a SessionDetails tuple containing other
1157e7e8b816SVernon Mauery * session info
1158e7e8b816SVernon Mauery * @return - ipmi::Cc success or error code
1159e7e8b816SVernon Mauery */
getSessionDetails(ipmi::Context::ptr ctx,const std::string & service,const std::string & objPath,uint8_t & sessionHandle,uint8_t & sessionState,SessionDetails & details)1160e7e8b816SVernon Mauery ipmi::Cc getSessionDetails(ipmi::Context::ptr ctx, const std::string& service,
1161e7e8b816SVernon Mauery const std::string& objPath, uint8_t& sessionHandle,
1162e7e8b816SVernon Mauery uint8_t& sessionState, SessionDetails& details)
1163f71444daSRajashekar Gade Reddy {
1164e7e8b816SVernon Mauery ipmi::PropertyMap sessionProps;
1165e7e8b816SVernon Mauery boost::system::error_code ec = ipmi::getAllDbusProperties(
1166e7e8b816SVernon Mauery ctx, service, objPath, session::sessionIntf, sessionProps);
1167f71444daSRajashekar Gade Reddy
1168e7e8b816SVernon Mauery if (ec)
1169f71444daSRajashekar Gade Reddy {
117024fffdc8SGeorge Liu lg2::error("Failed to fetch state property, service: {SERVICE}, "
117124fffdc8SGeorge Liu "object path: {OBJECTPATH}, interface: {INTERFACE}, "
117224fffdc8SGeorge Liu "error: {ERROR}",
117324fffdc8SGeorge Liu "SERVICE", service, "OBJECTPATH", objPath, "INTERFACE",
117424fffdc8SGeorge Liu session::sessionIntf, "ERROR", ec.message());
1175f71444daSRajashekar Gade Reddy return ipmi::ccUnspecifiedError;
1176f71444daSRajashekar Gade Reddy }
1177f71444daSRajashekar Gade Reddy
1178e7e8b816SVernon Mauery sessionState = ipmi::mappedVariant<uint8_t>(
1179e7e8b816SVernon Mauery sessionProps, "State", static_cast<uint8_t>(session::State::inactive));
1180e7e8b816SVernon Mauery if (sessionState == static_cast<uint8_t>(session::State::active))
1181e7e8b816SVernon Mauery {
11821318a5edSPatrick Williams sessionHandle =
11831318a5edSPatrick Williams ipmi::mappedVariant<uint8_t>(sessionProps, "SessionHandle", 0);
11841318a5edSPatrick Williams std::get<0>(details) =
11851318a5edSPatrick Williams ipmi::mappedVariant<uint8_t>(sessionProps, "UserID", 0xff);
1186e7e8b816SVernon Mauery // std::get<1>(details) = 0; // (default constructed to 0)
1187e7e8b816SVernon Mauery std::get<2>(details) =
1188e7e8b816SVernon Mauery ipmi::mappedVariant<uint8_t>(sessionProps, "CurrentPrivilege", 0);
1189e7e8b816SVernon Mauery // std::get<3>(details) = 0; // (default constructed to 0)
11901318a5edSPatrick Williams std::get<4>(details) =
11911318a5edSPatrick Williams ipmi::mappedVariant<uint8_t>(sessionProps, "ChannelNum", 0xff);
1192e7e8b816SVernon Mauery constexpr uint4_t rmcpPlusProtocol = 1;
1193e7e8b816SVernon Mauery std::get<5>(details) = rmcpPlusProtocol;
11941318a5edSPatrick Williams std::get<6>(details) =
11951318a5edSPatrick Williams ipmi::mappedVariant<uint32_t>(sessionProps, "RemoteIPAddr", 0);
1196e7e8b816SVernon Mauery // std::get<7>(details) = {{0}}; // default constructed to all 0
11971318a5edSPatrick Williams std::get<8>(details) =
11981318a5edSPatrick Williams ipmi::mappedVariant<uint16_t>(sessionProps, "RemotePort", 0);
1199e7e8b816SVernon Mauery }
1200e7e8b816SVernon Mauery
1201f71444daSRajashekar Gade Reddy return ipmi::ccSuccess;
1202f71444daSRajashekar Gade Reddy }
1203f71444daSRajashekar Gade Reddy
1204e7e8b816SVernon Mauery ipmi::RspType<uint8_t, // session handle,
1205f71444daSRajashekar Gade Reddy uint8_t, // total session count
1206f71444daSRajashekar Gade Reddy uint8_t, // active session count
1207e7e8b816SVernon Mauery std::optional<SessionDetails>>
ipmiAppGetSessionInfo(ipmi::Context::ptr ctx,uint8_t sessionIndex,ipmi::message::Payload & payload)12084d22640aSRajashekar Gade Reddy ipmiAppGetSessionInfo(ipmi::Context::ptr ctx, uint8_t sessionIndex,
12094d22640aSRajashekar Gade Reddy ipmi::message::Payload& payload)
1210f71444daSRajashekar Gade Reddy {
1211f71444daSRajashekar Gade Reddy uint32_t reqSessionId = 0;
1212f71444daSRajashekar Gade Reddy uint8_t reqSessionHandle = session::defaultSessionHandle;
1213f71444daSRajashekar Gade Reddy // initializing state to 0xff as 0 represents state as inactive.
1214f71444daSRajashekar Gade Reddy uint8_t state = 0xFF;
1215f71444daSRajashekar Gade Reddy
1216f71444daSRajashekar Gade Reddy uint8_t completionCode = getSessionInfoRequestData(
12174d22640aSRajashekar Gade Reddy ctx, sessionIndex, payload, reqSessionId, reqSessionHandle);
1218f71444daSRajashekar Gade Reddy
1219f71444daSRajashekar Gade Reddy if (completionCode)
1220f71444daSRajashekar Gade Reddy {
1221f71444daSRajashekar Gade Reddy return ipmi::response(completionCode);
1222f71444daSRajashekar Gade Reddy }
1223e7e8b816SVernon Mauery ipmi::ObjectTree objectTree;
1224e7e8b816SVernon Mauery boost::system::error_code ec = ipmi::getAllDbusObjects(
1225e7e8b816SVernon Mauery ctx, session::sessionManagerRootPath, session::sessionIntf, objectTree);
1226e7e8b816SVernon Mauery if (ec)
1227f71444daSRajashekar Gade Reddy {
122824fffdc8SGeorge Liu lg2::error("Failed to fetch object from dbus, "
122924fffdc8SGeorge Liu "interface: {INTERFACE}, error: {ERROR}",
123024fffdc8SGeorge Liu "INTERFACE", session::sessionIntf, "ERROR", ec.message());
1231e7e8b816SVernon Mauery return ipmi::responseUnspecifiedError();
1232e7e8b816SVernon Mauery }
1233f71444daSRajashekar Gade Reddy
1234e7e8b816SVernon Mauery uint8_t totalSessionCount = getTotalSessionCount();
1235e7e8b816SVernon Mauery uint8_t activeSessionCount = 0;
1236e7e8b816SVernon Mauery uint8_t sessionHandle = session::defaultSessionHandle;
1237ca93bb10SJohnathan Mantey uint8_t activeSessionHandle = 0;
1238e7e8b816SVernon Mauery std::optional<SessionDetails> maybeDetails;
1239e7e8b816SVernon Mauery uint8_t index = 0;
1240f71444daSRajashekar Gade Reddy for (auto& objectTreeItr : objectTree)
1241f71444daSRajashekar Gade Reddy {
1242f71444daSRajashekar Gade Reddy uint32_t sessionId = 0;
1243f71444daSRajashekar Gade Reddy std::string objectPath = objectTreeItr.first;
1244f71444daSRajashekar Gade Reddy
1245f71444daSRajashekar Gade Reddy if (!parseCloseSessionInputPayload(objectPath, sessionId,
1246f71444daSRajashekar Gade Reddy sessionHandle))
1247f71444daSRajashekar Gade Reddy {
1248f71444daSRajashekar Gade Reddy continue;
1249f71444daSRajashekar Gade Reddy }
1250f71444daSRajashekar Gade Reddy index++;
1251f71444daSRajashekar Gade Reddy auto& serviceMap = objectTreeItr.second;
1252f71444daSRajashekar Gade Reddy auto itr = serviceMap.begin();
1253f71444daSRajashekar Gade Reddy
1254f71444daSRajashekar Gade Reddy if (serviceMap.size() != 1)
1255f71444daSRajashekar Gade Reddy {
1256f71444daSRajashekar Gade Reddy return ipmi::responseUnspecifiedError();
1257f71444daSRajashekar Gade Reddy }
1258f71444daSRajashekar Gade Reddy
1259f71444daSRajashekar Gade Reddy std::string service = itr->first;
1260f71444daSRajashekar Gade Reddy uint8_t sessionState = 0;
12611318a5edSPatrick Williams completionCode =
12621318a5edSPatrick Williams getSessionState(ctx, service, objectPath, sessionState);
1263f71444daSRajashekar Gade Reddy if (completionCode)
1264f71444daSRajashekar Gade Reddy {
1265f71444daSRajashekar Gade Reddy return ipmi::response(completionCode);
1266f71444daSRajashekar Gade Reddy }
1267f71444daSRajashekar Gade Reddy
1268f71444daSRajashekar Gade Reddy if (sessionState == static_cast<uint8_t>(session::State::active))
1269f71444daSRajashekar Gade Reddy {
1270e7e8b816SVernon Mauery activeSessionCount++;
1271f71444daSRajashekar Gade Reddy }
1272f71444daSRajashekar Gade Reddy
1273ca93bb10SJohnathan Mantey if (index == sessionIndex || reqSessionId == sessionId ||
1274ca93bb10SJohnathan Mantey reqSessionHandle == sessionHandle)
1275f71444daSRajashekar Gade Reddy {
1276e7e8b816SVernon Mauery SessionDetails details{};
1277e7e8b816SVernon Mauery completionCode = getSessionDetails(ctx, service, objectPath,
1278e7e8b816SVernon Mauery sessionHandle, state, details);
1279f71444daSRajashekar Gade Reddy
1280f71444daSRajashekar Gade Reddy if (completionCode)
1281f71444daSRajashekar Gade Reddy {
1282f71444daSRajashekar Gade Reddy return ipmi::response(completionCode);
1283f71444daSRajashekar Gade Reddy }
1284ca93bb10SJohnathan Mantey activeSessionHandle = sessionHandle;
1285e7e8b816SVernon Mauery maybeDetails = std::move(details);
1286ca93bb10SJohnathan Mantey }
1287f71444daSRajashekar Gade Reddy }
1288f71444daSRajashekar Gade Reddy
1289e7e8b816SVernon Mauery if (state == static_cast<uint8_t>(session::State::active) ||
1290e7e8b816SVernon Mauery state == static_cast<uint8_t>(session::State::tearDownInProgress))
1291f71444daSRajashekar Gade Reddy {
1292ca93bb10SJohnathan Mantey return ipmi::responseSuccess(activeSessionHandle, totalSessionCount,
1293e7e8b816SVernon Mauery activeSessionCount, maybeDetails);
1294f71444daSRajashekar Gade Reddy }
1295f71444daSRajashekar Gade Reddy
1296f71444daSRajashekar Gade Reddy return ipmi::responseInvalidFieldRequest();
1297f71444daSRajashekar Gade Reddy }
1298f71444daSRajashekar Gade Reddy
getSysFWVersion(ipmi::Context::ptr & ctx)1299a809fa55SThang Tran std::optional<std::string> getSysFWVersion(ipmi::Context::ptr& ctx)
1300a809fa55SThang Tran {
1301a809fa55SThang Tran /*
1302a809fa55SThang Tran * The System Firmware version is detected via following steps:
1303a809fa55SThang Tran * - Get all of object paths that include
1304a809fa55SThang Tran * "xyz.openbmc_project.Software.Version" interface.
1305a809fa55SThang Tran * - Get the Purpose property of above object paths.
1306a809fa55SThang Tran * - If the Purpose is Host then get the Version property.
1307a809fa55SThang Tran */
1308a809fa55SThang Tran ipmi::ObjectTree objectTree;
1309a809fa55SThang Tran boost::system::error_code ec =
1310a809fa55SThang Tran ipmi::getAllDbusObjects(ctx, softwareRoot, versionIntf, objectTree);
1311a809fa55SThang Tran if (ec.value())
1312a809fa55SThang Tran {
1313a809fa55SThang Tran return std::nullopt;
1314a809fa55SThang Tran }
1315a809fa55SThang Tran
1316a809fa55SThang Tran for (const auto& [objPath, serviceMap] : objectTree)
1317a809fa55SThang Tran {
1318a809fa55SThang Tran for (const auto& [service, intfs] : serviceMap)
1319a809fa55SThang Tran {
1320a809fa55SThang Tran ipmi::PropertyMap props;
1321a809fa55SThang Tran ec = ipmi::getAllDbusProperties(ctx, service, objPath, versionIntf,
1322a809fa55SThang Tran props);
1323a809fa55SThang Tran if (ec.value())
1324a809fa55SThang Tran {
1325a809fa55SThang Tran continue;
1326a809fa55SThang Tran }
1327a809fa55SThang Tran
1328a809fa55SThang Tran std::string purposeProp = std::string(
1329a809fa55SThang Tran ipmi::mappedVariant<std::string>(props, "Purpose", ""));
1330a809fa55SThang Tran
1331a809fa55SThang Tran if (!purposeProp.ends_with(versionPurposeHostEnd))
1332a809fa55SThang Tran {
1333a809fa55SThang Tran continue;
1334a809fa55SThang Tran }
1335a809fa55SThang Tran
1336a809fa55SThang Tran std::string sysFWVersion = std::string(
1337a809fa55SThang Tran ipmi::mappedVariant<std::string>(props, "Version", ""));
1338a809fa55SThang Tran
1339a809fa55SThang Tran if (sysFWVersion.empty())
1340a809fa55SThang Tran {
1341a809fa55SThang Tran return std::nullopt;
1342a809fa55SThang Tran }
1343a809fa55SThang Tran
1344a809fa55SThang Tran return sysFWVersion;
1345a809fa55SThang Tran }
1346a809fa55SThang Tran }
1347a809fa55SThang Tran
1348a809fa55SThang Tran return std::nullopt;
1349a809fa55SThang Tran }
1350a809fa55SThang Tran
1351f542e8b0SXo Wang static std::unique_ptr<SysInfoParamStore> sysInfoParamStore;
1352f542e8b0SXo Wang
sysInfoReadSystemName()135387651333SXo Wang static std::string sysInfoReadSystemName()
135487651333SXo Wang {
135587651333SXo Wang // Use the BMC hostname as the "System Name."
135687651333SXo Wang char hostname[HOST_NAME_MAX + 1] = {};
135787651333SXo Wang if (gethostname(hostname, HOST_NAME_MAX) != 0)
135887651333SXo Wang {
135987651333SXo Wang perror("System info parameter: system name");
136087651333SXo Wang }
136187651333SXo Wang return hostname;
136287651333SXo Wang }
136387651333SXo Wang
136498b43babSJia, chunhui static constexpr uint8_t paramRevision = 0x11;
136598b43babSJia, chunhui static constexpr size_t configParameterLength = 16;
1366f542e8b0SXo Wang
136798b43babSJia, chunhui static constexpr size_t smallChunkSize = 14;
136898b43babSJia, chunhui static constexpr size_t fullChunkSize = 16;
1369449f2166SJia, chunhui static constexpr uint8_t progressMask = 0x3;
137010752832Skrishnar4 static constexpr uint8_t maxValidEncodingData = 0x02;
137198b43babSJia, chunhui
137298b43babSJia, chunhui static constexpr uint8_t setComplete = 0x0;
137398b43babSJia, chunhui static constexpr uint8_t setInProgress = 0x1;
137498b43babSJia, chunhui static uint8_t transferStatus = setComplete;
137598b43babSJia, chunhui
1376449f2166SJia, chunhui static constexpr uint8_t configDataOverhead = 2;
1377449f2166SJia, chunhui
137898b43babSJia, chunhui namespace ipmi
1379f542e8b0SXo Wang {
138098b43babSJia, chunhui constexpr Cc ccParmNotSupported = 0x80;
1381449f2166SJia, chunhui constexpr Cc ccSetInProgressActive = 0x81;
138298b43babSJia, chunhui
responseParmNotSupported()138398b43babSJia, chunhui static inline auto responseParmNotSupported()
1384f542e8b0SXo Wang {
138598b43babSJia, chunhui return response(ccParmNotSupported);
1386f542e8b0SXo Wang }
responseSetInProgressActive()1387449f2166SJia, chunhui static inline auto responseSetInProgressActive()
1388449f2166SJia, chunhui {
1389449f2166SJia, chunhui return response(ccSetInProgressActive);
1390449f2166SJia, chunhui }
139198b43babSJia, chunhui } // namespace ipmi
139298b43babSJia, chunhui
1393449f2166SJia, chunhui ipmi::RspType<uint8_t, // Parameter revision
139498b43babSJia, chunhui std::optional<uint8_t>, // data1 / setSelector / ProgressStatus
1395449f2166SJia, chunhui std::optional<std::vector<uint8_t>>> // data2-17
ipmiAppGetSystemInfo(ipmi::Context::ptr ctx,uint7_t reserved,bool getRevision,uint8_t paramSelector,uint8_t setSelector,uint8_t BlockSelector)1396a809fa55SThang Tran ipmiAppGetSystemInfo(ipmi::Context::ptr ctx, uint7_t reserved,
1397a809fa55SThang Tran bool getRevision, uint8_t paramSelector,
1398a809fa55SThang Tran uint8_t setSelector, uint8_t BlockSelector)
1399f542e8b0SXo Wang {
1400a5ae7728SSnehalatha V if (reserved || (paramSelector >= invalidParamSelectorStart &&
1401a5ae7728SSnehalatha V paramSelector <= invalidParamSelectorEnd))
1402c2566a93Sjayaprakash Mutyala {
1403c2566a93Sjayaprakash Mutyala return ipmi::responseInvalidFieldRequest();
1404c2566a93Sjayaprakash Mutyala }
14053771f5f2SPavanKumarIntel if (paramSelector >= oemCmdStart)
1406a5ae7728SSnehalatha V {
1407a5ae7728SSnehalatha V return ipmi::responseParmNotSupported();
1408a5ae7728SSnehalatha V }
1409c2566a93Sjayaprakash Mutyala if (getRevision)
1410f542e8b0SXo Wang {
141198b43babSJia, chunhui return ipmi::responseSuccess(paramRevision, std::nullopt, std::nullopt);
1412f542e8b0SXo Wang }
1413f542e8b0SXo Wang
141498b43babSJia, chunhui if (paramSelector == 0)
1415f542e8b0SXo Wang {
141698b43babSJia, chunhui return ipmi::responseSuccess(paramRevision, transferStatus,
141798b43babSJia, chunhui std::nullopt);
1418f542e8b0SXo Wang }
1419f542e8b0SXo Wang
142098b43babSJia, chunhui if (BlockSelector != 0) // 00h if parameter does not require a block number
1421f542e8b0SXo Wang {
142298b43babSJia, chunhui return ipmi::responseParmNotSupported();
1423f542e8b0SXo Wang }
1424f542e8b0SXo Wang
1425f542e8b0SXo Wang if (sysInfoParamStore == nullptr)
1426f542e8b0SXo Wang {
1427f542e8b0SXo Wang sysInfoParamStore = std::make_unique<SysInfoParamStore>();
142887651333SXo Wang sysInfoParamStore->update(IPMI_SYSINFO_SYSTEM_NAME,
142987651333SXo Wang sysInfoReadSystemName);
1430f542e8b0SXo Wang }
1431f542e8b0SXo Wang
1432a809fa55SThang Tran if (paramSelector == IPMI_SYSINFO_SYSTEM_FW_VERSION)
1433a809fa55SThang Tran {
1434a809fa55SThang Tran auto fwVersion = getSysFWVersion(ctx);
1435a809fa55SThang Tran
1436a809fa55SThang Tran if (fwVersion == std::nullopt)
1437a809fa55SThang Tran {
1438a809fa55SThang Tran return ipmi::responseUnspecifiedError();
1439a809fa55SThang Tran }
1440a809fa55SThang Tran sysInfoParamStore->update(IPMI_SYSINFO_SYSTEM_FW_VERSION, *fwVersion);
1441a809fa55SThang Tran }
1442a809fa55SThang Tran
1443f542e8b0SXo Wang // Parameters other than Set In Progress are assumed to be strings.
144498b43babSJia, chunhui std::tuple<bool, std::string> ret =
144598b43babSJia, chunhui sysInfoParamStore->lookup(paramSelector);
144698b43babSJia, chunhui bool found = std::get<0>(ret);
1447f542e8b0SXo Wang if (!found)
1448f542e8b0SXo Wang {
1449a5ae7728SSnehalatha V return ipmi::responseSensorInvalid();
1450f542e8b0SXo Wang }
145198b43babSJia, chunhui std::string& paramString = std::get<1>(ret);
1452449f2166SJia, chunhui std::vector<uint8_t> configData;
145398b43babSJia, chunhui size_t count = 0;
145498b43babSJia, chunhui if (setSelector == 0)
145598b43babSJia, chunhui { // First chunk has only 14 bytes.
1456449f2166SJia, chunhui configData.emplace_back(0); // encoding
1457449f2166SJia, chunhui configData.emplace_back(paramString.length()); // string length
1458449f2166SJia, chunhui count = std::min(paramString.length(), smallChunkSize);
1459449f2166SJia, chunhui configData.resize(count + configDataOverhead);
146098b43babSJia, chunhui std::copy_n(paramString.begin(), count,
1461a5ae7728SSnehalatha V configData.begin() + configDataOverhead); // 14 bytes chunk
1462a5ae7728SSnehalatha V
1463a5ae7728SSnehalatha V // Append zero's to remaining bytes
1464a5ae7728SSnehalatha V if (configData.size() < configParameterLength)
1465a5ae7728SSnehalatha V {
1466a5ae7728SSnehalatha V std::fill_n(std::back_inserter(configData),
1467a5ae7728SSnehalatha V configParameterLength - configData.size(), 0x00);
1468a5ae7728SSnehalatha V }
146998b43babSJia, chunhui }
147098b43babSJia, chunhui else
1471f542e8b0SXo Wang {
1472449f2166SJia, chunhui size_t offset = (setSelector * fullChunkSize) - configDataOverhead;
147398b43babSJia, chunhui if (offset >= paramString.length())
147498b43babSJia, chunhui {
147598b43babSJia, chunhui return ipmi::responseParmOutOfRange();
1476f542e8b0SXo Wang }
1477449f2166SJia, chunhui count = std::min(paramString.length() - offset, fullChunkSize);
1478449f2166SJia, chunhui configData.resize(count);
147998b43babSJia, chunhui std::copy_n(paramString.begin() + offset, count,
148098b43babSJia, chunhui configData.begin()); // 16 bytes chunk
148198b43babSJia, chunhui }
148298b43babSJia, chunhui return ipmi::responseSuccess(paramRevision, setSelector, configData);
1483f542e8b0SXo Wang }
1484f542e8b0SXo Wang
ipmiAppSetSystemInfo(uint8_t paramSelector,uint8_t data1,std::vector<uint8_t> configData)1485449f2166SJia, chunhui ipmi::RspType<> ipmiAppSetSystemInfo(uint8_t paramSelector, uint8_t data1,
1486449f2166SJia, chunhui std::vector<uint8_t> configData)
1487449f2166SJia, chunhui {
14883c5e413bSjayaprakash Mutyala if (paramSelector >= invalidParamSelectorStart &&
14893c5e413bSjayaprakash Mutyala paramSelector <= invalidParamSelectorEnd)
14903c5e413bSjayaprakash Mutyala {
14913c5e413bSjayaprakash Mutyala return ipmi::responseInvalidFieldRequest();
14923c5e413bSjayaprakash Mutyala }
14933771f5f2SPavanKumarIntel if (paramSelector >= oemCmdStart)
14943c5e413bSjayaprakash Mutyala {
14953c5e413bSjayaprakash Mutyala return ipmi::responseParmNotSupported();
14963c5e413bSjayaprakash Mutyala }
14973c5e413bSjayaprakash Mutyala
1498449f2166SJia, chunhui if (paramSelector == 0)
1499449f2166SJia, chunhui {
1500449f2166SJia, chunhui // attempt to set the 'set in progress' value (in parameter #0)
1501449f2166SJia, chunhui // when not in the set complete state.
1502449f2166SJia, chunhui if ((transferStatus != setComplete) && (data1 == setInProgress))
1503449f2166SJia, chunhui {
1504449f2166SJia, chunhui return ipmi::responseSetInProgressActive();
1505449f2166SJia, chunhui }
1506449f2166SJia, chunhui // only following 2 states are supported
1507449f2166SJia, chunhui if (data1 > setInProgress)
1508449f2166SJia, chunhui {
150924fffdc8SGeorge Liu lg2::error("illegal SetInProgress status");
1510449f2166SJia, chunhui return ipmi::responseInvalidFieldRequest();
1511449f2166SJia, chunhui }
1512449f2166SJia, chunhui
1513449f2166SJia, chunhui transferStatus = data1 & progressMask;
1514449f2166SJia, chunhui return ipmi::responseSuccess();
1515449f2166SJia, chunhui }
1516449f2166SJia, chunhui
1517449f2166SJia, chunhui if (configData.size() > configParameterLength)
1518449f2166SJia, chunhui {
1519449f2166SJia, chunhui return ipmi::responseInvalidFieldRequest();
1520449f2166SJia, chunhui }
1521449f2166SJia, chunhui
15223c5e413bSjayaprakash Mutyala // Append zero's to remaining bytes
15233c5e413bSjayaprakash Mutyala if (configData.size() < configParameterLength)
15243c5e413bSjayaprakash Mutyala {
15253c5e413bSjayaprakash Mutyala fill_n(back_inserter(configData),
15263c5e413bSjayaprakash Mutyala (configParameterLength - configData.size()), 0x00);
15273c5e413bSjayaprakash Mutyala }
15283c5e413bSjayaprakash Mutyala
1529449f2166SJia, chunhui if (!sysInfoParamStore)
1530449f2166SJia, chunhui {
1531449f2166SJia, chunhui sysInfoParamStore = std::make_unique<SysInfoParamStore>();
1532449f2166SJia, chunhui sysInfoParamStore->update(IPMI_SYSINFO_SYSTEM_NAME,
1533449f2166SJia, chunhui sysInfoReadSystemName);
1534449f2166SJia, chunhui }
1535449f2166SJia, chunhui
1536449f2166SJia, chunhui // lookup
1537449f2166SJia, chunhui std::tuple<bool, std::string> ret =
1538449f2166SJia, chunhui sysInfoParamStore->lookup(paramSelector);
1539449f2166SJia, chunhui bool found = std::get<0>(ret);
1540449f2166SJia, chunhui std::string& paramString = std::get<1>(ret);
1541449f2166SJia, chunhui if (!found)
1542449f2166SJia, chunhui {
1543449f2166SJia, chunhui // parameter does not exist. Init new
1544449f2166SJia, chunhui paramString = "";
1545449f2166SJia, chunhui }
1546449f2166SJia, chunhui
1547449f2166SJia, chunhui uint8_t setSelector = data1;
1548449f2166SJia, chunhui size_t count = 0;
1549449f2166SJia, chunhui if (setSelector == 0) // First chunk has only 14 bytes.
1550449f2166SJia, chunhui {
155110752832Skrishnar4 uint8_t encoding = configData.at(0);
155210752832Skrishnar4 if (encoding > maxValidEncodingData)
155310752832Skrishnar4 {
155410752832Skrishnar4 return ipmi::responseInvalidFieldRequest();
155510752832Skrishnar4 }
155610752832Skrishnar4
1557449f2166SJia, chunhui size_t stringLen = configData.at(1); // string length
1558449f2166SJia, chunhui count = std::min(stringLen, smallChunkSize);
1559449f2166SJia, chunhui count = std::min(count, configData.size());
1560449f2166SJia, chunhui paramString.resize(stringLen); // reserve space
1561449f2166SJia, chunhui std::copy_n(configData.begin() + configDataOverhead, count,
1562449f2166SJia, chunhui paramString.begin());
1563449f2166SJia, chunhui }
1564449f2166SJia, chunhui else
1565449f2166SJia, chunhui {
1566449f2166SJia, chunhui size_t offset = (setSelector * fullChunkSize) - configDataOverhead;
1567449f2166SJia, chunhui if (offset >= paramString.length())
1568449f2166SJia, chunhui {
1569449f2166SJia, chunhui return ipmi::responseParmOutOfRange();
1570449f2166SJia, chunhui }
1571449f2166SJia, chunhui count = std::min(paramString.length() - offset, configData.size());
1572449f2166SJia, chunhui std::copy_n(configData.begin(), count, paramString.begin() + offset);
1573449f2166SJia, chunhui }
1574449f2166SJia, chunhui sysInfoParamStore->update(paramSelector, paramString);
1575449f2166SJia, chunhui return ipmi::responseSuccess();
1576449f2166SJia, chunhui }
1577449f2166SJia, chunhui
1578bd0503a7SYong Li #ifdef ENABLE_I2C_WHITELIST_CHECK
convertStringToData(const std::string & command)157984bf9be5SRichard Marian Thomaiyar inline std::vector<uint8_t> convertStringToData(const std::string& command)
158084bf9be5SRichard Marian Thomaiyar {
158184bf9be5SRichard Marian Thomaiyar std::istringstream iss(command);
158284bf9be5SRichard Marian Thomaiyar std::string token;
158384bf9be5SRichard Marian Thomaiyar std::vector<uint8_t> dataValue;
158484bf9be5SRichard Marian Thomaiyar while (std::getline(iss, token, ' '))
158584bf9be5SRichard Marian Thomaiyar {
158684bf9be5SRichard Marian Thomaiyar dataValue.emplace_back(
158784bf9be5SRichard Marian Thomaiyar static_cast<uint8_t>(std::stoul(token, nullptr, base_16)));
158884bf9be5SRichard Marian Thomaiyar }
158984bf9be5SRichard Marian Thomaiyar return dataValue;
159084bf9be5SRichard Marian Thomaiyar }
159184bf9be5SRichard Marian Thomaiyar
populateI2CControllerWRAllowlist()159268d9d405SMatt Simmering static bool populateI2CControllerWRAllowlist()
159384bf9be5SRichard Marian Thomaiyar {
159484bf9be5SRichard Marian Thomaiyar nlohmann::json data = nullptr;
159568d9d405SMatt Simmering std::ifstream jsonFile(i2cControllerWRAllowlistFile);
159684bf9be5SRichard Marian Thomaiyar
159784bf9be5SRichard Marian Thomaiyar if (!jsonFile.good())
159884bf9be5SRichard Marian Thomaiyar {
159924fffdc8SGeorge Liu lg2::warning("i2c allow list file not found! file name: {FILE_NAME}",
160024fffdc8SGeorge Liu "FILE_NAME", i2cControllerWRAllowlistFile);
160184bf9be5SRichard Marian Thomaiyar return false;
160284bf9be5SRichard Marian Thomaiyar }
160384bf9be5SRichard Marian Thomaiyar
160484bf9be5SRichard Marian Thomaiyar try
160584bf9be5SRichard Marian Thomaiyar {
160684bf9be5SRichard Marian Thomaiyar data = nlohmann::json::parse(jsonFile, nullptr, false);
160784bf9be5SRichard Marian Thomaiyar }
1608a2ad2da8SPatrick Williams catch (const nlohmann::json::parse_error& e)
160984bf9be5SRichard Marian Thomaiyar {
161024fffdc8SGeorge Liu lg2::error("Corrupted i2c allow list config file, "
161124fffdc8SGeorge Liu "file name: {FILE_NAME}, error: {ERROR}",
161224fffdc8SGeorge Liu "FILE_NAME", i2cControllerWRAllowlistFile, "ERROR", e);
161384bf9be5SRichard Marian Thomaiyar return false;
161484bf9be5SRichard Marian Thomaiyar }
161584bf9be5SRichard Marian Thomaiyar
161684bf9be5SRichard Marian Thomaiyar try
161784bf9be5SRichard Marian Thomaiyar {
161884bf9be5SRichard Marian Thomaiyar // Example JSON Structure format
161984bf9be5SRichard Marian Thomaiyar // "filters": [
162084bf9be5SRichard Marian Thomaiyar // {
162184bf9be5SRichard Marian Thomaiyar // "Description": "Allow full read - ignore first byte write value
162284bf9be5SRichard Marian Thomaiyar // for 0x40 to 0x4F",
162384bf9be5SRichard Marian Thomaiyar // "busId": "0x01",
162484bf9be5SRichard Marian Thomaiyar // "slaveAddr": "0x40",
162584bf9be5SRichard Marian Thomaiyar // "slaveAddrMask": "0x0F",
162684bf9be5SRichard Marian Thomaiyar // "command": "0x00",
162784bf9be5SRichard Marian Thomaiyar // "commandMask": "0xFF"
162884bf9be5SRichard Marian Thomaiyar // },
162984bf9be5SRichard Marian Thomaiyar // {
163084bf9be5SRichard Marian Thomaiyar // "Description": "Allow full read - first byte match 0x05 and
163184bf9be5SRichard Marian Thomaiyar // ignore second byte",
163284bf9be5SRichard Marian Thomaiyar // "busId": "0x01",
163384bf9be5SRichard Marian Thomaiyar // "slaveAddr": "0x57",
163484bf9be5SRichard Marian Thomaiyar // "slaveAddrMask": "0x00",
163584bf9be5SRichard Marian Thomaiyar // "command": "0x05 0x00",
163684bf9be5SRichard Marian Thomaiyar // "commandMask": "0x00 0xFF"
163784bf9be5SRichard Marian Thomaiyar // },]
163884bf9be5SRichard Marian Thomaiyar
163984bf9be5SRichard Marian Thomaiyar nlohmann::json filters = data[filtersStr].get<nlohmann::json>();
164068d9d405SMatt Simmering std::vector<i2cControllerWRAllowlist>& allowlist = getWRAllowlist();
164184bf9be5SRichard Marian Thomaiyar for (const auto& it : filters.items())
164284bf9be5SRichard Marian Thomaiyar {
164384bf9be5SRichard Marian Thomaiyar nlohmann::json filter = it.value();
164484bf9be5SRichard Marian Thomaiyar if (filter.is_null())
164584bf9be5SRichard Marian Thomaiyar {
164624fffdc8SGeorge Liu lg2::error(
164724fffdc8SGeorge Liu "Corrupted I2C controller write read allowlist config file, "
164824fffdc8SGeorge Liu "file name: {FILE_NAME}",
164924fffdc8SGeorge Liu "FILE_NAME", i2cControllerWRAllowlistFile);
165084bf9be5SRichard Marian Thomaiyar return false;
165184bf9be5SRichard Marian Thomaiyar }
165284bf9be5SRichard Marian Thomaiyar const std::vector<uint8_t>& writeData =
165384bf9be5SRichard Marian Thomaiyar convertStringToData(filter[cmdStr].get<std::string>());
165484bf9be5SRichard Marian Thomaiyar const std::vector<uint8_t>& writeDataMask =
165584bf9be5SRichard Marian Thomaiyar convertStringToData(filter[cmdMaskStr].get<std::string>());
165684bf9be5SRichard Marian Thomaiyar if (writeDataMask.size() != writeData.size())
165784bf9be5SRichard Marian Thomaiyar {
165824fffdc8SGeorge Liu lg2::error("I2C controller write read allowlist filter "
165984bf9be5SRichard Marian Thomaiyar "mismatch for command & mask size");
166084bf9be5SRichard Marian Thomaiyar return false;
166184bf9be5SRichard Marian Thomaiyar }
166268d9d405SMatt Simmering allowlist.push_back(
166384bf9be5SRichard Marian Thomaiyar {static_cast<uint8_t>(std::stoul(
166484bf9be5SRichard Marian Thomaiyar filter[busIdStr].get<std::string>(), nullptr, base_16)),
166584bf9be5SRichard Marian Thomaiyar static_cast<uint8_t>(
166668d9d405SMatt Simmering std::stoul(filter[targetAddrStr].get<std::string>(),
166784bf9be5SRichard Marian Thomaiyar nullptr, base_16)),
166884bf9be5SRichard Marian Thomaiyar static_cast<uint8_t>(
166968d9d405SMatt Simmering std::stoul(filter[targetAddrMaskStr].get<std::string>(),
167084bf9be5SRichard Marian Thomaiyar nullptr, base_16)),
167184bf9be5SRichard Marian Thomaiyar writeData, writeDataMask});
167284bf9be5SRichard Marian Thomaiyar }
167368d9d405SMatt Simmering if (allowlist.size() != filters.size())
167484bf9be5SRichard Marian Thomaiyar {
167524fffdc8SGeorge Liu lg2::error(
167668d9d405SMatt Simmering "I2C controller write read allowlist filter size mismatch");
167784bf9be5SRichard Marian Thomaiyar return false;
167884bf9be5SRichard Marian Thomaiyar }
167984bf9be5SRichard Marian Thomaiyar }
1680a2ad2da8SPatrick Williams catch (const std::exception& e)
168184bf9be5SRichard Marian Thomaiyar {
168224fffdc8SGeorge Liu lg2::error("I2C controller write read allowlist "
168324fffdc8SGeorge Liu "unexpected exception: {ERROR}",
168424fffdc8SGeorge Liu "ERROR", e);
168584bf9be5SRichard Marian Thomaiyar return false;
168684bf9be5SRichard Marian Thomaiyar }
168784bf9be5SRichard Marian Thomaiyar return true;
168884bf9be5SRichard Marian Thomaiyar }
168984bf9be5SRichard Marian Thomaiyar
isWriteDataAllowlisted(const std::vector<uint8_t> & data,const std::vector<uint8_t> & dataMask,const std::vector<uint8_t> & writeData)169068d9d405SMatt Simmering static inline bool isWriteDataAllowlisted(const std::vector<uint8_t>& data,
169184bf9be5SRichard Marian Thomaiyar const std::vector<uint8_t>& dataMask,
169284bf9be5SRichard Marian Thomaiyar const std::vector<uint8_t>& writeData)
169384bf9be5SRichard Marian Thomaiyar {
169484bf9be5SRichard Marian Thomaiyar std::vector<uint8_t> processedDataBuf(data.size());
169584bf9be5SRichard Marian Thomaiyar std::vector<uint8_t> processedReqBuf(dataMask.size());
169684bf9be5SRichard Marian Thomaiyar std::transform(writeData.begin(), writeData.end(), dataMask.begin(),
169784bf9be5SRichard Marian Thomaiyar processedReqBuf.begin(), std::bit_or<uint8_t>());
169884bf9be5SRichard Marian Thomaiyar std::transform(data.begin(), data.end(), dataMask.begin(),
169984bf9be5SRichard Marian Thomaiyar processedDataBuf.begin(), std::bit_or<uint8_t>());
170084bf9be5SRichard Marian Thomaiyar
170184bf9be5SRichard Marian Thomaiyar return (processedDataBuf == processedReqBuf);
170284bf9be5SRichard Marian Thomaiyar }
170384bf9be5SRichard Marian Thomaiyar
isCmdAllowlisted(uint8_t busId,uint8_t targetAddr,std::vector<uint8_t> & writeData)170468d9d405SMatt Simmering static bool isCmdAllowlisted(uint8_t busId, uint8_t targetAddr,
170584bf9be5SRichard Marian Thomaiyar std::vector<uint8_t>& writeData)
170684bf9be5SRichard Marian Thomaiyar {
170768d9d405SMatt Simmering std::vector<i2cControllerWRAllowlist>& allowList = getWRAllowlist();
170868d9d405SMatt Simmering for (const auto& wlEntry : allowList)
170984bf9be5SRichard Marian Thomaiyar {
171084bf9be5SRichard Marian Thomaiyar if ((busId == wlEntry.busId) &&
171168d9d405SMatt Simmering ((targetAddr | wlEntry.targetAddrMask) ==
171268d9d405SMatt Simmering (wlEntry.targetAddr | wlEntry.targetAddrMask)))
171384bf9be5SRichard Marian Thomaiyar {
171484bf9be5SRichard Marian Thomaiyar const std::vector<uint8_t>& dataMask = wlEntry.dataMask;
171584bf9be5SRichard Marian Thomaiyar // Skip as no-match, if requested write data is more than the
171684bf9be5SRichard Marian Thomaiyar // write data mask size
171784bf9be5SRichard Marian Thomaiyar if (writeData.size() > dataMask.size())
171884bf9be5SRichard Marian Thomaiyar {
171984bf9be5SRichard Marian Thomaiyar continue;
172084bf9be5SRichard Marian Thomaiyar }
172168d9d405SMatt Simmering if (isWriteDataAllowlisted(wlEntry.data, dataMask, writeData))
172284bf9be5SRichard Marian Thomaiyar {
172384bf9be5SRichard Marian Thomaiyar return true;
172484bf9be5SRichard Marian Thomaiyar }
172584bf9be5SRichard Marian Thomaiyar }
172684bf9be5SRichard Marian Thomaiyar }
172784bf9be5SRichard Marian Thomaiyar return false;
172884bf9be5SRichard Marian Thomaiyar }
1729bd0503a7SYong Li #else
populateI2CControllerWRAllowlist()173068d9d405SMatt Simmering static bool populateI2CControllerWRAllowlist()
1731bd0503a7SYong Li {
173224fffdc8SGeorge Liu lg2::info("I2C_WHITELIST_CHECK is disabled, do not populate allowlist");
1733bd0503a7SYong Li return true;
1734bd0503a7SYong Li }
1735bd0503a7SYong Li #endif // ENABLE_I2C_WHITELIST_CHECK
173684bf9be5SRichard Marian Thomaiyar
173768d9d405SMatt Simmering /** @brief implements controller write read IPMI command which can be used for
173884bf9be5SRichard Marian Thomaiyar * low-level I2C/SMBus write, read or write-read access
173984bf9be5SRichard Marian Thomaiyar * @param isPrivateBus -to indicate private bus usage
174084bf9be5SRichard Marian Thomaiyar * @param busId - bus id
174184bf9be5SRichard Marian Thomaiyar * @param channelNum - channel number
174284bf9be5SRichard Marian Thomaiyar * @param reserved - skip 1 bit
174368d9d405SMatt Simmering * @param targetAddr - target address
174484bf9be5SRichard Marian Thomaiyar * @param read count - number of bytes to be read
174584bf9be5SRichard Marian Thomaiyar * @param writeData - data to be written
174684bf9be5SRichard Marian Thomaiyar *
174784bf9be5SRichard Marian Thomaiyar * @returns IPMI completion code plus response data
174884bf9be5SRichard Marian Thomaiyar * - readData - i2c response data
174984bf9be5SRichard Marian Thomaiyar */
ipmiControllerWriteRead(bool isPrivateBus,uint3_t busId,uint4_t channelNum,bool reserved,uint7_t targetAddr,uint8_t readCount,std::vector<uint8_t> writeData)17501318a5edSPatrick Williams ipmi::RspType<std::vector<uint8_t>> ipmiControllerWriteRead(
17511318a5edSPatrick Williams [[maybe_unused]] bool isPrivateBus, uint3_t busId,
17521318a5edSPatrick Williams [[maybe_unused]] uint4_t channelNum, bool reserved, uint7_t targetAddr,
17531318a5edSPatrick Williams uint8_t readCount, std::vector<uint8_t> writeData)
175484bf9be5SRichard Marian Thomaiyar {
1755c2af98beSJayaprakash Mutyala if (reserved)
1756c2af98beSJayaprakash Mutyala {
1757c2af98beSJayaprakash Mutyala return ipmi::responseInvalidFieldRequest();
1758c2af98beSJayaprakash Mutyala }
175984bf9be5SRichard Marian Thomaiyar const size_t writeCount = writeData.size();
176084bf9be5SRichard Marian Thomaiyar if (!readCount && !writeCount)
176184bf9be5SRichard Marian Thomaiyar {
176224fffdc8SGeorge Liu lg2::error("Controller write read command: Read & write count are 0");
176384bf9be5SRichard Marian Thomaiyar return ipmi::responseInvalidFieldRequest();
176484bf9be5SRichard Marian Thomaiyar }
1765bd0503a7SYong Li #ifdef ENABLE_I2C_WHITELIST_CHECK
176668d9d405SMatt Simmering if (!isCmdAllowlisted(static_cast<uint8_t>(busId),
176768d9d405SMatt Simmering static_cast<uint8_t>(targetAddr), writeData))
176884bf9be5SRichard Marian Thomaiyar {
176924fffdc8SGeorge Liu lg2::error("Controller write read request blocked!, "
177024fffdc8SGeorge Liu "bus: {BUS}, addr: {ADDR}",
177124fffdc8SGeorge Liu "BUS", static_cast<uint8_t>(busId), "ADDR", lg2::hex,
177224fffdc8SGeorge Liu static_cast<uint8_t>(targetAddr));
177384bf9be5SRichard Marian Thomaiyar }
1774bd0503a7SYong Li #endif // ENABLE_I2C_WHITELIST_CHECK
177584bf9be5SRichard Marian Thomaiyar std::vector<uint8_t> readBuf(readCount);
17761318a5edSPatrick Williams std::string i2cBus =
17771318a5edSPatrick Williams "/dev/i2c-" + std::to_string(static_cast<uint8_t>(busId));
177884bf9be5SRichard Marian Thomaiyar
177968d9d405SMatt Simmering ipmi::Cc ret = ipmi::i2cWriteRead(i2cBus, static_cast<uint8_t>(targetAddr),
17807dc4ac02SYong Li writeData, readBuf);
17817dc4ac02SYong Li if (ret != ipmi::ccSuccess)
178284bf9be5SRichard Marian Thomaiyar {
17837dc4ac02SYong Li return ipmi::response(ret);
178484bf9be5SRichard Marian Thomaiyar }
178584bf9be5SRichard Marian Thomaiyar return ipmi::responseSuccess(readBuf);
178684bf9be5SRichard Marian Thomaiyar }
178784bf9be5SRichard Marian Thomaiyar
registerNetFnAppFunctions()17885087b075SGeorge Liu void registerNetFnAppFunctions()
178998a23840SMatthew Barth {
179086a5082fSVernon Mauery // <Get Device ID>
179186a5082fSVernon Mauery ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
179286a5082fSVernon Mauery ipmi::app::cmdGetDeviceId, ipmi::Privilege::User,
179386a5082fSVernon Mauery ipmiAppGetDeviceId);
179486a5082fSVernon Mauery
17950573237fSTom // <Get BT Interface Capabilities>
1796cc99ba43SVernon Mauery ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
1797cc99ba43SVernon Mauery ipmi::app::cmdGetBtIfaceCapabilities,
1798cc99ba43SVernon Mauery ipmi::Privilege::User, ipmiAppGetBtCapabilities);
179998a23840SMatthew Barth
18000573237fSTom // <Reset Watchdog Timer>
180111df4f69SVernon Mauery ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
180211df4f69SVernon Mauery ipmi::app::cmdResetWatchdogTimer,
180311df4f69SVernon Mauery ipmi::Privilege::Operator, ipmiAppResetWatchdogTimer);
180498a23840SMatthew Barth
1805f71444daSRajashekar Gade Reddy ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
18065a98ea63SAppaRao Puli ipmi::app::cmdGetSessionInfo, ipmi::Privilege::User,
18075a98ea63SAppaRao Puli ipmiAppGetSessionInfo);
1808f71444daSRajashekar Gade Reddy
18090573237fSTom // <Set Watchdog Timer>
1810cfae948bSDeepak Kumar Sahu ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
1811cfae948bSDeepak Kumar Sahu ipmi::app::cmdSetWatchdogTimer,
1812cfae948bSDeepak Kumar Sahu ipmi::Privilege::Operator, ipmiSetWatchdogTimer);
181398a23840SMatthew Barth
1814e7023926SRajashekar Gade Reddy ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
1815e7023926SRajashekar Gade Reddy ipmi::app::cmdCloseSession, ipmi::Privilege::Callback,
1816e7023926SRajashekar Gade Reddy ipmiAppCloseSession);
1817e7023926SRajashekar Gade Reddy
181873f44518SWilliam A. Kennington III // <Get Watchdog Timer>
1819cfae948bSDeepak Kumar Sahu ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
18205a98ea63SAppaRao Puli ipmi::app::cmdGetWatchdogTimer, ipmi::Privilege::User,
18215a98ea63SAppaRao Puli ipmiGetWatchdogTimer);
182273f44518SWilliam A. Kennington III
18230573237fSTom // <Get Self Test Results>
1824b84a5282SVernon Mauery ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
1825b84a5282SVernon Mauery ipmi::app::cmdGetSelfTestResults,
1826b84a5282SVernon Mauery ipmi::Privilege::User, ipmiAppGetSelfTestResults);
182741fa24a1SNan Li
18280573237fSTom // <Get Device GUID>
18291554132bSVernon Mauery ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
18301554132bSVernon Mauery ipmi::app::cmdGetDeviceGuid, ipmi::Privilege::User,
18311554132bSVernon Mauery ipmiAppGetDeviceGuid);
183298a23840SMatthew Barth
18330573237fSTom // <Set ACPI Power State>
1834520c1315SDeepak Kumar Sahu ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
1835520c1315SDeepak Kumar Sahu ipmi::app::cmdSetAcpiPowerState,
1836520c1315SDeepak Kumar Sahu ipmi::Privilege::Admin, ipmiSetAcpiPowerState);
183718d77263SYong Li // <Get ACPI Power State>
18384e6d2571SDeepak Kumar Sahu ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
18394e6d2571SDeepak Kumar Sahu ipmi::app::cmdGetAcpiPowerState,
18405a98ea63SAppaRao Puli ipmi::Privilege::User, ipmiGetAcpiPowerState);
184118d77263SYong Li
184284bf9be5SRichard Marian Thomaiyar // Note: For security reason, this command will be registered only when
184368d9d405SMatt Simmering // there are proper I2C Controller write read allowlist
184468d9d405SMatt Simmering if (populateI2CControllerWRAllowlist())
184584bf9be5SRichard Marian Thomaiyar {
184668d9d405SMatt Simmering // Note: For security reasons, registering controller write read as
184768d9d405SMatt Simmering // admin privilege command, even though IPMI 2.0 specification allows it
184868d9d405SMatt Simmering // as operator privilege.
184984bf9be5SRichard Marian Thomaiyar ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
185084bf9be5SRichard Marian Thomaiyar ipmi::app::cmdMasterWriteRead,
185168d9d405SMatt Simmering ipmi::Privilege::Admin, ipmiControllerWriteRead);
185284bf9be5SRichard Marian Thomaiyar }
185384bf9be5SRichard Marian Thomaiyar
18545e007a5dSMarri Devender Rao // <Get System GUID Command>
1855b90a5328SVernon Mauery ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
1856b90a5328SVernon Mauery ipmi::app::cmdGetSystemGuid, ipmi::Privilege::User,
1857b90a5328SVernon Mauery ipmiAppGetSystemGuid);
18587cbe2286STom Joseph
18597cbe2286STom Joseph // <Get Channel Cipher Suites Command>
18605c3b72c6SAyushi Smriti ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
18615c3b72c6SAyushi Smriti ipmi::app::cmdGetChannelCipherSuites,
186279b4eeaaSVernon Mauery ipmi::Privilege::None, getChannelCipherSuites);
1863d2a57decSVernon Mauery
1864f542e8b0SXo Wang // <Get System Info Command>
186598b43babSJia, chunhui ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
186698b43babSJia, chunhui ipmi::app::cmdGetSystemInfoParameters,
186798b43babSJia, chunhui ipmi::Privilege::User, ipmiAppGetSystemInfo);
1868449f2166SJia, chunhui // <Set System Info Command>
1869449f2166SJia, chunhui ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
1870449f2166SJia, chunhui ipmi::app::cmdSetSystemInfoParameters,
1871449f2166SJia, chunhui ipmi::Privilege::Admin, ipmiAppSetSystemInfo);
187298a23840SMatthew Barth return;
187398a23840SMatthew Barth }
1874