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