1 
2 #include <assert.h>
3 
4 #include <hei_main.hpp>
5 #include <util/pdbg.hpp>
6 #include <util/trace.hpp>
7 
8 #include <filesystem>
9 #include <fstream>
10 #include <map>
11 #include <vector>
12 
13 namespace fs = std::filesystem;
14 
15 namespace analyzer
16 {
17 
18 //------------------------------------------------------------------------------
19 
__getChipDataFiles(std::map<libhei::ChipType_t,fs::path> & o_files)20 void __getChipDataFiles(std::map<libhei::ChipType_t, fs::path>& o_files)
21 {
22     o_files.clear();
23 
24     auto directory = "/usr/share/openpower-libhei/";
25 
26     for (const auto& entry : fs::directory_iterator(directory))
27     {
28         auto path = entry.path();
29 
30         std::ifstream file{path, std::ios::binary};
31         if (!file.good())
32         {
33             trace::err("Unable to open file: %s", path.string().c_str());
34             continue;
35         }
36 
37         // The first 8-bytes is the file keyword and the next 4-bytes is the
38         // chip type.
39         libhei::FileKeyword_t keyword;
40         libhei::ChipType_t chipType;
41 
42         const size_t sz_keyword = sizeof(keyword);
43         const size_t sz_chipType = sizeof(chipType);
44         const size_t sz_buffer = sz_keyword + sz_chipType;
45 
46         // Read the keyword and chip type from the file.
47         char buffer[sz_buffer];
48         file.read(buffer, sz_buffer);
49         if (!file.good())
50         {
51             trace::err("Unable to read file: %s", path.string().c_str());
52             continue;
53         }
54 
55         // Get the keyword.
56         memcpy(&keyword, &buffer[0], sz_keyword);
57         keyword = be64toh(keyword);
58 
59         // Ensure the keyword value is correct.
60         if (libhei::KW_CHIPDATA != keyword)
61         {
62             trace::err("Invalid chip data file: %s", path.string().c_str());
63             continue;
64         }
65 
66         // Get the chip type.
67         memcpy(&chipType, &buffer[sz_keyword], sz_chipType);
68         chipType = be32toh(chipType);
69 
70         // Trace each legitimate chip data file for debug.
71         trace::inf("File found: type=0x%0" PRIx32 " path=%s", chipType,
72                    path.string().c_str());
73 
74         // So far, so good. Add the entry.
75         auto ret = o_files.emplace(chipType, path);
76         assert(ret.second); // Should not have duplicate entries
77     }
78 }
79 
80 //------------------------------------------------------------------------------
81 
__initialize(const fs::path & i_path)82 void __initialize(const fs::path& i_path)
83 {
84     // Get file size.
85     const auto sz_buffer = fs::file_size(i_path);
86 
87     // Create a buffer large enough to hold the entire file.
88     std::vector<char> buffer(sz_buffer);
89 
90     // Open the chip data file.
91     std::ifstream file{i_path, std::ios::binary};
92     assert(file.good()); // We've opened it once before, so it should open now.
93 
94     // Read the entire file into the buffer.
95     file.read(buffer.data(), sz_buffer);
96     assert(file.good()); // Again, this should be readable.
97 
98     // This is not necessary, but it frees up memory before calling the memory
99     // intensive initialize() function.
100     file.close();
101 
102     // Initialize the isolator with this chip data file.
103     libhei::initialize(buffer.data(), sz_buffer);
104 }
105 
106 //------------------------------------------------------------------------------
107 
initializeIsolator(std::vector<libhei::Chip> & o_chips)108 void initializeIsolator(std::vector<libhei::Chip>& o_chips)
109 {
110     // Get all of the active chips to be analyzed.
111     util::pdbg::getActiveChips(o_chips);
112 
113     // Find all of the existing chip data files.
114     std::map<libhei::ChipType_t, fs::path> files;
115     __getChipDataFiles(files);
116 
117     // Keep track of models/levels that have already been initialized.
118     std::map<libhei::ChipType_t, unsigned int> initTypes;
119 
120     for (const auto& chip : o_chips)
121     {
122         auto chipType = chip.getType();
123 
124         // Mark this chip type as initialized (or will be if it hasn't been).
125         auto ret = initTypes.emplace(chipType, 1);
126         if (!ret.second)
127         {
128             // This type has already been initialized. Nothing more to do.
129             continue;
130         }
131 
132         // Get the file for this chip.
133         auto itr = files.find(chipType);
134 
135         // Ensure a chip data file exist for this chip.
136         assert(files.end() != itr);
137 
138         // Initialize this chip type.
139         __initialize(itr->second);
140     }
141 }
142 
143 //------------------------------------------------------------------------------
144 
145 } // namespace analyzer
146