firmware-update: fix for firmware update
updated firmware update module to support for KCS and USB
Tested:
Tested firmware update utility for USB and KCS
Signed-off-by: anil kumar appana <anil.kumarx.appana@intel.com>
Change-Id: I129cd8456eda369386ccdb13d5136708a50f87d1
diff --git a/src/firmware-update.cpp b/src/firmware-update.cpp
index 1095338..95d01f7 100644
--- a/src/firmware-update.cpp
+++ b/src/firmware-update.cpp
@@ -26,6 +26,8 @@
#include <sdbusplus/timer.hpp>
#include <sstream>
+static constexpr char *secondaryFitImageStartAddr = "22480000";
+static uint8_t getActiveBootImage(void);
static void register_netfn_firmware_functions() __attribute__((constructor));
// oem return code for firmware update control
@@ -81,24 +83,6 @@
FW_STATE_ERROR = 0x0f,
FW_STATE_AC_CYCLE_REQUIRED = 0x83,
};
- fw_update_status_cache() : _bus(getSdBus())
- {
- _match = std::make_shared<sdbusplus::bus::match::match>(
- *_bus,
- sdbusplus::bus::match::rules::propertiesChanged(
- FW_UPDATE_SERVER_PATH, FW_UPDATE_INTERFACE),
- [&](sdbusplus::message::message &msg) {
- if (DEBUG)
- std::cerr << "propertiesChanged lambda\n";
- std::map<std::string, ipmi::DbusVariant> props;
- std::vector<std::string> inval;
- std::string iface;
- msg.read(iface, props, inval);
- _parse_props(props);
- });
- _initial_fetch();
- }
-
uint8_t state()
{
if (DEBUG)
@@ -119,7 +103,6 @@
{
return _msg;
}
-#ifdef UPDATER_ENABLED
std::string get_software_obj_path()
{
return _software_obj_path;
@@ -148,10 +131,38 @@
{
std::cerr << "activation_timer_timout(): increase percentage...\n";
_percent = _percent + 5;
- std::cerr << "_percent = " << std::string((char *)&_percent) << "\n";
+ if (_percent >= 95)
+ {
+ /*changing the state to ready to update firmware utility */
+ _state = FW_STATE_READY;
+ }
+ std::cerr << " _percent = " << (int)_percent << "\n";
return _percent;
}
-#endif
+ /* API for changing state to ERROR */
+ void firmwareUpdateAbortState()
+ {
+ unlink(FIRMWARE_BUFFER_FILE);
+ // changing the state to error
+ _state = FW_STATE_ERROR;
+ }
+ void setDeferRestart(bool deferRestart)
+ {
+ _deferRestart = deferRestart;
+ }
+ void setInhibitDowngrade(bool inhibitDowngrade)
+ {
+ _inhibitDowngrade = inhibitDowngrade;
+ }
+ bool getDeferRestart()
+ {
+ return _deferRestart;
+ }
+ bool getInhibitDowngrade()
+ {
+ return _inhibitDowngrade;
+ }
+
protected:
void _parse_props(std::map<std::string, ipmi::DbusVariant> &properties)
{
@@ -218,36 +229,13 @@
if (DEBUG)
std::cerr << '\n';
}
- void _initial_fetch()
- {
-#ifndef UPDATER_ENABLED
- auto method = _bus->new_method_call(
- FW_UPDATE_SERVER_DBUS_NAME, FW_UPDATE_SERVER_PATH,
- "org.freedesktop.DBus.Properties", "GetAll");
- method.append(FW_UPDATE_INTERFACE);
- if (DEBUG)
- std::cerr << "fetch fw status via dbus...\n";
- try
- {
- auto reply = _bus->call(method);
-
- std::map<std::string, ipmi::DbusVariant> properties;
- reply.read(properties);
- _parse_props(properties);
- }
- catch (sdbusplus::exception::SdBusError &e)
- {
- std::cerr << "Failed in _initial_fetch(): SDBus Error: " << e.what()
- << "\n";
- return;
- }
-#endif
- }
std::shared_ptr<sdbusplus::asio::connection> _bus;
std::shared_ptr<sdbusplus::bus::match::match> _match;
uint8_t _state = 0;
uint8_t _percent = 0;
+ bool _deferRestart = false;
+ bool _inhibitDowngrade = false;
std::string _msg;
private:
@@ -378,15 +366,12 @@
rc = IPMI_CC_INVALID_FIELD_REQUEST;
break;
case fw_update_status_cache::FW_STATE_DOWNLOAD:
- unlink(FIRMWARE_BUFFER_FILE);
case fw_update_status_cache::FW_STATE_VERIFY:
break;
case fw_update_status_cache::FW_STATE_WRITE:
- rc = IPMI_CC_INVALID_FIELD_REQUEST;
break;
case fw_update_status_cache::FW_STATE_READY:
case fw_update_status_cache::FW_STATE_ERROR:
- unlink(FIRMWARE_BUFFER_FILE);
break;
case fw_update_status_cache::FW_STATE_AC_CYCLE_REQUIRED:
rc = IPMI_CC_INVALID_FIELD_REQUEST;
@@ -394,25 +379,7 @@
}
if (rc == IPMI_CC_OK)
{
- std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
- // attempt to reset the state machine -- this may fail
- auto method = bus->new_method_call(
- FW_UPDATE_SERVER_DBUS_NAME, FW_UPDATE_SERVER_PATH,
- "org.freedesktop.DBus.Properties", "Abort");
- try
- {
- auto reply = bus->call(method);
-
- ipmi::DbusVariant retval;
- reply.read(retval);
- if (std::get<int>(retval) != 0)
- rc = IPMI_CC_INVALID_FIELD_REQUEST;
- }
- catch (sdbusplus::exception::SdBusError &e)
- {
- std::cerr << "SDBus Error: " << e.what() << "\n";
- return IPMI_CC_UNSPECIFIED_ERROR;
- }
+ fw_update_status.firmwareUpdateAbortState();
}
return rc;
@@ -425,7 +392,6 @@
if (DEBUG)
std::cerr << "request start firmware update()\n";
-#ifdef UPDATER_ENABLED
// fwupdate URIs start with file:// or usb:// or tftp:// etc. By the time
// the code gets to this point, the file should be transferred start the
// request (creating a new file in /tmp/images causes the update manager to
@@ -435,59 +401,6 @@
std::filesystem::rename(
uri, "/tmp/images/" +
boost::uuids::to_string(boost::uuids::random_generator()()));
-#else
- std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
- auto method =
- bus->new_method_call(FW_UPDATE_SERVER_DBUS_NAME, FW_UPDATE_SERVER_PATH,
- FW_UPDATE_INTERFACE, "start");
- if (DEBUG)
- std::cerr << "fwupdate1.start: " << uri << '\n';
- method.append(uri);
- try
- {
- auto reply = bus->call(method);
-
- uint32_t retval;
- reply.read(retval);
- if (retval != 0)
- {
- if (DEBUG)
- std::cerr << "method returned non-zero: " << retval << "\n";
- return false;
- }
- return true;
- }
- catch (sdbusplus::exception::SdBusError &e)
- {
- std::cerr << "SDBus Error: " << e.what();
- return false;
- }
-#endif
- return true;
-}
-
-static bool request_abort_firmware_update()
-{
- std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
- auto method =
- bus->new_method_call(FW_UPDATE_SERVER_DBUS_NAME, FW_UPDATE_SERVER_PATH,
- FW_UPDATE_INTERFACE, "abort");
- try
- {
- auto reply = bus->call(method);
-
- unlink(FIRMWARE_BUFFER_FILE);
- uint32_t retval;
- reply.read(retval);
- if (retval != 0)
- return false;
- }
- catch (sdbusplus::exception::SdBusError &e)
- {
- std::cerr << "SDBus Error: " << e.what() << "\n";
- unlink(FIRMWARE_BUFFER_FILE);
- return false;
- }
return true;
}
@@ -578,32 +491,40 @@
std::shared_ptr<transfer_hash_check> xfer_hash_check;
-#ifdef UPDATER_ENABLED
static void activate_image(const char *obj_path)
{
- if (DEBUG)
+ // If flag is false means to reboot
+ if (fw_update_status.getDeferRestart() == false)
{
- std::cerr << "activateImage()...\n";
- std::cerr << "obj_path = " << obj_path << "\n";
- }
- std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
- auto method_call = bus->new_method_call(
- "xyz.openbmc_project.Software.BMC.Updater", obj_path,
- "org.freedesktop.DBus.Properties", "Set");
- method_call.append(
- "xyz.openbmc_project.Software.Activation", "RequestedActivation",
- std::variant<std::string>("xyz.openbmc_project.Software.Activation."
- "RequestedActivations.Active"));
- try
- {
- auto method_call_reply = bus->call(method_call);
+ if (DEBUG)
+ {
+ std::cerr << "activateImage()...\n";
+ std::cerr << "obj_path = " << obj_path << "\n";
+ }
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "activating Image: ",
+ phosphor::logging::entry("OBJPATH =%s", obj_path));
+ std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
+ bus->async_method_call(
+ [](const boost::system::error_code ec) {
+ if (ec)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "async_method_call error: activate_image failed");
+ return;
+ }
+ },
+ "xyz.openbmc_project.Software.BMC.Updater", obj_path,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Software.Activation", "RequestedActivation",
+ std::variant<std::string>("xyz.openbmc_project.Software.Activation."
+ "RequestedActivations.Active"));
}
- catch (sdbusplus::exception::SdBusError &e)
+ else
{
- std::cerr << "Failed in activate_image(): SDBus Error: " << e.what()
- << "\n";
- return;
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "Firmware image activation is deferred.");
}
}
@@ -693,7 +614,6 @@
"member='InterfacesAdded',path='/xyz/openbmc_project/software'",
callback);
}
-#endif
class MappedFile
{
@@ -979,13 +899,7 @@
rc = IPMI_CC_USB_ATTACH_FAIL;
}
}
- if (!request_abort_firmware_update())
- {
- if (DEBUG)
- std::cerr
- << "abort_start_firmware_update returns failure\n";
- rc = IPMI_CC_UNSPECIFIED_ERROR;
- }
+ fw_update_status.firmwareUpdateAbortState();
controls |= controls_transfer_aborted;
break;
case fw_update_control_request::CTRL_SET_FILENAME:
@@ -1311,50 +1225,9 @@
// 1 - primary, 2 - secondary
auto info = reinterpret_cast<struct fw_execution_context *>(response);
- std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
- auto method =
- bus->new_method_call(FW_UPDATE_SERVER_DBUS_NAME, FW_UPDATE_SERVER_PATH,
- "org.freedesktop.DBus.Properties", "GetAll");
- method.append(FW_UPDATE_SECURITY_INTERFACE);
- int active_img;
- bool safe_mode;
- std::string cert;
- try
- {
- auto reply = bus->call(method);
+ info->context = EXEC_CTX_FULL_LINUX;
- if (!reply.is_method_error())
- {
- std::vector<std::pair<std::string, ipmi::DbusVariant>> properties;
- reply.read(properties);
-
- for (const auto &t : properties)
- {
- auto key = t.first;
- auto value = t.second;
- if (key == "active_partition")
- {
- active_img = std::get<int>(value);
- }
- else if (key == "safe_mode")
- {
- safe_mode = std::get<bool>(value);
- }
- }
- }
- }
- catch (sdbusplus::exception::SdBusError &e)
- {
- std::cerr << "SDBus Error: " << e.what();
- return IPMI_CC_UNSPECIFIED_ERROR;
- }
-
- if (safe_mode)
- info->context = EXEC_CTX_SAFE_MODE_LINUX;
- else
- info->context = EXEC_CTX_FULL_LINUX;
-
- info->image_selection = active_img;
+ info->image_selection = getActiveBootImage();
// Status code.
ipmi_ret_t rc = IPMI_CC_OK;
@@ -1363,6 +1236,43 @@
return rc;
}
+uint8_t getActiveBootImage(void)
+{
+ // 0x01 - primaryImage
+ constexpr uint8_t primaryImage = 0x01;
+ // 0x02 - secondaryImage
+ constexpr uint8_t secondaryImage = 0x02;
+ uint8_t bootImage = primaryImage;
+
+ std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
+ auto method = bus->new_method_call(
+ "xyz.openbmc_project.U_Boot.Environment.Manager",
+ "/xyz/openbmc_project/u_boot/environment/mgr",
+ "xyz.openbmc_project.U_Boot.Environment.Manager", "Read");
+ method.append("bootcmd");
+ std::string value;
+ try
+ {
+ auto reply = bus->call(method);
+ reply.read(value);
+ }
+ catch (sdbusplus::exception::SdBusError &e)
+ {
+ std::cerr << "SDBus Error: " << e.what();
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+ /* cheking for secondary FitImage Address 22480000 */
+ if (value.find(secondaryFitImageStartAddr) != std::string::npos)
+ {
+ bootImage = secondaryImage;
+ }
+ else
+ {
+ bootImage = primaryImage;
+ }
+
+ return bootImage;
+}
/** @brief implements firmware get status command
* @parameter
* - none
@@ -1402,33 +1312,6 @@
uint8_t options;
} __attribute__((packed));
-bool fw_update_set_dbus_property(const std::string &path,
- const std::string &iface,
- const std::string &name,
- ipmi::DbusVariant value)
-{
- std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
- auto method =
- bus->new_method_call(FW_UPDATE_SERVER_DBUS_NAME, path.c_str(),
- "org.freedesktop.DBus.Properties", "Set");
- method.append(iface, name, value);
- try
- {
- auto reply = bus->call(method);
- auto err = reply.is_method_error();
- if (err)
- if (DEBUG)
- std::cerr << "failed to set prop " << path << '/' << iface
- << '.' << name << '\n';
- return err;
- }
- catch (sdbusplus::exception::SdBusError &e)
- {
- std::cerr << "SDBus Error: " << e.what();
- return false;
- }
-}
-
uint32_t fw_update_options = 0;
static ipmi_ret_t ipmi_firmware_update_options(
ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
@@ -1456,16 +1339,15 @@
if (fw_options->options & FW_UPDATE_OPTIONS_NO_DOWNREV)
{
fw_update_options |= FW_UPDATE_OPTIONS_NO_DOWNREV;
+ /*setting flag to flase for deferring downgrade support*/
+ fw_update_status.setInhibitDowngrade(true);
}
else
{
fw_update_options &= ~FW_UPDATE_OPTIONS_NO_DOWNREV;
- // send dbus
+ /*setting flag to true for downgrade support*/
+ fw_update_status.setInhibitDowngrade(false);
}
- const char *name = "inhibit_downgrade";
- fw_update_set_dbus_property(
- path, iface, name,
- (bool)(!!(fw_update_options & FW_UPDATE_OPTIONS_NO_DOWNREV)));
}
if ((fw_options->mask & FW_UPDATE_OPTIONS_DEFER_RESTART) &&
(fw_options->options & FW_UPDATE_OPTIONS_DEFER_RESTART) !=
@@ -1474,15 +1356,15 @@
if (fw_options->options & FW_UPDATE_OPTIONS_DEFER_RESTART)
{
fw_update_options |= FW_UPDATE_OPTIONS_DEFER_RESTART;
+ /* setting flag to true to stop image activation */
+ fw_update_status.setDeferRestart(true);
}
else
{
+ /* setting flag to false for image activation */
fw_update_options &= ~FW_UPDATE_OPTIONS_DEFER_RESTART;
+ fw_update_status.setDeferRestart(false);
}
- const char *name = "defer_restart";
- fw_update_set_dbus_property(
- path, iface, name,
- (bool)(!!(fw_update_options & FW_UPDATE_OPTIONS_DEFER_RESTART)));
}
if (fw_options->mask & FW_UPDATE_OPTIONS_SHA2_CHECK)
{