Пример #1
0
/**
  When called with a null NicPtr, this routine decrements the number of NICs
  this UNDI is supporting and removes the NIC_DATA_POINTER from the array.
  Otherwise, it increments the number of NICs this UNDI is supported and
  updates the pxe.Fudge to ensure a proper check sum results.

  @param  NicPtr               Pointer to the NIC data structure.

  @return None

**/
VOID
PxeUpdate (
  IN  NIC_DATA_INSTANCE *NicPtr,
  IN PXE_SW_UNDI        *PxePtr
  )
{
  if (NicPtr == NULL) {
    if (PxePtr->IFcnt > 0) {
      //
      // number of NICs this undi supports
      //
      PxePtr->IFcnt--;
    }

    PxePtr->Fudge = (UINT8) (PxePtr->Fudge - CalculateSum8 ((VOID *) PxePtr, PxePtr->Len));
    return ;
  }

  //
  // number of NICs this undi supports
  //
  PxePtr->IFcnt++;
  PxePtr->Fudge = (UINT8) (PxePtr->Fudge - CalculateSum8 ((VOID *) PxePtr, PxePtr->Len));

  return ;
}
Пример #2
0
/**
  Get the address of Xen ACPI Root System Description Pointer (RSDP)
  structure.

  @param  RsdpStructurePtr   Return pointer to RSDP structure

  @return EFI_SUCCESS        Find Xen RSDP structure successfully.
  @return EFI_NOT_FOUND      Don't find Xen RSDP structure.
  @return EFI_ABORTED        Find Xen RSDP structure, but it's not integrated.

**/
EFI_STATUS
EFIAPI
GetXenAcpiRsdp (
  OUT   EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER   **RsdpPtr
  )
{
  EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER   *RsdpStructurePtr;
  UINT8                                          *XenAcpiPtr;
  UINT8                                          Sum;

  //
  // Detect the RSDP structure
  //
  for (XenAcpiPtr = (UINT8*)(UINTN) XEN_ACPI_PHYSICAL_ADDRESS;
       XenAcpiPtr < (UINT8*)(UINTN) XEN_BIOS_PHYSICAL_END;
       XenAcpiPtr += 0x10) {

    RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)
                         (UINTN) XenAcpiPtr;

    if (!AsciiStrnCmp ((CHAR8 *) &RsdpStructurePtr->Signature, "RSD PTR ", 8)) {
      //
      // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.
      // This is only the first 20 bytes of the structure
      //
      Sum = CalculateSum8 (
              (CONST UINT8 *)RsdpStructurePtr,
              sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
              );
      if (Sum != 0) {
        return EFI_ABORTED;
      }

      if (RsdpStructurePtr->Revision >= 2) {
        //
        // RSDP ACPI 2.0/3.0 checksum, this is the entire table
        //
        Sum = CalculateSum8 (
                (CONST UINT8 *)RsdpStructurePtr,
                sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
                );
        if (Sum != 0) {
          return EFI_ABORTED;
        }
      }
      *RsdpPtr = RsdpStructurePtr;
      return EFI_SUCCESS;
    }
  }

  return EFI_NOT_FOUND;
}
Пример #3
0
/**
  Verify checksum of the FFS file header.

  @param  FfsHeader      Points to the FFS file header to be checked

  @retval TRUE           Checksum verification passed
  @retval FALSE          Checksum verification failed

**/
BOOLEAN
VerifyHeaderChecksum (
  IN EFI_FFS_FILE_HEADER  *FfsHeader
  )
{
  UINT8 HeaderChecksum;

  if (IS_FFS_FILE2 (FfsHeader)) {
    HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER2));
  } else {
    HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));
  }
  HeaderChecksum = (UINT8) (HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File);

  if (HeaderChecksum == 0) {
    return TRUE;
  } else {
    return FALSE;
  }
}
Пример #4
0
/**
  Get the address of Xen ACPI Root System Description Pointer (RSDP)
  structure.

  @param  RsdpStructurePtr   Return pointer to RSDP structure

  @return EFI_SUCCESS        Find Xen RSDP structure successfully.
  @return EFI_NOT_FOUND      Don't find Xen RSDP structure.
  @return EFI_ABORTED        Find Xen RSDP structure, but it's not integrated.

**/
STATIC
EFI_STATUS
EFIAPI
GetXenArmAcpiRsdp (
  OUT   EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER   **RsdpPtr
  )
{
  EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER   *RsdpStructurePtr;
  EFI_STATUS                                     Status;
  FDT_CLIENT_PROTOCOL                            *FdtClient;
  CONST UINT64                                   *Reg;
  UINT32                                         RegSize;
  UINTN                                          AddressCells, SizeCells;
  UINT64                                         RegBase;
  UINT8                                          Sum;

  RsdpStructurePtr = NULL;
  FdtClient = NULL;
  //
  // Get the RSDP structure address from DeviceTree
  //
  Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
                  (VOID **)&FdtClient);
  ASSERT_EFI_ERROR (Status);

  Status = FdtClient->FindCompatibleNodeReg (FdtClient, "xen,guest-acpi",
                        (CONST VOID **)&Reg, &AddressCells, &SizeCells,
                        &RegSize);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_WARN, "%a: No 'xen,guest-acpi' compatible DT node found\n",
      __FUNCTION__));
    return EFI_NOT_FOUND;
  }

  ASSERT (AddressCells == 2);
  ASSERT (SizeCells == 2);
  ASSERT (RegSize == 2 * sizeof (UINT64));

  RegBase = SwapBytes64(Reg[0]);
  RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)RegBase;

  if (RsdpStructurePtr && RsdpStructurePtr->Revision >= 2) {
    Sum = CalculateSum8 ((CONST UINT8 *)RsdpStructurePtr,
            sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER));
    if (Sum != 0) {
      return EFI_ABORTED;
    }
  }

  *RsdpPtr = RsdpStructurePtr;
  return EFI_SUCCESS;
}
Пример #5
0
/**
  Returns the two's complement checksum of all elements in a buffer
  of 8-bit values.

  This function first calculates the sum of the 8-bit values in the
  buffer specified by Buffer and Length.  The carry bits in the result
  of addition are dropped. Then, the two's complement of the sum is
  returned.  If Length is 0, then 0 is returned.

  If Buffer is NULL, then ASSERT().
  If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().

  @param  Buffer      Pointer to the buffer to carry out the checksum operation.
  @param  Length      The size, in bytes, of Buffer.

  @return Checksum    The 2's complement checksum of Buffer.

**/
UINT8
EFIAPI
CalculateCheckSum8 (
  IN      CONST UINT8              *Buffer,
  IN      UINTN                     Length
  )
{
  UINT8     CheckSum;

  CheckSum = CalculateSum8 (Buffer, Length);

  //
  // Return the checksum based on 2's complement.
  //
  return (UINT8) (0x100 - CheckSum);
}
Пример #6
0
/**
  Initialize the !PXE structure

  @param  PxePtr               Pointer to SW_UNDI data structure.

  @retval EFI_SUCCESS          This driver is added to Controller.
  @retval other                This driver does not support this device.

**/
VOID
PxeStructInit (
  IN PXE_SW_UNDI *PxePtr
  )
{
  //
  // Initialize the !PXE structure
  //
  PxePtr->Signature = PXE_ROMID_SIGNATURE;
  PxePtr->Len       = sizeof (PXE_SW_UNDI);
  //
  // cksum
  //
  PxePtr->Fudge     = 0;
  //
  // number of NICs this undi supports
  //
  PxePtr->IFcnt = 0;
  PxePtr->Rev       = PXE_ROMID_REV;
  PxePtr->MajorVer  = PXE_ROMID_MAJORVER;
  PxePtr->MinorVer  = PXE_ROMID_MINORVER;
  PxePtr->reserved1 = 0;

  PxePtr->Implementation = PXE_ROMID_IMP_SW_VIRT_ADDR |
    PXE_ROMID_IMP_FRAG_SUPPORTED |
    PXE_ROMID_IMP_CMD_LINK_SUPPORTED |
    PXE_ROMID_IMP_NVDATA_READ_ONLY |
    PXE_ROMID_IMP_STATION_ADDR_SETTABLE |
    PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED |
    PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED |
    PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED |
    PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED |
    PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED |
    PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED;

  PxePtr->EntryPoint  = (UINT64) (UINTN) UNDI_APIEntry_new;
  PxePtr->MinorVer    = PXE_ROMID_MINORVER_31;

  PxePtr->reserved2[0]  = 0;
  PxePtr->reserved2[1]  = 0;
  PxePtr->reserved2[2]  = 0;
  PxePtr->BusCnt        = 1;
  PxePtr->BusType[0]    = PXE_BUSTYPE_PCI;

  PxePtr->Fudge         = (UINT8) (PxePtr->Fudge - CalculateSum8 ((VOID *) PxePtr, PxePtr->Len));
}
/**
  Calculates the checksum of the header of a file.
  The header is a zero byte checksum, so zero means header is good

  @param FfsHeader       Pointer to FFS File Header

  @retval Checksum of the header

**/
STATIC
UINT8
CalculateHeaderChecksum (
  IN EFI_FFS_FILE_HEADER  *FileHeader
  )
{
  UINT8   Sum;

  // Calculate the sum of the header
  Sum = CalculateSum8 ((CONST VOID*)FileHeader,sizeof(EFI_FFS_FILE_HEADER));

  // State field (since this indicates the different state of file).
  Sum = (UINT8)(Sum - FileHeader->State);

  // Checksum field of the file is not part of the header checksum.
  Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);

  return Sum;
}
Пример #8
0
UINT8
CalculateChecksum8 (
  IN UINT8        *Buffer,
  IN UINTN        Size
  )
