blob: c5ea3ea4c2a38289bd415fcff024166d8eb876d1 [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>
Tom Joseph151d5332019-11-17 22:21:45 +05309
Riya Dixit49cfb132023-03-02 04:26:53 -060010PHOSPHOR_LOG2_USING;
11
Brad Bishop5079ac42021-08-19 18:35:06 -040012using namespace pldm::responder::dbus;
13
Tom Joseph151d5332019-11-17 22:21:45 +053014namespace pldm
15{
Tom Joseph151d5332019-11-17 22:21:45 +053016namespace responder
17{
Tom Joseph151d5332019-11-17 22:21:45 +053018namespace fru_parser
19{
Tom Joseph151d5332019-11-17 22:21:45 +053020using Json = nlohmann::json;
21using InternalFailure =
22 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
23
24const Json emptyJson{};
25const std::vector<Json> emptyJsonList{};
Tom Joseph151d5332019-11-17 22:21:45 +053026
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053027FruParser::FruParser(const std::string& dirPath,
28 const fs::path& fruMasterJsonPath)
Tom Joseph151d5332019-11-17 22:21:45 +053029{
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053030 if (fs::exists(fruMasterJsonPath))
31 {
32 setupDefaultDBusLookup(fruMasterJsonPath);
33 }
Deepak Kodihallida079602020-08-05 03:23:03 -050034 setupDefaultFruRecordMap();
35
Tom Joseph151d5332019-11-17 22:21:45 +053036 fs::path dir(dirPath);
Deepak Kodihallida079602020-08-05 03:23:03 -050037 if (fs::exists(dir) && !fs::is_empty(dir))
Tom Joseph151d5332019-11-17 22:21:45 +053038 {
Deepak Kodihallida079602020-08-05 03:23:03 -050039 setupFruRecordMap(dirPath);
Tom Joseph151d5332019-11-17 22:21:45 +053040 }
Tom Joseph151d5332019-11-17 22:21:45 +053041}
42
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053043void FruParser::setupDefaultDBusLookup(const fs::path& masterJsonPath)
John Wang55732c22020-05-14 10:33:00 +080044{
45 constexpr auto service = "xyz.openbmc_project.Inventory.Manager";
46 constexpr auto rootPath = "/xyz/openbmc_project/inventory";
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053047 std::ifstream jsonFile(masterJsonPath);
48 auto data = Json::parse(jsonFile, nullptr, false);
49 if (data.is_discarded())
50 {
Riya Dixit89644442024-03-31 05:39:59 -050051 error("Failed to parse FRU Dbus Lookup Map config file '{PATH}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050052 "PATH", masterJsonPath);
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053053 std::abort();
54 }
55 std::map<Interface, EntityType> defIntfToEntityType;
56 auto dbusMap = data.value("FruDBusLookupMap", emptyJson);
57 for (const auto& element : dbusMap.items())
58
59 {
60 try
61 {
62 defIntfToEntityType[static_cast<Interface>(element.key())] =
63 static_cast<EntityType>(element.value());
64 }
65 catch (const std::exception& e)
66 {
Riya Dixit89644442024-03-31 05:39:59 -050067 error("Failure in FRU dbus lookup map format, error - {ERROR}",
68 "ERROR", e);
Manojkiran Eda03b01ca2021-06-29 08:55:09 +053069 throw InternalFailure();
70 }
71 }
John Wang55732c22020-05-14 10:33:00 +080072
73 Interfaces interfaces{};
74 for (auto [intf, entityType] : defIntfToEntityType)
75 {
76 intfToEntityType[intf] = entityType;
77 interfaces.emplace(intf);
78 }
79
80 lookupInfo.emplace(service, rootPath, std::move(interfaces));
81}
82
John Wang55732c22020-05-14 10:33:00 +080083void FruParser::setupDefaultFruRecordMap()
84{
85 const FruRecordInfo generalRecordInfo = {
86 1, // generalRecordType
87 1, // encodingTypeASCII
88 {
89 // DSP0257 Table 5 General FRU Record Field Type Definitions
90 {"xyz.openbmc_project.Inventory.Decorator.Asset", "Model", "string",
91 2},
92 {"xyz.openbmc_project.Inventory.Decorator.Asset", "PartNumber",
93 "string", 3},
94 {"xyz.openbmc_project.Inventory.Decorator.Asset", "SerialNumber",
95 "string", 4},
96 {"xyz.openbmc_project.Inventory.Decorator.Asset", "Manufacturer",
97 "string", 5},
98 {"xyz.openbmc_project.Inventory.Item", "PrettyName", "string", 8},
99 {"xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
100 "string", 11},
101 {"xyz.openbmc_project.Inventory.Decorator.Revision", "Version",
102 "string", 10},
103 }};
104
105 for (auto [intf, entityType] : intfToEntityType)
106 {
107 recordMap[intf] = {generalRecordInfo};
108 }
109}
110
Tom Joseph151d5332019-11-17 22:21:45 +0530111void FruParser::setupFruRecordMap(const std::string& dirPath)
112{
113 for (auto& file : fs::directory_iterator(dirPath))
114 {
115 auto fileName = file.path().filename().string();
Tom Joseph151d5332019-11-17 22:21:45 +0530116 std::ifstream jsonFile(file.path());
117 auto data = Json::parse(jsonFile, nullptr, false);
118 if (data.is_discarded())
119 {
Riya Dixit89644442024-03-31 05:39:59 -0500120 error("Failed to parse FRU config file at '{PATH}'", "PATH",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500121 file.path());
Tom Joseph151d5332019-11-17 22:21:45 +0530122 throw InternalFailure();
123 }
124
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500125 try
Tom Joseph151d5332019-11-17 22:21:45 +0530126 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500127 auto record = data.value("record_details", emptyJson);
128 auto recordType =
129 static_cast<uint8_t>(record.value("fru_record_type", 0));
130 auto encType =
131 static_cast<uint8_t>(record.value("fru_encoding_type", 0));
132 auto dbusIntfName = record.value("dbus_interface_name", "");
133 auto entries = data.value("fru_fields", emptyJsonList);
134 std::vector<FieldInfo> fieldInfo;
135
136 for (const auto& entry : entries)
137 {
138 auto fieldType =
139 static_cast<uint8_t>(entry.value("fru_field_type", 0));
140 auto dbus = entry.value("dbus", emptyJson);
141 auto interface = dbus.value("interface", "");
142 auto property = dbus.value("property_name", "");
143 auto propType = dbus.value("property_type", "");
144 fieldInfo.emplace_back(
145 std::make_tuple(std::move(interface), std::move(property),
146 std::move(propType), std::move(fieldType)));
147 }
148
149 FruRecordInfo fruInfo;
Patrick Williams6da4f912023-05-10 07:50:53 -0500150 fruInfo = std::make_tuple(recordType, encType,
151 std::move(fieldInfo));
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500152
153 auto search = recordMap.find(dbusIntfName);
154
155 // PLDM FRU can have multiple records for the same FRU like General
156 // FRU record and multiple OEM FRU records. If the FRU item
157 // interface name is already in the map, that indicates a record
158 // info is already added for the FRU, so append the new record info
159 // to the same data.
160 if (search != recordMap.end())
161 {
162 search->second.emplace_back(std::move(fruInfo));
163 }
164 else
165 {
166 FruRecordInfos recordInfos{fruInfo};
167 recordMap.emplace(dbusIntfName, recordInfos);
168 }
Tom Joseph151d5332019-11-17 22:21:45 +0530169 }
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500170 catch (const std::exception&)
Tom Joseph151d5332019-11-17 22:21:45 +0530171 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500172 continue;
Tom Joseph151d5332019-11-17 22:21:45 +0530173 }
174 }
175}
176
177} // namespace fru_parser
178
179} // namespace responder
180
181} // namespace pldm