secmain.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,174 行 · 第 1/3 页

C
1,174
字号
/*++

Copyright (c) 2004 - 2006, Intel Corporation                                                        
All rights reserved. This program and the accompanying materials                          
are licensed and made available under the terms and conditions of the BSD License         
which accompanies this distribution.  The full text of the license may be found at        
http://opensource.org/licenses/bsd-license.php                                            
                                                                                          
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

Module Name:

  SecMain.c

Abstract:
  WinNt emulator of SEC phase. It's really a Win32 application, but this is
  Ok since all the other modules for NT32 are NOT Win32 applications.

  This program processes Windows environment variables and figures out
  what the memory layout will be, how may FD's will be loaded and also
  what the boot mode is. 

  The SEC registers a set of services with the SEC core. gPrivateDispatchTable
  is a list of PPI's produced by the SEC that are availble for usage in PEI.

  This code produces 128 K of temporary memory for the PEI stack by opening a
  Windows file and mapping it directly to memory addresses.

  The system.cmd script is used to set windows environment variables that drive
  the configuration opitons of the SEC.

--*/

#include "SecMain.h"

//
// Globals
//
EFI_PEI_PE_COFF_LOADER_PROTOCOL           *gPeiEfiPeiPeCoffLoader;
EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL  *gPeiEfiPeiFlushInstructionCache;
EFI_PEI_TRANSFER_CONTROL_PROTOCOL         *gPeiEfiPeiTransferControl;

//
// The SEC constructs a table of PPI's to pass up to subsequent phases.
//  This is done via the gPrivateDispatchTable.
//
EFI_NT_LOAD_AS_DLL_PPI                    mSecNtLoadAsDllPpi = {
  SecWinNtPeCoffLoaderLoadAsDll,
  SecWinNtPeCoffLoaderFreeLibrary
};

NT_PEI_LOAD_FILE_PPI                      mSecNtLoadFilePpi     = { SecWinNtPeiLoadFile };

PEI_NT_AUTOSCAN_PPI                       mSecNtAutoScanPpi     = { SecWinNtPeiAutoScan };

PEI_NT_THUNK_PPI                          mSecWinNtThunkPpi     = { SecWinNtWinNtThunkAddress };

PEI_STATUS_CODE_PPI                       mSecStatusCodePpi     = { SecPeiReportStatusCode };

NT_FWH_PPI                                mSecFwhInformationPpi = { SecWinNtFdAddress };

EFI_PEI_PPI_DESCRIPTOR                    gPrivateDispatchTable[] = {
  {
    EFI_PEI_PPI_DESCRIPTOR_PPI,
    &gEfiNtLoadAsDllPpiGuid,
    &mSecNtLoadAsDllPpi
  },
  {
    EFI_PEI_PPI_DESCRIPTOR_PPI,
    &gNtPeiLoadFileGuid,
    &mSecNtLoadFilePpi
  },
  {
    EFI_PEI_PPI_DESCRIPTOR_PPI,
    &gPeiNtAutoScanPpiGuid,
    &mSecNtAutoScanPpi
  },
  {
    EFI_PEI_PPI_DESCRIPTOR_PPI,
    &gPeiNtThunkPpiGuid,
    &mSecWinNtThunkPpi
  },
  {
    EFI_PEI_PPI_DESCRIPTOR_PPI,
    &gPeiStatusCodePpiGuid,
    &mSecStatusCodePpi
  },
  {
    EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
    &gNtFwhPpiGuid,
    &mSecFwhInformationPpi
  }
};

//
// Default information about where the FD is located.
//  This array gets filled in with information from EFI_FIRMWARE_VOLUMES
//  EFI_FIRMWARE_VOLUMES is a Windows environment variable set by system.cmd.
//  The number of array elements is allocated base on parsing
//  EFI_FIRMWARE_VOLUMES and the memory is never freed.
//
UINTN                                     gFdInfoCount = 0;
NT_FD_INFO                                *gFdInfo;

//
// Array that supports seperate memory rantes.
//  The memory ranges are set in system.cmd via the EFI_MEMORY_SIZE variable.
//  The number of array elements is allocated base on parsing
//  EFI_MEMORY_SIZE and the memory is never freed.
//
UINTN                                     gSystemMemoryCount = 0;
NT_SYSTEM_MEMORY                          *gSystemMemory;

UINTN                    mPdbNameModHandleArraySize = 0;
PDB_NAME_TO_MOD_HANDLE   *mPdbNameModHandleArray = NULL;

INTN
EFIAPI
main (
  IN  INTN  Argc,
  IN  CHAR8 **Argv,
  IN  CHAR8 **Envp
  )