/*++
  
Routine Description:

  This function calculates the value needed for a valid UINT8 checksum

Arguments:

  Buffer      Pointer to buffer containing byte data of component.
  Size        Size of the buffer

Returns:

  The 8 bit checksum value needed.

--*/
{
  return (UINT8) (0x100 - CalculateSum8 (Buffer, Size));
}
Пример #9
0
/**
  Process a QEMU_LOADER_ADD_POINTER command in order to see if its target byte
  array is an ACPI table, and if so, install it.

  This function assumes that the entire QEMU linker/loader command file has
  been processed successfuly in a prior first pass.

  @param[in] AddPointer        The QEMU_LOADER_ADD_POINTER command to process.

  @param[in] Tracker           The ORDERED_COLLECTION tracking the BLOB user
                               structures.

  @param[in] AcpiProtocol      The ACPI table protocol used to install tables.

  @param[in,out] InstalledKey  On input, an array of INSTALLED_TABLES_MAX UINTN
                               elements, allocated by the caller. On output,
                               the function will have stored (appended) the
                               AcpiProtocol-internal key of the ACPI table that
                               the function has installed, if the AddPointer
                               command identified an ACPI table that is
                               different from RSDT and XSDT.

  @param[in,out] NumInstalled  On input, the number of entries already used in
                               InstalledKey; it must be in [0,
                               INSTALLED_TABLES_MAX] inclusive. On output, the
                               parameter is incremented if the AddPointer
                               command identified an ACPI table that is
                               different from RSDT and XSDT.

  @retval EFI_INVALID_PARAMETER  NumInstalled was outside the allowed range on
                                 input.

  @retval EFI_OUT_OF_RESOURCES   The AddPointer command identified an ACPI
                                 table different from RSDT and XSDT, but there
                                 was no more room in InstalledKey.

  @retval EFI_SUCCESS            AddPointer has been processed. Either an ACPI
                                 table different from RSDT and XSDT has been
                                 installed (reflected by InstalledKey and
                                 NumInstalled), or RSDT or XSDT has been
                                 identified but not installed, or the fw_cfg
                                 blob pointed-into by AddPointer has been
                                 marked as hosting something else than just
                                 direct ACPI table contents.

  @return                        Error codes returned by
                                 AcpiProtocol->InstallAcpiTable().
**/
STATIC
EFI_STATUS
EFIAPI
Process2ndPassCmdAddPointer (
  IN     CONST QEMU_LOADER_ADD_POINTER *AddPointer,
  IN     CONST ORDERED_COLLECTION      *Tracker,
  IN     EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol,
  IN OUT UINTN                         InstalledKey[INSTALLED_TABLES_MAX],
  IN OUT INT32                         *NumInstalled
  )
{
  CONST ORDERED_COLLECTION_ENTRY                     *TrackerEntry;
  CONST ORDERED_COLLECTION_ENTRY                     *TrackerEntry2;
  CONST BLOB                                         *Blob;
  BLOB                                               *Blob2;
  CONST UINT8                                        *PointerField;
  UINT64                                             PointerValue;
  UINTN                                              Blob2Remaining;
  UINTN                                              TableSize;
  CONST EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
  CONST EFI_ACPI_DESCRIPTION_HEADER                  *Header;
  EFI_STATUS                                         Status;

  if (*NumInstalled < 0 || *NumInstalled > INSTALLED_TABLES_MAX) {
    return EFI_INVALID_PARAMETER;
  }

  TrackerEntry = OrderedCollectionFind (Tracker, AddPointer->PointerFile);
  TrackerEntry2 = OrderedCollectionFind (Tracker, AddPointer->PointeeFile);
  Blob = OrderedCollectionUserStruct (TrackerEntry);
  Blob2 = OrderedCollectionUserStruct (TrackerEntry2);
  PointerField = Blob->Base + AddPointer->PointerOffset;
  PointerValue = 0;
  CopyMem (&PointerValue, PointerField, AddPointer->PointerSize);

  //
  // We assert that PointerValue falls inside Blob2's contents. This is ensured
  // by the Blob2->Size check and later checks in ProcessCmdAddPointer().
  //
  Blob2Remaining = (UINTN)Blob2->Base;
  ASSERT(PointerValue >= Blob2Remaining);
  Blob2Remaining += Blob2->Size;
  ASSERT (PointerValue < Blob2Remaining);

  Blob2Remaining -= (UINTN) PointerValue;
  DEBUG ((EFI_D_VERBOSE, "%a: checking for ACPI header in \"%a\" at 0x%Lx "
    "(remaining: 0x%Lx): ", __FUNCTION__, AddPointer->PointeeFile,
    PointerValue, (UINT64)Blob2Remaining));

  TableSize = 0;

  //
  // To make our job simple, the FACS has a custom header. Sigh.
  //
  if (sizeof *Facs <= Blob2Remaining) {
    Facs = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)PointerValue;

    if (Facs->Length >= sizeof *Facs &&
        Facs->Length <= Blob2Remaining &&
        Facs->Signature ==
                EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
      DEBUG ((EFI_D_VERBOSE, "found \"%-4.4a\" size 0x%x\n",
        (CONST CHAR8 *)&Facs->Signature, Facs->Length));
      TableSize = Facs->Length;
    }
  }

  //
  // check for the uniform tables
  //
  if (TableSize == 0 && sizeof *Header <= Blob2Remaining) {
    Header = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)PointerValue;

    if (Header->Length >= sizeof *Header &&
        Header->Length <= Blob2Remaining &&
        CalculateSum8 ((CONST UINT8 *)Header, Header->Length) == 0) {
      //
      // This looks very much like an ACPI table from QEMU:
      // - Length field consistent with both ACPI and containing blob size
      // - checksum is correct
      //
      DEBUG ((EFI_D_VERBOSE, "found \"%-4.4a\" size 0x%x\n",
        (CONST CHAR8 *)&Header->Signature, Header->Length));
      TableSize = Header->Length;

      //
      // Skip RSDT and XSDT because those are handled by
      // EFI_ACPI_TABLE_PROTOCOL automatically.
      if (Header->Signature ==
                    EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE ||
          Header->Signature ==
                    EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
        return EFI_SUCCESS;
      }
    }
  }

  if (TableSize == 0) {
    DEBUG ((EFI_D_VERBOSE, "not found; marking fw_cfg blob as opaque\n"));
    Blob2->HostsOnlyTableData = FALSE;
    return EFI_SUCCESS;
  }

  if (*NumInstalled == INSTALLED_TABLES_MAX) {
    DEBUG ((EFI_D_ERROR, "%a: can't install more than %d tables\n",
      __FUNCTION__, INSTALLED_TABLES_MAX));
    return EFI_OUT_OF_RESOURCES;
  }

  Status = AcpiProtocol->InstallAcpiTable (AcpiProtocol,
                           (VOID *)(UINTN)PointerValue, TableSize,
                           &InstalledKey[*NumInstalled]);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "%a: InstallAcpiTable(): %r\n", __FUNCTION__,
      Status));
    return Status;
  }
  ++*NumInstalled;
  return EFI_SUCCESS;
}
Пример #10
0
EFI_STATUS
VerifyFfsFile (
  IN EFI_FFS_FILE_HEADER  *FfsHeader
  )
