blob: 882e26c88fbb61ca11bd23fc418781645f7ff355 [file] [log] [blame]
Richard Marian Thomaiyar7a362772019-06-16 19:11:35 +05301/*
2// Copyright (c) 2019 Intel 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
17#include "u-boot-env-mgr.hpp"
Chris Sidesfb729092024-05-17 14:47:31 -050018
Richard Marian Thomaiyar7a362772019-06-16 19:11:35 +053019#include <boost/process/child.hpp>
20#include <boost/process/io.hpp>
Chris Sidesfb729092024-05-17 14:47:31 -050021#include <phosphor-logging/elog-errors.hpp>
22#include <phosphor-logging/log.hpp>
Richard Marian Thomaiyar7a362772019-06-16 19:11:35 +053023#include <xyz/openbmc_project/Common/error.hpp>
24
Chris Sidesfb729092024-05-17 14:47:31 -050025#include <unordered_map>
26#include <vector>
27
Richard Marian Thomaiyar7a362772019-06-16 19:11:35 +053028template <typename... ArgTypes>
29static std::vector<std::string> executeCmd(const char* path,
30 ArgTypes&&... tArgs)
31{
32 std::vector<std::string> stdOutput;
33 boost::process::ipstream stdOutStream;
34 boost::process::child execProg(path, const_cast<char*>(tArgs)...,
35 boost::process::std_out > stdOutStream);
36 std::string stdOutLine;
37
38 while (stdOutStream && std::getline(stdOutStream, stdOutLine) &&
39 !stdOutLine.empty())
40 {
41 stdOutput.emplace_back(stdOutLine);
42 }
43
44 execProg.wait();
45
46 int retCode = execProg.exit_code();
47 if (retCode)
48 {
49 phosphor::logging::log<phosphor::logging::level::ERR>(
50 "Command execution failed",
51 phosphor::logging::entry("PATH=%d", path),
52 phosphor::logging::entry("RETURN_CODE:%d", retCode));
53 phosphor::logging::elog<
54 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
55 }
56
57 return stdOutput;
58}
59
60UBootEnvMgr::UBootEnvMgr(boost::asio::io_service& io_,
61 sdbusplus::asio::object_server& srv_,
62 std::shared_ptr<sdbusplus::asio::connection>& conn_) :
63 io(io_),
64 server(srv_), conn(conn_)
65{
66 iface = server.add_interface(uBootEnvMgrPath, uBootEnvMgrIface);
67 iface->register_method("ReadAll", [this]() { return readAllVariable(); });
68 iface->register_method("Read", [this](const std::string& key) {
69 std::unordered_map<std::string, std::string> env = readAllVariable();
70 auto it = env.find(key);
71 if (it != env.end())
72 {
73 return it->second;
74 }
75 return std::string{};
76 });
77
78 iface->register_method(
79 "Write", [this](const std::string& key, const std::string& value) {
Chris Sidesfb729092024-05-17 14:47:31 -050080 writeVariable(key, value);
81 });
Richard Marian Thomaiyar7a362772019-06-16 19:11:35 +053082 iface->initialize(true);
83}
84
85std::unordered_map<std::string, std::string> UBootEnvMgr::readAllVariable()
86{
87 std::unordered_map<std::string, std::string> env;
88 std::vector<std::string> output = executeCmd("/sbin/fw_printenv");
89 for (const auto& entry : output)
90 {
91 size_t pos = entry.find("=");
92 if (pos + 1 >= entry.size())
93 {
94 phosphor::logging::log<phosphor::logging::level::ERR>(
95 "Invalid U-Boot environment",
96 phosphor::logging::entry("ENTRY=%s", entry.c_str()));
97 continue;
98 }
99 // using string instead of string_view for null termination
100 std::string key = entry.substr(0, pos);
101 std::string value = entry.substr(pos + 1);
102 env.emplace(key, value);
103 }
104 return env;
105}
106
107void UBootEnvMgr::writeVariable(const std::string& key,
108 const std::string& value)
109{
110 executeCmd("/sbin/fw_setenv", key.c_str(), value.c_str());
111 return;
112}