blob: 0c47efae408337517e40f9fe86bda16b51630df7 [file] [log] [blame]
#include "config.h"
#include "item_updater_mmc.hpp"
#include "activation_mmc.hpp"
#include "utils.hpp"
#include "version.hpp"
#include <phosphor-logging/log.hpp>
#include <filesystem>
#include <format>
#include <iostream>
#include <thread>
namespace openpower
{
namespace software
{
namespace updater
{
using ::phosphor::logging::level;
using ::phosphor::logging::log;
// These functions are just a stub (empty) because the current eMMC
// implementation uses the BMC updater (repo phosphor-bmc-code-mgmt) to write
// the new host FW to flash since it's delivered as a "System" image in the
// same BMC tarball as the BMC image.
std::unique_ptr<Activation> ItemUpdaterMMC::createActivationObject(
const std::string& path, const std::string& versionId,
const std::string& extVersion,
sdbusplus::xyz::openbmc_project::Software::server::Activation::Activations
activationStatus,
AssociationList& assocs)
{
return std::make_unique<ActivationMMC>(
bus, path, *this, versionId, extVersion, activationStatus, assocs);
}
std::unique_ptr<Version> ItemUpdaterMMC::createVersionObject(
const std::string& objPath, const std::string& versionId,
const std::string& versionString,
sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose
versionPurpose,
const std::string& filePath)
{
auto version = std::make_unique<Version>(
bus, objPath, *this, versionId, versionString, versionPurpose, filePath,
std::bind(&ItemUpdaterMMC::erase, this, std::placeholders::_1));
version->deleteObject = std::make_unique<Delete>(bus, objPath, *version);
return version;
}
bool ItemUpdaterMMC::validateImage(const std::string&)
{
return true;
}
void ItemUpdaterMMC::processPNORImage() {}
void ItemUpdaterMMC::reset()
{
// Do not reset read-only files needed for reset or ext4 default files
const std::vector<std::string> exclusionList = {"alternate", "hostfw-a",
"hostfw-b", "lost+found",
"nvram", "running-ro"};
std::filesystem::path dirPath(std::string(MEDIA_DIR "hostfw/"));
// Delete all files in /media/hostfw/ except for those on exclusionList
for (const auto& p : std::filesystem::directory_iterator(dirPath))
{
if (std::find(exclusionList.begin(), exclusionList.end(),
p.path().stem().string()) == exclusionList.end())
{
std::filesystem::remove_all(p);
}
}
// Delete all BMC error logs to avoid discrepancies with the host error logs
utils::deleteAllErrorLogs(bus);
// Set attribute to clear hypervisor NVRAM
utils::setClearNvram(bus);
// reset the enabled property of dimms/cpu after factory reset
gardReset->reset();
// Remove files related to the Hardware Management Console / BMC web app
utils::clearHMCManaged(bus);
std::filesystem::path consolePath("/var/lib/bmcweb/ibm-management-console");
if (std::filesystem::exists(consolePath))
{
std::filesystem::remove_all(consolePath);
}
std::filesystem::path bmcdataPath("/home/root/bmcweb_persistent_data.json");
if (std::filesystem::exists(bmcdataPath))
{
std::filesystem::remove(bmcdataPath);
}
// Recreate default files.
// std::tuple<method, service_name>
const std::tuple<std::string, std::string> services[] = {
{"StartUnit", "obmc-flash-bios-init.service"},
{"StartUnit", "obmc-flash-bios-patch.service"},
{"StartUnit", "openpower-process-host-firmware.service"},
{"StartUnit", "openpower-update-bios-attr-table.service"},
{"RestartUnit", "org.open_power.HardwareIsolation.service"}};
for (const auto& service : services)
{
auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
SYSTEMD_INTERFACE,
std::get<0>(service).c_str());
method.append(std::get<1>(service), "replace");
// Ignore errors if the service is not found - not all systems
// may have these services
try
{
bus.call_noreply(method);
}
catch (const std::exception& e)
{}
}
// Wait a few seconds for the service files and reset operations to finish,
// otherwise the BMC may be rebooted and cause corruption.
constexpr auto resetWait = std::chrono::seconds(5);
std::this_thread::sleep_for(resetWait);
}
bool ItemUpdaterMMC::isVersionFunctional(const std::string& versionId)
{
return versionId == functionalVersionId;
}
void ItemUpdaterMMC::freePriority(uint8_t, const std::string&) {}
void ItemUpdaterMMC::deleteAll() {}
bool ItemUpdaterMMC::freeSpace()
{
return true;
}
void ItemUpdaterMMC::updateFunctionalAssociation(const std::string&) {}
void GardResetMMC::enableInventoryItems()
{
(void)enableInventoryItemsHelper(
"xyz.openbmc_project.PLDM",
"xyz.openbmc_project.Inventory.Item.CpuCore",
"/xyz/openbmc_project/inventory/system/chassis/motherboard");
(void)enableInventoryItemsHelper("xyz.openbmc_project.Inventory.Manager",
"xyz.openbmc_project.Inventory.Item.Dimm",
"/xyz/openbmc_project/inventory");
}
void GardResetMMC::enableInventoryItemsHelper(const std::string& service,
const std::string& intf,
const std::string& objPath)
{
const std::vector<std::string> intflist{intf};
std::vector<std::string> objs;
try
{
auto mapperCall = bus.new_method_call(
"xyz.openbmc_project.ObjectMapper",
"/xyz/openbmc_project/object_mapper",
"xyz.openbmc_project.ObjectMapper", "GetSubTreePaths");
mapperCall.append(objPath);
mapperCall.append(0);
mapperCall.append(intflist);
auto response = bus.call(mapperCall);
response.read(objs);
for (auto& obj : objs)
{
auto method = bus.new_method_call(service.c_str(), obj.c_str(),
"org.freedesktop.DBus.Properties",
"Set");
std::variant<bool> propertyVal{true};
method.append("xyz.openbmc_project.Object.Enable", "Enabled",
propertyVal);
bus.call_noreply(method);
}
}
catch (const sdbusplus::exception_t& e)
{
log<level::ERR>(
std::format("Failed to enable specified inventory items ex({}) "
"intf({}) objpath({})",
e.what(), intf, objPath)
.c_str());
}
}
void GardResetMMC::reset()
{
log<level::INFO>("GardResetMMC::reset");
(void)enableInventoryItems();
}
} // namespace updater
} // namespace software
} // namespace openpower