blob: e2c2317e272759a5a8a42e317c224dc2c8d52b96 [file] [log] [blame]
Tom Joseph151d5332019-11-17 22:21:45 +05301#include "fru_parser.hpp"
2
3#include <filesystem>
4#include <fstream>
5#include <iostream>
6#include <nlohmann/json.hpp>
7#include <xyz/openbmc_project/Common/error.hpp>
8
9namespace pldm
10{
11
12namespace responder
13{
14
15namespace fru_parser
16{
17
18using Json = nlohmann::json;
19using InternalFailure =
20 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
21
22const Json emptyJson{};
23const std::vector<Json> emptyJsonList{};
24const std::vector<std::string> emptyStringVec{};
25
26constexpr auto fruMasterJson = "FRU_Master.json";
27
28FruParser::FruParser(const std::string& dirPath)
29{
30 fs::path dir(dirPath);
31 if (!fs::exists(dir) || fs::is_empty(dir))
32 {
33 std::cerr << "FRU config directory does not exist or empty, DIR="
Tom Josephf0076332020-02-06 10:18:50 +053034 << dirPath << "\n";
35 return;
Tom Joseph151d5332019-11-17 22:21:45 +053036 }
37
38 fs::path masterFilePath = dir / fruMasterJson;
39 if (!fs::exists(masterFilePath))
40 {
41 std::cerr << "FRU D-Bus lookup JSON does not exist, PATH="
Tom Josephf0076332020-02-06 10:18:50 +053042 << masterFilePath << "\n";
Tom Joseph151d5332019-11-17 22:21:45 +053043 throw InternalFailure();
44 }
45
46 setupDBusLookup(masterFilePath);
47 setupFruRecordMap(dirPath);
48}
49
50void FruParser::setupDBusLookup(const fs::path& filePath)
51{
52 std::ifstream jsonFile(filePath);
53
54 auto data = Json::parse(jsonFile, nullptr, false);
55 if (data.is_discarded())
56 {
57 std::cerr << "Parsing FRU master config file failed, FILE=" << filePath;
58 throw InternalFailure();
59 }
60
61 Service service = data.value("service", "");
62 RootPath rootPath = data.value("root_path", "");
Deepak Kodihalli3cd61812020-03-10 06:38:45 -050063 auto entities = data.value("entities", emptyJsonList);
64 Interfaces interfaces{};
65 EntityType entityType{};
66 for (auto& entity : entities)
67 {
68 auto intf = entity.value("interface", "");
69 intfToEntityType[intf] =
70 std::move(entity.value("entity_type", entityType));
71 interfaces.emplace(std::move(intf));
72 }
Tom Joseph151d5332019-11-17 22:21:45 +053073 lookupInfo.emplace(std::make_tuple(std::move(service), std::move(rootPath),
74 std::move(interfaces)));
75}
76
77void FruParser::setupFruRecordMap(const std::string& dirPath)
78{
79 for (auto& file : fs::directory_iterator(dirPath))
80 {
81 auto fileName = file.path().filename().string();
82 if (fruMasterJson == fileName)
83 {
84 continue;
85 }
86
87 std::ifstream jsonFile(file.path());
88 auto data = Json::parse(jsonFile, nullptr, false);
89 if (data.is_discarded())
90 {
91
92 std::cerr << "Parsing FRU master config file failed, FILE="
93 << file.path();
94 throw InternalFailure();
95 }
96
97 auto record = data.value("record_details", emptyJson);
98 auto recordType =
99 static_cast<uint8_t>(record.value("fru_record_type", 0));
100 auto encType =
101 static_cast<uint8_t>(record.value("fru_encoding_type", 0));
102 auto dbusIntfName = record.value("dbus_interface_name", "");
103 auto entries = data.value("fru_fields", emptyJsonList);
104 std::vector<FieldInfo> fieldInfo;
105
106 for (const auto& entry : entries)
107 {
108 auto fieldType =
109 static_cast<uint8_t>(entry.value("fru_field_type", 0));
110 auto dbus = entry.value("dbus", emptyJson);
111 auto interface = dbus.value("interface", "");
112 auto property = dbus.value("property_name", "");
113 auto propType = dbus.value("property_type", "");
114 fieldInfo.emplace_back(
115 std::make_tuple(std::move(interface), std::move(property),
116 std::move(propType), std::move(fieldType)));
117 }
118
119 FruRecordInfo fruInfo;
120 fruInfo = std::make_tuple(recordType, encType, std::move(fieldInfo));
121
122 auto search = recordMap.find(dbusIntfName);
123
124 // PLDM FRU can have multiple records for the same FRU like General FRU
125 // record and multiple OEM FRU records. If the FRU item interface name
126 // is already in the map, that indicates a record info is already added
127 // for the FRU, so append the new record info to the same data.
128 if (search != recordMap.end())
129 {
130 search->second.emplace_back(std::move(fruInfo));
131 }
132 else
133 {
134 FruRecordInfos recordInfos{fruInfo};
135 recordMap.emplace(dbusIntfName, recordInfos);
136 }
137 }
138}
139
140} // namespace fru_parser
141
142} // namespace responder
143
144} // namespace pldm