/** 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 ; }
/** 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; }
/** 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; } }
/** 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; }
/** 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); }
/** 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; }
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)); }
/** 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; }
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; }
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; }