/*++

Routine Description:

  Verify the current pointer points to a FFS file header.

Arguments:

  FfsHeader     Pointer to an alleged FFS file.

Returns:

  EFI_SUCCESS           The Ffs header is valid.
  EFI_NOT_FOUND         This "file" is the beginning of free space.
  EFI_VOLUME_CORRUPTED  The Ffs header is not valid.
  EFI_ABORTED           The erase polarity is not known.

--*/
{
  BOOLEAN             ErasePolarity;
  EFI_STATUS          Status;
  EFI_FFS_FILE_HEADER2 BlankHeader;
  UINT8               Checksum;
  UINT32              FileLength;
  UINT8               SavedChecksum;
  UINT8               SavedState;
  UINT8               FileGuidString[80];
  UINT32              FfsHeaderSize;

  //
  // Verify library has been initialized.
  //
  if (mFvHeader == NULL || mFvLength == 0) {
    return EFI_ABORTED;
  }
  //
  // Verify FV header
  //
  Status = VerifyFv (mFvHeader);
  if (EFI_ERROR (Status)) {
    return EFI_ABORTED;
  }
  //
  // Get the erase polarity.
  //
  Status = GetErasePolarity (&ErasePolarity);
  if (EFI_ERROR (Status)) {
    return EFI_ABORTED;
  }

  FfsHeaderSize = GetFfsHeaderLength(FfsHeader);
  //
  // Check if we have free space
  //
  if (ErasePolarity) {
    memset (&BlankHeader, -1, FfsHeaderSize);
  } else {
    memset (&BlankHeader, 0, FfsHeaderSize);
  }

  if (memcmp (&BlankHeader, FfsHeader, FfsHeaderSize) == 0) {
    return EFI_NOT_FOUND;
  }
  //
  // Convert the GUID to a string so we can at least report which file
  // if we find an error.
  //
  PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE);
  //
  // Verify file header checksum
  //
  SavedState = FfsHeader->State;
  FfsHeader->State = 0;
  SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File;
  FfsHeader->IntegrityCheck.Checksum.File = 0;
  Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FfsHeaderSize);
  FfsHeader->State = SavedState;
  FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum;
  if (Checksum != 0) {
    Error (NULL, 0, 0006, "invalid FFS file header checksum", "Ffs file with Guid %s", FileGuidString);
    return EFI_ABORTED;
  }
  //
  // Verify file checksum
  //
  if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
    //
    // Verify file data checksum
    //
    FileLength          = GetFfsFileLength (FfsHeader);
    Checksum            = CalculateSum8 ((UINT8 *) ((UINT8 *)FfsHeader + FfsHeaderSize), FileLength - FfsHeaderSize);
    Checksum            = Checksum + FfsHeader->IntegrityCheck.Checksum.File;
    if (Checksum != 0) {
      Error (NULL, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString);
      return EFI_ABORTED;
    }
  } else {
    //
    // File does not have a checksum
    // Verify contents are 0xAA as spec'd
    //
    if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
      Error (NULL, 0, 0006, "invalid fixed FFS file header checksum", "Ffs file with Guid %s", FileGuidString);
      return EFI_ABORTED;
    }
  }

  return EFI_SUCCESS;
}
Пример #11
0
EFI_STATUS
VerifyFfsFile (
  IN EFI_FFS_FILE_HEADER  *FfsHeader
  )
