blob: af8e6df4be068fa4ebd44bf58f9c104b366c91ac [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
Jason M. Billsb2e3a752025-10-06 06:02:23 -070019#include <boost/process/v1/child.hpp>
20#include <boost/process/v1/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;
Jason M. Billsb2e3a752025-10-06 06:02:23 -070033 boost::process::v1::ipstream stdOutStream;
34 boost::process::v1::child execProg(
35 path, const_cast<char*>(tArgs)...,
36 boost::process::v1::std_out > stdOutStream);
Richard Marian Thomaiyar7a362772019-06-16 19:11:35 +053037 std::string stdOutLine;
38
39 while (stdOutStream && std::getline(stdOutStream, stdOutLine) &&
40 !stdOutLine.empty())
41 {
42 stdOutput.emplace_back(stdOutLine);
43 }
44
45 execProg.wait();
46
47 int retCode = execProg.exit_code();
48 if (retCode)
49 {
50 phosphor::logging::log<phosphor::logging::level::ERR>(
51 "Command execution failed",
52 phosphor::logging::entry("PATH=%d", path),
53 phosphor::logging::entry("RETURN_CODE:%d", retCode));
54 phosphor::logging::elog<
55 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
56 }
57
58 return stdOutput;
59}
60
Jason M. Bills7e4ddca2025-02-26 09:41:15 -080061UBootEnvMgr::UBootEnvMgr(boost::asio::io_context& io_,
Richard Marian Thomaiyar7a362772019-06-16 19:11:35 +053062 sdbusplus::asio::object_server& srv_,
63 std::shared_ptr<sdbusplus::asio::connection>& conn_) :
Jason M. Bills7e4ddca2025-02-26 09:41:15 -080064 io(io_), server(srv_), conn(conn_)
Richard Marian Thomaiyar7a362772019-06-16 19:11:35 +053065{
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) {
Jason M. Bills0e89e192025-04-23 07:55:14 -070080 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}