secmain.c

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

C
1,174
字号
                  PAGE_READWRITE,
                  0,
                  MapSize,
                  NULL
                  );
  if (NtMapHandle == NULL) {
    return EFI_DEVICE_ERROR;
  }
  //
  // Get the virtual address (address in the emulator) of the mapped file
  //
  VirtualAddress = MapViewOfFileEx (
                    NtMapHandle,
                    FILE_MAP_ALL_ACCESS,
                    0,
                    0,
                    MapSize,
                    (LPVOID) (UINTN) *BaseAddress
                    );
  if (VirtualAddress == NULL) {
    return EFI_DEVICE_ERROR;
  }

  if (MapSize == 0) {
    //
    // Seek to the end of the file to figure out the true file size.
    //
    FileSize = SetFilePointer (
                NtFileHandle,
                0,
                NULL,
                FILE_END
                );
    if (FileSize == -1) {
      return EFI_DEVICE_ERROR;
    }

    *Length = (UINT64) FileSize;
  } else {
    *Length = (UINT64) MapSize;
  }

  *BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAddress;

  return EFI_SUCCESS;
}

#define BYTES_PER_RECORD  512

EFI_STATUS
EFIAPI
SecPeiReportStatusCode (
  IN EFI_PEI_SERVICES           **PeiServices,
  IN EFI_STATUS_CODE_TYPE       CodeType,
  IN EFI_STATUS_CODE_VALUE      Value,
  IN UINT32                     Instance,
  IN EFI_GUID                   * CallerId,
  IN EFI_STATUS_CODE_DATA       * Data OPTIONAL
  )