/*++

Routine Description:
  Main entry point to SEC for WinNt. This is a Windows program

Arguments:
  Argc - Number of command line arguments
  Argv - Array of command line argument strings
  Envp - Array of environmemt variable strings

Returns:
  0 - Normal exit
  1 - Abnormal exit

--*/
{
  EFI_STATUS            Status;
  EFI_PHYSICAL_ADDRESS  InitialStackMemory;
  UINT64                InitialStackMemorySize;
  EFI_BOOT_MODE         BootMode;
  UINTN                 Index;
  UINTN                 Index1;
  UINTN                 Index2;
  UINTN                 PeiIndex;
  CHAR8                 *MemorySizeStr;
  CHAR8                 *FirmwareVolumesStr;
  CHAR8                 *BootModeStr;
  CHAR16                *FileName;
  CHAR8                 *FileNameAscii;
  BOOLEAN               Done;
  VOID                  *PeiCoreFile;

  printf ("\nEDK SEC Main NT Emulation Environment from www.TianoCore.org\n");

  //
  // Make some Windows calls to Set the process to the highest priority in the
  //  idle class. We need this to have good performance.
  //
  SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS);
  SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);

  //
  // Set defaults in case we can not find an environment variable
  //
  MemorySizeStr       = "64";
  FirmwareVolumesStr  = "..\\Fv\\FvRecovery.fd";
  BootModeStr         = "0";

  //
  // Parse the environment varialbes for the ones we care about.
  //
  for (Index = 0; Envp[Index] != NULL; Index++) {
    if (strncmp (Envp[Index], EFI_MEMORY_SIZE_STR, sizeof (EFI_MEMORY_SIZE_STR) - 1) == 0) {
      MemorySizeStr = &Envp[Index][sizeof (EFI_MEMORY_SIZE_STR)];
    }

    if (strncmp (Envp[Index], EFI_FIRMWARE_VOLUMES_STR, sizeof (EFI_FIRMWARE_VOLUMES_STR) - 1) == 0) {
      FirmwareVolumesStr = &Envp[Index][sizeof (EFI_FIRMWARE_VOLUMES_STR)];
    }

    if (strncmp (Envp[Index], EFI_BOOT_MODE_STR, sizeof (EFI_BOOT_MODE_STR) - 1) == 0) {
      BootModeStr = &Envp[Index][sizeof (EFI_BOOT_MODE_STR)];
    }
  }
  //
  // Allocate space for gSystemMemory Array
  //
  gSystemMemoryCount  = CountSeperatorsInString (MemorySizeStr, '!') + 1;
  gSystemMemory       = calloc (gSystemMemoryCount, sizeof (NT_SYSTEM_MEMORY));
  if (gSystemMemory == NULL) {
    printf ("ERROR : Can not allocate memory for %s.  Exiting.\n", MemorySizeStr);
    exit (1);
  }
  //
  // Allocate space for gSystemMemory Array
  //
  gFdInfoCount  = CountSeperatorsInString (FirmwareVolumesStr, '!') + 1;
  gFdInfo       = calloc (gFdInfoCount, sizeof (NT_FD_INFO));
  if (gFdInfo == NULL) {
    printf ("ERROR : Can not allocate memory for %s.  Exiting.\n", FirmwareVolumesStr);
    exit (1);
  }
  //
  // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)
  //
  BootMode = atoi (BootModeStr);
  printf ("  BootMode 0x%02x\n", BootMode);

  //
  // Open up a 128K file to emulate temp memory for PEI.
  //  on a real platform this would be SRAM, or using the cache as RAM.
  //  Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping
  //
  InitialStackMemory      = 0;
  InitialStackMemorySize  = 0x20000;
  Status = WinNtOpenFile (
            L"SecStack",
            (UINT32) InitialStackMemorySize,
            OPEN_ALWAYS,
            &InitialStackMemory,
            &InitialStackMemorySize
            );
  if (EFI_ERROR (Status)) {
    printf ("ERROR : Can not open SecStack Exiting\n");
    exit (1);
  }

  printf ("  SEC passing in %d bytes of temp RAM to PEI\n", InitialStackMemorySize);

  //
  // Open All the firmware volumes and remember the info in the gFdInfo global
  //
  for (Done = FALSE, Index = 0, PeiIndex = 0, PeiCoreFile = NULL; !Done; Index++) {
    FileNameAscii = FirmwareVolumesStr;
    for (Index1 = 0; (FirmwareVolumesStr[Index1] != '!') && (FirmwareVolumesStr[Index1] != 0); Index1++)
      ;
    if (FirmwareVolumesStr[Index1] == 0) {
      Done = TRUE;
    } else {
      FirmwareVolumesStr[Index1]  = '\0';
      FirmwareVolumesStr          = FirmwareVolumesStr + Index1 + 1;
    }
    //
    // Convert Ascii string to Unicode string
    //
    FileName = AsciiToUnicode (FileNameAscii, NULL);

    //
    // Open the FD and remmeber where it got mapped into our processes address space
    //
    Status = WinNtOpenFile (
              FileName,
              0,
              OPEN_EXISTING,
              &gFdInfo[Index].Address,
              &gFdInfo[Index].Size
              );
    if (EFI_ERROR (Status)) {
      printf ("ERROR : Can not open Firmware Device File %S (%r).  Exiting.\n", FileName, Status);
      exit (1);
    }

    printf ("  FD loaded from");
    //
    // printf can't print filenames directly as the \ gets interperted as an
    //  escape character.
    //
    for (Index2 = 0; FileName[Index2] != '\0'; Index2++) {
      printf ("%c", FileName[Index2]);
    }

    free (FileName);

    if (PeiCoreFile == NULL) {
      //
      // Assume the beginning of the FD is an FV and look for the PEI Core.
      // Load the first one we find.
      //
      Status = SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) gFdInfo[Index].Address, &PeiCoreFile);
      if (!EFI_ERROR (Status)) {
        PeiIndex = Index;
        printf (" contains SEC Core");
      }
    }

    printf ("\n");
  }
  //
  // Calculate memory regions and store the information in the gSystemMemory
  //  global for later use. The autosizing code will use this data to
  //  map this memory into the SEC process memory space.
  //
  for (Index = 0, Done = FALSE; !Done; Index++) {
    //
    // Save the size of the memory and make a Unicode filename SystemMemory00, ...
    //
    gSystemMemory[Index].Size = atoi (MemorySizeStr) * 0x100000;
#ifdef USE_VC8
    _snwprintf_s (gSystemMemory[Index].FileName, NT_SYSTEM_MEMORY_FILENAME_SIZE, NT_SYSTEM_MEMORY_FILENAME_SIZE, L"SystemMemory%02d", Index);
#else
    _snwprintf (gSystemMemory[Index].FileName, NT_SYSTEM_MEMORY_FILENAME_SIZE, L"SystemMemory%02d", Index);
#endif

    //
    // Find the next region
    //
    for (Index1 = 0; MemorySizeStr[Index1] != '!' && MemorySizeStr[Index1] != 0; Index1++)
      ;
    if (MemorySizeStr[Index1] == 0) {
      Done = TRUE;
    }

    MemorySizeStr = MemorySizeStr + Index1 + 1;
  }

  printf ("\n");

  //
  // Hand off to PEI Core
  //
  SecLoadFromCore ((UINTN) InitialStackMemory, (UINTN) InitialStackMemorySize, (UINTN) gFdInfo[0].Address, PeiCoreFile);

  //
  // If we get here, then the PEI Core returned. This is an error as PEI should
  //  always hand off to DXE.
  //
  printf ("ERROR : PEI Core returned\n");
  exit (1);
}

