1 /*
2 // Copyright (c) 2018 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 "system.hpp"
18
19 #include "mdrv2.hpp"
20
21 #include <fstream>
22 #include <iomanip>
23 #include <iostream>
24 #include <sstream>
25
26 static constexpr const char* biosActiveObjPath =
27 "/xyz/openbmc_project/software/bios_active";
28 static constexpr const char* biosVersionIntf =
29 "xyz.openbmc_project.Software.Version";
30 static constexpr const char* biosVersionProp = "Version";
31
32 namespace phosphor
33 {
34 namespace smbios
35 {
36
uuid(std::string)37 std::string System::uuid(std::string /* value */)
38 {
39 uint8_t* dataIn = storage;
40 dataIn = getSMBIOSTypePtr(dataIn, systemType);
41 if (dataIn != nullptr)
42 {
43 auto systemInfo = reinterpret_cast<struct SystemInfo*>(dataIn);
44 std::stringstream stream;
45 stream << std::setfill('0') << std::hex;
46 stream << std::setw(8) << systemInfo->uuid.timeLow;
47 stream << "-";
48 stream << std::setw(4) << systemInfo->uuid.timeMid;
49 stream << "-";
50 stream << std::setw(4) << systemInfo->uuid.timeHiAndVer;
51 stream << "-";
52 stream << std::setw(2) << static_cast<int>(systemInfo->uuid.clockSeqHi);
53 stream << std::setw(2)
54 << static_cast<int>(systemInfo->uuid.clockSeqLow);
55 stream << "-";
56 static_assert(sizeof(systemInfo->uuid.node) == 6);
57 stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[0]);
58 stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[1]);
59 stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[2]);
60 stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[3]);
61 stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[4]);
62 stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[5]);
63
64 return sdbusplus::server::xyz::openbmc_project::common::UUID::uuid(
65 stream.str());
66 }
67
68 return sdbusplus::server::xyz::openbmc_project::common::UUID::uuid(
69 "00000000-0000-0000-0000-000000000000");
70 }
71
getService(sdbusplus::bus_t & bus,const std::string & objectPath,const std::string & interface)72 static std::string getService(sdbusplus::bus_t& bus,
73 const std::string& objectPath,
74 const std::string& interface)
75 {
76 auto method =
77 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
78 "/xyz/openbmc_project/object_mapper",
79 "xyz.openbmc_project.ObjectMapper", "GetObject");
80
81 method.append(objectPath);
82 method.append(std::vector<std::string>({interface}));
83
84 std::vector<std::pair<std::string, std::vector<std::string>>> response;
85
86 try
87 {
88 auto reply = bus.call(method);
89 reply.read(response);
90 }
91 catch (const sdbusplus::exception_t& e)
92 {
93 lg2::error("Error in mapper method call - {ERROR}, SERVICE - "
94 "{SERVICE}, PATH - {PATH}",
95 "ERROR", e.what(), "SERVICE", objectPath.c_str(), "PATH",
96 interface.c_str());
97
98 return std::string{};
99 }
100
101 return response[0].first;
102 }
103
setProperty(sdbusplus::bus_t & bus,const std::string & objectPath,const std::string & interface,const std::string & propertyName,const std::string & value)104 static void setProperty(sdbusplus::bus_t& bus, const std::string& objectPath,
105 const std::string& interface,
106 const std::string& propertyName,
107 const std::string& value)
108 {
109 auto service = getService(bus, objectPath, interface);
110 if (service.empty())
111 {
112 return;
113 }
114
115 auto method = bus.new_method_call(service.c_str(), objectPath.c_str(),
116 "org.freedesktop.DBus.Properties", "Set");
117 method.append(interface.c_str(), propertyName.c_str(),
118 std::variant<std::string>{value});
119
120 bus.call_noreply(method);
121 }
122
version(std::string)123 std::string System::version(std::string /* value */)
124 {
125 std::string result = "No BIOS Version";
126 uint8_t* dataIn = storage;
127 dataIn = getSMBIOSTypePtr(dataIn, biosType);
128 if (dataIn != nullptr)
129 {
130 auto biosInfo = reinterpret_cast<struct BIOSInfo*>(dataIn);
131 std::string tempS =
132 positionToString(biosInfo->biosVersion, biosInfo->length, dataIn);
133 if (std::find_if(tempS.begin(), tempS.end(),
134 [](char ch) { return !isprint(ch); }) != tempS.end())
135 {
136 std::ofstream smbiosFile(smbiosFilePath, std::ios_base::trunc);
137 if (!smbiosFile.good())
138 {
139 lg2::error("Open MDRV2 table file failure");
140 return result;
141 }
142 smbiosFile.clear();
143 smbiosFile.close();
144 lg2::error(
145 "Find non-print char, delete the broken MDRV2 table file!");
146 return sdbusplus::server::xyz::openbmc_project::inventory::
147 decorator::Revision::version(result);
148 }
149 result = tempS;
150
151 setProperty(*bus, biosActiveObjPath, biosVersionIntf, biosVersionProp,
152 result);
153 }
154 lg2::info("VERSION INFO - BIOS - {VER}", "VER", result);
155
156 return sdbusplus::server::xyz::openbmc_project::inventory::decorator::
157 Revision::version(result);
158 }
159
160 } // namespace smbios
161 } // namespace phosphor
162