1 #include "config.h"
2 
3 #include "item_updater_mmc.hpp"
4 
5 #include "activation_mmc.hpp"
6 #include "utils.hpp"
7 #include "version.hpp"
8 
9 #include <phosphor-logging/log.hpp>
10 
11 #include <filesystem>
12 #include <format>
13 #include <iostream>
14 #include <thread>
15 
16 namespace openpower
17 {
18 namespace software
19 {
20 namespace updater
21 {
22 
23 using ::phosphor::logging::level;
24 using ::phosphor::logging::log;
25 // These functions are just a stub (empty) because the current eMMC
26 // implementation uses the BMC updater (repo phosphor-bmc-code-mgmt) to write
27 // the new host FW to flash since it's delivered as a "System" image in the
28 // same BMC tarball as the BMC image.
29 
createActivationObject(const std::string & path,const std::string & versionId,const std::string & extVersion,sdbusplus::xyz::openbmc_project::Software::server::Activation::Activations activationStatus,AssociationList & assocs)30 std::unique_ptr<Activation> ItemUpdaterMMC::createActivationObject(
31     const std::string& path, const std::string& versionId,
32     const std::string& extVersion,
33     sdbusplus::xyz::openbmc_project::Software::server::Activation::Activations
34         activationStatus,
35     AssociationList& assocs)
36 {
37     return std::make_unique<ActivationMMC>(
38         bus, path, *this, versionId, extVersion, activationStatus, assocs);
39 }
40 
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)41 std::unique_ptr<Version> ItemUpdaterMMC::createVersionObject(
42     const std::string& objPath, const std::string& versionId,
43     const std::string& versionString,
44     sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose
45         versionPurpose,
46     const std::string& filePath)
47 {
48     auto version = std::make_unique<Version>(
49         bus, objPath, *this, versionId, versionString, versionPurpose, filePath,
50         std::bind(&ItemUpdaterMMC::erase, this, std::placeholders::_1));
51     version->deleteObject = std::make_unique<Delete>(bus, objPath, *version);
52     return version;
53 }
54 
validateImage(const std::string &)55 bool ItemUpdaterMMC::validateImage(const std::string&)
56 {
57     return true;
58 }
59 
processPNORImage()60 void ItemUpdaterMMC::processPNORImage() {}
61 
reset()62 void ItemUpdaterMMC::reset()
63 {
64     // Do not reset read-only files needed for reset or ext4 default files
65     const std::vector<std::string> exclusionList = {
66         "alternate",  "hostfw-a", "hostfw-b",
67         "lost+found", "nvram",    "running-ro"};
68     std::filesystem::path dirPath(std::string(MEDIA_DIR "hostfw/"));
69     // Delete all files in /media/hostfw/ except for those on exclusionList
70     for (const auto& p : std::filesystem::directory_iterator(dirPath))
71     {
72         if (std::find(exclusionList.begin(), exclusionList.end(),
73                       p.path().stem().string()) == exclusionList.end())
74         {
75             std::filesystem::remove_all(p);
76         }
77     }
78 
79     // Delete all BMC error logs to avoid discrepancies with the host error logs
80     utils::deleteAllErrorLogs(bus);
81 
82     // Set attribute to clear hypervisor NVRAM
83     utils::setClearNvram(bus);
84 
85     // reset the enabled property of dimms/cpu after factory reset
86     gardReset->reset();
87 
88     // Remove files related to the Hardware Management Console / BMC web app
89     utils::clearHMCManaged(bus);
90     std::filesystem::path consolePath("/var/lib/bmcweb/ibm-management-console");
91     if (std::filesystem::exists(consolePath))
92     {
93         std::filesystem::remove_all(consolePath);
94     }
95     std::filesystem::path bmcdataPath("/home/root/bmcweb_persistent_data.json");
96     if (std::filesystem::exists(bmcdataPath))
97     {
98         std::filesystem::remove(bmcdataPath);
99     }
100 
101     // Recreate default files.
102     // std::tuple<method, service_name>
103     const std::tuple<std::string, std::string> services[] = {
104         {"StartUnit", "obmc-flash-bios-init.service"},
105         {"StartUnit", "obmc-flash-bios-patch.service"},
106         {"StartUnit", "openpower-process-host-firmware.service"},
107         {"StartUnit", "openpower-update-bios-attr-table.service"},
108         {"RestartUnit", "org.open_power.HardwareIsolation.service"}};
109 
110     for (const auto& service : services)
111     {
112         auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
113                                           SYSTEMD_INTERFACE,
114                                           std::get<0>(service).c_str());
115         method.append(std::get<1>(service), "replace");
116         // Ignore errors if the service is not found - not all systems
117         // may have these services
118         try
119         {
120             bus.call_noreply(method);
121         }
122         catch (const std::exception& e)
123         {}
124     }
125 
126     // Wait a few seconds for the service files and reset operations to finish,
127     // otherwise the BMC may be rebooted and cause corruption.
128     constexpr auto resetWait = std::chrono::seconds(5);
129     std::this_thread::sleep_for(resetWait);
130 }
131 
isVersionFunctional(const std::string & versionId)132 bool ItemUpdaterMMC::isVersionFunctional(const std::string& versionId)
133 {
134     return versionId == functionalVersionId;
135 }
136 
freePriority(uint8_t,const std::string &)137 void ItemUpdaterMMC::freePriority(uint8_t, const std::string&) {}
138 
deleteAll()139 void ItemUpdaterMMC::deleteAll() {}
140 
freeSpace()141 bool ItemUpdaterMMC::freeSpace()
142 {
143     return true;
144 }
145 
updateFunctionalAssociation(const std::string &)146 void ItemUpdaterMMC::updateFunctionalAssociation(const std::string&) {}
enableInventoryItems()147 void GardResetMMC::enableInventoryItems()
148 {
149     (void)enableInventoryItemsHelper(
150         "xyz.openbmc_project.PLDM",
151         "xyz.openbmc_project.Inventory.Item.CpuCore",
152         "/xyz/openbmc_project/inventory/system/chassis/motherboard");
153 
154     (void)enableInventoryItemsHelper("xyz.openbmc_project.Inventory.Manager",
155                                      "xyz.openbmc_project.Inventory.Item.Dimm",
156                                      "/xyz/openbmc_project/inventory");
157 }
158 
enableInventoryItemsHelper(const std::string & service,const std::string & intf,const std::string & objPath)159 void GardResetMMC::enableInventoryItemsHelper(const std::string& service,
160                                               const std::string& intf,
161                                               const std::string& objPath)
162 {
163     const std::vector<std::string> intflist{intf};
164 
165     std::vector<std::string> objs;
166     try
167     {
168         auto mapperCall = bus.new_method_call(
169             "xyz.openbmc_project.ObjectMapper",
170             "/xyz/openbmc_project/object_mapper",
171             "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths");
172         mapperCall.append(objPath);
173         mapperCall.append(0);
174         mapperCall.append(intflist);
175 
176         auto response = bus.call(mapperCall);
177         response.read(objs);
178         for (auto& obj : objs)
179         {
180             auto method =
181                 bus.new_method_call(service.c_str(), obj.c_str(),
182                                     "org.freedesktop.DBus.Properties", "Set");
183             std::variant<bool> propertyVal{true};
184             method.append("xyz.openbmc_project.Object.Enable", "Enabled",
185                           propertyVal);
186             bus.call_noreply(method);
187         }
188     }
189     catch (const sdbusplus::exception_t& e)
190     {
191         log<level::ERR>(
192             std::format("Failed to enable specified inventory items ex({}) "
193                         "intf({}) objpath({})",
194                         e.what(), intf, objPath)
195                 .c_str());
196     }
197 }
198 
reset()199 void GardResetMMC::reset()
200 {
201     log<level::INFO>("GardResetMMC::reset");
202     (void)enableInventoryItems();
203 }
204 
205 } // namespace updater
206 } // namespace software
207 } // namespace openpower
208