--- /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
+//\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
+\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
+ // 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
+ 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
+ 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
+ } 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
+ do {\r
+ Status = MicrocodeReadData (InFptr, &Data);\r
+ if (Status == STATUS_SUCCESS) {\r
+ *(unsigned int *) Ptr = Data;\r
+ Ptr += sizeof (Data);\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