blob: 024fabc58048bb089a64dc97162b0f368c2113f8 [file] [log] [blame]
Lei YUd19df252019-10-25 17:31:52 +08001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "config.h"
17
18#include "updater.hpp"
19
Lei YUcfc040c2019-10-29 17:10:26 +080020#include "types.hpp"
Lei YU9ab6d752019-10-28 17:03:20 +080021#include "utility.hpp"
22
23#include <fstream>
24#include <phosphor-logging/log.hpp>
25
26using namespace phosphor::logging;
27namespace util = phosphor::power::util;
28
Lei YUd19df252019-10-25 17:31:52 +080029namespace updater
30{
31
Lei YU9ab6d752019-10-28 17:03:20 +080032namespace internal
33{
34
35/* Get the device name from the device path */
36std::string getDeviceName(std::string devPath)
37{
38 if (devPath.back() == '/')
39 {
40 devPath.pop_back();
41 }
42 return fs::path(devPath).stem().string();
43}
44
45std::string getDevicePath(const std::string& psuInventoryPath)
46{
47 auto data = util::loadJSONFromFile(PSU_JSON_PATH);
48
49 if (data == nullptr)
50 {
51 return {};
52 }
53
54 auto devicePath = data["psuDevices"][psuInventoryPath];
55 if (devicePath.empty())
56 {
57 log<level::WARNING>("Unable to find psu devices or path");
58 }
59 return devicePath;
60}
61
62} // namespace internal
63
Lei YUd19df252019-10-25 17:31:52 +080064bool update(const std::string& psuInventoryPath, const std::string& imageDir)
65{
Lei YU9ab6d752019-10-28 17:03:20 +080066 auto devPath = internal::getDevicePath(psuInventoryPath);
67 if (devPath.empty())
68 {
69 return false;
70 }
71
72 // TODO: check if it is ready to update
73 // and return if not ready
74
75 Updater updater(psuInventoryPath, devPath, imageDir);
76 int ret = updater.doUpdate();
77 return ret == 0;
78}
79
80Updater::Updater(const std::string& psuInventoryPath,
81 const std::string& devPath, const std::string& imageDir) :
82 bus(sdbusplus::bus::new_default()),
83 psuInventoryPath(psuInventoryPath), devPath(devPath),
84 devName(internal::getDeviceName(devPath)), imageDir(imageDir)
85{
86 fs::path p = fs::path(devPath) / "driver";
87 try
88 {
89 driverPath =
90 fs::canonical(p); // Get the path that points to the driver dir
91 }
92 catch (const fs::filesystem_error& e)
93 {
94 log<level::ERR>("Failed to get canonical path",
95 entry("DEVPATH=%s", devPath.c_str()),
96 entry("ERROR=%s", e.what()));
97 throw;
98 }
99 bindUnbind(false);
100}
101
102Updater::~Updater()
103{
104 bindUnbind(true);
105}
106
107// During PSU update, it needs to access the PSU i2c device directly, so it
108// needs to unbind the driver during the update, and re-bind after it's done.
109// After unbind, the hwmon sysfs will be gone, and the psu-monitor will report
110// errors. So set the PSU inventory's Present property to false so that
111// psu-monitor will not report any errors.
112void Updater::bindUnbind(bool doBind)
113{
114 if (!doBind)
115 {
116 // Set non-present before unbind the driver
117 setPresent(doBind);
118 }
119 auto p = driverPath;
120 p /= doBind ? "bind" : "unbind";
121 std::ofstream out(p.string());
122 out << devName;
123
124 if (doBind)
125 {
126 // Set to present after bind the driver
127 setPresent(doBind);
128 }
129}
130
131void Updater::setPresent(bool present)
132{
133 try
134 {
135 auto service = util::getService(psuInventoryPath, INVENTORY_IFACE, bus);
136 util::setProperty(INVENTORY_IFACE, PRESENT_PROP, psuInventoryPath,
137 service, bus, present);
138 }
139 catch (const std::exception& e)
140 {
141 log<level::ERR>("Failed to set present property",
142 entry("PSU=%s", psuInventoryPath.c_str()),
143 entry("PRESENT=%d", present));
144 }
145}
146
147int Updater::doUpdate()
148{
Lei YUd19df252019-10-25 17:31:52 +0800149 // TODO
Lei YU9ab6d752019-10-28 17:03:20 +0800150 return 0;
Lei YUd19df252019-10-25 17:31:52 +0800151}
152
153} // namespace updater