/*++

Routine Description:

  This routine produces the ReportStatusCode PEI service. It's passed 
  up to the PEI Core via a PPI. T

  This code currently uses the NT clib printf. This does not work the same way 
  as the EFI Print (), as %t, %g, %s as Unicode are not supported.

Arguments:
  (see EFI_PEI_REPORT_STATUS_CODE)

Returns:
  EFI_SUCCESS - Always return success

--*/
// TODO:    PeiServices - add argument and description to function comment
// TODO:    CodeType - add argument and description to function comment
// TODO:    Value - add argument and description to function comment
// TODO:    Instance - add argument and description to function comment
// TODO:    CallerId - add argument and description to function comment
// TODO:    Data - add argument and description to function comment
{
  CHAR8           *Format;
  EFI_DEBUG_INFO  *DebugInfo;
  VA_LIST         Marker;
  CHAR8           PrintBuffer[BYTES_PER_RECORD * 2];
  CHAR8           *Filename;
  CHAR8           *Description;
  UINT32          LineNumber;

  if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {
    //
    // This supports DEBUG () marcos
    // Data format
    //  EFI_STATUS_CODE_DATA
    //  EFI_DEBUG_INFO
    //
    // The first 12 * UINT64 bytes of the string are really an
    // arguement stack to support varargs on the Format string.
    //
    DebugInfo = (EFI_DEBUG_INFO *) (Data + 1);
    Marker    = (VA_LIST) (DebugInfo + 1);
    Format    = (CHAR8 *) (((UINT64 *) Marker) + 12);

    AvSPrint (PrintBuffer, BYTES_PER_RECORD, Format, Marker);
    printf (PrintBuffer);
  }

  if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) &&
      ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED)
      ) {
    if (ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
      //
      // Support ASSERT () macro
      //
      printf ("ASSERT %s(%d): %s\n", Filename, LineNumber, Description);
      EFI_BREAKPOINT ();
    }
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
SecWinNtPeCoffLoaderLoadAsDll (
  IN CHAR8    *PdbFileName,
  IN VOID     **ImageEntryPoint,
  OUT VOID    **ModHandle
  )
/*++

Routine Description:
  Loads the .DLL file is present when a PE/COFF file is loaded.  This provides source level
  debugging for drivers that have cooresponding .DLL files on the local system.

Arguments:
  PdbFileName     - The name of the .PDB file.  This was found from the PE/COFF
                    file's debug directory entry.
  ImageEntryPoint - A pointer to the DLL entry point of the .DLL file was loaded.
  ModHandle       - A pointer to the DLL Module of the .DLL file was loaded.

Returns:
  EFI_SUCCESS         - The .DLL file was loaded, and the DLL entry point is returned in
                        ImageEntryPoint
  EFI_NOT_FOUND       - The .DLL file could not be found
  EFI_UNSUPPORTED     - The .DLL file was loaded, but the entry point to the .DLL file
                        could not determined.
  EFI_ALREADY_STARTED - The .DLL file was already loaded

--*/
{
  CHAR16  *DllFileName;
  HMODULE Library;
  UINTN   Index;

  *ImageEntryPoint  = NULL;
  *ModHandle        = NULL;

  //
  // Check whether the ModHandle is already registered. If it does, that means
  // the DLL file is already loaded. To load it second times will cause the 
  // first time load information crash.
  //
  Library = GetModHandle (PdbFileName);
  if (Library != NULL) {
     return EFI_ALREADY_STARTED;
  }

  //
  // Convert filename from ASCII to Unicode
  //
  DllFileName = AsciiToUnicode (PdbFileName, &Index);

  //
  // Check that we have a valid filename
  //
  if (Index < 5 || DllFileName[Index - 4] != '.') {
    free (DllFileName);
    return EFI_NOT_FOUND;
  }
  //
  // Replace .PDB with .DLL on the filename
  //
  DllFileName[Index - 3]  = 'D';
  DllFileName[Index - 2]  = 'L';
  DllFileName[Index - 1]  = 'L';

  //
  // Load the .DLL file into the user process's address space
  //
  Library = LoadLibraryEx (DllFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);
  if (Library == NULL) {
    free (DllFileName);
    return EFI_NOT_FOUND;
  }
  //
  // InitializeDriver is the entry point we put in all our EFI DLL's. The
  // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() supresses the normal
  // DLL entry point of DllMain, and prevents other modules that are referenced
  // in side the DllFileName from being loaded.
  //
  *ImageEntryPoint = (VOID *) (UINTN) GetProcAddress (Library, "InitializeDriver");
  if (*ImageEntryPoint == NULL) {
    free (DllFileName);
    return EFI_UNSUPPORTED;
  }

  *ModHandle = Library;

  //
  // Register this module handle, this is used to check second times load.
  //
  AddModHandle (PdbFileName, Library);

  free (DllFileName);
  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
SecWinNtPeCoffLoaderFreeLibrary (
  IN VOID     *ModHandle
  )
/*++

Routine Description:
  Free resources allocated by SecWinNtPeCoffLoaderLoadAsDll

Arguments:
  MohHandle   - Handle of the resources to free to undo the work.

Returns:
  EFI_SUCCESS - This resource is freed successfully.

--*/
{
  if (ModHandle != NULL) {
    RemoveModeHandle (ModHandle);
    FreeLibrary (ModHandle);
  }
  return EFI_SUCCESS;
}

VOID
SecLoadFromCore (
  IN  UINTN   LargestRegion,
  IN  UINTN   LargestRegionSize,
  IN  UINTN   BootFirmwareVolumeBase,
  IN  VOID    *PeiCorePe32File
  )
/*++

Routine Description:
  This is the service to load the PEI Core from the Firmware Volume

Arguments:
  LargestRegion           - Memory to use for PEI.
  LargestRegionSize       - Size of Memory to use for PEI
  BootFirmwareVolumeBase  - Start of the Boot FV
  PeiCorePe32File         - PEI Core PE32 

Returns:
  Success means control is transfered and thus we should never return

--*/
{
  EFI_STATUS                  Status;
  EFI_PHYSICAL_ADDRESS        TopOfMemory;
  VOID                        *TopOfStack;
  UINT64                      PeiCoreSize;
  EFI_PHYSICAL_ADDRESS        PeiCoreEntryPoint;
  EFI_PHYSICAL_ADDRESS        PeiImageAddress;
  EFI_PEI_STARTUP_DESCRIPTOR  PeiStartup;

  //
  // Install the PEI Protocols that are shared between PEI and DXE
  //
  InstallEfiPeiFlushInstructionCache (&gPeiEfiPeiFlushInstructionCache);
  InstallEfiPeiTransferControl (&gPeiEfiPeiTransferControl);

  gPeiEfiPeiPeCoffLoader = NULL;
  InstallEfiPeiPeCoffLoader (NULL, &gPeiEfiPeiPeCoffLoader, (EFI_PEI_PPI_DESCRIPTOR *) &mSecNtLoadAsDllPpi);

  //
  // Compute Top Of Memory for Stack and PEI Core Allocations
  //
  TopOfMemory = LargestRegion + ((LargestRegionSize) & (~15));

  //
  // Allocate 128KB for the Stack
  //
  TopOfStack  = (VOID *) (UINTN) (TopOfMemory - sizeof (EFI_PEI_STARTUP_DESCRIPTOR));
  TopOfMemory = TopOfMemory - EFI_STACK_SIZE;

  //
  // Bind this information into the SEC hand-off state
  //
  PeiStartup.DispatchTable      = (EFI_PEI_PPI_DESCRIPTOR *) &gPrivateDispatchTable;
  PeiStartup.SizeOfCacheAsRam   = EFI_STACK_SIZE;
  PeiStartup.BootFirmwareVolume = BootFirmwareVolumeBase;

  CopyMem (TopOfStack, &PeiStartup, sizeof (EFI_PEI_STARTUP_DESCRIPTOR));

  //
  // Load the PEI Core from a Firmware Volume
  //
  Status = SecWinNtPeiLoadFile (
            PeiCorePe32File,
            &PeiImageAddress,
            &PeiCoreSize,
            &PeiCoreEntryPoint
            );
  if (EFI_ERROR (Status)) {
    return ;
  }
  //
  // Transfer control to the PEI Core
  //
  SecSwitchStacks (
    (VOID *) (UINTN) PeiCoreEntryPoint,
    (VOID *) (UINTN) TopOfStack,
    (VOID *) (UINTN) TopOfStack,
    (VOID *) (UINTN) NULL
    );

  //
  // If we get here, then the PEI Core returned.  This is an error
  //
  return ;
}

EFI_STATUS
EFIAPI
SecWinNtPeiAutoScan (
  IN  UINTN                 Index,
  OUT EFI_PHYSICAL_ADDRESS  *MemoryBase,
  OUT UINT64                *MemorySize
  )
/*++

Routine Description:
  This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
  It allows discontiguous memory regions to be supported by the emulator.
  It uses gSystemMemory[] and gSystemMemoryCount that were created by
  parsing the Windows environment variable EFI_MEMORY_SIZE.
  The size comes from the varaible and the address comes from the call to
  WinNtOpenFile. 

Arguments:
  Index      - Which memory region to use
  MemoryBase - Return Base address of memory region
  MemorySize - Return size in bytes of the memory region

Returns:
  EFI_SUCCESS - If memory region was mapped
  EFI_UNSUPPORTED - If Index is not supported

--*/
{
  EFI_STATUS  Status;

  if (Index >= gSystemMemoryCount) {
    return EFI_UNSUPPORTED;
  }

  *MemoryBase = 0;
  Status = WinNtOpenFile (
            gSystemMemory[Index].FileName,
            (UINT32) gSystemMemory[Index].Size,
            OPEN_ALWAYS,
            MemoryBase,
            MemorySize
            );

  gSystemMemory[Index].Memory = *MemoryBase;

  return Status;
}

EFI_STATUS
EFIAPI
SecWinNtWinNtThunkAddress (
  IN OUT UINT64                *InterfaceSize,
  IN OUT EFI_PHYSICAL_ADDRESS  *InterfaceBase
  )
/*++

Routine Description:
  Since the SEC is the only Windows program in stack it must export
  an interface to do Win API calls. That's what the WinNtThunk address

⌨️ 快捷键说明

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