blob: 70f1d9b0da302c56a3b2dcbfac49e7041ef2ee23 [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{};
Tom Joseph151d5332019-11-17 22:21:45 +053027
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053028FruParser::FruParser(const std::string& dirPath,
29 const fs::path& fruMasterJsonPath)
Tom Joseph151d5332019-11-17 22:21:45 +053030{
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053031 if (fs::exists(fruMasterJsonPath))
32 {
33 setupDefaultDBusLookup(fruMasterJsonPath);
34 }
Deepak Kodihallida079602020-08-05 03:23:03 -050035 setupDefaultFruRecordMap();
36
Tom Joseph151d5332019-11-17 22:21:45 +053037 fs::path dir(dirPath);
Deepak Kodihallida079602020-08-05 03:23:03 -050038 if (fs::exists(dir) && !fs::is_empty(dir))
Tom Joseph151d5332019-11-17 22:21:45 +053039 {
Deepak Kodihallida079602020-08-05 03:23:03 -050040 setupFruRecordMap(dirPath);
Tom Joseph151d5332019-11-17 22:21:45 +053041 }
Tom Joseph151d5332019-11-17 22:21:45 +053042}
43
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053044void FruParser::setupDefaultDBusLookup(const fs::path& masterJsonPath)
John Wang55732c22020-05-14 10:33:00 +080045{
46 constexpr auto service = "xyz.openbmc_project.Inventory.Manager";
47 constexpr auto rootPath = "/xyz/openbmc_project/inventory";
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053048 std::ifstream jsonFile(masterJsonPath);
49 auto data = Json::parse(jsonFile, nullptr, false);
50 if (data.is_discarded())
51 {
Riya Dixit49cfb132023-03-02 04:26:53 -060052 error(
53 "Parsing FRU Dbus Lookup Map config file failed, FILE={JSON_PATH}",
54 "JSON_PATH", masterJsonPath.c_str());
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053055 std::abort();
56 }
57 std::map<Interface, EntityType> defIntfToEntityType;
58 auto dbusMap = data.value("FruDBusLookupMap", emptyJson);
59 for (const auto& element : dbusMap.items())
60
61 {
62 try
63 {
64 defIntfToEntityType[static_cast<Interface>(element.key())] =
65 static_cast<EntityType>(element.value());
66 }
67 catch (const std::exception& e)
68 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -050069 error("FRU DBus lookup map format error: {ERROR}", "ERROR", e);
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053070 throw InternalFailure();
71 }
72 }
John Wang55732c22020-05-14 10:33:00 +080073
74 Interfaces interfaces{};
75 for (auto [intf, entityType] : defIntfToEntityType)
76 {
77 intfToEntityType[intf] = entityType;
78 interfaces.emplace(intf);
79 }
80
81 lookupInfo.emplace(service, rootPath, std::move(interfaces));
82}
83
John Wang55732c22020-05-14 10:33:00 +080084void FruParser::setupDefaultFruRecordMap()
85{
86 const FruRecordInfo generalRecordInfo = {
87 1, // generalRecordType
88 1, // encodingTypeASCII
89 {
90 // DSP0257 Table 5 General FRU Record Field Type Definitions
91 {"xyz.openbmc_project.Inventory.Decorator.Asset", "Model", "string",
92 2},
93 {"xyz.openbmc_project.Inventory.Decorator.Asset", "PartNumber",
94 "string", 3},
95 {"xyz.openbmc_project.Inventory.Decorator.Asset", "SerialNumber",
96 "string", 4},
97 {"xyz.openbmc_project.Inventory.Decorator.Asset", "Manufacturer",
98 "string", 5},
99 {"xyz.openbmc_project.Inventory.Item", "PrettyName", "string", 8},
100 {"xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
101 "string", 11},
102 {"xyz.openbmc_project.Inventory.Decorator.Revision", "Version",
103 "string", 10},
104 }};
105
106 for (auto [intf, entityType] : intfToEntityType)
107 {
108 recordMap[intf] = {generalRecordInfo};
109 }
110}
111
Tom Joseph151d5332019-11-17 22:21:45 +0530112void FruParser::setupFruRecordMap(const std::string& dirPath)
113{
114 for (auto& file : fs::directory_iterator(dirPath))
115 {
116 auto fileName = file.path().filename().string();
Tom Joseph151d5332019-11-17 22:21:45 +0530117 std::ifstream jsonFile(file.path());
118 auto data = Json::parse(jsonFile, nullptr, false);
119 if (data.is_discarded())
120 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600121 error("Parsing FRU config file failed, FILE={FILE_PATH}",
122 "FILE_PATH", file.path().c_str());
Tom Joseph151d5332019-11-17 22:21:45 +0530123 throw InternalFailure();
124 }
125
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500126 try
Tom Joseph151d5332019-11-17 22:21:45 +0530127 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500128 auto record = data.value("record_details", emptyJson);
129 auto recordType =
130 static_cast<uint8_t>(record.value("fru_record_type", 0));
131 auto encType =
132 static_cast<uint8_t>(record.value("fru_encoding_type", 0));
133 auto dbusIntfName = record.value("dbus_interface_name", "");
134 auto entries = data.value("fru_fields", emptyJsonList);
135 std::vector<FieldInfo> fieldInfo;
136
137 for (const auto& entry : entries)
138 {
139 auto fieldType =
140 static_cast<uint8_t>(entry.value("fru_field_type", 0));
141 auto dbus = entry.value("dbus", emptyJson);
142 auto interface = dbus.value("interface", "");
143 auto property = dbus.value("property_name", "");
144 auto propType = dbus.value("property_type", "");
145 fieldInfo.emplace_back(
146 std::make_tuple(std::move(interface), std::move(property),
147 std::move(propType), std::move(fieldType)));
148 }
149
150 FruRecordInfo fruInfo;
Patrick Williams6da4f912023-05-10 07:50:53 -0500151 fruInfo = std::make_tuple(recordType, encType,
152 std::move(fieldInfo));
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500153
154 auto search = recordMap.find(dbusIntfName);
155
156 // PLDM FRU can have multiple records for the same FRU like General
157 // FRU record and multiple OEM FRU records. If the FRU item
158 // interface name is already in the map, that indicates a record
159 // info is already added for the FRU, so append the new record info
160 // to the same data.
161 if (search != recordMap.end())
162 {
163 search->second.emplace_back(std::move(fruInfo));
164 }
165 else
166 {
167 FruRecordInfos recordInfos{fruInfo};
168 recordMap.emplace(dbusIntfName, recordInfos);
169 }
Tom Joseph151d5332019-11-17 22:21:45 +0530170 }
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500171 catch (const std::exception&)
Tom Joseph151d5332019-11-17 22:21:45 +0530172 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500173 continue;
Tom Joseph151d5332019-11-17 22:21:45 +0530174 }
175 }
176}
177
178} // namespace fru_parser
179
180} // namespace responder
181
182} // namespace pldm