1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "bios_setting.hpp"
16 
17 #include "commands.hpp"
18 #include "errors.hpp"
19 #include "handler.hpp"
20 
21 #include <ipmid/api-types.hpp>
22 #include <stdplus/fd/create.hpp>
23 #include <stdplus/fd/managed.hpp>
24 #include <stdplus/fd/ops.hpp>
25 #include <stdplus/print.hpp>
26 
27 #include <filesystem>
28 #include <fstream>
29 #include <span>
30 #include <vector>
31 
32 namespace google
33 {
34 namespace ipmi
35 {
36 
37 std::vector<uint8_t> readBiosSettingFromFile(const std::string& biosSettingPath)
38 {
39     std::vector<uint8_t> biosSettings;
40     try
41     {
42         stdplus::ManagedFd managedFd = stdplus::fd::open(
43             biosSettingPath,
44             stdplus::fd::OpenFlags(stdplus::fd::OpenAccess::ReadOnly));
45         biosSettings = stdplus::fd::readAll<std::vector<uint8_t>>(managedFd);
46     }
47     catch (const std::exception& e)
48     {
49         stdplus::print(stderr, "Read unsuccessful: {}\n", e.what());
50         return {};
51     }
52     return biosSettings;
53 }
54 
55 Resp readBiosSetting(std::span<const uint8_t>, HandlerInterface*,
56                      const std::string& biosSettingPath)
57 {
58     std::vector<uint8_t> biosSettings =
59         readBiosSettingFromFile(biosSettingPath);
60     size_t settingsLength = biosSettings.size();
61     if (settingsLength == 0)
62     {
63         return ::ipmi::responseRetBytesUnavailable();
64     }
65 
66     // Reply format is: Length of the payload (1 byte) + payload
67     std::vector<std::uint8_t> reply;
68     reply.reserve(1 + settingsLength);
69     reply.emplace_back(static_cast<uint8_t>(settingsLength));
70     reply.insert(reply.end(), biosSettings.begin(), biosSettings.end());
71 
72     return ::ipmi::responseSuccess(SysOEMCommands::SysReadBiosSetting, reply);
73 }
74 
75 } // namespace ipmi
76 } // namespace google
77