xref: /aosp_15_r20/external/intel-media-driver/media_driver/agnostic/common/cm/cm_visa.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2017, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file      cm_visa.cpp
24 //! \brief     Contains ISAfile definitions
25 //!
26 
27 #include "cm_visa.h"
28 #include "cm_def_os.h"
29 #include <fstream>
30 #include "mos_utilities.h"
31 
32 using namespace vISA;
33 
ISAfile(const uint8_t * data,unsigned size)34 ISAfile::ISAfile(const uint8_t *data, unsigned size) : version(0), data(data), end(data + size),
35 size(size), error(0), errorIndex(0), header(0), kernel_data_loaded(false), function_data_loaded(false) { }
36 
ISAfile(const ISAfile & other)37 ISAfile::ISAfile(const ISAfile& other) {
38     version = other.version;
39     data = other.data;
40     end = other.end;
41     size = other.size;
42     unsigned int error_length = std::strlen(other.error) + 1;
43     char *perror = new char[error_length];
44     MOS_SecureMemcpy(perror, error_length, other.error, error_length);
45     error = perror;
46     kernel_data_loaded = other.kernel_data_loaded;
47     function_data_loaded = other.function_data_loaded;
48     errorIndex = other.errorIndex;
49     header = new Header(other.version);
50     *header = *other.header;
51     for (KernelBody *kb : other.kernel_data) {
52         KernelBody *kb2 = new KernelBody(other.version);
53         *kb2 = *kb;
54         kernel_data.push_back(kb2);
55     }
56     for (FunctionBody *fb : other.function_data) {
57         FunctionBody *fb2 = new FunctionBody(other.version);
58         *fb2 = *fb;
59         function_data.push_back(fb2);
60     }
61 }
62 
operator =(const ISAfile & other)63 ISAfile& ISAfile::operator= (const ISAfile& other) {
64     if (this != &other) {
65         version = other.version;
66         data = other.data;
67         end = other.end;
68         size = other.size;
69         delete[] error;
70         unsigned int error_length = std::strlen(other.error) + 1;
71         char *perror = new char[error_length];
72         MOS_SecureMemcpy(perror, error_length, other.error, error_length);
73         error = perror;
74         kernel_data_loaded = other.kernel_data_loaded;
75         function_data_loaded = other.function_data_loaded;
76         errorIndex = other.errorIndex;
77         *header = *other.header;
78         for (KernelBody *kb : kernel_data)
79             delete kb;
80         for (FunctionBody *fb : function_data)
81             delete fb;
82         for (KernelBody *kb : other.kernel_data)
83             kernel_data.push_back(&*kb);
84         for (FunctionBody *fb : other.function_data)
85             function_data.push_back(&*fb);
86     }
87     return *this;
88 }
89 
~ISAfile()90 ISAfile::~ISAfile() {
91     delete header;
92     delete[] error;
93     for (KernelBody *kb : kernel_data)
94         delete kb;
95     for (FunctionBody *f : function_data)
96         delete f;
97 }
98 
readFile()99 bool ISAfile::readFile() {
100     bool status = true;
101     status &= loadHeader();
102     if (version < 302)
103         return false;
104     status &= loadKernelData();
105     status &= loadFunctionData();
106     return status;
107 }
108 
loadHeader()109 bool ISAfile::loadHeader() {
110     header = new Header(version);
111     const uint8_t *p = header->parse(data, end, this);
112     if (!p) {
113         delete header;
114         return false; //error loading header
115     }
116     return true;
117 }
118 
loadKernelData()119 bool ISAfile::loadKernelData() {
120     const uint8_t *p = 0;
121     for (Kernel *k : header->getKernelInfo()) {
122         KernelBody *kb = new KernelBody(version);
123         p = kb->parse(data + k->getOffset(), end, this);
124         if (!p) {
125             delete kb;
126             return false; //error loading kernel_data
127         }
128         kernel_data.push_back(kb);
129     }
130     kernel_data_loaded = true;
131     return true;
132 }
133 
loadFunctionData()134 bool ISAfile::loadFunctionData() {
135     const uint8_t *p = 0;
136     for (Function *f : header->getFunctionInfo()) {
137         FunctionBody *fb = new FunctionBody(version);
138         p = fb->parse(data + f->getOffset(), end, this);
139         if (!p) {
140             delete fb;
141             return false; //error loading kernel_data
142         }
143         function_data.push_back(fb);
144     }
145     function_data_loaded = true;
146     return true;
147 }
148 
getKernelsData()149 std::vector<KernelBody*> &ISAfile::getKernelsData() {
150     if (!kernel_data_loaded) loadKernelData();
151     return kernel_data;
152 }
153 
getFunctionsData()154 std::vector<FunctionBody*> &ISAfile::getFunctionsData() {
155     if (!function_data_loaded) loadFunctionData();
156     return function_data;
157 }
158 
readField(const uint8_t * p,const uint8_t * buffEnd,Field & field,unsigned dataSize)159 const uint8_t* ISAfile::readField(const uint8_t *p, const uint8_t *buffEnd,
160     Field &field, unsigned dataSize) {
161     switch (field.type) {
162     case Datatype::ONE: field.number8 = *((int8_t *)p); p++; break;
163     case Datatype::TWO: field.number16 = *((int16_t *)p); p += 2; break;
164     case Datatype::FOUR: field.number32 = *((int32_t *)p); p += 4; break;
165     case Datatype::EIGHT: field.number64 = *((int64_t *)p); p += 8; break;
166     case Datatype::VARCHAR:
167     {
168         if (p + dataSize > buffEnd) {
169             // error: truncated
170             p = 0;
171             return 0;
172         }
173         char *string = new char[dataSize + 1];
174         MOS_SecureMemcpy(string, dataSize + 1, p, dataSize);
175         string[dataSize] = '\0';
176         field.size = dataSize;
177         field.varchar = string;
178         p += dataSize;
179         break;
180     }
181     case Datatype::VARCHAR_POOL:
182     {
183         const uint8_t *strEnd = (const uint8_t *)std::memchr(p, 0, end - p);
184         auto len = strEnd - p;
185         char *string = new char[len + 1];
186         MOS_SecureMemcpy(string, len + 1, p, len);
187         string[len] = '\0';
188         field.size = (uint32_t)len + 1;
189         field.varchar = string;
190         p = strEnd + 1;
191         break;
192     }
193     case Datatype::GDATA:
194     {
195         // copy only if no out of bound.
196         if (p + dataSize < end) {
197             uint8_t *gdata = new uint8_t[dataSize];
198             MOS_SecureMemcpy(gdata, dataSize , p, dataSize);
199             field.gdata = gdata;
200             field.size = dataSize;
201             p += dataSize;
202         } else {
203             field.gdata = nullptr;
204             field.size = 0;
205         }
206         break;
207     }
208     default: break;
209     }
210     return p;
211 }
212 
setError(const char * e,unsigned index)213 const uint8_t *ISAfile::setError(const char * e, unsigned index) {
214     error = e;
215     errorIndex = index;
216     return 0;
217 }
218 
writeToFile(const char * filename,std::vector<uint8_t> & originalBuffer)219 bool ISAfile::writeToFile(const char *filename, std::vector<uint8_t> &originalBuffer) {
220     if (!header) {
221         setError("Header not loaded", 0);
222         return false;
223     }
224     if (!kernel_data_loaded)
225         loadKernelData();
226     if (!function_data_loaded)
227         loadFunctionData();
228 
229     std::ofstream newFile(filename, std::ios::out | std::ios::binary);
230     if (!newFile) {
231         setError("Error creating new file ", 0);
232         return false;
233     }
234 
235     // buffer
236     std::vector<char> buffer;
237     // header
238     header->addToBuffer(buffer, this);
239 
240     // kernel body
241     for (KernelBody* k : kernel_data) {
242         k->addToBuffer(buffer, this);
243     }
244 
245     // function body
246     for (FunctionBody* f : function_data) {
247         f->addToBuffer(buffer, this);
248     }
249 
250     // gen binaries for this kernel
251     for (Kernel *k : header->getKernelInfo()) {
252         for (GenBinary *g : k->getGenBinaryInfo()) {
253             uint32_t offset = g->getBinaryOffset();
254             if (offset > originalBuffer.size()) {
255                 setError("Error writing GEN binary into ISA file, bad offset from original file", 0);
256                 return false;
257             }
258             for (uint32_t b = 0; b < g->getBinarySize(); b++) {
259                 buffer.push_back(static_cast<char>(originalBuffer[offset + b]));
260             }
261         }
262     }
263 
264     newFile.write(buffer.data(), buffer.size());
265     newFile.close();
266     return true;
267 }
268 
addToBuffer(Field & field,std::vector<char> & buffer)269 void ISAfile::addToBuffer(Field &field, std::vector<char> &buffer) {
270     switch (field.type) {
271     case Datatype::ONE: buffer.push_back(field.ui8[0]); break;
272     case Datatype::TWO: buffer.push_back(field.ui8[0]); buffer.push_back(field.ui8[1]); break;
273     case Datatype::FOUR: buffer.push_back(field.ui8[0]); buffer.push_back(field.ui8[1]);
274         buffer.push_back(field.ui8[2]); buffer.push_back(field.ui8[3]); break;
275     case Datatype::EIGHT: buffer.push_back(field.ui8[0]); buffer.push_back(field.ui8[1]);
276         buffer.push_back(field.ui8[2]); buffer.push_back(field.ui8[3]);
277         buffer.push_back(field.ui8[4]); buffer.push_back(field.ui8[5]);
278         buffer.push_back(field.ui8[6]); buffer.push_back(field.ui8[7]); break;
279     case Datatype::VARCHAR:
280     {
281         for (unsigned i = 0; i < field.size; i++) {
282             buffer.push_back(static_cast<char>(field.varchar[i]));
283         }
284         break;
285     }
286     case Datatype::VARCHAR_POOL:
287     {
288         for (unsigned i = 0; i < field.size; i++) {
289             buffer.push_back(static_cast<char>(field.varchar[i]));
290         }
291         break;
292     }
293     case Datatype::GDATA:
294     {
295         for (unsigned i = 0; i < field.size; i++) {
296             buffer.push_back(static_cast<char>(field.gdata[i]));
297         }
298         break;
299     }
300     default: break;
301     }
302 }
303