blob: 610ac8df1bb843bfcda3e27c617260eddb4d3ce1 [file] [log] [blame]
Alpana Kumari26a74af2019-09-10 23:53:58 -05001#include "config.h"
2
3#include "defines.hpp"
4#include "parser.hpp"
5#include "utils.hpp"
6
7#include <CLI/CLI.hpp>
8#include <exception>
9#include <fstream>
10#include <iostream>
11#include <iterator>
12#include <nlohmann/json.hpp>
13
14using namespace std;
15using namespace openpower::vpd;
16
17static void populateInterfaces(const nlohmann::json& js,
18 inventory::InterfaceMap& interfaces,
19 const Parsed& vpdMap)
20{
21 for (const auto& ifs : js.items())
22 {
23 const string& inf = ifs.key();
24 inventory::PropertyMap props;
25
26 for (const auto& itr : ifs.value().items())
27 {
28 const string& rec = itr.value().value("recordName", "");
29 const string& kw = itr.value().value("keywordName", "");
30
31 if (!rec.empty() && !kw.empty() && vpdMap.count(rec) &&
32 vpdMap.at(rec).count(kw))
33 {
34 props.emplace(itr.key(), string(vpdMap.at(rec).at(kw).begin(),
35 vpdMap.at(rec).at(kw).end()));
36 }
37 }
38 interfaces.emplace(inf, move(props));
39 }
40}
41
42static void populateDbus(Store& vpdStore, nlohmann::json& js,
43 const string& objectPath, const string& filePath)
44{
45 inventory::InterfaceMap interfaces;
46 inventory::ObjectMap objects;
47 sdbusplus::message::object_path object(objectPath);
48 const auto& vpdMap = vpdStore.getVpdMap();
49 string preIntrStr = "com.ibm.ipzvpd.";
50
51 // Each record in the VPD becomes an interface and all keywords within the
52 // record are properties under that interface.
53 for (const auto& record : vpdMap)
54 {
55 inventory::PropertyMap prop;
56 for (auto kwVal : record.second)
57 {
58 std::vector<uint8_t> vec(kwVal.second.begin(), kwVal.second.end());
59 std::string kw = kwVal.first;
60 if (kw[0] == '#')
61 {
62 kw = std::string("PD_") + kw[1];
63 }
64 prop.emplace(move(kw), move(vec));
65 }
66 interfaces.emplace(preIntrStr + record.first, move(prop));
67 }
68
69 // Populate interfaces and properties that are common to every FRU
70 // and additional interface that might be defined on a per-FRU basis.
71 if (js.find("commonInterfaces") != js.end())
72 {
73 populateInterfaces(js["commonInterfaces"], interfaces, vpdMap);
74 }
75 if (js["frus"][filePath].find("extraInterfaces") !=
76 js["frus"][filePath].end())
77 {
78 populateInterfaces(js["frus"][filePath]["extraInterfaces"], interfaces,
79 vpdMap);
80 }
81
82 objects.emplace(move(object), move(interfaces));
83
84 // Notify PIM
85 inventory::callPIM(move(objects));
86}
87
88int main(int argc, char** argv)
89{
90 int rc = 0;
91
92 try
93 {
94 using namespace CLI;
95 using json = nlohmann::json;
96
97 App app{"ibm-read-vpd - App to read IPZ format VPD, parse it and store "
98 "in DBUS"};
99 string file{};
100
101 app.add_option("-f, --file", file, "File containing VPD in IPZ format")
102 ->required()
103 ->check(ExistingFile);
104
105 CLI11_PARSE(app, argc, argv);
106
107 // Make sure that the file path we get is for a supported EEPROM
108 ifstream inventoryJson(INVENTORY_JSON);
109 auto js = json::parse(inventoryJson);
110
111 if ((js.find("frus") == js.end()) ||
112 (js["frus"].find(file) == js["frus"].end()))
113 {
114 throw std::runtime_error("Device path missing in inventory JSON");
115 }
116
117 const string& objectPath = js["frus"][file].value("inventoryPath", "");
118
119 if (objectPath.empty())
120 {
121 throw std::runtime_error("Could not find D-Bus object path in "
122 "inventory JSON");
123 }
124
125 ifstream vpdFile(file, ios::binary);
126 Binary vpd((istreambuf_iterator<char>(vpdFile)),
127 istreambuf_iterator<char>());
128
129 // Use ipz vpd Parser
130 auto vpdStore = parse(move(vpd));
131
132 // Write it to the inventory
133 populateDbus(vpdStore, js, objectPath, file);
134 }
135 catch (exception& e)
136 {
137 cerr << e.what() << "\n";
138 rc = -1;
139 }
140
141 return rc;
142}