blob: aba8c56944ab91c379c05def42d708697ef9a309 [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
Jason M. Bills7e4ddca2025-02-26 09:41:15 -080060UBootEnvMgr::UBootEnvMgr(boost::asio::io_context& io_,
Richard Marian Thomaiyar7a362772019-06-16 19:11:35 +053061 sdbusplus::asio::object_server& srv_,
62 std::shared_ptr<sdbusplus::asio::connection>& conn_) :
Jason M. Bills7e4ddca2025-02-26 09:41:15 -080063 io(io_), server(srv_), conn(conn_)
Richard Marian Thomaiyar7a362772019-06-16 19:11:35 +053064{
65 iface = server.add_interface(uBootEnvMgrPath, uBootEnvMgrIface);
66 iface->register_method("ReadAll", [this]() { return readAllVariable(); });
67 iface->register_method("Read", [this](const std::string& key) {
68 std::unordered_map<std::string, std::string> env = readAllVariable();
69 auto it = env.find(key);
70 if (it != env.end())
71 {
72 return it->second;
73 }
74 return std::string{};
75 });
76
77 iface->register_method(
78 "Write", [this](const std::string& key, const std::string& value) {
Chris Sidesfb729092024-05-17 14:47:31 -050079 writeVariable(key, value);
80 });
Richard Marian Thomaiyar7a362772019-06-16 19:11:35 +053081 iface->initialize(true);
82}
83
84std::unordered_map<std::string, std::string> UBootEnvMgr::readAllVariable()
85{
86 std::unordered_map<std::string, std::string> env;
87 std::vector<std::string> output = executeCmd("/sbin/fw_printenv");
88 for (const auto& entry : output)
89 {
90 size_t pos = entry.find("=");
91 if (pos + 1 >= entry.size())
92 {
93 phosphor::logging::log<phosphor::logging::level::ERR>(
94 "Invalid U-Boot environment",
95 phosphor::logging::entry("ENTRY=%s", entry.c_str()));
96 continue;
97 }
98 // using string instead of string_view for null termination
99 std::string key = entry.substr(0, pos);
100 std::string value = entry.substr(pos + 1);
101 env.emplace(key, value);
102 }
103 return env;
104}
105
106void UBootEnvMgr::writeVariable(const std::string& key,
107 const std::string& value)
108{
109 executeCmd("/sbin/fw_setenv", key.c_str(), value.c_str());
110 return;
111}