side-switch: check priority of running image
If the running image does not have the highest priority, then return a
side switch is needed
Tested:
- Running image has priority 0:
<6> Checking for side switch reboot
<6> Running firmware version path is /xyz/openbmc_project/software/74575136
<6> Running firmware version priority is 0
<6> Side switch not needed
- Running image has priority 1:
<6> Checking for side switch reboot
<6> Running firmware version path is /xyz/openbmc_project/software/74575136
<6> Running firmware version priority is 1
<6> Running image is at priority 1, execute side switch
- Running image has priority 1, alternate has priority 2
<6> Checking for side switch reboot
<6> Running firmware version path is /xyz/openbmc_project/software/ef4fd5ae
<6> Running firmware version priority is 1
<6> /xyz/openbmc_project/software/ef4fd5ae is the running image, skip
<6> Side switch not needed
- Running image is priority 3, alternate has priority 2
<6> Checking for side switch reboot
<6> Running firmware version path is /xyz/openbmc_project/software/ef4fd5ae
<6> Running firmware version priority is 3
<6> /xyz/openbmc_project/software/bf984b17 has a higher priority, 2, then running priority
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: Id05f7b7f624059f4e2d7181283577e0cbd10e88f
diff --git a/side-switch/meson.build b/side-switch/meson.build
index 9104a5f..64ac49e 100644
--- a/side-switch/meson.build
+++ b/side-switch/meson.build
@@ -1,10 +1,12 @@
source = [
'side_switch.cpp',
+ '../utils.cpp',
]
executable(
'phosphor-bmc-side-switch',
source,
+ include_directories: ['..'],
dependencies: [
phosphor_logging_dep,
],
diff --git a/side-switch/side_switch.cpp b/side-switch/side_switch.cpp
index 2de3933..fb558c4 100644
--- a/side-switch/side_switch.cpp
+++ b/side-switch/side_switch.cpp
@@ -1,12 +1,138 @@
#include "side_switch.hpp"
+#include "utils.hpp"
+
#include <phosphor-logging/lg2.hpp>
+#include <sdbusplus/bus.hpp>
+
+#include <exception>
+#include <string>
+#include <variant>
+#include <vector>
PHOSPHOR_LOG2_USING;
+bool sideSwitchNeeded()
+{
+ auto bus = sdbusplus::bus::new_default();
+ std::string fwRunningVersionPath;
+ uint8_t fwRunningPriority = 0;
+
+ // Get active image
+ try
+ {
+ std::vector<std::string> paths =
+ utils::getProperty<std::vector<std::string>>(
+ bus, "/xyz/openbmc_project/software/functional",
+ "xyz.openbmc_project.Association", "endpoints");
+ if (paths.size() != 1)
+ {
+ info("side-switch only supports BMC-purpose image systems");
+ return (false);
+ }
+ fwRunningVersionPath = paths[0];
+ info("Running firmware version path is {FW_PATH}", "FW_PATH",
+ fwRunningVersionPath);
+ }
+ catch (const std::exception& e)
+ {
+ error("failed to retrieve active firmware version: {ERROR}", "ERROR",
+ e);
+ return (false);
+ }
+
+ // Check if active image has highest priority (0)
+ try
+ {
+ fwRunningPriority = utils::getProperty<uint8_t>(
+ bus, fwRunningVersionPath.c_str(),
+ "xyz.openbmc_project.Software.RedundancyPriority", "Priority");
+ info("Running firmware version priority is {FW_PRIORITY}",
+ "FW_PRIORITY", fwRunningPriority);
+ }
+ catch (const std::exception& e)
+ {
+ error("failed to read priority from active image: {ERROR}", "ERROR", e);
+ return (false);
+ }
+
+ // If running at highest priority (0) then no side switch needed
+ if (fwRunningPriority == 0)
+ {
+ info("Running image is at priority 0, no side switch needed");
+ return (false);
+ }
+
+ // Need to check if any other BMC images on system have a higher priority
+ std::vector<std::string> allSoftwarePaths;
+ try
+ {
+ auto method = bus.new_method_call("xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper",
+ "GetSubTreePaths");
+ method.append("/xyz/openbmc_project/software");
+ method.append(0); // Depth 0 to search all
+ method.append(
+ std::vector<std::string>({"xyz.openbmc_project.Software.Version"}));
+ auto reply = bus.call(method);
+ reply.read(allSoftwarePaths);
+ if (allSoftwarePaths.size() <= 1)
+ {
+ info("only 1 image present in flash so no side switch needed");
+ return (false);
+ }
+ }
+ catch (const std::exception& e)
+ {
+ error("failed to retrieve all firmware versions: {ERROR}", "ERROR", e);
+ return (false);
+ }
+
+ // Cycle through all firmware images looking for a BMC version that
+ // has a higher priority then our running image
+ for (auto& fwPath : allSoftwarePaths)
+ {
+ if (fwPath == fwRunningVersionPath)
+ {
+ info("{FW_PATH} is the running image, skip", "FW_PATH", fwPath);
+ continue;
+ }
+ try
+ {
+ uint8_t thisPathPri = utils::getProperty<uint8_t>(
+ bus, fwPath.c_str(),
+ "xyz.openbmc_project.Software.RedundancyPriority", "Priority");
+
+ if (thisPathPri < fwRunningPriority)
+ {
+ info(
+ "{FW_PATH} has a higher priority, {FW_PRIORITY}, then running priority",
+ "FW_PATH", fwPath, "FW_PRIORITY", thisPathPri);
+ return (true);
+ }
+ }
+ catch (const std::exception& e)
+ {
+ // This could just be a host firmware image, just keep going
+ info("failed to read a BMC priority from {FW_PATH}: {ERROR}",
+ "FW_PATH", fwPath, "ERROR", e);
+ continue;
+ }
+ }
+
+ return (false);
+}
+
int main()
{
info("Checking for side switch reboot");
- // TODO - Future commits in series to fill in logic
+ if (!sideSwitchNeeded())
+ {
+ info("Side switch not needed");
+ return 0;
+ }
+
+ // TODO - Future commits in series to fill in rest of logic
}
diff --git a/side-switch/side_switch.hpp b/side-switch/side_switch.hpp
index 6f70f09..684cae9 100644
--- a/side-switch/side_switch.hpp
+++ b/side-switch/side_switch.hpp
@@ -1 +1,7 @@
#pragma once
+
+/** @brief Determine if a side switch is needed
+ *
+ * @return True if side switch needed, false otherwise
+ */
+bool sideSwitchNeeded();