git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2066 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			2763 lines
		
	
	
		
			80 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2763 lines
		
	
	
		
			80 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
i
 | 
						|
 | 
						|
Copyright (c) 2004, 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:
 | 
						|
 | 
						|
  GenFvImageLib.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  This file contains functions required to generate a Firmware Volume.
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
//
 | 
						|
// Include files
 | 
						|
//
 | 
						|
#ifdef __GNUC__
 | 
						|
#include <uuid/uuid.h>
 | 
						|
#include <sys/stat.h>
 | 
						|
#endif
 | 
						|
#include <string.h>
 | 
						|
#ifndef __GNUC__
 | 
						|
#include <io.h>
 | 
						|
#endif
 | 
						|
#include <assert.h>
 | 
						|
 | 
						|
#include <Common/UefiBaseTypes.h>
 | 
						|
#include <Common/FirmwareVolumeImageFormat.h>
 | 
						|
#include <Common/Variable.h>
 | 
						|
#include <Common/WorkingBlockHeader.h>
 | 
						|
#include <Guid/FirmwareFileSystem.h>
 | 
						|
 | 
						|
#include "GenFvImageLib.h"
 | 
						|
#include "GenFvImageLibInternal.h"
 | 
						|
#include "CommonLib.h"
 | 
						|
#include "Crc32.h"
 | 
						|
#include "EfiUtilityMsgs.h"
 | 
						|
#include "FvLib.h"
 | 
						|
#include "Compress.h"
 | 
						|
#include "WinNtInclude.h"
 | 
						|
 | 
						|
//
 | 
						|
// Different file separater for Linux and Windows
 | 
						|
//
 | 
						|
#ifdef __GNUC__
 | 
						|
#define FILE_SEP_CHAR '/'
 | 
						|
#define FILE_SEP_STRING "/"
 | 
						|
#else
 | 
						|
#define FILE_SEP_CHAR '\\'
 | 
						|
#define FILE_SEP_STRING "\\"
 | 
						|
#endif
 | 
						|
 | 
						|
static UINT32 MaxFfsAlignment = 0;
 | 
						|
//
 | 
						|
// Local function prototypes
 | 
						|
//
 | 
						|
EFI_STATUS
 | 
						|
GetPe32Info (
 | 
						|
  IN UINT8                  *Pe32,
 | 
						|
  OUT UINT32                *EntryPoint,
 | 
						|
  OUT UINT32                *BaseOfCode,
 | 
						|
  OUT UINT16                *MachineType
 | 
						|
  );
 | 
						|
 | 
						|
//
 | 
						|
// Local function implementations.
 | 
						|
//
 | 
						|
EFI_GUID  FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;
 | 
						|
EFI_GUID  DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };
 | 
						|
 | 
						|
//
 | 
						|
// This data array will be located at the base of the Firmware Volume Header (FVH)
 | 
						|
// in the boot block.  It must not exceed 14 bytes of code.  The last 2 bytes
 | 
						|
// will be used to keep the FVH checksum consistent.
 | 
						|
// This code will be run in response to a starutp IPI for HT-enabled systems.
 | 
						|
//
 | 
						|
#define SIZEOF_STARTUP_DATA_ARRAY 0x10
 | 
						|
 | 
						|
UINT8                                   m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
 | 
						|
  //
 | 
						|
  // EA D0 FF 00 F0               ; far jmp F000:FFD0
 | 
						|
  // 0, 0, 0, 0, 0, 0, 0, 0, 0,   ; Reserved bytes
 | 
						|
  // 0, 0                         ; Checksum Padding
 | 
						|
  //
 | 
						|
  0xEA,
 | 
						|
  0xD0,
 | 
						|
  0xFF,
 | 
						|
  0x0,
 | 
						|
  0xF0,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00
 | 
						|
};
 | 
						|
 | 
						|
