blob: a2e2e927b6d93bb0c11cf40e9ffebc361a375ac8 [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
Pavithra Barithayae8beb892020-04-14 23:24:25 -050097 try
Tom Joseph151d5332019-11-17 22:21:45 +053098 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -050099 auto record = data.value("record_details", emptyJson);
100 auto recordType =
101 static_cast<uint8_t>(record.value("fru_record_type", 0));
102 auto encType =
103 static_cast<uint8_t>(record.value("fru_encoding_type", 0));
104 auto dbusIntfName = record.value("dbus_interface_name", "");
105 auto entries = data.value("fru_fields", emptyJsonList);
106 std::vector<FieldInfo> fieldInfo;
107
108 for (const auto& entry : entries)
109 {
110 auto fieldType =
111 static_cast<uint8_t>(entry.value("fru_field_type", 0));
112 auto dbus = entry.value("dbus", emptyJson);
113 auto interface = dbus.value("interface", "");
114 auto property = dbus.value("property_name", "");
115 auto propType = dbus.value("property_type", "");
116 fieldInfo.emplace_back(
117 std::make_tuple(std::move(interface), std::move(property),
118 std::move(propType), std::move(fieldType)));
119 }
120
121 FruRecordInfo fruInfo;
122 fruInfo =
123 std::make_tuple(recordType, encType, std::move(fieldInfo));
124
125 auto search = recordMap.find(dbusIntfName);
126
127 // PLDM FRU can have multiple records for the same FRU like General
128 // FRU record and multiple OEM FRU records. If the FRU item
129 // interface name is already in the map, that indicates a record
130 // info is already added for the FRU, so append the new record info
131 // to the same data.
132 if (search != recordMap.end())
133 {
134 search->second.emplace_back(std::move(fruInfo));
135 }
136 else
137 {
138 FruRecordInfos recordInfos{fruInfo};
139 recordMap.emplace(dbusIntfName, recordInfos);
140 }
Tom Joseph151d5332019-11-17 22:21:45 +0530141 }
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500142 catch (const std::exception& e)
Tom Joseph151d5332019-11-17 22:21:45 +0530143 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500144 continue;
Tom Joseph151d5332019-11-17 22:21:45 +0530145 }
146 }
147}
148
149} // namespace fru_parser
150
151} // namespace responder
152
153} // namespace pldm