xref: /openbmc/smbios-mdr/src/system.cpp (revision c13c8754)
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 
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 
72 static std::string getService(sdbusplus::bus_t& bus,
73                               const std::string& objectPath,
74                               const std::string& interface)
75 {
76     auto method = bus.new_method_call("xyz.openbmc_project.ObjectMapper",
77                                       "/xyz/openbmc_project/object_mapper",
78                                       "xyz.openbmc_project.ObjectMapper",
79                                       "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 
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 
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 = positionToString(biosInfo->biosVersion,
132                                              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                 phosphor::logging::log<phosphor::logging::level::ERR>(
140                     "Open MDRV2 table file failure");
141                 return result;
142             }
143             smbiosFile.clear();
144             smbiosFile.close();
145             phosphor::logging::log<phosphor::logging::level::ERR>(
146                 "Find non-print char, delete the broken MDRV2 table file!");
147             return sdbusplus::server::xyz::openbmc_project::inventory::
148                 decorator::Revision::version(result);
149         }
150         result = tempS;
151 
152         setProperty(*bus, biosActiveObjPath, biosVersionIntf, biosVersionProp,
153                     result);
154     }
155     lg2::info("VERSION INFO - BIOS - {VER}", "VER", result);
156 
157     return sdbusplus::server::xyz::openbmc_project::inventory::decorator::
158         Revision::version(result);
159 }
160 
161 } // namespace smbios
162 } // namespace phosphor
163