#pragma once #include "lpcsnoop/snoop.hpp" #include #include #include #include #include #include #include #include #include #include #include const std::string ipmiSnoopObject = "/xyz/openbmc_project/state/boot/raw"; const int hostParseIdx = 3; const int maxPostcode = 255; const int maxPosition = 4; bool sevenSegmentLedEnabled = true; std::vector led_lines; using Selector = sdbusplus::xyz::openbmc_project::Chassis::Buttons::server::HostSelector; std::unique_ptr matchSignal; const std::string selectorService = "xyz.openbmc_project.Chassis.Buttons"; const std::string selectorObject = "/xyz/openbmc_project/Chassis/Buttons/HostSelector"; const std::string selectorIface = "xyz.openbmc_project.Chassis.Buttons.HostSelector"; const std::string rawObject = "/xyz/openbmc_project/state/boot"; const std::string rawIface = "xyz.openbmc_project.State.Boot.Raw"; const std::string rawService = "xyz.openbmc_project.State.Boot.Raw"; uint32_t getSelectorPosition(sdbusplus::bus_t& bus) { const std::string propertyName = "Position"; auto method = bus.new_method_call(selectorService.c_str(), selectorObject.c_str(), "org.freedesktop.DBus.Properties", "Get"); method.append(selectorIface.c_str(), propertyName); try { std::variant value{}; auto reply = bus.call(method); reply.read(value); return std::get(value); } catch (const sdbusplus::exception_t& ex) { std::cerr << "GetProperty call failed. " << ex.what() << std::endl; return 0; } } struct IpmiPostReporter : PostObject { IpmiPostReporter(sdbusplus::bus_t& bus, const char* objPath) : PostObject(bus, objPath), bus(bus), propertiesChangedSignalRaw( bus, sdbusplus::bus::match::rules::propertiesChanged(objPath, rawIface), [this, &bus](sdbusplus::message_t& msg) { using primarycode_t = uint64_t; using secondarycode_t = std::vector; using postcode_t = std::tuple; /* sevenSegmentLedEnabled flag is set when GPIO pins are not there 7 seg display for fewer platforms. So, the code for postcode dispay and Get Selector position can be skipped in those platforms. */ if (!sevenSegmentLedEnabled) { return; } std::string objectName; std::string InterfaceName; std::map> msgData; msg.read(InterfaceName, msgData); std::filesystem::path name(msg.get_path()); objectName = name.filename(); std::string hostNumStr = objectName.substr(hostParseIdx); size_t hostNum = std::stoi(hostNumStr); size_t position = getSelectorPosition(bus); if (position > maxPosition) { std::cerr << "Invalid position. Position should be 1 to 4 " "for all hosts " << std::endl; } // Check if it was the Value property that changed. auto valPropMap = msgData.find("Value"); if (valPropMap == msgData.end()) { std::cerr << "Value property is not found " << std::endl; return; } uint64_t postcode = std::get<0>(std::get(valPropMap->second)); if (postcode <= maxPostcode) { if (position == hostNum) { uint8_t postcode_8bit = static_cast(postcode & 0x0000FF); // write postcode into seven segment display if (postCodeDisplay(postcode_8bit) < 0) { fprintf(stderr, "Error in display the postcode\n"); } } else { fprintf(stderr, "Host Selector Position and host " "number is not matched..\n"); } } else { fprintf(stderr, "invalid postcode value \n"); } }) { } sdbusplus::bus_t& bus; sdbusplus::bus::match_t propertiesChangedSignalRaw; int postCodeDisplay(uint8_t); void getSelectorPositionSignal(sdbusplus::bus_t& bus); }; // Configure the seven segment display connected GPIOs direction int configGPIODirOutput() { std::string gpioStr; // Need to define gpio names LED_POST_CODE_0 to 8 in dts file std::string gpioName = "LED_POST_CODE_"; const int value = 0; for (int iteration = 0; iteration < 8; iteration++) { gpioStr = gpioName + std::to_string(iteration); gpiod::line gpioLine = gpiod::find_line(gpioStr); if (!gpioLine) { std::string errMsg = "Failed to find the " + gpioStr + " line"; std::cerr << errMsg.c_str() << std::endl; /* sevenSegmentLedEnabled flag is unset when GPIO pins are not there * 7 seg display for fewer platforms. */ sevenSegmentLedEnabled = false; return -1; } led_lines.push_back(gpioLine); // Request GPIO output to specified value try { gpioLine.request({__FUNCTION__, gpiod::line_request::DIRECTION_OUTPUT, gpiod::line_request::FLAG_ACTIVE_LOW}, value); } catch (std::exception&) { std::string errMsg = "Failed to request " + gpioStr + " output"; std::cerr << errMsg.c_str() << std::endl; return -1; } } return 0; } // Display the received postcode into seven segment display int IpmiPostReporter::postCodeDisplay(uint8_t status) { for (int iteration = 0; iteration < 8; iteration++) { // split byte to write into GPIOs int value = !((status >> iteration) & 0x01); led_lines[iteration].set_value(value); } return 0; }