blob: 13f740e586dd127c249c4f78ca349c3317b5ae74 [file] [log] [blame]
Tom Joseph151d5332019-11-17 22:21:45 +05301#include "fru_parser.hpp"
2
George Liu6492f522020-06-16 10:34:05 +08003#include <nlohmann/json.hpp>
Riya Dixit49cfb132023-03-02 04:26:53 -06004#include <phosphor-logging/lg2.hpp>
George Liu6492f522020-06-16 10:34:05 +08005#include <xyz/openbmc_project/Common/error.hpp>
6
Tom Joseph151d5332019-11-17 22:21:45 +05307#include <filesystem>
8#include <fstream>
9#include <iostream>
Tom Joseph151d5332019-11-17 22:21:45 +053010
Riya Dixit49cfb132023-03-02 04:26:53 -060011PHOSPHOR_LOG2_USING;
12
Brad Bishop5079ac42021-08-19 18:35:06 -040013using namespace pldm::responder::dbus;
14
Tom Joseph151d5332019-11-17 22:21:45 +053015namespace pldm
16{
Tom Joseph151d5332019-11-17 22:21:45 +053017namespace responder
18{
Tom Joseph151d5332019-11-17 22:21:45 +053019namespace fru_parser
20{
Tom Joseph151d5332019-11-17 22:21:45 +053021using Json = nlohmann::json;
22using InternalFailure =
23 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
24
25const Json emptyJson{};
26const std::vector<Json> emptyJsonList{};
27const std::vector<std::string> emptyStringVec{};
28
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053029FruParser::FruParser(const std::string& dirPath,
30 const fs::path& fruMasterJsonPath)
Tom Joseph151d5332019-11-17 22:21:45 +053031{
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053032 if (fs::exists(fruMasterJsonPath))
33 {
34 setupDefaultDBusLookup(fruMasterJsonPath);
35 }
Deepak Kodihallida079602020-08-05 03:23:03 -050036 setupDefaultFruRecordMap();
37
Tom Joseph151d5332019-11-17 22:21:45 +053038 fs::path dir(dirPath);
Deepak Kodihallida079602020-08-05 03:23:03 -050039 if (fs::exists(dir) && !fs::is_empty(dir))
Tom Joseph151d5332019-11-17 22:21:45 +053040 {
Deepak Kodihallida079602020-08-05 03:23:03 -050041 setupFruRecordMap(dirPath);
Tom Joseph151d5332019-11-17 22:21:45 +053042 }
Tom Joseph151d5332019-11-17 22:21:45 +053043}
44
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053045void FruParser::setupDefaultDBusLookup(const fs::path& masterJsonPath)
John Wang55732c22020-05-14 10:33:00 +080046{
47 constexpr auto service = "xyz.openbmc_project.Inventory.Manager";
48 constexpr auto rootPath = "/xyz/openbmc_project/inventory";
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053049 std::ifstream jsonFile(masterJsonPath);
50 auto data = Json::parse(jsonFile, nullptr, false);
51 if (data.is_discarded())
52 {
Riya Dixit49cfb132023-03-02 04:26:53 -060053 error(
54 "Parsing FRU Dbus Lookup Map config file failed, FILE={JSON_PATH}",
55 "JSON_PATH", masterJsonPath.c_str());
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053056 std::abort();
57 }
58 std::map<Interface, EntityType> defIntfToEntityType;
59 auto dbusMap = data.value("FruDBusLookupMap", emptyJson);
60 for (const auto& element : dbusMap.items())
61
62 {
63 try
64 {
65 defIntfToEntityType[static_cast<Interface>(element.key())] =
66 static_cast<EntityType>(element.value());
67 }
68 catch (const std::exception& e)
69 {
Riya Dixit49cfb132023-03-02 04:26:53 -060070 error("FRU DBus lookup map format error");
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053071 throw InternalFailure();
72 }
73 }
John Wang55732c22020-05-14 10:33:00 +080074
75 Interfaces interfaces{};
76 for (auto [intf, entityType] : defIntfToEntityType)
77 {
78 intfToEntityType[intf] = entityType;
79 interfaces.emplace(intf);
80 }
81
82 lookupInfo.emplace(service, rootPath, std::move(interfaces));
83}
84
John Wang55732c22020-05-14 10:33:00 +080085void FruParser::setupDefaultFruRecordMap()
86{
87 const FruRecordInfo generalRecordInfo = {
88 1, // generalRecordType
89 1, // encodingTypeASCII
90 {
91 // DSP0257 Table 5 General FRU Record Field Type Definitions
92 {"xyz.openbmc_project.Inventory.Decorator.Asset", "Model", "string",
93 2},
94 {"xyz.openbmc_project.Inventory.Decorator.Asset", "PartNumber",
95 "string", 3},
96 {"xyz.openbmc_project.Inventory.Decorator.Asset", "SerialNumber",
97 "string", 4},
98 {"xyz.openbmc_project.Inventory.Decorator.Asset", "Manufacturer",
99 "string", 5},
100 {"xyz.openbmc_project.Inventory.Item", "PrettyName", "string", 8},
101 {"xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
102 "string", 11},
103 {"xyz.openbmc_project.Inventory.Decorator.Revision", "Version",
104 "string", 10},
105 }};
106
107 for (auto [intf, entityType] : intfToEntityType)
108 {
109 recordMap[intf] = {generalRecordInfo};
110 }
111}
112
Tom Joseph151d5332019-11-17 22:21:45 +0530113void FruParser::setupFruRecordMap(const std::string& dirPath)
114{
115 for (auto& file : fs::directory_iterator(dirPath))
116 {
117 auto fileName = file.path().filename().string();
Tom Joseph151d5332019-11-17 22:21:45 +0530118 std::ifstream jsonFile(file.path());
119 auto data = Json::parse(jsonFile, nullptr, false);
120 if (data.is_discarded())
121 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600122 error("Parsing FRU config file failed, FILE={FILE_PATH}",
123 "FILE_PATH", file.path().c_str());
Tom Joseph151d5332019-11-17 22:21:45 +0530124 throw InternalFailure();
125 }
126
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500127 try
Tom Joseph151d5332019-11-17 22:21:45 +0530128 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500129 auto record = data.value("record_details", emptyJson);
130 auto recordType =
131 static_cast<uint8_t>(record.value("fru_record_type", 0));
132 auto encType =
133 static_cast<uint8_t>(record.value("fru_encoding_type", 0));
134 auto dbusIntfName = record.value("dbus_interface_name", "");
135 auto entries = data.value("fru_fields", emptyJsonList);
136 std::vector<FieldInfo> fieldInfo;
137
138 for (const auto& entry : entries)
139 {
140 auto fieldType =
141 static_cast<uint8_t>(entry.value("fru_field_type", 0));
142 auto dbus = entry.value("dbus", emptyJson);
143 auto interface = dbus.value("interface", "");
144 auto property = dbus.value("property_name", "");
145 auto propType = dbus.value("property_type", "");
146 fieldInfo.emplace_back(
147 std::make_tuple(std::move(interface), std::move(property),
148 std::move(propType), std::move(fieldType)));
149 }
150
151 FruRecordInfo fruInfo;
152 fruInfo =
153 std::make_tuple(recordType, encType, std::move(fieldInfo));
154
155 auto search = recordMap.find(dbusIntfName);
156
157 // PLDM FRU can have multiple records for the same FRU like General
158 // FRU record and multiple OEM FRU records. If the FRU item
159 // interface name is already in the map, that indicates a record
160 // info is already added for the FRU, so append the new record info
161 // to the same data.
162 if (search != recordMap.end())
163 {
164 search->second.emplace_back(std::move(fruInfo));
165 }
166 else
167 {
168 FruRecordInfos recordInfos{fruInfo};
169 recordMap.emplace(dbusIntfName, recordInfos);
170 }
Tom Joseph151d5332019-11-17 22:21:45 +0530171 }
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500172 catch (const std::exception& e)
Tom Joseph151d5332019-11-17 22:21:45 +0530173 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500174 continue;
Tom Joseph151d5332019-11-17 22:21:45 +0530175 }
176 }
177}
178
179} // namespace fru_parser
180
181} // namespace responder
182
183} // namespace pldm