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::xyz::openbmc_project::Common::server::UUID::uuid( 65 stream.str()); 66 } 67 68 return sdbusplus::xyz::openbmc_project::Common::server::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 = 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 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 uint8_t biosVerByte = biosInfo->biosVersion; 132 std::string tempS = 133 positionToString(biosInfo->biosVersion, biosInfo->length, dataIn); 134 if (std::find_if(tempS.begin(), tempS.end(), 135 [](char ch) { return !isprint(ch); }) != tempS.end()) 136 { 137 std::ofstream smbiosFile(mdrType2File, std::ios_base::trunc); 138 if (!smbiosFile.good()) 139 { 140 phosphor::logging::log<phosphor::logging::level::ERR>( 141 "Open MDRV2 table file failure"); 142 return result; 143 } 144 smbiosFile.clear(); 145 smbiosFile.close(); 146 phosphor::logging::log<phosphor::logging::level::ERR>( 147 "Find non-print char, delete the broken MDRV2 table file!"); 148 return sdbusplus::xyz::openbmc_project::Inventory::Decorator:: 149 server::Revision::version(result); 150 } 151 result = tempS; 152 153 setProperty(bus, biosActiveObjPath, biosVersionIntf, biosVersionProp, 154 result); 155 } 156 lg2::info("VERSION INFO - BIOS - {VER}", "VER", result); 157 158 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server:: 159 Revision::version(result); 160 } 161 162 } // namespace smbios 163 } // namespace phosphor 164