/*++

Routine Description:

  Verify the current pointer points to a FFS file header.

Arguments:

  FfsHeader     Pointer to an alleged FFS file.

Returns:

  EFI_SUCCESS           The Ffs header is valid.
  EFI_NOT_FOUND         This "file" is the beginning of free space.
  EFI_VOLUME_CORRUPTED  The Ffs header is not valid.
  EFI_ABORTED           The erase polarity is not known.

--*/
{
  BOOLEAN             ErasePolarity;
  EFI_STATUS          Status;
  EFI_FFS_FILE_HEADER BlankHeader;
  UINT8               Checksum;
  UINT32              FileLength;
  UINT32              OccupiedFileLength;
  UINT8               SavedChecksum;
  UINT8               SavedState;
  UINT8               FileGuidString[80];
  UINT32              TailSize;
#if (PI_SPECIFICATION_VERSION < 0x00010000)  
  EFI_FFS_FILE_TAIL   *Tail;
#endif
  
  //
  // Verify library has been initialized.
  //
  if (mFvHeader == NULL || mFvLength == 0) {
    return EFI_ABORTED;
  }
  //
  // Verify FV header
  //
  Status = VerifyFv (mFvHeader);
  if (EFI_ERROR (Status)) {
    return EFI_ABORTED;
  }
  //
  // Get the erase polarity.
  //
  Status = GetErasePolarity (&ErasePolarity);
  if (EFI_ERROR (Status)) {
    return EFI_ABORTED;
  }
  //
  // Check if we have free space
  //
  if (ErasePolarity) {
    memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER));
  } else {
    memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
  }

  if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) {
    return EFI_NOT_FOUND;
  }
  //
  // Convert the GUID to a string so we can at least report which file
  // if we find an error.
  //
  PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE);
  if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
    TailSize = sizeof (EFI_FFS_FILE_TAIL);
  } else {
    TailSize = 0;
  }
  //
  // Verify file header checksum
  //
  SavedState = FfsHeader->State;
  FfsHeader->State = 0;
  SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File;
  FfsHeader->IntegrityCheck.Checksum.File = 0;
  Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));
  FfsHeader->State = SavedState;
  FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum;
  if (Checksum != 0) {
    Error (NULL, 0, 0, FileGuidString, "invalid FFS file header checksum");
    return EFI_ABORTED;
  }
  //
  // Verify file checksum
  //
  if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
    //
    // Verify file data checksum
    //
    FileLength          = GetLength (FfsHeader->Size);
    OccupiedFileLength  = (FileLength + 0x07) & (-1 << 3);
