blob: d2c82149ca6fcbf4e925139e3837a33211e8c591 [file] [log] [blame]
Deepak Kodihallic6e8fb52019-05-02 08:35:31 -05001#include "pdr.hpp"
2
3namespace pldm
4{
5
6namespace responder
7{
8
9namespace pdr
10{
George Liue53193f2020-02-24 09:23:26 +080011using namespace pldm::responder::pdr_utils;
Deepak Kodihallic6e8fb52019-05-02 08:35:31 -050012
George Liue53193f2020-02-24 09:23:26 +080013void generate(const std::string& dir, RepoInterface& repo)
Deepak Kodihallic6e8fb52019-05-02 08:35:31 -050014{
George Liue53193f2020-02-24 09:23:26 +080015 // A map of PDR type to a lambda that handles creation of that PDR type.
16 // The lambda essentially would parse the platform specific PDR JSONs to
17 // generate the PDR structures. This function iterates through the map to
18 // invoke all lambdas, so that all PDR types can be created.
19 std::map<Type, std::function<void(const Json& json, RepoInterface& repo)>>
20 generators = {
21 {PLDM_STATE_EFFECTER_PDR,
22 [](const auto& json, RepoInterface& repo) {
23 static const std::vector<Json> emptyList{};
24 static const Json empty{};
25 auto entries = json.value("entries", emptyList);
26 for (const auto& e : entries)
27 {
28 size_t pdrSize = 0;
29 auto effecters = e.value("effecters", emptyList);
30 static const Json empty{};
31 for (const auto& effecter : effecters)
32 {
33 auto set = effecter.value("set", empty);
34 auto statesSize = set.value("size", 0);
35 if (!statesSize)
36 {
37 std::cerr << "Malformed PDR JSON return "
38 "pdrEntry;- no state set "
39 "info, TYPE="
40 << PLDM_STATE_EFFECTER_PDR << "\n";
41 throw InternalFailure();
42 }
43 pdrSize += sizeof(state_effecter_possible_states) -
44 sizeof(bitfield8_t) +
45 (sizeof(bitfield8_t) * statesSize);
46 }
47 pdrSize +=
48 sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
49
50 std::vector<uint8_t> entry{};
51 entry.resize(pdrSize);
52
53 pldm_state_effecter_pdr* pdr =
54 reinterpret_cast<pldm_state_effecter_pdr*>(
55 entry.data());
56 pdr->hdr.record_handle = 0;
57 pdr->hdr.version = 1;
58 pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
59 pdr->hdr.record_change_num = 0;
60 pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr);
61
62 pdr->terminus_handle = 0;
63 pdr->effecter_id = effecter::nextId();
64 pdr->entity_type = e.value("type", 0);
65 pdr->entity_instance = e.value("instance", 0);
66 pdr->container_id = e.value("container", 0);
67 pdr->effecter_semantic_id = 0;
68 pdr->effecter_init = PLDM_NO_INIT;
69 pdr->has_description_pdr = false;
70 pdr->composite_effecter_count = effecters.size();
71
72 using namespace effecter::dbus_mapping;
73 Paths paths{};
74 uint8_t* start = entry.data() +
75 sizeof(pldm_state_effecter_pdr) -
76 sizeof(uint8_t);
77 for (const auto& effecter : effecters)
78 {
79 auto set = effecter.value("set", empty);
80 state_effecter_possible_states* possibleStates =
81 reinterpret_cast<state_effecter_possible_states*>(
82 start);
83 possibleStates->state_set_id = set.value("id", 0);
84 possibleStates->possible_states_size =
85 set.value("size", 0);
86
87 start += sizeof(possibleStates->state_set_id) +
88 sizeof(possibleStates->possible_states_size);
89 static const std::vector<uint8_t> emptyStates{};
90 auto states = set.value("states", emptyStates);
91 for (const auto& state : states)
92 {
93 auto index = state / 8;
94 auto bit = state - (index * 8);
95 bitfield8_t* bf =
96 reinterpret_cast<bitfield8_t*>(start + index);
97 bf->byte |= 1 << bit;
98 }
99 start += possibleStates->possible_states_size;
100
101 auto dbus = effecter.value("dbus", empty);
102 paths.emplace_back(std::move(dbus));
103 }
104 add(pdr->effecter_id, std::move(paths));
105 PdrEntry pdrEntry{};
106 pdrEntry.data = entry.data();
107 pdrEntry.size = pdrSize;
108 repo.addRecord(pdrEntry);
109 }
110 }}};
111
112 Type pdrType{};
113 for (const auto& dirEntry : fs::directory_iterator(dir))
114 {
115 try
116 {
117 auto json = readJson(dirEntry.path().string());
118 if (!json.empty())
119 {
120 pdrType = json.value("pdrType", 0);
121 generators.at(pdrType)(json, repo);
122 }
123 }
124 catch (const InternalFailure& e)
125 {
126 std::cerr << "PDR config directory does not exist or empty, TYPE= "
127 << pdrType << "PATH= " << dirEntry
128 << " ERROR=" << e.what() << "\n";
129 }
130 catch (const Json::exception& e)
131 {
132 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType
133 << "PATH= " << dirEntry << " ERROR=" << e.what() << "\n";
134 pldm::utils::reportError(
135 "xyz.openbmc_project.bmc.pldm.InternalFailure");
136 }
137 catch (const std::exception& e)
138 {
139 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType
140 << " ERROR=" << e.what() << "\n";
141 pldm::utils::reportError(
142 "xyz.openbmc_project.bmc.pldm.InternalFailure");
143 }
144 }
145}
146
147RepoInterface& getRepo(const std::string& dir)
148{
149 static Repo repo;
Deepak Kodihallic6e8fb52019-05-02 08:35:31 -0500150 if (repo.empty())
151 {
152 generate(dir, repo);
153 }
154
155 return repo;
156}
157
George Liue53193f2020-02-24 09:23:26 +0800158Repo getRepoByType(const std::string& dir, Type pdrType)
159{
160 Repo pdrRepo;
161 RepoInterface& repo = getRepo(dir);
162
163 uint8_t* pdrData = nullptr;
164 uint32_t pdrSize{};
165 auto record = pldm_pdr_find_record_by_type(repo.getPdr(), pdrType, NULL,
166 &pdrData, &pdrSize);
167 while (record)
168 {
169 PdrEntry pdrEntry{};
170 pdrEntry.data = pdrData;
171 pdrEntry.size = pdrSize;
172 pdrEntry.handle.recordHandle = repo.getRecordHandle(record);
173 pdrRepo.addRecord(pdrEntry);
174
175 pdrData = nullptr;
176 pdrSize = 0;
177 record = pldm_pdr_find_record_by_type(repo.getPdr(), pdrType, record,
178 &pdrData, &pdrSize);
179 }
180
181 return pdrRepo;
182}
183
184const pldm_pdr_record* getRecordByHandle(RepoInterface& pdrRepo,
185 RecordHandle recordHandle,
186 PdrEntry& pdrEntry)
187{
188 uint8_t* pdrData = nullptr;
189 auto record =
190 pldm_pdr_find_record(pdrRepo.getPdr(), recordHandle, &pdrData,
191 &pdrEntry.size, &pdrEntry.handle.nextRecordHandle);
192 if (record)
193 {
194 pdrEntry.data = pdrData;
195 }
196
197 return record;
198}
199
Deepak Kodihallic6e8fb52019-05-02 08:35:31 -0500200} // namespace pdr
201} // namespace responder
202} // namespace pldm