blob: a63dae657e95ff42a7c73aec85c6469c8fe6b628 [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", "");
63 Interfaces interfaces = data.value("interfaces", emptyStringVec);
64 lookupInfo.emplace(std::make_tuple(std::move(service), std::move(rootPath),
65 std::move(interfaces)));
66}
67
68void FruParser::setupFruRecordMap(const std::string& dirPath)
69{
70 for (auto& file : fs::directory_iterator(dirPath))
71 {
72 auto fileName = file.path().filename().string();
73 if (fruMasterJson == fileName)
74 {
75 continue;
76 }
77
78 std::ifstream jsonFile(file.path());
79 auto data = Json::parse(jsonFile, nullptr, false);
80 if (data.is_discarded())
81 {
82
83 std::cerr << "Parsing FRU master config file failed, FILE="
84 << file.path();
85 throw InternalFailure();
86 }
87
88 auto record = data.value("record_details", emptyJson);
89 auto recordType =
90 static_cast<uint8_t>(record.value("fru_record_type", 0));
91 auto encType =
92 static_cast<uint8_t>(record.value("fru_encoding_type", 0));
93 auto dbusIntfName = record.value("dbus_interface_name", "");
94 auto entries = data.value("fru_fields", emptyJsonList);
95 std::vector<FieldInfo> fieldInfo;
96
97 for (const auto& entry : entries)
98 {
99 auto fieldType =
100 static_cast<uint8_t>(entry.value("fru_field_type", 0));
101 auto dbus = entry.value("dbus", emptyJson);
102 auto interface = dbus.value("interface", "");
103 auto property = dbus.value("property_name", "");
104 auto propType = dbus.value("property_type", "");
105 fieldInfo.emplace_back(
106 std::make_tuple(std::move(interface), std::move(property),
107 std::move(propType), std::move(fieldType)));
108 }
109
110 FruRecordInfo fruInfo;
111 fruInfo = std::make_tuple(recordType, encType, std::move(fieldInfo));
112
113 auto search = recordMap.find(dbusIntfName);
114
115 // PLDM FRU can have multiple records for the same FRU like General FRU
116 // record and multiple OEM FRU records. If the FRU item interface name
117 // is already in the map, that indicates a record info is already added
118 // for the FRU, so append the new record info to the same data.
119 if (search != recordMap.end())
120 {
121 search->second.emplace_back(std::move(fruInfo));
122 }
123 else
124 {
125 FruRecordInfos recordInfos{fruInfo};
126 recordMap.emplace(dbusIntfName, recordInfos);
127 }
128 }
129}
130
131} // namespace fru_parser
132
133} // namespace responder
134
135} // namespace pldm