+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2004-2006 Intel Corporation. All rights reserved\r
-This program and the accompanying materials are licensed and made available \r
-under the terms and conditions of the BSD License which accompanies this \r
-distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- Microcode.c\r
-\r
-Abstract:\r
-\r
- Utility for working with microcode patch files in the Intel \r
- Platform Innovation Framework for EFI build environment.\r
-\r
---*/\r
-\r
-#include <stdio.h>\r
-#include <string.h> // for memset()\r
-#include <ctype.h>\r
-#include <stdlib.h> // for malloc()\r
-\r
-#include "EfiUtilityMsgs.h"\r
-#include "Microcode.h"\r
-\r
-#define MAX_LINE_LEN 256\r
-\r
-#define STATUS_IGNORE 0xA\r
-\r
-//\r
-// Structure definition for a microcode header\r
-//\r
-typedef struct {\r
- unsigned int HeaderVersion;\r
- unsigned int PatchId;\r
- unsigned int Date;\r
- unsigned int CpuId;\r
- unsigned int Checksum;\r
- unsigned int LoaderVersion;\r
- unsigned int PlatformId;\r
- unsigned int DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid\r
- unsigned int TotalSize; // number of bytes\r
- unsigned int Reserved[3];\r
-} MICROCODE_IMAGE_HEADER;\r
-\r
-static\r
-STATUS\r
-MicrocodeReadData (\r
- FILE *InFptr,\r
- unsigned int *Data\r
- );\r
-\r
-void\r
-MicrocodeConstructor (\r
- void\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Constructor of module Microcode\r
-\r
-Arguments:\r
-\r
- None\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-{\r
-}\r
-\r
-void\r
-MicrocodeDestructor (\r
- void\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Destructor of module Microcode\r
-\r
-Arguments:\r
-\r
- None\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-{\r
-}\r
-\r
-static\r
-STATUS\r
-MicrocodeReadData (\r
- FILE *InFptr,\r
- unsigned int *Data\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Read a 32-bit microcode data value from a text file and convert to raw binary form.\r
-\r
-Arguments:\r
- InFptr - file pointer to input text file\r
- Data - pointer to where to return the data parsed\r
-\r
-Returns:\r
- STATUS_SUCCESS - no errors or warnings, Data contains valid information\r
- STATUS_ERROR - errors were encountered\r
-\r
---*/\r
-{\r
- char Line[MAX_LINE_LEN];\r
- char *cptr;\r
- unsigned int ctr;\r
-\r
- Line[MAX_LINE_LEN - 1] = 0;\r
- *Data = 0;\r
- if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {\r
- return STATUS_ERROR;\r
- }\r
- //\r
- // If it was a binary file, then it may have overwritten our null terminator\r
- //\r
- if (Line[MAX_LINE_LEN - 1] != 0) {\r
- return STATUS_ERROR;\r
- }\r
-\r
- // Strip leading white-space characters (except carriage returns) from Line\r
- //\r
- if (isspace(Line[0]) && Line[0] != '\n') {\r
- while (isspace(Line[0])) {\r
- for (ctr = 0; ctr < strlen(Line); ctr++)\r
- if (Line[ctr] != '\n')\r
- Line[ctr] = Line[ctr + 1];\r
- }\r
- }\r
-\r
- //\r
- // Look for\r
- // dd 000000001h ; comment\r
- // dd XXXXXXXX\r
- // DD XXXXXXXXX\r
- // DD XXXXXXXXX\r
- //\r
- for (cptr = Line; *cptr && isspace(*cptr); cptr++) {\r
- }\r
- if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {\r
- //\r
- // Skip blanks and look for a hex digit\r
- //\r
- cptr += 3;\r
- for (; *cptr && isspace(*cptr); cptr++) {\r
- }\r
- if (isxdigit (*cptr)) {\r
- if (sscanf (cptr, "%X", Data) != 1) {\r
- return STATUS_ERROR;\r
- }\r
- }\r
- return STATUS_SUCCESS;\r
- }\r
- if (strlen(Line) == 1) {\r
- return STATUS_IGNORE;\r
- }\r
- if (tolower(cptr[0]) == ';') {\r
- return STATUS_IGNORE;\r
- }\r
- return STATUS_ERROR;\r
-}\r
-\r
-STATUS\r
-MicrocodeParseFile (\r
- char *InFileName,\r
- char *OutFileName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Parse a microcode text file, and write the binary results to an output file.\r
-\r
-Arguments:\r
- InFileName - input text file to parse\r
- OutFileName - output file to write raw binary data from parsed input file\r
-\r
-Returns:\r
- STATUS_SUCCESS - no errors or warnings\r
- STATUS_ERROR - errors were encountered\r
-\r
---*/\r
-{\r
- FILE *InFptr;\r
- FILE *OutFptr;\r
- STATUS Status;\r
- MICROCODE_IMAGE_HEADER *Header;\r
- unsigned int Size;\r
- unsigned int Size2;\r
- unsigned int Data;\r
- unsigned int Checksum;\r
- char *Buffer;\r
- char *Ptr;\r
- char *OrigPtr;\r
- unsigned int TotalSize;\r
-\r
- Status = STATUS_ERROR;\r
- InFptr = NULL;\r
- OutFptr = NULL;\r
- Buffer = NULL;\r
- //\r
- // Open the input text file\r
- //\r
- if ((InFptr = fopen (InFileName, "r")) == NULL) {\r
- Error (NULL, 0, 0, InFileName, "failed to open input microcode file for reading");\r
- return STATUS_ERROR;\r
- }\r
- //\r
- // Make two passes on the input file. The first pass is to determine how\r
- // much data is in the file so we can allocate a working buffer. Then\r
- // we'll allocate a buffer and re-read the file into the buffer for processing.\r
- //\r
- Size = 0;\r
- do {\r
- Status = MicrocodeReadData (InFptr, &Data);\r
- if (Status == STATUS_SUCCESS) {\r
- Size += sizeof (Data);\r
- }\r
- if (Status == STATUS_IGNORE) {\r
- Status = STATUS_SUCCESS;\r
- }\r
- } while (Status == STATUS_SUCCESS);\r
- //\r
- // Error if no data.\r
- //\r
- if (Size == 0) {\r
- Error (NULL, 0, 0, InFileName, "no parse-able data found in file");\r
- goto Done;\r
- }\r
- if (Size < sizeof (MICROCODE_IMAGE_HEADER)) {\r
- Error (NULL, 0, 0, InFileName, "amount of parse-able data is insufficient to contain a microcode header");\r
- goto Done;\r
- }\r
- //\r
- // Allocate a buffer for the data\r
- //\r
- Buffer = (char *) _malloc (Size);\r
- if (Buffer == NULL) {\r
- Error (NULL, 0, 0, "memory allocation failure", NULL);\r
- goto Done;\r
- }\r
- //\r
- // Re-read the file, storing the data into our buffer\r
- //\r
- fseek (InFptr, 0, SEEK_SET);\r
- Ptr = Buffer;\r
- OrigPtr = Ptr;\r
- do {\r
- OrigPtr = Ptr;\r
- Status = MicrocodeReadData (InFptr, &Data);\r
- if (Status == STATUS_SUCCESS) {\r
- *(unsigned int *) Ptr = Data;\r
- Ptr += sizeof (Data);\r
- }\r
- if (Status == STATUS_IGNORE) {\r
- Ptr = OrigPtr;\r
- Status = STATUS_SUCCESS;\r
- }\r
- } while (Status == STATUS_SUCCESS);\r
- //\r
- // Can't do much checking on the header because, per the spec, the\r
- // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,\r
- // and the TotalSize field is invalid (actually missing). Thus we can't\r
- // even verify the Reserved fields are 0.\r
- //\r
- Header = (MICROCODE_IMAGE_HEADER *) Buffer;\r
- if (Header->DataSize == 0) {\r
- TotalSize = 2048;\r
- } else {\r
- TotalSize = Header->TotalSize;\r
- }\r
- if (TotalSize != Size) {\r
- Error (NULL, 0, 0, InFileName, "file contents do not contain expected TotalSize 0x%04X", TotalSize);\r
- goto Done;\r
- }\r
- //\r
- // Checksum the contents\r
- //\r
- Ptr = Buffer;\r
- Checksum = 0;\r
- Size2 = 0;\r
- while (Size2 < Size) {\r
- Checksum += *(unsigned int *) Ptr;\r
- Ptr += 4;\r
- Size2 += 4;\r
- }\r
- if (Checksum != 0) {\r
- Error (NULL, 0, 0, InFileName, "checksum failed on file contents");\r
- goto Done;\r
- }\r
- //\r
- // Open the output file and write the buffer contents\r
- //\r
- if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
- Error (NULL, 0, 0, OutFileName, "failed to open output microcode file for writing");\r
- goto Done;\r
- }\r
- if (fwrite (Buffer, Size, 1, OutFptr) != 1) {\r
- Error (NULL, 0, 0, OutFileName, "failed to write microcode data to output file");\r
- goto Done;\r
- }\r
- Status = STATUS_SUCCESS;\r
-Done:\r
- if (Buffer != NULL) {\r
- free (Buffer);\r
- }\r
- if (InFptr != NULL) {\r
- fclose (InFptr);\r
- }\r
- if (OutFptr != NULL) {\r
- fclose (OutFptr);\r
- if (Status == STATUS_ERROR) {\r
- remove (OutFileName);\r
- }\r
- }\r
- return Status;\r
-}\r