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