#if (PI_SPECIFICATION_VERSION < 0x00010000)  
    Checksum            = CalculateSum8 ((UINT8 *) FfsHeader, FileLength - TailSize);
    Checksum            = (UINT8) (Checksum - FfsHeader->State);
#else
    Checksum            = CalculateSum8 ((UINT8 *) ((UINTN)FfsHeader + sizeof (EFI_FFS_FILE_HEADER)), FileLength - TailSize - sizeof (EFI_FFS_FILE_HEADER));
    Checksum            =  Checksum + (UINT8)FfsHeader->IntegrityCheck.Checksum.File;
#endif
    if (Checksum != 0) {
      Error (NULL, 0, 0, FileGuidString, "invalid FFS file checksum");
      return EFI_ABORTED;
    }
  } else {
    //
    // File does not have a checksum
    // Verify contents are 0x5A(Framework) and 0xAA(PI 1.0) as spec'd
    //
    if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
      Error (NULL, 0, 0, FileGuidString, "invalid fixed file checksum");
      return EFI_ABORTED;
    }
  }
#if (PI_SPECIFICATION_VERSION < 0x00010000)  
  //
  // Check if the tail is present and verify it if it is.
  //
  if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
    //
    // Verify tail is complement of integrity check field in the header.
    //
    Tail = (EFI_FFS_FILE_TAIL *) ((UINTN) FfsHeader + GetLength (FfsHeader->Size) - sizeof (EFI_FFS_FILE_TAIL));
    if (FfsHeader->IntegrityCheck.TailReference != (EFI_FFS_FILE_TAIL)~(*Tail)) {
      Error (NULL, 0, 0, FileGuidString, "invalid FFS file tail");
      return EFI_ABORTED;
    }
  }
