xref: /aosp_15_r20/external/intel-media-driver/media_softlet/agnostic/common/vp/hal/utils/vp_visa.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2022, 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      vp_visa.cpp
24 //! \brief     Contains ISAfile definitions
25 //!
26 
27 #include "vp_visa.h"
28 #include <fstream>
29 #include "mos_utilities.h"
30 
31 using namespace vp::vISA;
32 
ISAfile(const uint8_t * data,unsigned size)33 ISAfile::ISAfile(const uint8_t *data, unsigned size) : version(0), data(data), end(data + size),
34 size(size), error(0), errorIndex(0), header(0), kernel_data_loaded(false), function_data_loaded(false) { }
35 
ISAfile(const ISAfile & other)36 ISAfile::ISAfile(const ISAfile& other) {
37     version = other.version;
38     data = other.data;
39     end = other.end;
40     size = other.size;
41     int error_length = std::strlen(other.error);
42     error = new char[error_length + 1];
43     if (nullptr == error)
44     {
45         MOS_OS_ASSERTMESSAGE("create array failed!");
46         return;
47     }
48     char *perror = const_cast<char*>(error);
49     perror[error_length] = '\0';
50     MOS_SecureMemcpy(perror, error_length + 1, other.error, error_length);
51     kernel_data_loaded = other.kernel_data_loaded;
52     function_data_loaded = other.function_data_loaded;
53     errorIndex = other.errorIndex;
54     header = new Header(other.version);
55     *header = *other.header;
56     for (KernelBody *kb : other.kernel_data) {
57         KernelBody *kb2 = new KernelBody(other.version);
58         *kb2 = *kb;
59         kernel_data.push_back(kb2);
60     }
61     for (FunctionBody *fb : other.function_data) {
62         FunctionBody *fb2 = new FunctionBody(other.version);
63         *fb2 = *fb;
64         function_data.push_back(fb2);
65     }
66 }
67 
operator =(const ISAfile & other)68 ISAfile& ISAfile::operator= (const ISAfile& other) {
69     if (this != &other) {
70         version = other.version;
71         data = other.data;
72         end = other.end;
73         size = other.size;
74         delete[] error;
75         int   error_length = std::strlen(other.error);
76         error = new char[error_length + 1];
77         if (nullptr == error)
78         {
79             MOS_OS_ASSERTMESSAGE("create array failed!");
80             return *this;
81         }
82         char *perror = const_cast<char *>(error);
83         perror[error_length] = '\0';
84         MOS_SecureMemcpy(perror, error_length + 1, other.error, error_length);
85         kernel_data_loaded = other.kernel_data_loaded;
86         function_data_loaded = other.function_data_loaded;
87         errorIndex = other.errorIndex;
88         *header = *other.header;
89         for (KernelBody *kb : kernel_data)
90             delete kb;
91         for (FunctionBody *fb : function_data)
92             delete fb;
93         for (KernelBody *kb : other.kernel_data)
94             kernel_data.push_back(&*kb);
95         for (FunctionBody *fb : other.function_data)
96             function_data.push_back(&*fb);
97     }
98     return *this;
99 }
100 
~ISAfile()101 ISAfile::~ISAfile() {
102     delete header;
103     for (KernelBody *kb : kernel_data)
104         delete kb;
105     for (FunctionBody *f : function_data)
106         delete f;
107     if (error)
108     {
109         delete[] error;
110         error = nullptr;
111     }
112 }
113 
readFile()114 bool ISAfile::readFile() {
115     bool status = true;
116     status &= loadHeader();
117     if (version < 302)
118         return false;
119     status &= loadKernelData();
120     status &= loadFunctionData();
121     return status;
122 }
123 
loadHeader()124 bool ISAfile::loadHeader() {
125     header = new Header(version);
126     const uint8_t *p = header->parse(data, end, this);
127     if (!p) {
128         delete header;
129         return false; //error loading header
130     }
131     return true;
132 }
133 
loadKernelData()134 bool ISAfile::loadKernelData() {
135     const uint8_t *p = 0;
136     for (Kernel *k : header->getKernelInfo()) {
137         KernelBody *kb = new KernelBody(version);
138         p = kb->parse(data + k->getOffset(), end, this);
139         if (!p) {
140             delete kb;
141             return false; //error loading kernel_data
142         }
143         kernel_data.push_back(kb);
144     }
145     kernel_data_loaded = true;
146     return true;
147 }
148 
loadFunctionData()149 bool ISAfile::loadFunctionData() {
150     const uint8_t *p = 0;
151     for (Function *f : header->getFunctionInfo()) {
152         FunctionBody *fb = new FunctionBody(version);
153         p = fb->parse(data + f->getOffset(), end, this);
154         if (!p) {
155             delete fb;
156             return false; //error loading kernel_data
157         }
158         function_data.push_back(fb);
159     }
160     function_data_loaded = true;
161     return true;
162 }
163 
getKernelsData()164 std::vector<KernelBody*> &ISAfile::getKernelsData() {
165     if (!kernel_data_loaded) loadKernelData();
166     return kernel_data;
167 }
168 
getFunctionsData()169 std::vector<FunctionBody*> &ISAfile::getFunctionsData() {
170     if (!function_data_loaded) loadFunctionData();
171     return function_data;
172 }
173 
readField(const uint8_t * p,const uint8_t * buffEnd,Field & field,unsigned dataSize)174 const uint8_t* ISAfile::readField(const uint8_t *p, const uint8_t *buffEnd,
175     Field &field, unsigned dataSize) {
176     switch (field.type) {
177     case Datatype::ONE: field.number8 = *((int8_t *)p); p++; break;
178     case Datatype::TWO: field.number16 = *((int16_t *)p); p += 2; break;
179     case Datatype::FOUR: field.number32 = *((int32_t *)p); p += 4; break;
180     case Datatype::EIGHT: field.number64 = *((int64_t *)p); p += 8; break;
181     case Datatype::VARCHAR:
182     {
183         if (p + dataSize > buffEnd) {
184             // error: truncated
185             p = 0;
186             return 0;
187         }
188         char *string = new char[dataSize + 1];
189         MOS_SecureMemcpy(string, dataSize + 1, p, dataSize);
190         string[dataSize] = '\0';
191         field.size = dataSize;
192         field.varchar = string;
193         p += dataSize;
194         break;
195     }
196     case Datatype::VARCHAR_POOL:
197     {
198         const uint8_t *strEnd = (const uint8_t *)std::memchr(p, 0, end - p);
199         auto len = strEnd - p;
200         char *string = new char[len + 1];
201         MOS_SecureMemcpy(string, len + 1, p, len);
202         string[len] = '\0';
203         field.size = (uint32_t)len + 1;
204         field.varchar = string;
205         p = strEnd + 1;
206         break;
207     }
208     case Datatype::GDATA:
209     {
210         // copy only if no out of bound.
211         if (p + dataSize < end) {
212             uint8_t *gdata = new uint8_t[dataSize];
213             MOS_SecureMemcpy(gdata, dataSize , p, dataSize);
214             field.gdata = gdata;
215             field.size = dataSize;
216             p += dataSize;
217         } else {
218             field.gdata = nullptr;
219             field.size = 0;
220         }
221         break;
222     }
223     default: break;
224     }
225     return p;
226 }
227 
setError(const char * e,unsigned index)228 const uint8_t *ISAfile::setError(const char * e, unsigned index) {
229     error = e;
230     errorIndex = index;
231     return 0;
232 }
233 
writeToFile(const char * filename,std::vector<uint8_t> & originalBuffer)234 bool ISAfile::writeToFile(const char *filename, std::vector<uint8_t> &originalBuffer) {
235     if (!header) {
236         setError("Header not loaded", 0);
237         return false;
238     }
239     if (!kernel_data_loaded)
240         loadKernelData();
241     if (!function_data_loaded)
242         loadFunctionData();
243 
244     std::ofstream newFile(filename, std::ios::out | std::ios::binary);
245     if (!newFile) {
246         setError("Error creating new file ", 0);
247         return false;
248     }
249 
250     // buffer
251     std::vector<char> buffer;
252     // header
253     header->addToBuffer(buffer, this);
254 
255     // kernel body
256     for (KernelBody* k : kernel_data) {
257         k->addToBuffer(buffer, this);
258     }
259 
260     // function body
261     for (FunctionBody* f : function_data) {
262         f->addToBuffer(buffer, this);
263     }
264 
265     // gen binaries for this kernel
266     for (Kernel *k : header->getKernelInfo()) {
267         for (GenBinary *g : k->getGenBinaryInfo()) {
268             uint32_t offset = g->getBinaryOffset();
269             if (offset > originalBuffer.size()) {
270                 setError("Error writing GEN binary into ISA file, bad offset from original file", 0);
271                 return false;
272             }
273             for (uint32_t b = 0; b < g->getBinarySize(); b++) {
274                 buffer.push_back(static_cast<char>(originalBuffer[offset + b]));
275             }
276         }
277     }
278 
279     newFile.write(buffer.data(), buffer.size());
280     newFile.close();
281     return true;
282 }
283 
addToBuffer(Field & field,std::vector<char> & buffer)284 void ISAfile::addToBuffer(Field &field, std::vector<char> &buffer) {
285     switch (field.type) {
286     case Datatype::ONE: buffer.push_back(field.ui8[0]); break;
287     case Datatype::TWO: buffer.push_back(field.ui8[0]); buffer.push_back(field.ui8[1]); break;
288     case Datatype::FOUR: buffer.push_back(field.ui8[0]); buffer.push_back(field.ui8[1]);
289         buffer.push_back(field.ui8[2]); buffer.push_back(field.ui8[3]); break;
290     case Datatype::EIGHT: buffer.push_back(field.ui8[0]); buffer.push_back(field.ui8[1]);
291         buffer.push_back(field.ui8[2]); buffer.push_back(field.ui8[3]);
292         buffer.push_back(field.ui8[4]); buffer.push_back(field.ui8[5]);
293         buffer.push_back(field.ui8[6]); buffer.push_back(field.ui8[7]); break;
294     case Datatype::VARCHAR:
295     {
296         for (unsigned i = 0; i < field.size; i++) {
297             buffer.push_back(static_cast<char>(field.varchar[i]));
298         }
299         break;
300     }
301     case Datatype::VARCHAR_POOL:
302     {
303         for (unsigned i = 0; i < field.size; i++) {
304             buffer.push_back(static_cast<char>(field.varchar[i]));
305         }
306         break;
307     }
308     case Datatype::GDATA:
309     {
310         for (unsigned i = 0; i < field.size; i++) {
311             buffer.push_back(static_cast<char>(field.gdata[i]));
312         }
313         break;
314     }
315     default: break;
316     }
317 }
318