EFI_STATUS
WinNtOpenFile (
  IN  CHAR16                    *FileName,
  IN  UINT32                    MapSize,
  IN  DWORD                     CreationDisposition,
  IN OUT  EFI_PHYSICAL_ADDRESS  *BaseAddress,
  OUT UINT64                    *Length
  )
/*++

Routine Description:
  Opens and memory maps a file using WinNt services. If BaseAddress is non zero
  the process will try and allocate the memory starting at BaseAddress.

Arguments:
  FileName            - The name of the file to open and map
  MapSize             - The amount of the file to map in bytes
  CreationDisposition - The flags to pass to CreateFile().  Use to create new files for
                        memory emulation, and exiting files for firmware volume emulation
  BaseAddress         - The base address of the mapped file in the user address space.
                         If passed in as NULL the a new memory region is used.
                         If passed in as non NULL the request memory region is used for
                          the mapping of the file into the process space.
  Length              - The size of the mapped region in bytes

Returns:
  EFI_SUCCESS      - The file was opened and mapped.
  EFI_NOT_FOUND    - FileName was not found in the current directory
  EFI_DEVICE_ERROR - An error occured attempting to map the opened file

--*/
{
  HANDLE  NtFileHandle;
  HANDLE  NtMapHandle;
  VOID    *VirtualAddress;
  UINTN   FileSize;

  //
  // Use Win API to open/create a file
  //
  NtFileHandle = CreateFile (
                  FileName,
                  GENERIC_READ | GENERIC_WRITE,
                  FILE_SHARE_READ,
                  NULL,
                  CreationDisposition,
                  FILE_ATTRIBUTE_NORMAL,
                  NULL
                  );
  if (NtFileHandle == INVALID_HANDLE_VALUE) {
    return EFI_NOT_FOUND;
  }
  //
  // Map the open file into a memory range
  //
  NtMapHandle = CreateFileMapping (
                  NtFileHandle,
                  NULL,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?