UINT8                                   m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
 | 
						|
  //
 | 
						|
  // EB CE                               ; jmp short ($-0x30)
 | 
						|
  // ; (from offset 0x0 to offset 0xFFD0)
 | 
						|
  // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
 | 
						|
  // 0, 0                                ; Checksum Padding
 | 
						|
  //
 | 
						|
  0xEB,
 | 
						|
  0xCE,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00,
 | 
						|
  0x00
 | 
						|
};
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
ParseFvInf (
 | 
						|
  IN MEMORY_FILE  *InfFile,
 | 
						|
  IN FV_INFO      *FvInfo
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function parses a FV.INF file and copies info into a FV_INFO structure.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  InfFile         Memory file image.
 | 
						|
  FvInfo          Information read from INF file.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS       INF file information successfully retrieved.
 | 
						|
  EFI_ABORTED       INF file has an invalid format.
 | 
						|
  EFI_NOT_FOUND     A required string was not found in the INF file.
 | 
						|
--*/
 | 
						|
{
 | 
						|
  CHAR8       Value[_MAX_PATH];
 | 
						|
  UINT64      Value64;
 | 
						|
  UINTN       Index;
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize FV info
 | 
						|
  //
 | 
						|
  memset (FvInfo, 0, sizeof (FV_INFO));
 | 
						|
 | 
						|
  //
 | 
						|
  // Read the FV base address
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Get the base address
 | 
						|
    //
 | 
						|
    Status = AsciiStringToUint64 (Value, FALSE, &Value64);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value");
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
 | 
						|
    FvInfo->BaseAddress = Value64;
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value");
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the FV Guid
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Get the guid value
 | 
						|
    //
 | 
						|
    Status = StringToGuid (Value, &FvInfo->FvGuid);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the FV file name
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // copy the file name
 | 
						|
    //
 | 
						|
    strcpy (FvInfo->FvName, Value);
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified");
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the Sym file name
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // copy the file name
 | 
						|
    //
 | 
						|
    strcpy (FvInfo->SymName, Value);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Symbols not required, so init to NULL.
 | 
						|
    //
 | 
						|
    strcpy (FvInfo->SymName, "");
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the read disabled capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update the read disabled flag
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the read enabled capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update the read disabled flag
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the read status attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update the read disabled flag
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_READ_STATUS;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the write disabled capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update the write disabled flag
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the write enabled capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update the write disabled flag
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the write status attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update the write disabled flag
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the lock capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update the attribute flag
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the lock status attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update the attribute flag
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the sticky write attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update the attribute flag
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the memory mapped attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update the attribute flag
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the erase polarity attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update the attribute flag
 | 
						|
    //
 | 
						|
    if (strcmp (Value, ONE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY;
 | 
						|
    } else if (strcmp (Value, ZERO_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the alignment capabilities attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the word alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the dword alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the word alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the qword alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 32 byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 64 byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 128 byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 256 byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 512 byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 1K byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 2K byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 4K byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 8K byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 16K byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 32K byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the 64K byte alignment capability attribute
 | 
						|
  //
 | 
						|
  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value);
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Update attribute
 | 
						|
    //
 | 
						|
    if (strcmp (Value, TRUE_STRING) == 0) {
 | 
						|
      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K;
 | 
						|
    } else if (strcmp (Value, FALSE_STRING) != 0) {
 | 
						|
      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified");
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) &&
 | 
						|
      (
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) ||
 | 
						|
        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K)
 | 
						|
      )
 | 
						|
     ) {
 | 
						|
    Error (
 | 
						|
      NULL,
 | 
						|
      0,
 | 
						|
      0,
 | 
						|
      "illegal combination of alignment attributes",
 | 
						|
      "if %s is not %s, no individual alignments can be %s",
 | 
						|
      EFI_FVB_ALIGNMENT_CAP_STRING,
 | 
						|
      TRUE_STRING,
 | 
						|
      TRUE_STRING
 | 
						|
      );
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read block maps
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {
 | 
						|
    //
 | 
						|
    // Read the number of blocks
 | 
						|
    //
 | 
						|
    Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);
 | 
						|
 | 
						|
    if (Status == EFI_SUCCESS) {
 | 
						|
      //
 | 
						|
      // Update the number of blocks
 | 
						|
      //
 | 
						|
      Status = AsciiStringToUint64 (Value, FALSE, &Value64);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING);
 | 
						|
        return EFI_ABORTED;
 | 
						|
      }
 | 
						|
 | 
						|
      FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // If there is no number of blocks, but there is a size, then we have a mismatched pair
 | 
						|
      // and should return an error.
 | 
						|
      //
 | 
						|
      Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
 | 
						|
        return EFI_ABORTED;
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // We are done
 | 
						|
        //
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Read the size of blocks
 | 
						|
    //
 | 
						|
    Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
 | 
						|
 | 
						|
    if (Status == EFI_SUCCESS) {
 | 
						|
      //
 | 
						|
      // Update the number of blocks
 | 
						|
      //
 | 
						|
      Status = AsciiStringToUint64 (Value, FALSE, &Value64);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING);
 | 
						|
        return EFI_ABORTED;
 | 
						|
      }
 | 
						|
 | 
						|
      FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // There is a number of blocks, but there is no size, so we have a mismatched pair
 | 
						|
      // and should return an error.
 | 
						|
      //
 | 
						|
      Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read files
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {
 | 
						|
    //
 | 
						|
    // Read the number of blocks
 | 
						|
    //
 | 
						|
    Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);
 | 
						|
 | 
						|
    if (Status == EFI_SUCCESS) {
 | 
						|
      //
 | 
						|
      // Add the file
 | 
						|
      //
 | 
						|
      strcpy (FvInfo->FvFiles[Index], Value);
 | 
						|
    } else {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (FindSection (InfFile, COMPONENT_SECTION_STRING)) {
 | 
						|
    Index = 0;
 | 
						|
    //
 | 
						|
    // Read component FV_VARIABLE
 | 
						|
    //
 | 
						|
    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_VARIABLE_STRING, 0, Value);
 | 
						|
 | 
						|
    if (Status == EFI_SUCCESS) {
 | 
						|
      //
 | 
						|
      // Add the component
 | 
						|
      //
 | 
						|
      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING);
 | 
						|
      Status = AsciiStringToUint64 (Value, FALSE, &Value64);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING);
 | 
						|
        return EFI_ABORTED;
 | 
						|
      }
 | 
						|
 | 
						|
      FvInfo->FvComponents[Index].Size = (UINTN) Value64;
 | 
						|
    } else {
 | 
						|
      printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING);
 | 
						|
    }
 | 
						|
 | 
						|
    Index++;
 | 
						|
    //
 | 
						|
    // Read component FV_EVENT_LOG
 | 
						|
    //
 | 
						|
    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value);
 | 
						|
 | 
						|
    if (Status == EFI_SUCCESS) {
 | 
						|
      //
 | 
						|
      // Add the component
 | 
						|
      //
 | 
						|
      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING);
 | 
						|
      Status = AsciiStringToUint64 (Value, FALSE, &Value64);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING);
 | 
						|
        return EFI_ABORTED;
 | 
						|
      }
 | 
						|
 | 
						|
      FvInfo->FvComponents[Index].Size = (UINTN) Value64;
 | 
						|
    } else {
 | 
						|
      printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING);
 | 
						|
    }
 | 
						|
 | 
						|
    Index++;
 | 
						|
    //
 | 
						|
    // Read component FV_FTW_WORKING
 | 
						|
    //
 | 
						|
    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value);
 | 
						|
 | 
						|
    if (Status == EFI_SUCCESS) {
 | 
						|
      //
 | 
						|
      // Add the component
 | 
						|
      //
 | 
						|
      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING);
 | 
						|
      Status = AsciiStringToUint64 (Value, FALSE, &Value64);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING);
 | 
						|
        return EFI_ABORTED;
 | 
						|
      }
 | 
						|
 | 
						|
      FvInfo->FvComponents[Index].Size = (UINTN) Value64;
 | 
						|
    } else {
 | 
						|
      printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING);
 | 
						|
    }
 | 
						|
 | 
						|
    Index++;
 | 
						|
    //
 | 
						|
    // Read component FV_FTW_SPARE
 | 
						|
    //
 | 
						|
    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value);
 | 
						|
 | 
						|
    if (Status == EFI_SUCCESS) {
 | 
						|
      //
 | 
						|
      // Add the component
 | 
						|
      //
 | 
						|
      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING);
 | 
						|
      Status = AsciiStringToUint64 (Value, FALSE, &Value64);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING);
 | 
						|
        return EFI_ABORTED;
 | 
						|
      }
 | 
						|
 | 
						|
      FvInfo->FvComponents[Index].Size = (UINTN) Value64;
 | 
						|
    } else {
 | 
						|
      printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Compute size for easy access later
 | 
						|
  //
 | 
						|
  FvInfo->Size = 0;
 | 
						|
  for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {
 | 
						|
    FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
UpdateFfsFileState (
 | 
						|
  IN EFI_FFS_FILE_HEADER          *FfsFile,
 | 
						|
  IN EFI_FIRMWARE_VOLUME_HEADER   *FvHeader
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function changes the FFS file attributes based on the erase polarity
 | 
						|
  of the FV.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FfsFile   File header.
 | 
						|
  FvHeader  FV header.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
 | 
						|
    FfsFile->State = (UINT8)~(FfsFile->State);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
ReadFfsAlignment (
 | 
						|
  IN EFI_FFS_FILE_HEADER    *FfsFile,
 | 
						|
  IN OUT UINT32             *Alignment
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function determines the alignment of the FFS input file from the file
 | 
						|
  attributes.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FfsFile       FFS file to parse
 | 
						|
  Alignment     The minimum required alignment of the FFS file, in bytes
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS              The function completed successfully.
 | 
						|
  EFI_INVALID_PARAMETER    One of the input parameters was invalid.
 | 
						|
  EFI_ABORTED              An error occurred.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Verify input parameters.
 | 
						|
  //
 | 
						|
  if (FfsFile == NULL || Alignment == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  switch ((FfsFile->Attributes >> 3) & 0x07) {
 | 
						|
 | 
						|
  case 0:
 | 
						|
    //
 | 
						|
    // 8 byte alignment, mini alignment requirement for FFS file. 
 | 
						|
    //
 | 
						|
    *Alignment = (1 << 3);
 | 
						|
    break;
 | 
						|
 | 
						|
  case 1:
 | 
						|
    //
 | 
						|
    // 16 byte alignment
 | 
						|
    //
 | 
						|
    *Alignment = (1 << 4);
 | 
						|
    break;
 | 
						|
 | 
						|
  case 2:
 | 
						|
    //
 | 
						|
    // 128 byte alignment
 | 
						|
    //
 | 
						|
    *Alignment = (1 << 7);
 | 
						|
    break;
 | 
						|
 | 
						|
  case 3:
 | 
						|
    //
 | 
						|
    // 512 byte alignment
 | 
						|
    //
 | 
						|
    *Alignment = (1 << 9);
 | 
						|
    break;
 | 
						|
 | 
						|
  case 4:
 | 
						|
    //
 | 
						|
    // 1K byte alignment
 | 
						|
    //
 | 
						|
    *Alignment = (1 << 10);
 | 
						|
    break;
 | 
						|
 | 
						|
  case 5:
 | 
						|
    //
 | 
						|
    // 4K byte alignment
 | 
						|
    //
 | 
						|
    *Alignment = (1 << 12);
 | 
						|
    break;
 | 
						|
 | 
						|
  case 6:
 | 
						|
    //
 | 
						|
    // 32K byte alignment
 | 
						|
    //
 | 
						|
    *Alignment = (1 << 15);
 | 
						|
    break;
 | 
						|
 | 
						|
  case 7:
 | 
						|
    //
 | 
						|
    // 64K byte alignment
 | 
						|
    //
 | 
						|
    *Alignment = (1 << 16);
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
AddPadFile (
 | 
						|
  IN OUT MEMORY_FILE  *FvImage,
 | 
						|
  IN UINT32           DataAlignment
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function adds a pad file to the FV image if it required to align the
 | 
						|
  data of the next file.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FvImage         The memory image of the FV to add it to.  The current offset
 | 
						|
                  must be valid.
 | 
						|
  DataAlignment   The data alignment of the next FFS file.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS              The function completed successfully.
 | 
						|
  EFI_INVALID_PARAMETER    One of the input parameters was invalid.
 | 
						|
  EFI_OUT_OF_RESOURCES     Insufficient resources exist in the FV to complete
 | 
						|
                           the pad file add.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_FFS_FILE_HEADER *PadFile;
 | 
						|
  EFI_GUID            PadFileGuid;
 | 
						|
  UINTN               PadFileSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify input parameters.
 | 
						|
  //
 | 
						|
  if (FvImage == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Basic assumption is we start from an 8 byte aligned address
 | 
						|
  // and our file header is a multiple of 8 bytes
 | 
						|
  //
 | 
						|
  assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);
 | 
						|
  assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check if a pad file is necessary
 | 
						|
  //
 | 
						|
  if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Write pad file header
 | 
						|
  //
 | 
						|
  PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify that we have enough space for the file header
 | 
						|
  //
 | 
						|
  if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
#ifdef __GNUC__
 | 
						|
  {
 | 
						|
    uuid_t tmp_id;
 | 
						|
    uuid_generate (tmp_id);
 | 
						|
    memcpy (&PadFileGuid, tmp_id, sizeof (EFI_GUID));
 | 
						|
  }
 | 
						|
#else
 | 
						|
  UuidCreate (&PadFileGuid);
 | 
						|
#endif
 | 
						|
  memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
 | 
						|
  memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));
 | 
						|
  PadFile->Type       = EFI_FV_FILETYPE_FFS_PAD;
 | 
						|
  PadFile->Attributes = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Calculate the pad file size
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // This is the earliest possible valid offset (current plus pad file header
 | 
						|
  // plus the next file header)
 | 
						|
  //
 | 
						|
  PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);
 | 
						|
 | 
						|
  //
 | 
						|
  // Add whatever it takes to get to the next aligned address
 | 
						|
  //
 | 
						|
  while ((PadFileSize % DataAlignment) != 0) {
 | 
						|
    PadFileSize++;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Subtract the next file header size
 | 
						|
  //
 | 
						|
  PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);
 | 
						|
 | 
						|
  //
 | 
						|
  // Subtract the starting offset to get size
 | 
						|
  //
 | 
						|
  PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;
 | 
						|
 | 
						|
  //
 | 
						|
  // Write pad file size (calculated size minus next file header size)
 | 
						|
  //
 | 
						|
  PadFile->Size[0]  = (UINT8) (PadFileSize & 0xFF);
 | 
						|
  PadFile->Size[1]  = (UINT8) ((PadFileSize >> 8) & 0xFF);
 | 
						|
  PadFile->Size[2]  = (UINT8) ((PadFileSize >> 16) & 0xFF);
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill in checksums and state, they must be 0 for checksumming.
 | 
						|
  //
 | 
						|
  PadFile->IntegrityCheck.Checksum.Header = 0;
 | 
						|
  PadFile->IntegrityCheck.Checksum.File   = 0;
 | 
						|
  PadFile->State                          = 0;
 | 
						|
  PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
 | 
						|
  if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
 | 
						|
    PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);
 | 
						|
  } else {
 | 
						|
    PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
 | 
						|
  }
 | 
						|
 | 
						|
  PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
 | 
						|
  UpdateFfsFileState (
 | 
						|
    (EFI_FFS_FILE_HEADER *) PadFile,
 | 
						|
    (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify that we have enough space (including the padding
 | 
						|
  //
 | 
						|
  if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Update the current FV pointer
 | 
						|
  //
 | 
						|
  FvImage->CurrentFilePointer += PadFileSize;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
IsVtfFile (
 | 
						|
  IN EFI_FFS_FILE_HEADER    *FileBuffer
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function checks the header to validate if it is a VTF file
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FileBuffer     Buffer in which content of a file has been read.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  TRUE    If this is a VTF file
 | 
						|
  FALSE   If this is not a VTF file
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_GUID  VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
 | 
						|
  if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {
 | 
						|
    return TRUE;
 | 
						|
  } else {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
FfsRebaseImageRead (
 | 
						|
  IN     VOID    *FileHandle,
 | 
						|
  IN     UINTN   FileOffset,
 | 
						|
  IN OUT UINT32  *ReadSize,
 | 
						|
  OUT    VOID    *Buffer
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FileHandle - The handle to the PE/COFF file
 | 
						|
 | 
						|
  FileOffset - The offset, in bytes, into the file to read
 | 
						|
 | 
						|
  ReadSize   - The number of bytes to read from the file starting at FileOffset
 | 
						|
 | 
						|
  Buffer     - A pointer to the buffer to read the data into.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  CHAR8   *Destination8;
 | 
						|
  CHAR8   *Source8;
 | 
						|
  UINT32  Length;
 | 
						|
 | 
						|
  Destination8  = Buffer;
 | 
						|
  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
 | 
						|
  Length        = *ReadSize;
 | 
						|
  while (Length--) {
 | 
						|
    *(Destination8++) = *(Source8++);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
AddSymFile (
 | 
						|
  IN UINT64               BaseAddress,
 | 
						|
  IN EFI_FFS_FILE_HEADER  *FfsFile,
 | 
						|
  IN OUT MEMORY_FILE      *SymImage,
 | 
						|
  IN CHAR8                *SourceFileName
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function adds the SYM tokens in the source file to the destination file.
 | 
						|
  The SYM tokens are updated to reflect the base address.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  BaseAddress     The base address for the new SYM tokens.
 | 
						|
  FfsFile         Pointer to the beginning of the FFS file in question.
 | 
						|
  SymImage        The memory file to update with symbol information.
 | 
						|
  SourceFileName  The source file.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS              The function completed successfully.
 | 
						|
  EFI_INVALID_PARAMETER    One of the input parameters was invalid.
 | 
						|
  EFI_ABORTED              An error occurred.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  FILE                      *SourceFile;
 | 
						|
 | 
						|
  CHAR8                     Buffer[_MAX_PATH];
 | 
						|
  CHAR8                     Type[_MAX_PATH];
 | 
						|
  CHAR8                     Address[_MAX_PATH];
 | 
						|
  CHAR8                     Section[_MAX_PATH];
 | 
						|
  CHAR8                     Token[_MAX_PATH];
 | 
						|
  CHAR8                     SymFileName[_MAX_PATH];
 | 
						|
  CHAR8                     CodeModuleName[_MAX_PATH];
 | 
						|
  CHAR8                     *Ptr;
 | 
						|
 | 
						|
  UINT64                    TokenAddress;
 | 
						|
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_FILE_SECTION_POINTER  Pe32Section;
 | 
						|
  UINT32                    EntryPoint;
 | 
						|
  UINT32                    BaseOfCode;
 | 
						|
  UINT16                    MachineType;
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify input parameters.
 | 
						|
  //
 | 
						|
  if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {
 | 
						|
    Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check if we want to add this file
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // Get the file name
 | 
						|
  //
 | 
						|
  strcpy (Buffer, SourceFileName);
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy the file name for the path of the sym file and truncate the name portion.
 | 
						|
  //
 | 
						|
  strcpy (SymFileName, Buffer);
 | 
						|
  Ptr = strrchr (SymFileName, FILE_SEP_CHAR);
 | 
						|
  assert (Ptr);
 | 
						|
  Ptr[0] = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the file extension and make it lower case
 | 
						|
  //
 | 
						|
  Ptr = strrchr (SymFileName, '.');
 | 
						|
  if (Ptr != NULL) {
 | 
						|
    strlwr (Ptr);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check if it is PEI file
 | 
						|
  //
 | 
						|
  if (strstr (Buffer, ".pei") != NULL) {
 | 
						|
    //
 | 
						|
    // Find the human readable portion
 | 
						|
    //
 | 
						|
    if (!strtok (Buffer, "-") ||
 | 
						|
        !strtok (NULL, "-") ||
 | 
						|
        !strtok (NULL, "-") ||
 | 
						|
        !strtok (NULL, "-") ||
 | 
						|
        !strtok (NULL, "-") ||
 | 
						|
        !strcpy (Buffer, strtok (NULL, "."))
 | 
						|
          ) {
 | 
						|
      Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Save code module name
 | 
						|
    //
 | 
						|
    strcpy (CodeModuleName, Buffer);
 | 
						|
 | 
						|
    //
 | 
						|
    // Add the symbol file name and extension to the file path.
 | 
						|
    //
 | 
						|
    strcat (Buffer, ".sym");
 | 
						|
    strcat (SymFileName, FILE_SEP_CHAR);
 | 
						|
    strcat (SymFileName, Buffer);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Only handle PEIM files.
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Find PE32 section
 | 
						|
  //
 | 
						|
  Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);
 | 
						|
 | 
						|
  //
 | 
						|
  // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
 | 
						|
  //
 | 
						|
  if (Status == EFI_NOT_FOUND) {
 | 
						|
    Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    Status = GetPe32Info (
 | 
						|
              (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
 | 
						|
              &EntryPoint,
 | 
						|
              &BaseOfCode,
 | 
						|
              &MachineType
 | 
						|
              );
 | 
						|
  } else if (Status == EFI_NOT_FOUND) {
 | 
						|
    //
 | 
						|
    // For PIC, hardcode.
 | 
						|
    //
 | 
						|
    BaseOfCode = 0x60;
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the source file
 | 
						|
  //
 | 
						|
  SourceFile = fopen (SymFileName, "r");
 | 
						|
  if (SourceFile == NULL) {
 | 
						|
    //
 | 
						|
    // SYM files are not required.
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the first line
 | 
						|
  //
 | 
						|
  if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {
 | 
						|
    Buffer[0] = 0;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Make sure it matches the expected sym format
 | 
						|
  //
 | 
						|
  if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
 | 
						|
    fclose (SourceFile);
 | 
						|
    Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read in the file
 | 
						|
  //
 | 
						|
  while (feof (SourceFile) == 0) {
 | 
						|
    //
 | 
						|
    // Read a line
 | 
						|
    //
 | 
						|
    if (fscanf (
 | 
						|
          SourceFile,
 | 
						|
          "%s | %s | %s | %s\n",
 | 
						|
          Type,
 | 
						|
          Address,
 | 
						|
          Section,
 | 
						|
          Token
 | 
						|
          ) == 4) {
 | 
						|
      //
 | 
						|
      // If the token starts with "??" ignore it
 | 
						|
      //
 | 
						|
      if (Token[0] == '?' && Token[1] == '?') {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Get the token address
 | 
						|
      //
 | 
						|
      AsciiStringToUint64 (Address, TRUE, &TokenAddress);
 | 
						|
 | 
						|
      //
 | 
						|
      // Add the base address
 | 
						|
      //
 | 
						|
      TokenAddress += BaseAddress;
 | 
						|
 | 
						|
      //
 | 
						|
      // If PE32 or TE section then find the start of code.  For PIC it is hardcoded.
 | 
						|
      //
 | 
						|
      if (Pe32Section.Pe32Section) {
 | 
						|
        //
 | 
						|
        // Add the offset of the PE32 section
 | 
						|
        //
 | 
						|
        TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;
 | 
						|
 | 
						|
        //
 | 
						|
        // Add the size of the PE32 section header
 | 
						|
        //
 | 
						|
        TokenAddress += sizeof (EFI_PE32_SECTION);
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // For PIC hardcoded.
 | 
						|
        //
 | 
						|
        TokenAddress += 0x28;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Add the beginning of the code
 | 
						|
      //
 | 
						|
      TokenAddress += BaseOfCode;
 | 
						|
 | 
						|
      sprintf (
 | 
						|
        Buffer,
 | 
						|
        "%s | %016I64X | %s | _%s%s\n",
 | 
						|
        Type,
 | 
						|
        TokenAddress,
 | 
						|
        Section,
 | 
						|
        CodeModuleName,
 | 
						|
        Token
 | 
						|
        );
 | 
						|
      memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);
 | 
						|
      SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fclose (SourceFile);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
AddFile (
 | 
						|
  IN OUT MEMORY_FILE          *FvImage,
 | 
						|
  IN FV_INFO                  *FvInfo,
 | 
						|
  IN UINTN                    Index,
 | 
						|
  IN OUT EFI_FFS_FILE_HEADER  **VtfFileImage,
 | 
						|
  IN OUT MEMORY_FILE          *SymImage
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function adds a file to the FV image.  The file will pad to the
 | 
						|
  appropriate alignment if required.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FvImage       The memory image of the FV to add it to.  The current offset
 | 
						|
                must be valid.
 | 
						|
  FvInfo        Pointer to information about the FV.
 | 
						|
  Index         The file in the FvInfo file list to add.
 | 
						|
  VtfFileImage  A pointer to the VTF file within the FvImage.  If this is equal
 | 
						|
                to the end of the FvImage then no VTF previously found.
 | 
						|
  SymImage      The memory image of the Sym file to update if symbols are present.
 | 
						|
                The current offset must be valid.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS              The function completed successfully.
 | 
						|
  EFI_INVALID_PARAMETER    One of the input parameters was invalid.
 | 
						|
  EFI_ABORTED              An error occurred.
 | 
						|
  EFI_OUT_OF_RESOURCES     Insufficient resources exist to complete the add.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  FILE                  *NewFile;
 | 
						|
  UINTN                 FileSize;
 | 
						|
  UINT8                 *FileBuffer;
 | 
						|
  UINTN                 NumBytesRead;
 | 
						|
  UINT32                CurrentFileAlignment;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_PHYSICAL_ADDRESS  CurrentFileBaseAddress;
 | 
						|
  UINT8                 VtfHeaderChecksum;
 | 
						|
  UINT8                 VtfFileChecksum;
 | 
						|
  UINT8                 FileState;
 | 
						|
  EFI_FFS_FILE_TAIL     TailValue;
 | 
						|
  UINT32                TailSize;
 | 
						|
  //
 | 
						|
  // Verify input parameters.
 | 
						|
  //
 | 
						|
  if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read the file to add
 | 
						|
  //
 | 
						|
  NewFile = fopen (FvInfo->FvFiles[Index], "rb");
 | 
						|
 | 
						|
  if (NewFile == NULL) {
 | 
						|
    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Get the file size
 | 
						|
  //
 | 
						|
  FileSize = _filelength (fileno (NewFile));
 | 
						|
 | 
						|
  //
 | 
						|
  // Read the file into a buffer
 | 
						|
  //
 | 
						|
  FileBuffer = malloc (FileSize);
 | 
						|
  if (FileBuffer == NULL) {
 | 
						|
    Error (NULL, 0, 0, "memory allocation failure", NULL);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);
 | 
						|
 | 
						|
  //
 | 
						|
  // Done with the file, from this point on we will just use the buffer read.
 | 
						|
  //
 | 
						|
  fclose (NewFile);
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify read successful
 | 
						|
  //
 | 
						|
  if (NumBytesRead != sizeof (UINT8) * FileSize) {
 | 
						|
    free (FileBuffer);
 | 
						|
    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Verify space exists to add the file
 | 
						|
  //
 | 
						|
  if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
 | 
						|
    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Update the file state based on polarity of the FV.
 | 
						|
  //
 | 
						|
  UpdateFfsFileState (
 | 
						|
    (EFI_FFS_FILE_HEADER *) FileBuffer,
 | 
						|
    (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // If we have a VTF file, add it at the top.
 | 
						|
  //
 | 
						|
  if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {
 | 
						|
    if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {
 | 
						|
      //
 | 
						|
      // No previous VTF, add this one.
 | 
						|
      //
 | 
						|
      *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);
 | 
						|
      //
 | 
						|
      // Sanity check. The file MUST align appropriately
 | 
						|
      //
 | 
						|
      if ((((UINTN) *VtfFileImage) & 0x07) != 0) {
 | 
						|
        Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // copy VTF File Header
 | 
						|
      //
 | 
						|
      memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));
 | 
						|
 | 
						|
      //
 | 
						|
      // Copy VTF body
 | 
						|
      //
 | 
						|
      memcpy (
 | 
						|
        (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),
 | 
						|
        FileBuffer + sizeof (EFI_FFS_FILE_HEADER),
 | 
						|
        FileSize - sizeof (EFI_FFS_FILE_HEADER)
 | 
						|
        );
 | 
						|
 | 
						|
      //
 | 
						|
      // re-calculate the VTF File Header
 | 
						|
      //
 | 
						|
      FileState = (*VtfFileImage)->State;
 | 
						|
      (*VtfFileImage)->State = 0;
 | 
						|
      *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;
 | 
						|
      (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;
 | 
						|
      (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;
 | 
						|
 | 
						|
      VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));
 | 
						|
      (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;
 | 
						|
      //
 | 
						|
      // Determine if it has a tail
 | 
						|
      //
 | 
						|
      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
 | 
						|
        TailSize = sizeof (EFI_FFS_FILE_TAIL);
 | 
						|
      } else {
 | 
						|
        TailSize = 0;
 | 
						|
      }
 | 
						|
 | 
						|
      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {
 | 
						|
        VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);
 | 
						|
        (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;
 | 
						|
      } else {
 | 
						|
        (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // If it has a file tail, update it
 | 
						|
      //
 | 
						|
      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
 | 
						|
        TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));
 | 
						|
        *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
 | 
						|
      }
 | 
						|
      (*VtfFileImage)->State = FileState;
 | 
						|
      free (FileBuffer);
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Already found a VTF file.
 | 
						|
      //
 | 
						|
      Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);
 | 
						|
      free (FileBuffer);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check if alignment is required
 | 
						|
  //
 | 
						|
  Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);
 | 
						|
    free (FileBuffer);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Find the largest alignment of all the FFS files in the FV
 | 
						|
  //
 | 
						|
  if (CurrentFileAlignment > MaxFfsAlignment) {
 | 
						|
    MaxFfsAlignment = CurrentFileAlignment;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Add pad file if necessary
 | 
						|
  //
 | 
						|
  Status = AddPadFile (FvImage, CurrentFileAlignment);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    printf ("ERROR: Could not align the file data properly.\n");
 | 
						|
    free (FileBuffer);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Add file
 | 
						|
  //
 | 
						|
  if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {
 | 
						|
    //
 | 
						|
    // Copy the file
 | 
						|
    //
 | 
						|
    memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
 | 
						|
 | 
						|
    //
 | 
						|
    // If the file is XIP, rebase
 | 
						|
    //
 | 
						|
    CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);
 | 
						|
    //
 | 
						|
    //    Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);
 | 
						|
    //    if (EFI_ERROR(Status)) {
 | 
						|
    //      printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);
 | 
						|
    //      return EFI_ABORTED;
 | 
						|
    //    }
 | 
						|
    //
 | 
						|
    // Update Symbol file
 | 
						|
    //
 | 
						|
    Status = AddSymFile (
 | 
						|
              CurrentFileBaseAddress,
 | 
						|
              (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,
 | 
						|
              SymImage,
 | 
						|
              FvInfo->FvFiles[Index]
 | 
						|
              );
 | 
						|
    assert (!EFI_ERROR (Status));
 | 
						|
 | 
						|
    //
 | 
						|
    // Update the current pointer in the FV image
 | 
						|
    //
 | 
						|
    FvImage->CurrentFilePointer += FileSize;
 | 
						|
  } else {
 | 
						|
    printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Make next file start at QWord Boundry
 | 
						|
  //
 | 
						|
  while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {
 | 
						|
    FvImage->CurrentFilePointer++;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Free allocated memory.
 | 
						|
  //
 | 
						|
  free (FileBuffer);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
AddVariableBlock (
 | 
						|
  IN UINT8                    *FvImage,
 | 
						|
  IN UINTN                    Size,
 | 
						|
  IN FV_INFO                  *FvInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
 | 
						|
  VARIABLE_STORE_HEADER       *VarStoreHeader;
 | 
						|
  //
 | 
						|
  // Variable block should exclude FvHeader. Since the length of
 | 
						|
  // FvHeader depends on the block map, which is variable length,
 | 
						|
  // we could only decide the actual variable block length here.
 | 
						|
  //
 | 
						|
  FvHeader                  = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
 | 
						|
  FvImage                   = FvImage + FvHeader->HeaderLength;
 | 
						|
 | 
						|
  VarStoreHeader            = (VARIABLE_STORE_HEADER *) FvImage;
 | 
						|
 | 
						|
  VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;
 | 
						|
  VarStoreHeader->Size      = Size - FvHeader->HeaderLength;
 | 
						|
  VarStoreHeader->Format    = VARIABLE_STORE_FORMATTED;
 | 
						|
  VarStoreHeader->State     = VARIABLE_STORE_HEALTHY;
 | 
						|
  VarStoreHeader->Reserved  = 0;
 | 
						|
  VarStoreHeader->Reserved1 = 0;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
AddEventLogBlock (
 | 
						|
  IN UINT8                    *FvImage,
 | 
						|
  IN UINTN                    Size,
 | 
						|
  IN FV_INFO                  *FvInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
AddFTWWorkingBlock (
 | 
						|
  IN UINT8                    *FvImage,
 | 
						|
  IN UINTN                    Size,
 | 
						|
  IN FV_INFO                  *FvInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;
 | 
						|
  UINT32                                  Crc32;
 | 
						|
 | 
						|
  Crc32     = 0;
 | 
						|
  FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;
 | 
						|
  memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));
 | 
						|
  FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
 | 
						|
  CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);
 | 
						|
  FTWHeader->Crc = Crc32;
 | 
						|
  if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {
 | 
						|
    FTWHeader->WorkingBlockValid    = 0;
 | 
						|
    FTWHeader->WorkingBlockInvalid  = 1;
 | 
						|
  } else {
 | 
						|
    FTWHeader->WorkingBlockValid    = 1;
 | 
						|
    FTWHeader->WorkingBlockInvalid  = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
AddFTWSpareBlock (
 | 
						|
  IN UINT8                    *FvImage,
 | 
						|
  IN UINTN                    Size,
 | 
						|
  IN FV_INFO                  *FvInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
GenNonFFSFv (
 | 
						|
  IN UINT8                    *FvImage,
 | 
						|
  IN FV_INFO                  *FvInfo
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function generate the non FFS FV image, such as the working block
 | 
						|
  and spare block. How each component of the FV is built is component
 | 
						|
  specific.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FvImage       The memory image of the FV to add it to.  The current offset
 | 
						|
                must be valid.
 | 
						|
  FvInfo        Pointer to information about the FV.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS              The function completed successfully.
 | 
						|
  EFI_INVALID_PARAMETER    One of the input parameters was invalid.
 | 
						|
  EFI_ABORTED              An error occurred.
 | 
						|
  EFI_OUT_OF_RESOURCES     Insufficient resources exist to complete the add.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN                       Index;
 | 
						|
  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
 | 
						|
  UINT64                      TotalSize;
 | 
						|
 | 
						|
  FvHeader  = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
 | 
						|
  TotalSize = 0;
 | 
						|
 | 
						|
  for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {
 | 
						|
    if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {
 | 
						|
      AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
 | 
						|
    } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {
 | 
						|
      AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
 | 
						|
    } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {
 | 
						|
      AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
 | 
						|
    } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {
 | 
						|
      AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
 | 
						|
    } else {
 | 
						|
      printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
 | 
						|
    FvImage   = FvImage + FvInfo->FvComponents[Index].Size;
 | 
						|
    TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Index and TotalSize is zero mean there's no component, so this is an empty fv
 | 
						|
  //
 | 
						|
  if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {
 | 
						|
    printf ("Error. Component size does not sum up to FV size.\n");
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
PadFvImage (
 | 
						|
  IN MEMORY_FILE          *FvImage,
 | 
						|
  IN EFI_FFS_FILE_HEADER  *VtfFileImage
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function places a pad file between the last file in the FV and the VTF
 | 
						|
  file if the VTF file exists.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FvImage       Memory file for the FV memory image
 | 
						|
  VtfFileImage  The address of the VTF file.  If this is the end of the FV
 | 
						|
                image, no VTF exists and no pad file is needed.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS             Completed successfully.
 | 
						|
  EFI_INVALID_PARAMETER   One of the input parameters was NULL.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_FFS_FILE_HEADER *PadFile;
 | 
						|
  UINTN               FileSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // If there is no VTF or the VTF naturally follows the previous file without a
 | 
						|
  // pad file, then there's nothing to do
 | 
						|
  //
 | 
						|
  if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Pad file starts at beginning of free space
 | 
						|
  //
 | 
						|
  PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
 | 
						|
 | 
						|
  //
 | 
						|
  // write header
 | 
						|
  //
 | 
						|
  memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
 | 
						|
  memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));
 | 
						|
  PadFile->Type       = EFI_FV_FILETYPE_FFS_PAD;
 | 
						|
  PadFile->Attributes = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // FileSize includes the EFI_FFS_FILE_HEADER
 | 
						|
  //
 | 
						|
  FileSize          = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;
 | 
						|
  PadFile->Size[0]  = (UINT8) (FileSize & 0x000000FF);
 | 
						|
  PadFile->Size[1]  = (UINT8) ((FileSize & 0x0000FF00) >> 8);
 | 
						|
  PadFile->Size[2]  = (UINT8) ((FileSize & 0x00FF0000) >> 16);
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill in checksums and state, must be zero during checksum calculation.
 | 
						|
  //
 | 
						|
  PadFile->IntegrityCheck.Checksum.Header = 0;
 | 
						|
  PadFile->IntegrityCheck.Checksum.File   = 0;
 | 
						|
  PadFile->State                          = 0;
 | 
						|
  PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
 | 
						|
  if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
 | 
						|
    PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);
 | 
						|
  } else {
 | 
						|
    PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
 | 
						|
  }
 | 
						|
 | 
						|
  PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
 | 
						|
 | 
						|
  UpdateFfsFileState (
 | 
						|
    (EFI_FFS_FILE_HEADER *) PadFile,
 | 
						|
    (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
 | 
						|
    );
 | 
						|
  //
 | 
						|
  // Update the current FV pointer
 | 
						|
  //
 | 
						|
  FvImage->CurrentFilePointer = FvImage->Eof;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
UpdateResetVector (
 | 
						|
  IN MEMORY_FILE            *FvImage,
 | 
						|
  IN FV_INFO                *FvInfo,
 | 
						|
  IN EFI_FFS_FILE_HEADER    *VtfFile
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This parses the FV looking for the PEI core and then plugs the address into
 | 
						|
  the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
 | 
						|
  complete an IA32 Bootstrap FV.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FvImage       Memory file for the FV memory image
 | 
						|
  FvInfo        Information read from INF file.
 | 
						|
  VtfFile       Pointer to the VTF file in the FV image.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS             Function Completed successfully.
 | 
						|
  EFI_ABORTED             Error encountered.
 | 
						|
  EFI_INVALID_PARAMETER   A required parameter was NULL.
 | 
						|
  EFI_NOT_FOUND           PEI Core file not found.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_FFS_FILE_HEADER       *PeiCoreFile;
 | 
						|
  EFI_FFS_FILE_HEADER       *SecCoreFile;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_FILE_SECTION_POINTER  Pe32Section;
 | 
						|
  UINT32                    EntryPoint;
 | 
						|
  UINT32                    BaseOfCode;
 | 
						|
  UINT16                    MachineType;
 | 
						|
  EFI_PHYSICAL_ADDRESS      PeiCorePhysicalAddress;
 | 
						|
  EFI_PHYSICAL_ADDRESS      SecCorePhysicalAddress;
 | 
						|
  EFI_PHYSICAL_ADDRESS      *SecCoreEntryAddressPtr;
 | 
						|
  UINT32                    *Ia32ResetAddressPtr;
 | 
						|
  UINT8                     *BytePointer;
 | 
						|
  UINT8                     *BytePointer2;
 | 
						|
  UINT16                    *WordPointer;
 | 
						|
  UINT16                    CheckSum;
 | 
						|
  UINTN                     Index;
 | 
						|
  EFI_FFS_FILE_STATE        SavedState;
 | 
						|
  EFI_FFS_FILE_TAIL         TailValue;
 | 
						|
  UINT32                    TailSize;
 | 
						|
  UINT64                    FitAddress;
 | 
						|
  FIT_TABLE                 *FitTablePtr;
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify input parameters
 | 
						|
  //
 | 
						|
  if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Initialize FV library
 | 
						|
  //
 | 
						|
  InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify VTF file
 | 
						|
  //
 | 
						|
  Status = VerifyFfsFile (VtfFile);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Find the PEI Core
 | 
						|
  //
 | 
						|
  Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
 | 
						|
  if (EFI_ERROR (Status) || PeiCoreFile == NULL) {
 | 
						|
    Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // PEI Core found, now find PE32 or TE section
 | 
						|
  //
 | 
						|
  Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
 | 
						|
  if (Status == EFI_NOT_FOUND) {
 | 
						|
    Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = GetPe32Info (
 | 
						|
            (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
 | 
						|
            &EntryPoint,
 | 
						|
            &BaseOfCode,
 | 
						|
            &MachineType
 | 
						|
            );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Physical address is FV base + offset of PE32 + offset of the entry point
 | 
						|
  //
 | 
						|
  PeiCorePhysicalAddress = FvInfo->BaseAddress;
 | 
						|
  PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
 | 
						|
  PeiCorePhysicalAddress += EntryPoint;
 | 
						|
 | 
						|
  if (MachineType == EFI_IMAGE_MACHINE_IA64) {
 | 
						|
    //
 | 
						|
    // Update PEI_CORE address
 | 
						|
    //
 | 
						|
    //
 | 
						|
    // Set the uncached attribute bit in the physical address
 | 
						|
    //
 | 
						|
    PeiCorePhysicalAddress |= 0x8000000000000000ULL;
 | 
						|
 | 
						|
    //
 | 
						|
    // Check if address is aligned on a 16 byte boundary
 | 
						|
    //
 | 
						|
    if (PeiCorePhysicalAddress & 0xF) {
 | 
						|
      printf (
 | 
						|
        "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
 | 
						|
        PeiCorePhysicalAddress
 | 
						|
        );
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // First Get the FIT table address
 | 
						|
    //
 | 
						|
    FitAddress  = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;
 | 
						|
 | 
						|
    FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));
 | 
						|
 | 
						|
    Status      = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);
 | 
						|
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      UpdateFitCheckSum (FitTablePtr);
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Find the Sec Core
 | 
						|
    //
 | 
						|
    Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);
 | 
						|
    if (EFI_ERROR (Status) || SecCoreFile == NULL) {
 | 
						|
      Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Sec Core found, now find PE32 section
 | 
						|
    //
 | 
						|
    Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = GetPe32Info (
 | 
						|
              (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
 | 
						|
              &EntryPoint,
 | 
						|
              &BaseOfCode,
 | 
						|
              &MachineType
 | 
						|
              );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Physical address is FV base + offset of PE32 + offset of the entry point
 | 
						|
    //
 | 
						|
    SecCorePhysicalAddress = FvInfo->BaseAddress;
 | 
						|
    SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
 | 
						|
    SecCorePhysicalAddress += EntryPoint;
 | 
						|
 | 
						|
    //
 | 
						|
    // Update SEC_CORE address
 | 
						|
    //
 | 
						|
    //
 | 
						|
    // Set the uncached attribute bit in the physical address
 | 
						|
    //
 | 
						|
    SecCorePhysicalAddress |= 0x8000000000000000ULL;
 | 
						|
 | 
						|
    //
 | 
						|
    // Update the address
 | 
						|
    //
 | 
						|
    SecCoreEntryAddressPtr  = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);
 | 
						|
    *SecCoreEntryAddressPtr = SecCorePhysicalAddress;
 | 
						|
 | 
						|
    //
 | 
						|
    // Check if address is aligned on a 16 byte boundary
 | 
						|
    //
 | 
						|
    if (SecCorePhysicalAddress & 0xF) {
 | 
						|
      printf (
 | 
						|
        "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
 | 
						|
        SecCorePhysicalAddress
 | 
						|
        );
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  } else if (MachineType == EFI_IMAGE_MACHINE_IA32) {
 | 
						|
    //
 | 
						|
    // Get the location to update
 | 
						|
    //
 | 
						|
    Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);
 | 
						|
 | 
						|
    //
 | 
						|
    // Write lower 32 bits of physical address
 | 
						|
    //
 | 
						|
    *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;
 | 
						|
 | 
						|
    //
 | 
						|
    // Update the BFV base address
 | 
						|
    //
 | 
						|
    Ia32ResetAddressPtr   = (UINT32 *) ((UINTN) FvImage->Eof - 4);
 | 
						|
    *Ia32ResetAddressPtr  = (UINT32) (FvInfo->BaseAddress);
 | 
						|
 | 
						|
    CheckSum              = 0x0000;
 | 
						|
 | 
						|
    //
 | 
						|
    // Update the Startup AP in the FVH header block ZeroVector region.
 | 
						|
    //
 | 
						|
    BytePointer   = (UINT8 *) ((UINTN) FvImage->FileImage);
 | 
						|
    BytePointer2  = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;
 | 
						|
    for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {
 | 
						|
      *BytePointer++ = *BytePointer2++;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Calculate the checksum
 | 
						|
    //
 | 
						|
    WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);
 | 
						|
    for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {
 | 
						|
      CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));
 | 
						|
      WordPointer++;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Update the checksum field
 | 
						|
    //
 | 
						|
    BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
 | 
						|
    BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);
 | 
						|
    WordPointer   = (UINT16 *) BytePointer;
 | 
						|
    *WordPointer  = (UINT16) (0x10000 - (UINT32) CheckSum);
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Determine if it has an FFS file tail.
 | 
						|
  //
 | 
						|
  if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
 | 
						|
    TailSize = sizeof (EFI_FFS_FILE_TAIL);
 | 
						|
  } else {
 | 
						|
    TailSize = 0;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Now update file checksum
 | 
						|
  //
 | 
						|
  SavedState  = VtfFile->State;
 | 
						|
  VtfFile->IntegrityCheck.Checksum.File = 0;
 | 
						|
  VtfFile->State                        = 0;
 | 
						|
  if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {
 | 
						|
    VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
 | 
						|
                                              (UINT8 *) VtfFile,
 | 
						|
                                              GetLength (VtfFile->Size) - TailSize
 | 
						|
                                              );
 | 
						|
  } else {
 | 
						|
    VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
 | 
						|
  }
 | 
						|
 | 
						|
  VtfFile->State = SavedState;
 | 
						|
 | 
						|
  //
 | 
						|
  // Update tail if present
 | 
						|
  //
 | 
						|
  if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
 | 
						|
    TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));
 | 
						|
    *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
GetPe32Info (
 | 
						|
  IN UINT8                  *Pe32,
 | 
						|
  OUT UINT32                *EntryPoint,
 | 
						|
  OUT UINT32                *BaseOfCode,
 | 
						|
  OUT UINT16                *MachineType
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Retrieves the PE32 entry point offset and machine type from PE image or TeImage.  
 | 
						|
  See EfiImage.h for machine types.  The entry point offset is from the beginning 
 | 
						|
  of the PE32 buffer passed in.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pe32          Beginning of the PE32.
 | 
						|
  EntryPoint    Offset from the beginning of the PE32 to the image entry point.
 | 
						|
  BaseOfCode    Base address of code.
 | 
						|
  MachineType   Magic number for the machine type.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS             Function completed successfully.
 | 
						|
  EFI_ABORTED             Error encountered.
 | 
						|
  EFI_INVALID_PARAMETER   A required parameter was NULL.
 | 
						|
  EFI_UNSUPPORTED         The operation is unsupported.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_IMAGE_DOS_HEADER  *DosHeader;
 | 
						|
  EFI_IMAGE_NT_HEADERS  *NtHeader;
 | 
						|
  EFI_TE_IMAGE_HEADER   *TeHeader;
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify input parameters
 | 
						|
  //
 | 
						|
  if (Pe32 == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // First check whether it is one TE Image.
 | 
						|
  //
 | 
						|
  TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;
 | 
						|
  if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
 | 
						|
    //
 | 
						|
    // By TeImage Header to get output
 | 
						|
    //
 | 
						|
    *EntryPoint   = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
 | 
						|
    *BaseOfCode   = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
 | 
						|
    *MachineType  = TeHeader->Machine;
 | 
						|
  } else {
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Then check whether 
 | 
						|
    // First is the DOS header
 | 
						|
    //
 | 
						|
    DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Verify DOS header is expected
 | 
						|
    //
 | 
						|
    if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
 | 
						|
      printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Immediately following is the NT header.
 | 
						|
    //
 | 
						|
    NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Verify NT header is expected
 | 
						|
    //
 | 
						|
    if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {
 | 
						|
      printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Get output
 | 
						|
    //
 | 
						|
    *EntryPoint   = NtHeader->OptionalHeader.AddressOfEntryPoint;
 | 
						|
    *BaseOfCode   = NtHeader->OptionalHeader.BaseOfCode;
 | 
						|
    *MachineType  = NtHeader->FileHeader.Machine;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify machine type is supported
 | 
						|
  //
 | 
						|
  if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC) {
 | 
						|
    printf ("ERROR: Unrecognized machine type in the PE32 file.\n");
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
//
 | 
						|
// Exposed function implementations (prototypes are defined in GenFvImageLib.h)
 | 
						|
//
 | 
						|
EFI_STATUS
 | 
						|
GenerateFvImage (
 | 
						|
  IN CHAR8    *InfFileImage,
 | 
						|
  IN UINTN    InfFileSize,
 | 
						|
  OUT UINT8   **FvImage,
 | 
						|
  OUT UINTN   *FvImageSize,
 | 
						|
  OUT CHAR8   **FvFileName,
 | 
						|
  OUT UINT8   **SymImage,
 | 
						|
  OUT UINTN   *SymImageSize,
 | 
						|
  OUT CHAR8   **SymFileName
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This is the main function which will be called from application.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  InfFileImage  Buffer containing the INF file contents.
 | 
						|
  InfFileSize   Size of the contents of the InfFileImage buffer.
 | 
						|
  FvImage       Pointer to the FV image created.
 | 
						|
  FvImageSize   Size of the FV image created and pointed to by FvImage.
 | 
						|
  FvFileName    Requested name for the FV file.
 | 
						|
  SymImage      Pointer to the Sym image created.
 | 
						|
  SymImageSize  Size of the Sym image created and pointed to by SymImage.
 | 
						|
  SymFileName   Requested name for the Sym file.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS             Function completed successfully.
 | 
						|
  EFI_OUT_OF_RESOURCES    Could not allocate required resources.
 | 
						|
  EFI_ABORTED             Error encountered.
 | 
						|
  EFI_INVALID_PARAMETER   A required parameter was NULL.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  MEMORY_FILE                 InfMemoryFile;
 | 
						|
  MEMORY_FILE                 FvImageMemoryFile;
 | 
						|
  MEMORY_FILE                 SymImageMemoryFile;
 | 
						|
  FV_INFO                     FvInfo;
 | 
						|
  UINTN                       Index;
 | 
						|
  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
 | 
						|
  EFI_FFS_FILE_HEADER         *VtfFileImage;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for invalid parameter
 | 
						|
  //
 | 
						|
  if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Initialize file structures
 | 
						|
  //
 | 
						|
  InfMemoryFile.FileImage           = InfFileImage;
 | 
						|
  InfMemoryFile.CurrentFilePointer  = InfFileImage;
 | 
						|
  InfMemoryFile.Eof                 = InfFileImage + InfFileSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse the FV inf file for header information
 | 
						|
  //
 | 
						|
  Status = ParseFvInf (&InfMemoryFile, &FvInfo);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    printf ("ERROR: Could not parse the input INF file.\n");
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Update the file name return values
 | 
						|
  //
 | 
						|
  strcpy (*FvFileName, FvInfo.FvName);
 | 
						|
  strcpy (*SymFileName, FvInfo.SymName);
 | 
						|
 | 
						|
  //
 | 
						|
  // Calculate the FV size
 | 
						|
  //
 | 
						|
  *FvImageSize = FvInfo.Size;
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate the FV
 | 
						|
  //
 | 
						|
  *FvImage = malloc (*FvImageSize);
 | 
						|
  if (*FvImage == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Allocate space for symbol file storage
 | 
						|
  //
 | 
						|
  *SymImage = malloc (SYMBOL_FILE_SIZE);
 | 
						|
  if (*SymImage == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Initialize the FV to the erase polarity
 | 
						|
  //
 | 
						|
  if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {
 | 
						|
    memset (*FvImage, -1, *FvImageSize);
 | 
						|
  } else {
 | 
						|
    memset (*FvImage, 0, *FvImageSize);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Initialize FV header
 | 
						|
  //
 | 
						|
  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the zero vector to all zeros.
 | 
						|
  //
 | 
						|
  memset (FvHeader->ZeroVector, 0, 16);
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy the FFS GUID
 | 
						|
  //
 | 
						|
  memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));
 | 
						|
 | 
						|
  FvHeader->FvLength    = *FvImageSize;
 | 
						|
  FvHeader->Signature   = EFI_FVH_SIGNATURE;
 | 
						|
  FvHeader->Attributes  = FvInfo.FvAttributes;
 | 
						|
  FvHeader->Revision    = EFI_FVH_REVISION;
 | 
						|
  FvHeader->Reserved[0] = 0;
 | 
						|
  FvHeader->Reserved[1] = 0;
 | 
						|
  FvHeader->Reserved[2] = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy firmware block map
 | 
						|
  //
 | 
						|
  for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {
 | 
						|
    FvHeader->FvBlockMap[Index].NumBlocks   = FvInfo.FvBlocks[Index].NumBlocks;
 | 
						|
    FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Add block map terminator
 | 
						|
  //
 | 
						|
  FvHeader->FvBlockMap[Index].NumBlocks   = 0;
 | 
						|
  FvHeader->FvBlockMap[Index].BlockLength = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Complete the header
 | 
						|
  //
 | 
						|
  FvHeader->HeaderLength  = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);
 | 
						|
  FvHeader->Checksum      = 0;
 | 
						|
  FvHeader->Checksum      = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
 | 
						|
 | 
						|
  //
 | 
						|
  // If there is no FFS file, find and generate each components of the FV
 | 
						|
  //
 | 
						|
  if (FvInfo.FvFiles[0][0] == 0) {
 | 
						|
    Status = GenNonFFSFv (*FvImage, &FvInfo);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      printf ("ERROR: Could not generate NonFFS FV.\n");
 | 
						|
      free (*FvImage);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Initialize our "file" view of the buffer
 | 
						|
  //
 | 
						|
  FvImageMemoryFile.FileImage           = *FvImage;
 | 
						|
  FvImageMemoryFile.CurrentFilePointer  = *FvImage + FvHeader->HeaderLength;
 | 
						|
  FvImageMemoryFile.Eof                 = *FvImage +*FvImageSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize our "file" view of the symbol file.
 | 
						|
  //
 | 
						|
  SymImageMemoryFile.FileImage          = *SymImage;
 | 
						|
  SymImageMemoryFile.CurrentFilePointer = *SymImage;
 | 
						|
  SymImageMemoryFile.Eof                = *FvImage + SYMBOL_FILE_SIZE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the FV library.
 | 
						|
  //
 | 
						|
  InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size);
 | 
						|
 | 
						|
  //
 | 
						|
  // Files start on 8 byte alignments, so move to the next 8 byte aligned
 | 
						|
  // address.  For now, just assert if it isn't.  Currently FV header is
 | 
						|
  // always a multiple of 8 bytes.
 | 
						|
  // BUGBUG: Handle this better
 | 
						|
  //
 | 
						|
  assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the VTF file address.
 | 
						|
  //
 | 
						|
  VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;
 | 
						|
 | 
						|
  //
 | 
						|
  // Add files to FV
 | 
						|
  //
 | 
						|
  for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {
 | 
						|
    //
 | 
						|
    // Add the file
 | 
						|
    //
 | 
						|
    Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile);
 | 
						|
 | 
						|
    //
 | 
						|
    // Exit if error detected while adding the file
 | 
						|
    //
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);
 | 
						|
      free (*FvImage);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If there is a VTF file, some special actions need to occur.
 | 
						|
  //
 | 
						|
  if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {
 | 
						|
    //
 | 
						|
    // Pad from the end of the last file to the beginning of the VTF file.
 | 
						|
    //
 | 
						|
    Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");
 | 
						|
      free (*FvImage);
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Update reset vector (SALE_ENTRY for IPF)
 | 
						|
    // Now for IA32 and IA64 platform, the fv which has bsf file must have the 
 | 
						|
    // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the   
 | 
						|
    // reset vector. If the PEI Core is found, the VTF file will probably get  
 | 
						|
    // corrupted by updating the entry point.                                  
 | 
						|
    //
 | 
						|
    if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) {       
 | 
						|
      Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);
 | 
						|
      if (EFI_ERROR(Status)) {                                               
 | 
						|
        printf ("ERROR: Could not update the reset vector.\n");              
 | 
						|
        free (*FvImage);                                                     
 | 
						|
        return EFI_ABORTED;                                                  
 | 
						|
      }                                                                      
 | 
						|
    }
 | 
						|
  } 
 | 
						|
  //
 | 
						|
  // Determine final Sym file size
 | 
						|
  //
 | 
						|
  *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Update FV Alignment attribute to the largest alignment of all the FFS files in the FV
 | 
						|
  //
 | 
						|
  if (FvHeader->Attributes | EFI_FVB_ALIGNMENT_CAP) {
 | 
						|
    for (Index = 1; Index <= 16; Index ++) {
 | 
						|
      if ((1 << Index) < MaxFfsAlignment) {
 | 
						|
        //
 | 
						|
        // Unset the unsupported alignment attribute.
 | 
						|
        //
 | 
						|
        FvHeader->Attributes = FvHeader->Attributes & ~((1 << Index) * EFI_FVB_ALIGNMENT_CAP);
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Set the supported alignment attribute.
 | 
						|
        //
 | 
						|
        FvHeader->Attributes = FvHeader->Attributes | ((1 << Index) * EFI_FVB_ALIGNMENT_CAP);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    
 | 
						|
    //
 | 
						|
    // Update Checksum for FvHeader
 | 
						|
    //
 | 
						|
    FvHeader->Checksum      = 0;
 | 
						|
    FvHeader->Checksum      = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
UpdatePeiCoreEntryInFit (
 | 
						|
  IN FIT_TABLE     *FitTablePtr,
 | 
						|
  IN UINT64        PeiCorePhysicalAddress
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
 | 
						|
  Sec to Pei Core
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FitTablePtr             - The pointer of FIT_TABLE.
 | 
						|
  PeiCorePhysicalAddress  - The address of Pei Core entry.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS             - The PEI_CORE FIT entry was updated successfully.
 | 
						|
  EFI_NOT_FOUND           - Not found the PEI_CORE FIT entry.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  FIT_TABLE *TmpFitPtr;
 | 
						|
  UINTN     Index;
 | 
						|
  UINTN     NumFitComponents;
 | 
						|
 | 
						|
  TmpFitPtr         = FitTablePtr;
 | 
						|
  NumFitComponents  = TmpFitPtr->CompSize;
 | 
						|
 | 
						|
  for (Index = 0; Index < NumFitComponents; Index++) {
 | 
						|
    if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {
 | 
						|
      TmpFitPtr->CompAddress = PeiCorePhysicalAddress;
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    TmpFitPtr++;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
UpdateFitCheckSum (
 | 
						|
  IN FIT_TABLE   *FitTablePtr
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function is used to update the checksum for FIT.
 | 
						|
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FitTablePtr             - The pointer of FIT_TABLE.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
 | 
						|
    FitTablePtr->CheckSum = 0;
 | 
						|
    FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);
 | 
						|
  }
 | 
						|
}
 |