xref: /aosp_15_r20/external/intel-media-driver/Tools/MediaDriverTools/GenKrnBin/main.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 // Disable deprecated
2 #pragma warning(disable : 4995)
3 
4 #include <assert.h>
5 #include <list>
6 #include <string>
7 #include <vector>
8 #include <fstream>
9 #include <algorithm>
10 #include "linkfile.h"
11 
12 #ifdef LINUX_
13 #include <dirent.h>
14 #include <sys/stat.h>
15 #include <strings.h>
16 #include <cstring>
17 #endif
18 
19 using namespace std;
20 
21 // Defaults
22 #define KERNEL                      "kernel"
23 #define KERNEL_HEADER_FILE_NAME     "krnheader.h"
24 
25 char KERNEL_COMPONENT_DIR[MAX_STRING_SIZE]        = "";
26 char KERNEL_HEADER_FILE[MAX_STRING_SIZE]        = "";
27 char KERNEL_TEMP_HEADER_FILE[MAX_STRING_SIZE]    = "";
28 char KERNEL_BINARY_FILE[MAX_STRING_SIZE]        = "";
29 char KERNEL_SEARCH_DIR[MAX_STRING_SIZE]            = "";
30 
31 char  KERNEL_HEADER_PREFIX[8]       = "";
32 char  KERNEL_HEADER_GEN[8]          = "";
33 char  KERNEL_HEADER_KIND[16]        = "";
34 char  KERNEL_HEADER_PREFIX_UPPER[8] = "";
35 char  KERNEL_HEADER_SENTRY[64]      = "";
36 char  KERNEL_IDR[16]                = "";
37 
38 static const char *COPYRIGHT        =
39     "/*\n"
40     " * Copyright (c) 2019, Intel Corporation\n"
41     " *\n"
42     " * Permission is hereby granted, free of charge, to any person obtaining a\n"
43     " * copy of this software and associated documentation files (the\n"
44     " * 'Software'), to deal in the Software without restriction, including\n"
45     " * without limitation the rights to use, copy, modify, merge, publish,\n"
46     " * distribute, sublicense, and/or sell copies of the Software, and to\n"
47     " * permit persons to whom the Software is furnished to do so, subject to\n"
48     " * the following conditions:\n"
49     " *\n"
50     " * The above copyright notice and this permission notice shall be included\n"
51     " * in all copies or substantial portions of the Software.\n"
52     " *\n"
53     " * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS\n"
54     " * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n"
55     " * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n"
56     " * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n"
57     " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n"
58     " * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n"
59     " * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
60     "*/\n"
61     "\n"
62     "////////////////////////////////////////////////////////////////////////////////\n"
63     "// !!! WARNING - AUTO GENERATED FILE. DO NOT EDIT DIRECTLY. !!!\n"
64     "// Generated by GenKrnBin.exe tool\n"
65     "////////////////////////////////////////////////////////////////////////////////\n"
66 ;
67 
68 #define INDEX_OPEN_FORMAT_STRING         "#ifndef %s\n#define %s\n\n\0",              \
69     KERNEL_HEADER_SENTRY,                                                                   \
70     KERNEL_HEADER_SENTRY
71 #define INDEX_ENTRY_FORMAT_STRING(index) "#define %s_%s %d\n\0",                          \
72     KERNEL_IDR, index, dwKernelCount
73 #define INDEX_CLOSE_FORMAT_STRING        "\n#endif // %s\0", KERNEL_HEADER_SENTRY
74 #define INDEX_ENTRY_FORMAT_INT(index,i)  "#define %s_%s %d\n\0",                          \
75     KERNEL_IDR, index, i
76 #define KERNEL_NAME_DEFINE(index)        "#define %s_%s   \\\n",                          \
77     KERNEL_IDR, index
78 #define KERNEL_NAME_ENTRY(index)         "    _" "T(\"%s\"),\\\n",                        \
79     index
80 #define KERNEL_ID_ENTRY(index)           "    _" "T(\"%03d\"),\\\n",                      \
81     index
82 
83 #ifdef LINUX_
84 #define StrCmp strncasecmp
85 #else
86 #define StrCmp strnicmp
87 #endif
88 
89 void ConcatenateKernelBinary(char *pKernelName, bool bVerbose);
90 
91 // scratch global variables for writing files
92 char    g_Buffer[MAX_STRING_SIZE];
93 bool    g_bReturn;
94 
95 // size_t is integral data type returned by the language operator sizeof and is defined in the <cstring> header file (among others) as an unsigned integral type
96 unsigned int   g_SizetOfTextToWrite;
97 unsigned int   g_dwNumBytesWritten;
98 
99 // globals used in multiple functions
100 FILE          *g_hKernelBinary        = NULL;
101 unsigned int   g_dwTotalKernelCount   = 0;
102 unsigned int   g_dwCurrentKernelCount = 0;
103 
104 // offset table
105 unsigned int  *g_pOffsetTable;
106 unsigned int   g_dwOffsetTableSize;
107 unsigned int   g_dwCurrentKernel;
108 
109 #ifdef LINUX_
strupr(char * str)110 char strupr(char *str)
111 {
112     char *ptr = str;
113 
114     while (*ptr != '\0')
115     {
116         if (islower(*ptr))
117         *ptr = toupper(*ptr);
118         ptr++;
119     }
120 }
121 
122 #define _strupr_s strupr
123 #endif
124 
main(int argc,char * argv[])125 int main(int argc, char *argv[])
126 {
127     // list template class is based on a doubly-linked list
128     list <string> KernelList; // creates an empty list for elements of type "string"
129     list <string>::const_iterator iterator; // allows iterating over list <string>
130     FILE *hKernelDirs, *hKernels, *hHeaderFile, *hTempHeaderFile;
131 
132     // TCHAR data type is char string used to represent a string of either the WCHAR or char type
133     char SearchString[MAX_STRING_SIZE];
134     char KernelNameNoExt[MAX_STRING_SIZE];
135     char KernelNameFull[MAX_STRING_SIZE];
136     char KernelBinName[MAX_STRING_SIZE];
137     bool  bKernelNames, bVerbose;
138     char* pcHeaderFile, pcTempHeaderFile;
139     unsigned int dwKernelCount, dwHeaderSize, dwTempHeaderSize, dwBytesRead;
140 
141     bVerbose = false;
142     if (argc < 5)
143     {
144         fprintf(stderr, "Usage: GenKrnBin.exe <kernel root dir> <component> [-verbose]\n");
145         exit (-1);
146     }
147 
148     int idx = 5;        // scan the command-line options from index 3
149     while (idx < argc)
150     {
151         if (StrCmp(argv[idx], "-verbose", 8) == 0)
152         {
153             bVerbose = true;
154         }
155         ++idx;
156     }
157 
158 #ifdef LINUX_
159     sprintf(KERNEL_COMPONENT_DIR,"%s", argv[1]);
160     strncpy(KERNEL_HEADER_PREFIX, argv[2], sizeof(KERNEL_HEADER_PREFIX));
161     strncpy(KERNEL_HEADER_GEN, argv[3], sizeof(KERNEL_HEADER_GEN));
162     strncpy(KERNEL_HEADER_KIND, argv[4], sizeof(KERNEL_HEADER_KIND));
163     strncpy(KERNEL_HEADER_PREFIX_UPPER, argv[2], sizeof(KERNEL_HEADER_PREFIX));
164    _strupr_s(KERNEL_HEADER_PREFIX_UPPER);
165 
166     sprintf(KERNEL_HEADER_FILE, "%s/ig%skrn_%s_%s.h", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX, KERNEL_HEADER_GEN, KERNEL_HEADER_KIND);
167     sprintf(KERNEL_TEMP_HEADER_FILE, "%s/%stemp%s", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX, KERNEL_HEADER_FILE_NAME);
168     sprintf(KERNEL_BINARY_FILE, "%s/ig%skrn_%s_%s.bin", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX, KERNEL_HEADER_GEN, KERNEL_HEADER_KIND);
169     sprintf(KERNEL_SEARCH_DIR, "%s/g*", KERNEL_COMPONENT_DIR);
170     sprintf(KERNEL_HEADER_SENTRY, "__%sKRNHEADER_H__", KERNEL_HEADER_PREFIX_UPPER);
171     sprintf(KERNEL_IDR, "IDR_%s", KERNEL_HEADER_PREFIX_UPPER);
172 #else
173     sprintf(KERNEL_COMPONENT_DIR,"%s", argv[1]);
174     strncpy(KERNEL_HEADER_PREFIX, argv[2], sizeof(KERNEL_HEADER_PREFIX));
175     strncpy(KERNEL_HEADER_PREFIX_UPPER, argv[2], sizeof(KERNEL_HEADER_PREFIX));
176     _strupr_s(KERNEL_HEADER_PREFIX_UPPER);
177 
178     sprintf(KERNEL_HEADER_FILE, "%s\\ig%skrn_g11_icllp.h", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX);
179     sprintf(KERNEL_TEMP_HEADER_FILE, "%s\\%stemp%s", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX, KERNEL_HEADER_FILE_NAME);
180     sprintf(KERNEL_BINARY_FILE, "%s\\ig%skrn_g11_icllp.bin", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX);
181     sprintf(KERNEL_SEARCH_DIR, "%s\\g*", KERNEL_COMPONENT_DIR);
182     sprintf(KERNEL_HEADER_SENTRY, "__%sKRNHEADER_H__", KERNEL_HEADER_PREFIX_UPPER);
183     sprintf(KERNEL_IDR, "IDR_%s", KERNEL_HEADER_PREFIX_UPPER);
184 #endif
185     bKernelNames = true;
186 
187     /////////////////////////////////////////////////
188     // Generate a superset list of all the kernels //
189     /////////////////////////////////////////////////
190 
191 
192 #ifdef LINUX_
193     sprintf(SearchString, "%s", KERNEL_COMPONENT_DIR);
194 
195     struct dirent* ent = NULL;
196 
197     DIR *pDir=NULL;
198     pDir=opendir(SearchString);
199     int n;
200 
201     while (NULL != (ent=readdir(pDir)))
202     {
203         n = strlen(ent->d_name);
204         //printf("kernel name  = %s; ent->d_reclen = %d\n", ent->d_name, n);
205         //printf("kernel offset= %s\n", ent->d_name + n - 4);
206 
207         if ((StrCmp(ent->d_name + n - 4, ".krn", 4) == 0) ||
208             (StrCmp(ent->d_name + n - 4, ".hex", 4) == 0))
209         {
210             KernelList.push_back(string(ent->d_name));
211             continue;
212         }
213         else
214         {
215             continue;
216         }
217     };
218 
219     closedir(pDir);
220 #endif
221 
222     // include LinkFile.txt
223     KernelList.push_back(string("LinkFile.krn"));
224 
225     // remove duplicate entries from the list (create superset)
226     KernelList.sort();
227 
228     // assumes list is sorted. removes subsequent consecutive equal values.
229     KernelList.unique();
230 
231     ///////////////////////////////////////////////////////////////////
232     // Create a temp header that defines the indicies into the table //
233     ///////////////////////////////////////////////////////////////////
234 
235     // create the header file that will define the kernel IDs
236     hHeaderFile = fopen(KERNEL_HEADER_FILE, "w");
237     if (hHeaderFile == NULL)
238     {
239         fprintf(stderr, "Failed to open Temp Header File\n");
240         exit (-1);
241     }
242 
243     // print the copyright comment text to the file
244     fwrite(COPYRIGHT, 1, strlen(COPYRIGHT), hHeaderFile);
245 
246     fprintf(hHeaderFile, INDEX_OPEN_FORMAT_STRING);
247     fprintf(hHeaderFile, INDEX_ENTRY_FORMAT_INT("LINKFILE_VERSION", LINKFILE_VERSION));
248     fprintf(hHeaderFile, INDEX_ENTRY_FORMAT_INT("LINKFILE_HEADER" , sizeof(LinkFileHeader)));
249     fprintf(hHeaderFile, "\n");
250 
251     for (iterator = KernelList.begin(), dwKernelCount = 0;
252         iterator != KernelList.end(); iterator++, dwKernelCount++)
253     {
254         strncpy(KernelNameNoExt, iterator->c_str(), MAX_STRING_SIZE);
255 
256         *(strrchr(KernelNameNoExt, '.')) = '\0';
257         char *c;
258 
259         while ((c = strchr(KernelNameNoExt, '.')) != NULL) *c = '_';
260         fprintf(hHeaderFile, INDEX_ENTRY_FORMAT_STRING(KernelNameNoExt));
261     }
262 
263     fprintf(hHeaderFile, INDEX_ENTRY_FORMAT_STRING("TOTAL_NUM_KERNELS"));
264 
265     // kernel names are defined in the same sequence as they are loaded
266     if (bKernelNames)
267     {
268         fprintf(hHeaderFile, "\n#if _DEBUG || _RELEASE_INTERNAL\n");
269         fprintf(hHeaderFile, KERNEL_NAME_DEFINE("KERNEL_NAMES"));
270         for (iterator = KernelList.begin(), dwKernelCount = 0;
271         iterator != KernelList.end(); iterator++, dwKernelCount++)
272         {
273             strncpy(KernelNameNoExt, iterator->c_str(), MAX_STRING_SIZE);
274             *(strrchr(KernelNameNoExt, '.')) = '\0';
275             char *c;
276             while ((c = strchr(KernelNameNoExt, '.')) != NULL) *c = '_';
277             fprintf(hHeaderFile, KERNEL_NAME_ENTRY(KernelNameNoExt));
278         }
279         fprintf(hHeaderFile, "    _" "T(\"\")\n");
280         fprintf(hHeaderFile, "#else // !_DEBUG\n");
281         fprintf(hHeaderFile, KERNEL_NAME_DEFINE("KERNEL_NAMES"));
282         for (int i = 0; i < dwKernelCount; i++)
283         {
284             fprintf(hHeaderFile, KERNEL_ID_ENTRY(i));
285         }
286         fprintf(hHeaderFile, "    _" "T(\"\")\n");
287         fprintf(hHeaderFile, "#endif // _DEBUG\n");
288     }
289 
290     fprintf(hHeaderFile, INDEX_CLOSE_FORMAT_STRING);
291     fprintf(hHeaderFile, "\n");
292     g_dwTotalKernelCount = dwKernelCount;
293     fclose(hHeaderFile);
294 
295     ///////////////////////////////////////////////////////////////////
296     // Create bin containing kernel table and actual kernel binaries //
297     ///////////////////////////////////////////////////////////////////
298     // allocate kernel offset table
299     g_dwOffsetTableSize = (g_dwTotalKernelCount + 1) * sizeof(unsigned int);
300     g_pOffsetTable      = (unsigned int *)malloc(g_dwOffsetTableSize);
301     if (!g_pOffsetTable)
302     {
303         fprintf(stderr, "Failed to allocate offset table\n");
304         exit (-1);
305     }
306 
307     // do for every family specific folder
308     // create the file that will be the concatenation of all kernel binaries
309     sprintf(KernelBinName, "%s", KERNEL_BINARY_FILE);
310     g_hKernelBinary = fopen(KernelBinName, "wb");
311     if (g_hKernelBinary == NULL)
312     {
313         fprintf(stderr, "Failed to open Kernel Bin File\n");
314         exit (-1);
315     }
316 
317     // write empty offset table
318     memset(g_pOffsetTable,  0, g_dwOffsetTableSize);
319     fwrite( g_pOffsetTable, 1, g_dwOffsetTableSize, (FILE *)g_hKernelBinary);
320 
321     // create link information for the current family folder
322 #ifdef LINUX_
323     sprintf(KernelNameFull, "%s", KERNEL_COMPONENT_DIR);
324 #else
325     sprintf(KernelNameFull, "%s", KERNEL_COMPONENT_DIR);
326 #endif
327     CreateLinkFile(KernelNameFull, KernelList);
328 
329     // for every kernel in the superset list
330     g_dwCurrentKernel = 0;
331     for (iterator = KernelList.begin(); iterator != KernelList.end(); iterator++, g_dwCurrentKernel++)
332     {
333         // check if this kernel exists for this platform
334         // cFileName contains file name
335 #ifdef LINUX_
336         sprintf(KernelNameFull, "%s/%s", KERNEL_COMPONENT_DIR, iterator->c_str());
337 #else
338         sprintf(KernelNameFull, "%s\\%s", KERNEL_COMPONENT_DIR, iterator->c_str());
339 #endif
340         // add kernel binary, update offset table
341         ConcatenateKernelBinary(KernelNameFull, bVerbose);
342     }
343 
344     // write offset table
345     fseek(g_hKernelBinary, 0, SEEK_SET);
346     fwrite(g_pOffsetTable, 1, g_dwOffsetTableSize, g_hKernelBinary);
347 
348     fclose(g_hKernelBinary);
349 
350 #ifdef LINUX_
351     sprintf(KernelNameFull, "%s", KERNEL_COMPONENT_DIR);
352 #else
353     sprintf(KernelNameFull, "%s", KERNEL_COMPONENT_DIR);
354 #endif
355 
356     DeleteLinkFile(KernelNameFull);
357 
358     // free offset table
359     if (g_pOffsetTable)
360     {
361         free(g_pOffsetTable);
362     }
363 
364     return 0;
365 }
366 
ConcatenateKernelBinary(char * pKernelName,bool bVerbose)367 void ConcatenateKernelBinary(char *pKernelName, bool bVerbose)
368 {
369     FILE *hKernel;
370     char pBuffer[MAX_STRING_SIZE];
371     unsigned int dwBytesRead, dwBytesWritten, dwBinaryPos, dwFileSize;
372     int   iLength;
373 
374     // update offset table
375     dwBinaryPos = ftell(g_hKernelBinary) - g_dwOffsetTableSize;
376     g_pOffsetTable[g_dwCurrentKernel] = dwBinaryPos;
377 
378     // the function opens an existing file and returns a handle that can be used to access the object
379     // open .krn/.hex file
380     hKernel = fopen(pKernelName, "r");
381 
382     if (hKernel == NULL)
383     {
384         fclose(hKernel);
385         g_pOffsetTable[g_dwCurrentKernel + 1] = dwBinaryPos;
386         return;
387     }
388     else
389     {
390         fseek(hKernel, 0, SEEK_END);
391         dwFileSize = ftell(hKernel);
392         fseek(hKernel, 0, SEEK_SET);
393     }
394 
395     // print kernel name processed
396     if (bVerbose)
397     {
398         fprintf(stderr, "%s\n", pKernelName);
399     }
400 
401     // .hex file
402     iLength = strlen(pKernelName);
403     if (StrCmp(&pKernelName[iLength-4], ".hex", 4) == 0)
404     {
405         int    iLine = 1;
406         char   pBinBuffer[MAX_STRING_SIZE];
407         int    iBinLeft = MAX_STRING_SIZE;
408         unsigned int * pBinCurrent = (unsigned int *)pBinBuffer;
409         char  *pBuffCurrent = pBuffer;
410         int    iBuffLeft  = 0;
411 
412         dwBytesRead = 0;
413         do
414         {
415             // shift and read hex data
416             if (iBuffLeft < 35)
417             {
418                 // move incomplete line to the beginning of the buffer
419                 if (iBuffLeft)
420                 {
421                     memcpy(pBuffer, pBuffCurrent, iBuffLeft);
422                 }
423 
424                 // fill buffer (leave room for 0 at the end of the string)
425                 pBuffCurrent = pBuffer;
426                 if (dwBytesRead = fread(pBuffCurrent + iBuffLeft, 1, sizeof(pBuffer) - iBuffLeft - 1, hKernel))
427                 {
428                     // add data
429                     iBuffLeft += dwBytesRead;
430 
431                     // terminate string with 0 to avoid parsing issues
432                     pBuffCurrent[iBuffLeft] = 0;
433 
434                     // no data to read - EOF
435                     if (dwBytesRead == 0)
436                     {
437                         if (iBuffLeft > 4)
438                         {
439                             fprintf(stderr, "Hex file %s is not 32 bytes aligned. Left %d bytes not processed. May have critical issue!!!\n", pKernelName, iBuffLeft);
440                         }
441                         iBuffLeft = -1;
442                     }
443                 }
444                 else
445                 {
446                     if (iBuffLeft > 4)
447                     {
448                         fprintf(stderr, "Hex file %s is not 32 bytes aligned. Left %d bytes not processed. May have critical issue!!!\n", pKernelName, iBuffLeft);
449                     }
450                     iBuffLeft = -1;
451                 }
452             }
453 
454             // process hex data one line at a time (35 chars => "xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx")
455             while (iBuffLeft >= 35 && iBinLeft > 0)
456             {
457                 // skip CR/LF/TAB (control characters)
458                 while (iBuffLeft > 35 && *pBuffCurrent < 32)
459                 {
460                     pBuffCurrent++;
461                     iBuffLeft--;
462                 }
463 
464                 // convert hex to bin (4 DW = 16 B = 128 bits/line)
465                 if ( 4 != sscanf(pBuffCurrent, "%08x %08x %08x %08x", pBinCurrent, pBinCurrent+1, pBinCurrent+2, pBinCurrent+3) )
466                 {
467                     fprintf(stderr, "Fail to process file %s at line %d\n", pKernelName, iLine);
468                     exit(-1);
469                 }
470 
471                 // line counter
472                 iLine++;
473 
474                 // increment hex buffer
475                 pBuffCurrent += 35;
476                 iBuffLeft    -= 35;
477 
478                 // increment bin buffer
479                 pBinCurrent += 4;
480                 iBinLeft    -= 4 * sizeof(unsigned int);
481 
482             }
483 
484             if (iBinLeft == 0 || iBuffLeft < 0)
485             {
486                 // get actual size of binary buffer
487                 dwBytesRead = sizeof(pBinBuffer) - iBinLeft;
488 
489                 dwBinaryPos = ftell(g_hKernelBinary);
490                 fwrite(pBinBuffer, 1, dwBytesRead, g_hKernelBinary);
491 
492                 if (iBuffLeft >= 0)
493                 {
494                     pBinCurrent = (unsigned int *)pBinBuffer;
495                     iBinLeft    = sizeof(pBinBuffer);
496                 }
497             }
498         } while (dwBytesRead > 0 && iBuffLeft >= 0);
499     }
500     else
501     {
502         if (fread(pBuffer, 1, sizeof(pBuffer), hKernel))
503         {
504             dwBinaryPos = ftell(g_hKernelBinary);
505             fwrite(pBuffer, 1, dwFileSize, g_hKernelBinary);
506         }
507     }
508 
509     dwBinaryPos = ftell(g_hKernelBinary) - g_dwOffsetTableSize;
510     g_pOffsetTable[g_dwCurrentKernel+1] = dwBinaryPos;
511 
512     // close kernel file
513     if (hKernel != NULL) fclose(hKernel);
514 }
515