#endif
  return EFI_SUCCESS;
}
EFI_STATUS
ConvertMpsTable (
    IN OUT VOID          **Table
                 )
/*++

  Routine Description:

  Convert MP Table if the Location of the SMBios Table is lower than Address 0x100000
  Assumption here:
  As in legacy Bios, MP table is required to place in E/F Seg,
  So here we just check if the range is E/F seg,
  and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
  Arguments:
  Table     - pointer to the table

  Returns:
  EFI_SUCCESS - Convert Table successfully
  Other       - Failed

  --*/
{
    UINT32                                       Data32;
    UINT32                                       FPLength;
    EFI_LEGACY_MP_TABLE_FLOATING_POINTER         *MpsFloatingPointerOri;
    EFI_LEGACY_MP_TABLE_FLOATING_POINTER         *MpsFloatingPointerNew;
    EFI_LEGACY_MP_TABLE_HEADER                   *MpsTableOri;
    EFI_LEGACY_MP_TABLE_HEADER                   *MpsTableNew;
    VOID                                         *OemTableOri;
    VOID                                         *OemTableNew;
    EFI_STATUS                                   Status;
    EFI_PHYSICAL_ADDRESS                         BufferPtr;

    //
    // Get MP configuration Table
    //
    MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*Table);
    //
    // Get Floating pointer structure length
    //
    FPLength = MpsFloatingPointerOri->Length * 16;
    ASSERT(CalculateSum8((UINT8*)MpsFloatingPointerOri, FPLength) == 0);
    Data32   = FPLength + SYS_TABLE_PAD (FPLength);
    MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress);
    ASSERT(MpsTableOri != NULL);
    ASSERT(CalculateSum8((UINT8*)MpsTableOri, MpsTableOri->BaseTableLength) == 0);

    Data32 += MpsTableOri->BaseTableLength;
    Data32 += MpsTableOri->ExtendedTableLength;
    if (MpsTableOri->OemTablePointer != 0x00) {
        Data32 += SYS_TABLE_PAD (Data32);
        Data32 += MpsTableOri->OemTableSize;
    }

    //
    // Relocate memory
    //
    BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
    Status = gBS->AllocatePages (
        AllocateMaxAddress,
        EfiACPIMemoryNVS,
        EFI_SIZE_TO_PAGES(Data32),
        &BufferPtr
                                 );
    ASSERT_EFI_ERROR (Status);
    MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr;
    CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength);
    //
    // If Mp Table exists
    //
    if (MpsTableOri != NULL) {
        //
        // Get Mps table length, including Ext table
        //
        BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength);
        MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr;
        CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength);

        if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){
            BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength;
            BufferPtr += SYS_TABLE_PAD (BufferPtr);
            OemTableNew = (VOID *)(UINTN)BufferPtr;
            OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer;
            CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize);
            MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew;
        }
        MpsTableNew->Checksum = 0;
        MpsTableNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsTableNew, MpsTableOri->BaseTableLength);
        MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew;
        MpsFloatingPointerNew->Checksum = 0;
        MpsFloatingPointerNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsFloatingPointerNew, FPLength);
    }
    //
    // Change the pointer
    //
    *Table = MpsFloatingPointerNew;

    return EFI_SUCCESS;
}
EFI_STATUS
ConvertSmbiosTable (
    IN OUT VOID        **Table
                    )
