blob: a59d61add30f78a47363c74ba7e844ddb4ccda9f [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>
4#include <xyz/openbmc_project/Common/error.hpp>
5
Tom Joseph151d5332019-11-17 22:21:45 +05306#include <filesystem>
7#include <fstream>
8#include <iostream>
Tom Joseph151d5332019-11-17 22:21:45 +05309
10namespace pldm
11{
12
13namespace responder
14{
15
16namespace fru_parser
17{
18
19using Json = nlohmann::json;
20using InternalFailure =
21 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
22
23const Json emptyJson{};
24const std::vector<Json> emptyJsonList{};
25const std::vector<std::string> emptyStringVec{};
26
Tom Joseph151d5332019-11-17 22:21:45 +053027FruParser::FruParser(const std::string& dirPath)
28{
Deepak Kodihallida079602020-08-05 03:23:03 -050029 setupDefaultDBusLookup();
30 setupDefaultFruRecordMap();
31
Tom Joseph151d5332019-11-17 22:21:45 +053032 fs::path dir(dirPath);
Deepak Kodihallida079602020-08-05 03:23:03 -050033 if (fs::exists(dir) && !fs::is_empty(dir))
Tom Joseph151d5332019-11-17 22:21:45 +053034 {
Deepak Kodihallida079602020-08-05 03:23:03 -050035 setupFruRecordMap(dirPath);
Tom Joseph151d5332019-11-17 22:21:45 +053036 }
Tom Joseph151d5332019-11-17 22:21:45 +053037}
38
John Wang55732c22020-05-14 10:33:00 +080039void FruParser::setupDefaultDBusLookup()
40{
41 constexpr auto service = "xyz.openbmc_project.Inventory.Manager";
42 constexpr auto rootPath = "/xyz/openbmc_project/inventory";
43
44 // DSP0249 1.0.0 Table 15 Entity ID Codes
45 const std::map<Interface, EntityType> defIntfToEntityType = {
46 {"xyz.openbmc_project.Inventory.Item.Chassis", 45},
47 {"xyz.openbmc_project.Inventory.Item.Board", 60},
Jayashankar Padatha137f902021-06-04 07:16:11 -050048 {"xyz.openbmc_project.Inventory.Item.PCIeDevice", 61},
John Wang55732c22020-05-14 10:33:00 +080049 {"xyz.openbmc_project.Inventory.Item.Board.Motherboard", 64},
Jayashankar Padatha137f902021-06-04 07:16:11 -050050 {"xyz.openbmc_project.Inventory.Item.Dimm", 66},
John Wang55732c22020-05-14 10:33:00 +080051 {"xyz.openbmc_project.Inventory.Item.Panel", 69},
Jayashankar Padatha137f902021-06-04 07:16:11 -050052 {"xyz.openbmc_project.Inventory.Item.DiskBackplane", 73},
53 {"xyz.openbmc_project.Inventory.Item.Fan", 93},
John Wang55732c22020-05-14 10:33:00 +080054 {"xyz.openbmc_project.Inventory.Item.PowerSupply", 120},
Jayashankar Padatha137f902021-06-04 07:16:11 -050055 {"xyz.openbmc_project.Inventory.Item.Battery", 121},
John Wang55732c22020-05-14 10:33:00 +080056 {"xyz.openbmc_project.Inventory.Item.Vrm", 123},
57 {"xyz.openbmc_project.Inventory.Item.Cpu", 135},
58 {"xyz.openbmc_project.Inventory.Item.Bmc", 137},
Jayashankar Padatha137f902021-06-04 07:16:11 -050059 {"xyz.openbmc_project.Inventory.Item.Connector", 185},
60 {"xyz.openbmc_project.Inventory.Item.PCIeSlot", 186},
Deepak Kodihallida079602020-08-05 03:23:03 -050061 {"xyz.openbmc_project.Inventory.Item.System", 11521},
Jayashankar Padatha137f902021-06-04 07:16:11 -050062 {"xyz.openbmc_project.Inventory.Item.Tpm", 24576},
John Wang55732c22020-05-14 10:33:00 +080063 };
64
65 Interfaces interfaces{};
66 for (auto [intf, entityType] : defIntfToEntityType)
67 {
68 intfToEntityType[intf] = entityType;
69 interfaces.emplace(intf);
70 }
71
72 lookupInfo.emplace(service, rootPath, std::move(interfaces));
73}
74
John Wang55732c22020-05-14 10:33:00 +080075void FruParser::setupDefaultFruRecordMap()
76{
77 const FruRecordInfo generalRecordInfo = {
78 1, // generalRecordType
79 1, // encodingTypeASCII
80 {
81 // DSP0257 Table 5 General FRU Record Field Type Definitions
82 {"xyz.openbmc_project.Inventory.Decorator.Asset", "Model", "string",
83 2},
84 {"xyz.openbmc_project.Inventory.Decorator.Asset", "PartNumber",
85 "string", 3},
86 {"xyz.openbmc_project.Inventory.Decorator.Asset", "SerialNumber",
87 "string", 4},
88 {"xyz.openbmc_project.Inventory.Decorator.Asset", "Manufacturer",
89 "string", 5},
90 {"xyz.openbmc_project.Inventory.Item", "PrettyName", "string", 8},
91 {"xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
92 "string", 11},
93 {"xyz.openbmc_project.Inventory.Decorator.Revision", "Version",
94 "string", 10},
95 }};
96
97 for (auto [intf, entityType] : intfToEntityType)
98 {
99 recordMap[intf] = {generalRecordInfo};
100 }
101}
102
Tom Joseph151d5332019-11-17 22:21:45 +0530103void FruParser::setupFruRecordMap(const std::string& dirPath)
104{
105 for (auto& file : fs::directory_iterator(dirPath))
106 {
107 auto fileName = file.path().filename().string();
Tom Joseph151d5332019-11-17 22:21:45 +0530108 std::ifstream jsonFile(file.path());
109 auto data = Json::parse(jsonFile, nullptr, false);
110 if (data.is_discarded())
111 {
112
Deepak Kodihallida079602020-08-05 03:23:03 -0500113 std::cerr << "Parsing FRU config file failed, FILE=" << file.path();
Tom Joseph151d5332019-11-17 22:21:45 +0530114 throw InternalFailure();
115 }
116
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500117 try
Tom Joseph151d5332019-11-17 22:21:45 +0530118 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500119 auto record = data.value("record_details", emptyJson);
120 auto recordType =
121 static_cast<uint8_t>(record.value("fru_record_type", 0));
122 auto encType =
123 static_cast<uint8_t>(record.value("fru_encoding_type", 0));
124 auto dbusIntfName = record.value("dbus_interface_name", "");
125 auto entries = data.value("fru_fields", emptyJsonList);
126 std::vector<FieldInfo> fieldInfo;
127
128 for (const auto& entry : entries)
129 {
130 auto fieldType =
131 static_cast<uint8_t>(entry.value("fru_field_type", 0));
132 auto dbus = entry.value("dbus", emptyJson);
133 auto interface = dbus.value("interface", "");
134 auto property = dbus.value("property_name", "");
135 auto propType = dbus.value("property_type", "");
136 fieldInfo.emplace_back(
137 std::make_tuple(std::move(interface), std::move(property),
138 std::move(propType), std::move(fieldType)));
139 }
140
141 FruRecordInfo fruInfo;
142 fruInfo =
143 std::make_tuple(recordType, encType, std::move(fieldInfo));
144
145 auto search = recordMap.find(dbusIntfName);
146
147 // PLDM FRU can have multiple records for the same FRU like General
148 // FRU record and multiple OEM FRU records. If the FRU item
149 // interface name is already in the map, that indicates a record
150 // info is already added for the FRU, so append the new record info
151 // to the same data.
152 if (search != recordMap.end())
153 {
154 search->second.emplace_back(std::move(fruInfo));
155 }
156 else
157 {
158 FruRecordInfos recordInfos{fruInfo};
159 recordMap.emplace(dbusIntfName, recordInfos);
160 }
Tom Joseph151d5332019-11-17 22:21:45 +0530161 }
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500162 catch (const std::exception& e)
Tom Joseph151d5332019-11-17 22:21:45 +0530163 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500164 continue;
Tom Joseph151d5332019-11-17 22:21:45 +0530165 }
166 }
167}
168
169} // namespace fru_parser
170
171} // namespace responder
172
173} // namespace pldm