genfvimagelib.c

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

C
2,197
字号
  EFI_STATUS                            Status;
  EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
  UINTN                                 MemoryImagePointer;
  UINTN                                 MemoryImagePointerAligned;

  EFI_PHYSICAL_ADDRESS                  ImageAddress;
  UINT64                                ImageSize;
  EFI_PHYSICAL_ADDRESS                  EntryPoint;

  UINT32                                Pe32FileSize;
  UINT32                                NewPe32BaseAddress;

  UINTN                                 Index;
  EFI_FILE_SECTION_POINTER              CurrentPe32Section;
  UINT8                                 FileGuidString[80];

  //
  // Verify input parameters
  //
  if (FfsFile == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Convert the GUID to a string so we can at least report which file
  // if we find an error.
  //
  PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);

  //
  // Do some nominal checks on the file, then check for XIP.
  //
  Status = VerifyFfsFile (FfsFile);
  if (EFI_ERROR (Status)) {
    Error (NULL, 0, 0, "invalid FFS file", FileGuidString);
    return EFI_INVALID_PARAMETER;
  }

  if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
      FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
      FfsFile->Type != EFI_FV_FILETYPE_PEIM
      ) {
    //
    // File is not XIP, so don't rebase
    //
    return EFI_SUCCESS;
  }
  //
  // Rebase each PE32 section
  //
  for (Index = 1;; Index++) {
    Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
    if (EFI_ERROR (Status)) {
      break;
    }
    //
    // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
    //
    NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile);

    //
    // Initialize context
    //
    memset (&ImageContext, 0, sizeof (ImageContext));
    ImageContext.Handle     = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
    ImageContext.ImageRead  = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;

    Status                  = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);

    if (EFI_ERROR (Status)) {
      Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString);
      return Status;
    }
    //
    // Allocate a buffer for the image to be loaded into.
    //
    Pe32FileSize              = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size);
    MemoryImagePointer        = (UINTN) (malloc (Pe32FileSize + 0x1000));
    MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);
    if (MemoryImagePointerAligned == 0) {
      Error (NULL, 0, 0, "memory allocation failure", NULL);
      return EFI_OUT_OF_RESOURCES;
    }

    //
    // bugbug
    //
    ImageContext.ImageAddress = MemoryImagePointerAligned;
    Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);
    if (EFI_ERROR (Status)) {
      Error (NULL, 0, 0, "LoadImage() failure", FileGuidString);
      free ((VOID *) MemoryImagePointer);
      return Status;
    }

    Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);
    if (EFI_ERROR (Status)) {
      Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString);
      free ((VOID *) MemoryImagePointer);
      return Status;
    }

    ImageAddress  = ImageContext.ImageAddress;
    ImageSize     = ImageContext.ImageSize;
    EntryPoint    = ImageContext.EntryPoint;

    if (ImageSize > Pe32FileSize) {
      Error (
        NULL,
        0,
        0,
        "rebased PE32 is larger than original PE32 image",
        "0x%X > 0x%X on file %s",
        ImageSize,
        Pe32FileSize,
        FileGuidString
        );
      free ((VOID *) MemoryImagePointer);
      return EFI_ABORTED;
    }

    memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize);

    free ((VOID *) MemoryImagePointer);
  }
  //
  // the above for loop will always exit with EFI_NOT_FOUND if it completes
  // normally.  If Index == 1 at exit, then no PE32 sections were found.  If it
  // exits with any other error code, then something broke...
  //
  if (Status != EFI_NOT_FOUND) {
    Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString);
    return Status;
  }

  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, '\\');
  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, "\\");
    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) {
      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 {
        //
        // BUGBUG: Don't know why this is 0x28 bytes.
        //
        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");

⌨️ 快捷键说明

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