/*++

  Routine Description:

  Convert Smbios Table if the Location of the SMBios Table is lower than Address 0x100000
  Assumption here:
  As in legacy Bios, Smbios table is required to place in E/F Seg,
  So here we just check if the range is F seg,
  and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
  Arguments:
  Table     - pointer to the table

  Returns:
  EFI_SUCCESS - Convert Table successfully
  Other       - Failed

  --*/
{
    SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew;
    SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri;
    EFI_STATUS               Status;
    UINT32                   SmbiosEntryLen;
    UINT32                   BufferLen;
    EFI_PHYSICAL_ADDRESS     BufferPtr;

    SmbiosTableNew  = NULL;
    SmbiosTableOri  = NULL;

    //
    // Get Smibos configuration Table
    //
    SmbiosTableOri =  (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)((*Table));


    ASSERT(CalculateSum8((UINT8*)SmbiosTableOri, sizeof(SMBIOS_TABLE_ENTRY_POINT)) == 0);
    //
    // Relocate the Smibos memory
    //
    BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
    if (SmbiosTableOri->SmbiosBcdRevision != 0x21) {
        SmbiosEntryLen  = SmbiosTableOri->EntryPointLength;
    } else {
        //
        // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1
        //
        SmbiosEntryLen = 0x1F;
    }
    BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength;
    Status = gBS->AllocatePages (
        AllocateMaxAddress,
        EfiACPIMemoryNVS,
        EFI_SIZE_TO_PAGES(BufferLen),
        &BufferPtr
                                 );
    ASSERT_EFI_ERROR (Status);
    SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr;
    CopyMem (
        SmbiosTableNew,
        SmbiosTableOri,
        SmbiosEntryLen
             );
    //
    // Get Smbios Structure table address, and make sure the start address is 32-bit align
    //
    BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen);
    CopyMem (
        (VOID *)(UINTN)BufferPtr,
        (VOID *)(UINTN)(SmbiosTableOri->TableAddress),
        SmbiosTableOri->TableLength
             );
    SmbiosTableNew->TableAddress = (UINT32)BufferPtr;
    SmbiosTableNew->IntermediateChecksum = 0;
    SmbiosTableNew->IntermediateChecksum =
            CalculateCheckSum8 ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10);
    //
    // Change the SMBIOS pointer
    //
    *Table = SmbiosTableNew;

    return EFI_SUCCESS;
}