// Disable deprecated #pragma warning(disable : 4995) #include #include #include #include #include #include #include "linkfile.h" #ifdef LINUX_ #include #include #include #include #endif using namespace std; // Defaults #define KERNEL "kernel" #define KERNEL_HEADER_FILE_NAME "krnheader.h" char KERNEL_COMPONENT_DIR[MAX_STRING_SIZE] = ""; char KERNEL_HEADER_FILE[MAX_STRING_SIZE] = ""; char KERNEL_TEMP_HEADER_FILE[MAX_STRING_SIZE] = ""; char KERNEL_BINARY_FILE[MAX_STRING_SIZE] = ""; char KERNEL_SEARCH_DIR[MAX_STRING_SIZE] = ""; char KERNEL_HEADER_PREFIX[8] = ""; char KERNEL_HEADER_GEN[8] = ""; char KERNEL_HEADER_KIND[16] = ""; char KERNEL_HEADER_PREFIX_UPPER[8] = ""; char KERNEL_HEADER_SENTRY[64] = ""; char KERNEL_IDR[16] = ""; static const char *COPYRIGHT = "/*\n" " * Copyright (c) 2019, Intel Corporation\n" " *\n" " * Permission is hereby granted, free of charge, to any person obtaining a\n" " * copy of this software and associated documentation files (the\n" " * 'Software'), to deal in the Software without restriction, including\n" " * without limitation the rights to use, copy, modify, merge, publish,\n" " * distribute, sublicense, and/or sell copies of the Software, and to\n" " * permit persons to whom the Software is furnished to do so, subject to\n" " * the following conditions:\n" " *\n" " * The above copyright notice and this permission notice shall be included\n" " * in all copies or substantial portions of the Software.\n" " *\n" " * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS\n" " * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n" " * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n" " * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n" " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n" " * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n" " * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n" "*/\n" "\n" "////////////////////////////////////////////////////////////////////////////////\n" "// !!! WARNING - AUTO GENERATED FILE. DO NOT EDIT DIRECTLY. !!!\n" "// Generated by GenKrnBin.exe tool\n" "////////////////////////////////////////////////////////////////////////////////\n" ; #define INDEX_OPEN_FORMAT_STRING "#ifndef %s\n#define %s\n\n\0", \ KERNEL_HEADER_SENTRY, \ KERNEL_HEADER_SENTRY #define INDEX_ENTRY_FORMAT_STRING(index) "#define %s_%s %d\n\0", \ KERNEL_IDR, index, dwKernelCount #define INDEX_CLOSE_FORMAT_STRING "\n#endif // %s\0", KERNEL_HEADER_SENTRY #define INDEX_ENTRY_FORMAT_INT(index,i) "#define %s_%s %d\n\0", \ KERNEL_IDR, index, i #define KERNEL_NAME_DEFINE(index) "#define %s_%s \\\n", \ KERNEL_IDR, index #define KERNEL_NAME_ENTRY(index) " _" "T(\"%s\"),\\\n", \ index #define KERNEL_ID_ENTRY(index) " _" "T(\"%03d\"),\\\n", \ index #ifdef LINUX_ #define StrCmp strncasecmp #else #define StrCmp strnicmp #endif void ConcatenateKernelBinary(char *pKernelName, bool bVerbose); // scratch global variables for writing files char g_Buffer[MAX_STRING_SIZE]; bool g_bReturn; // size_t is integral data type returned by the language operator sizeof and is defined in the header file (among others) as an unsigned integral type unsigned int g_SizetOfTextToWrite; unsigned int g_dwNumBytesWritten; // globals used in multiple functions FILE *g_hKernelBinary = NULL; unsigned int g_dwTotalKernelCount = 0; unsigned int g_dwCurrentKernelCount = 0; // offset table unsigned int *g_pOffsetTable; unsigned int g_dwOffsetTableSize; unsigned int g_dwCurrentKernel; #ifdef LINUX_ char strupr(char *str) { char *ptr = str; while (*ptr != '\0') { if (islower(*ptr)) *ptr = toupper(*ptr); ptr++; } } #define _strupr_s strupr #endif int main(int argc, char *argv[]) { // list template class is based on a doubly-linked list list KernelList; // creates an empty list for elements of type "string" list ::const_iterator iterator; // allows iterating over list FILE *hKernelDirs, *hKernels, *hHeaderFile, *hTempHeaderFile; // TCHAR data type is char string used to represent a string of either the WCHAR or char type char SearchString[MAX_STRING_SIZE]; char KernelNameNoExt[MAX_STRING_SIZE]; char KernelNameFull[MAX_STRING_SIZE]; char KernelBinName[MAX_STRING_SIZE]; bool bKernelNames, bVerbose; char* pcHeaderFile, pcTempHeaderFile; unsigned int dwKernelCount, dwHeaderSize, dwTempHeaderSize, dwBytesRead; bVerbose = false; if (argc < 5) { fprintf(stderr, "Usage: GenKrnBin.exe [-verbose]\n"); exit (-1); } int idx = 5; // scan the command-line options from index 3 while (idx < argc) { if (StrCmp(argv[idx], "-verbose", 8) == 0) { bVerbose = true; } ++idx; } #ifdef LINUX_ sprintf(KERNEL_COMPONENT_DIR,"%s", argv[1]); strncpy(KERNEL_HEADER_PREFIX, argv[2], sizeof(KERNEL_HEADER_PREFIX)); strncpy(KERNEL_HEADER_GEN, argv[3], sizeof(KERNEL_HEADER_GEN)); strncpy(KERNEL_HEADER_KIND, argv[4], sizeof(KERNEL_HEADER_KIND)); strncpy(KERNEL_HEADER_PREFIX_UPPER, argv[2], sizeof(KERNEL_HEADER_PREFIX)); _strupr_s(KERNEL_HEADER_PREFIX_UPPER); sprintf(KERNEL_HEADER_FILE, "%s/ig%skrn_%s_%s.h", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX, KERNEL_HEADER_GEN, KERNEL_HEADER_KIND); sprintf(KERNEL_TEMP_HEADER_FILE, "%s/%stemp%s", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX, KERNEL_HEADER_FILE_NAME); sprintf(KERNEL_BINARY_FILE, "%s/ig%skrn_%s_%s.bin", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX, KERNEL_HEADER_GEN, KERNEL_HEADER_KIND); sprintf(KERNEL_SEARCH_DIR, "%s/g*", KERNEL_COMPONENT_DIR); sprintf(KERNEL_HEADER_SENTRY, "__%sKRNHEADER_H__", KERNEL_HEADER_PREFIX_UPPER); sprintf(KERNEL_IDR, "IDR_%s", KERNEL_HEADER_PREFIX_UPPER); #else sprintf(KERNEL_COMPONENT_DIR,"%s", argv[1]); strncpy(KERNEL_HEADER_PREFIX, argv[2], sizeof(KERNEL_HEADER_PREFIX)); strncpy(KERNEL_HEADER_PREFIX_UPPER, argv[2], sizeof(KERNEL_HEADER_PREFIX)); _strupr_s(KERNEL_HEADER_PREFIX_UPPER); sprintf(KERNEL_HEADER_FILE, "%s\\ig%skrn_g11_icllp.h", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX); sprintf(KERNEL_TEMP_HEADER_FILE, "%s\\%stemp%s", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX, KERNEL_HEADER_FILE_NAME); sprintf(KERNEL_BINARY_FILE, "%s\\ig%skrn_g11_icllp.bin", KERNEL_COMPONENT_DIR, KERNEL_HEADER_PREFIX); sprintf(KERNEL_SEARCH_DIR, "%s\\g*", KERNEL_COMPONENT_DIR); sprintf(KERNEL_HEADER_SENTRY, "__%sKRNHEADER_H__", KERNEL_HEADER_PREFIX_UPPER); sprintf(KERNEL_IDR, "IDR_%s", KERNEL_HEADER_PREFIX_UPPER); #endif bKernelNames = true; ///////////////////////////////////////////////// // Generate a superset list of all the kernels // ///////////////////////////////////////////////// #ifdef LINUX_ sprintf(SearchString, "%s", KERNEL_COMPONENT_DIR); struct dirent* ent = NULL; DIR *pDir=NULL; pDir=opendir(SearchString); int n; while (NULL != (ent=readdir(pDir))) { n = strlen(ent->d_name); //printf("kernel name = %s; ent->d_reclen = %d\n", ent->d_name, n); //printf("kernel offset= %s\n", ent->d_name + n - 4); if ((StrCmp(ent->d_name + n - 4, ".krn", 4) == 0) || (StrCmp(ent->d_name + n - 4, ".hex", 4) == 0)) { KernelList.push_back(string(ent->d_name)); continue; } else { continue; } }; closedir(pDir); #endif // include LinkFile.txt KernelList.push_back(string("LinkFile.krn")); // remove duplicate entries from the list (create superset) KernelList.sort(); // assumes list is sorted. removes subsequent consecutive equal values. KernelList.unique(); /////////////////////////////////////////////////////////////////// // Create a temp header that defines the indicies into the table // /////////////////////////////////////////////////////////////////// // create the header file that will define the kernel IDs hHeaderFile = fopen(KERNEL_HEADER_FILE, "w"); if (hHeaderFile == NULL) { fprintf(stderr, "Failed to open Temp Header File\n"); exit (-1); } // print the copyright comment text to the file fwrite(COPYRIGHT, 1, strlen(COPYRIGHT), hHeaderFile); fprintf(hHeaderFile, INDEX_OPEN_FORMAT_STRING); fprintf(hHeaderFile, INDEX_ENTRY_FORMAT_INT("LINKFILE_VERSION", LINKFILE_VERSION)); fprintf(hHeaderFile, INDEX_ENTRY_FORMAT_INT("LINKFILE_HEADER" , sizeof(LinkFileHeader))); fprintf(hHeaderFile, "\n"); for (iterator = KernelList.begin(), dwKernelCount = 0; iterator != KernelList.end(); iterator++, dwKernelCount++) { strncpy(KernelNameNoExt, iterator->c_str(), MAX_STRING_SIZE); *(strrchr(KernelNameNoExt, '.')) = '\0'; char *c; while ((c = strchr(KernelNameNoExt, '.')) != NULL) *c = '_'; fprintf(hHeaderFile, INDEX_ENTRY_FORMAT_STRING(KernelNameNoExt)); } fprintf(hHeaderFile, INDEX_ENTRY_FORMAT_STRING("TOTAL_NUM_KERNELS")); // kernel names are defined in the same sequence as they are loaded if (bKernelNames) { fprintf(hHeaderFile, "\n#if _DEBUG || _RELEASE_INTERNAL\n"); fprintf(hHeaderFile, KERNEL_NAME_DEFINE("KERNEL_NAMES")); for (iterator = KernelList.begin(), dwKernelCount = 0; iterator != KernelList.end(); iterator++, dwKernelCount++) { strncpy(KernelNameNoExt, iterator->c_str(), MAX_STRING_SIZE); *(strrchr(KernelNameNoExt, '.')) = '\0'; char *c; while ((c = strchr(KernelNameNoExt, '.')) != NULL) *c = '_'; fprintf(hHeaderFile, KERNEL_NAME_ENTRY(KernelNameNoExt)); } fprintf(hHeaderFile, " _" "T(\"\")\n"); fprintf(hHeaderFile, "#else // !_DEBUG\n"); fprintf(hHeaderFile, KERNEL_NAME_DEFINE("KERNEL_NAMES")); for (int i = 0; i < dwKernelCount; i++) { fprintf(hHeaderFile, KERNEL_ID_ENTRY(i)); } fprintf(hHeaderFile, " _" "T(\"\")\n"); fprintf(hHeaderFile, "#endif // _DEBUG\n"); } fprintf(hHeaderFile, INDEX_CLOSE_FORMAT_STRING); fprintf(hHeaderFile, "\n"); g_dwTotalKernelCount = dwKernelCount; fclose(hHeaderFile); /////////////////////////////////////////////////////////////////// // Create bin containing kernel table and actual kernel binaries // /////////////////////////////////////////////////////////////////// // allocate kernel offset table g_dwOffsetTableSize = (g_dwTotalKernelCount + 1) * sizeof(unsigned int); g_pOffsetTable = (unsigned int *)malloc(g_dwOffsetTableSize); if (!g_pOffsetTable) { fprintf(stderr, "Failed to allocate offset table\n"); exit (-1); } // do for every family specific folder // create the file that will be the concatenation of all kernel binaries sprintf(KernelBinName, "%s", KERNEL_BINARY_FILE); g_hKernelBinary = fopen(KernelBinName, "wb"); if (g_hKernelBinary == NULL) { fprintf(stderr, "Failed to open Kernel Bin File\n"); exit (-1); } // write empty offset table memset(g_pOffsetTable, 0, g_dwOffsetTableSize); fwrite( g_pOffsetTable, 1, g_dwOffsetTableSize, (FILE *)g_hKernelBinary); // create link information for the current family folder #ifdef LINUX_ sprintf(KernelNameFull, "%s", KERNEL_COMPONENT_DIR); #else sprintf(KernelNameFull, "%s", KERNEL_COMPONENT_DIR); #endif CreateLinkFile(KernelNameFull, KernelList); // for every kernel in the superset list g_dwCurrentKernel = 0; for (iterator = KernelList.begin(); iterator != KernelList.end(); iterator++, g_dwCurrentKernel++) { // check if this kernel exists for this platform // cFileName contains file name #ifdef LINUX_ sprintf(KernelNameFull, "%s/%s", KERNEL_COMPONENT_DIR, iterator->c_str()); #else sprintf(KernelNameFull, "%s\\%s", KERNEL_COMPONENT_DIR, iterator->c_str()); #endif // add kernel binary, update offset table ConcatenateKernelBinary(KernelNameFull, bVerbose); } // write offset table fseek(g_hKernelBinary, 0, SEEK_SET); fwrite(g_pOffsetTable, 1, g_dwOffsetTableSize, g_hKernelBinary); fclose(g_hKernelBinary); #ifdef LINUX_ sprintf(KernelNameFull, "%s", KERNEL_COMPONENT_DIR); #else sprintf(KernelNameFull, "%s", KERNEL_COMPONENT_DIR); #endif DeleteLinkFile(KernelNameFull); // free offset table if (g_pOffsetTable) { free(g_pOffsetTable); } return 0; } void ConcatenateKernelBinary(char *pKernelName, bool bVerbose) { FILE *hKernel; char pBuffer[MAX_STRING_SIZE]; unsigned int dwBytesRead, dwBytesWritten, dwBinaryPos, dwFileSize; int iLength; // update offset table dwBinaryPos = ftell(g_hKernelBinary) - g_dwOffsetTableSize; g_pOffsetTable[g_dwCurrentKernel] = dwBinaryPos; // the function opens an existing file and returns a handle that can be used to access the object // open .krn/.hex file hKernel = fopen(pKernelName, "r"); if (hKernel == NULL) { fclose(hKernel); g_pOffsetTable[g_dwCurrentKernel + 1] = dwBinaryPos; return; } else { fseek(hKernel, 0, SEEK_END); dwFileSize = ftell(hKernel); fseek(hKernel, 0, SEEK_SET); } // print kernel name processed if (bVerbose) { fprintf(stderr, "%s\n", pKernelName); } // .hex file iLength = strlen(pKernelName); if (StrCmp(&pKernelName[iLength-4], ".hex", 4) == 0) { int iLine = 1; char pBinBuffer[MAX_STRING_SIZE]; int iBinLeft = MAX_STRING_SIZE; unsigned int * pBinCurrent = (unsigned int *)pBinBuffer; char *pBuffCurrent = pBuffer; int iBuffLeft = 0; dwBytesRead = 0; do { // shift and read hex data if (iBuffLeft < 35) { // move incomplete line to the beginning of the buffer if (iBuffLeft) { memcpy(pBuffer, pBuffCurrent, iBuffLeft); } // fill buffer (leave room for 0 at the end of the string) pBuffCurrent = pBuffer; if (dwBytesRead = fread(pBuffCurrent + iBuffLeft, 1, sizeof(pBuffer) - iBuffLeft - 1, hKernel)) { // add data iBuffLeft += dwBytesRead; // terminate string with 0 to avoid parsing issues pBuffCurrent[iBuffLeft] = 0; // no data to read - EOF if (dwBytesRead == 0) { if (iBuffLeft > 4) { fprintf(stderr, "Hex file %s is not 32 bytes aligned. Left %d bytes not processed. May have critical issue!!!\n", pKernelName, iBuffLeft); } iBuffLeft = -1; } } else { if (iBuffLeft > 4) { fprintf(stderr, "Hex file %s is not 32 bytes aligned. Left %d bytes not processed. May have critical issue!!!\n", pKernelName, iBuffLeft); } iBuffLeft = -1; } } // process hex data one line at a time (35 chars => "xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx") while (iBuffLeft >= 35 && iBinLeft > 0) { // skip CR/LF/TAB (control characters) while (iBuffLeft > 35 && *pBuffCurrent < 32) { pBuffCurrent++; iBuffLeft--; } // convert hex to bin (4 DW = 16 B = 128 bits/line) if ( 4 != sscanf(pBuffCurrent, "%08x %08x %08x %08x", pBinCurrent, pBinCurrent+1, pBinCurrent+2, pBinCurrent+3) ) { fprintf(stderr, "Fail to process file %s at line %d\n", pKernelName, iLine); exit(-1); } // line counter iLine++; // increment hex buffer pBuffCurrent += 35; iBuffLeft -= 35; // increment bin buffer pBinCurrent += 4; iBinLeft -= 4 * sizeof(unsigned int); } if (iBinLeft == 0 || iBuffLeft < 0) { // get actual size of binary buffer dwBytesRead = sizeof(pBinBuffer) - iBinLeft; dwBinaryPos = ftell(g_hKernelBinary); fwrite(pBinBuffer, 1, dwBytesRead, g_hKernelBinary); if (iBuffLeft >= 0) { pBinCurrent = (unsigned int *)pBinBuffer; iBinLeft = sizeof(pBinBuffer); } } } while (dwBytesRead > 0 && iBuffLeft >= 0); } else { if (fread(pBuffer, 1, sizeof(pBuffer), hKernel)) { dwBinaryPos = ftell(g_hKernelBinary); fwrite(pBuffer, 1, dwFileSize, g_hKernelBinary); } } dwBinaryPos = ftell(g_hKernelBinary) - g_dwOffsetTableSize; g_pOffsetTable[g_dwCurrentKernel+1] = dwBinaryPos; // close kernel file if (hKernel != NULL) fclose(hKernel); }