30 UINT8 File[QEMU_LOADER_FNAME_SIZE];
35 BOOLEAN HostsOnlyTableData;
118 if (Pointer1 == Pointer2) {
222 if (Collection ==
NULL) {
223 return EFI_OUT_OF_RESOURCES;
226 for (LoaderEntry = LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry) {
229 if (LoaderEntry->Type != QemuLoaderCmdAddPointer) {
233 AddPointer = &LoaderEntry->Command.AddPointer;
235 if (AddPointer->PointerSize >= 8) {
239 if (AddPointer->PointeeFile[QEMU_LOADER_FNAME_SIZE - 1] !=
'\0') {
240 DEBUG ((DEBUG_ERROR,
"%a: malformed file name\n", __func__));
241 Status = EFI_PROTOCOL_ERROR;
248 (VOID *)AddPointer->PointeeFile
254 "%a: restricting blob \"%a\" from 64-bit allocation\n",
256 AddPointer->PointeeFile
259 case EFI_ALREADY_STARTED:
264 case EFI_OUT_OF_RESOURCES:
271 *AllocationsRestrictedTo32Bit = Collection;
324 FIRMWARE_CONFIG_ITEM FwCfgItem;
331 if (Allocate->File[QEMU_LOADER_FNAME_SIZE - 1] !=
'\0') {
332 DEBUG ((DEBUG_ERROR,
"%a: malformed file name\n", __func__));
333 return EFI_PROTOCOL_ERROR;
336 if (Allocate->Alignment > EFI_PAGE_SIZE) {
339 "%a: unsupported alignment 0x%x\n",
343 return EFI_UNSUPPORTED;
347 if (EFI_ERROR (Status)) {
350 "%a: QemuFwCfgFindFile(\"%a\"): %r\n",
359 Address = MAX_UINT64;
361 AllocationsRestrictedTo32Bit,
365 Address = MAX_UINT32;
368 Status =
gBS->AllocatePages (
374 if (EFI_ERROR (Status)) {
380 Status = EFI_OUT_OF_RESOURCES;
384 CopyMem (Blob->File, Allocate->File, QEMU_LOADER_FNAME_SIZE);
385 Blob->Size = FwCfgSize;
386 Blob->Base = (VOID *)(
UINTN)Address;
387 Blob->HostsOnlyTableData =
TRUE;
393 "%a: duplicated file \"%a\"\n",
397 Status = EFI_PROTOCOL_ERROR;
400 if (EFI_ERROR (Status)) {
410 "%a: File=\"%a\" Alignment=0x%x Zone=%d Size=0x%Lx "
417 (UINT64)(
UINTN)Blob->Base
427 EV_PLATFORM_CONFIG_FLAGS,
428 EV_POSTCODE_INFO_ACPI_DATA,
430 (VOID *)(
UINTN)Blob->Base,
440 gBS->FreePages (Address, NumPages);
476 if ((AddPointer->PointerFile[QEMU_LOADER_FNAME_SIZE - 1] !=
'\0') ||
477 (AddPointer->PointeeFile[QEMU_LOADER_FNAME_SIZE - 1] !=
'\0'))
479 DEBUG ((DEBUG_ERROR,
"%a: malformed file name\n", __func__));
480 return EFI_PROTOCOL_ERROR;
485 if ((TrackerEntry ==
NULL) || (TrackerEntry2 ==
NULL)) {
488 "%a: invalid blob reference(s) \"%a\" / \"%a\"\n",
490 AddPointer->PointerFile,
491 AddPointer->PointeeFile
493 return EFI_PROTOCOL_ERROR;
498 if (((AddPointer->PointerSize != 1) && (AddPointer->PointerSize != 2) &&
499 (AddPointer->PointerSize != 4) && (AddPointer->PointerSize != 8)) ||
500 (Blob->Size < AddPointer->PointerSize) ||
501 (Blob->Size - AddPointer->PointerSize < AddPointer->PointerOffset))
505 "%a: invalid pointer location or size in \"%a\"\n",
507 AddPointer->PointerFile
509 return EFI_PROTOCOL_ERROR;
512 PointerField = Blob->Base + AddPointer->PointerOffset;
514 CopyMem (&PointerValue, PointerField, AddPointer->PointerSize);
515 if (PointerValue >= Blob2->Size) {
518 "%a: invalid pointer value in \"%a\"\n",
520 AddPointer->PointerFile
522 return EFI_PROTOCOL_ERROR;
531 PointerValue += (UINT64)(
UINTN)Blob2->Base;
532 if ((AddPointer->PointerSize < 8) &&
533 (
RShiftU64 (PointerValue, AddPointer->PointerSize * 8) != 0))
537 "%a: relocated pointer value unrepresentable in "
540 AddPointer->PointerFile
542 return EFI_PROTOCOL_ERROR;
545 CopyMem (PointerField, &PointerValue, AddPointer->PointerSize);
549 "%a: PointerFile=\"%a\" PointeeFile=\"%a\" "
550 "PointerOffset=0x%x PointerSize=%d\n",
552 AddPointer->PointerFile,
553 AddPointer->PointeeFile,
554 AddPointer->PointerOffset,
555 AddPointer->PointerSize
586 if (AddChecksum->File[QEMU_LOADER_FNAME_SIZE - 1] !=
'\0') {
587 DEBUG ((DEBUG_ERROR,
"%a: malformed file name\n", __func__));
588 return EFI_PROTOCOL_ERROR;
592 if (TrackerEntry ==
NULL) {
595 "%a: invalid blob reference \"%a\"\n",
599 return EFI_PROTOCOL_ERROR;
603 if ((Blob->Size <= AddChecksum->ResultOffset) ||
604 (Blob->Size < AddChecksum->Length) ||
605 (Blob->Size - AddChecksum->Length < AddChecksum->Start))
609 "%a: invalid checksum range in \"%a\"\n",
613 return EFI_PROTOCOL_ERROR;
617 Blob->Base + AddChecksum->Start,
622 "%a: File=\"%a\" ResultOffset=0x%x Start=0x%x "
626 AddChecksum->ResultOffset,
672 RETURN_STATUS Status;
673 FIRMWARE_CONFIG_ITEM PointerItem;
674 UINTN PointerItemSize;
679 if ((WritePointer->PointerFile[QEMU_LOADER_FNAME_SIZE - 1] !=
'\0') ||
680 (WritePointer->PointeeFile[QEMU_LOADER_FNAME_SIZE - 1] !=
'\0'))
682 DEBUG ((DEBUG_ERROR,
"%a: malformed file name\n", __func__));
683 return EFI_PROTOCOL_ERROR;
687 (
CONST CHAR8 *)WritePointer->PointerFile,
695 "%a: invalid fw_cfg file or blob reference \"%a\" / \"%a\"\n",
697 WritePointer->PointerFile,
698 WritePointer->PointeeFile
700 return EFI_PROTOCOL_ERROR;
703 if (((WritePointer->PointerSize != 1) && (WritePointer->PointerSize != 2) &&
704 (WritePointer->PointerSize != 4) && (WritePointer->PointerSize != 8)) ||
705 (PointerItemSize < WritePointer->PointerSize) ||
706 (PointerItemSize - WritePointer->PointerSize <
707 WritePointer->PointerOffset))
711 "%a: invalid pointer location or size in \"%a\"\n",
713 WritePointer->PointerFile
715 return EFI_PROTOCOL_ERROR;
719 PointerValue = WritePointer->PointeeOffset;
720 if (PointerValue >= PointeeBlob->Size) {
721 DEBUG ((DEBUG_ERROR,
"%a: invalid PointeeOffset\n", __func__));
722 return EFI_PROTOCOL_ERROR;
731 PointerValue += (UINT64)(
UINTN)PointeeBlob->Base;
732 if ((WritePointer->PointerSize < 8) &&
733 (
RShiftU64 (PointerValue, WritePointer->PointerSize * 8) != 0))
737 "%a: pointer value unrepresentable in \"%a\"\n",
739 WritePointer->PointerFile
741 return EFI_PROTOCOL_ERROR;
748 if (S3Context !=
NULL) {
754 WritePointer->PointerSize,
755 WritePointer->PointerOffset,
758 if (EFI_ERROR (SaveStatus)) {
772 PointeeBlob->HostsOnlyTableData =
FALSE;
776 "%a: PointerFile=\"%a\" PointeeFile=\"%a\" "
777 "PointerOffset=0x%x PointeeOffset=0x%x PointerSize=%d\n",
779 WritePointer->PointerFile,
780 WritePointer->PointeeFile,
781 WritePointer->PointerOffset,
782 WritePointer->PointeeOffset,
783 WritePointer->PointerSize
804 RETURN_STATUS Status;
805 FIRMWARE_CONFIG_ITEM PointerItem;
806 UINTN PointerItemSize;
810 (
CONST CHAR8 *)WritePointer->PointerFile,
823 "%a: PointerFile=\"%a\" PointerOffset=0x%x PointerSize=%d\n",
825 WritePointer->PointerFile,
826 WritePointer->PointerOffset,
827 WritePointer->PointerSize
835#define INSTALLED_TABLES_MAX 128
903 IN OUT UINTN InstalledKey[INSTALLED_TABLES_MAX],
904 IN OUT INT32 *NumInstalled,
913 CONST UINT8 *PointerField;
915 UINTN Blob2Remaining;
921 if ((*NumInstalled < 0) || (*NumInstalled > INSTALLED_TABLES_MAX)) {
922 return EFI_INVALID_PARAMETER;
929 PointerField = Blob->Base + AddPointer->PointerOffset;
931 CopyMem (&PointerValue, PointerField, AddPointer->PointerSize);
937 Blob2Remaining = (
UINTN)Blob2->Base;
938 ASSERT (PointerValue >= Blob2Remaining);
939 Blob2Remaining += Blob2->Size;
940 ASSERT (PointerValue < Blob2Remaining);
945 (VOID *)(
UINTN)PointerValue
947 if (EFI_ERROR (Status)) {
954 "%a: PointerValue=0x%Lx already processed, skipping.\n",
964 Blob2Remaining -= (
UINTN)PointerValue;
967 "%a: checking for ACPI header in \"%a\" at 0x%Lx "
968 "(remaining: 0x%Lx): ",
970 AddPointer->PointeeFile,
972 (UINT64)Blob2Remaining
980 if (
sizeof *Facs <= Blob2Remaining) {
983 if ((Facs->Length >=
sizeof *Facs) &&
984 (Facs->Length <= Blob2Remaining) &&
990 "found \"%-4.4a\" size 0x%x\n",
991 (
CONST CHAR8 *)&Facs->Signature,
994 TableSize = Facs->Length;
1001 if ((TableSize == 0) && (
sizeof *Header <= Blob2Remaining)) {
1004 if ((Header->Length >=
sizeof *Header) &&
1005 (Header->Length <= Blob2Remaining) &&
1015 "found \"%-4.4a\" size 0x%x\n",
1016 (
CONST CHAR8 *)&Header->Signature,
1019 TableSize = Header->Length;
1024 if ((Header->Signature ==
1026 (Header->Signature ==
1034 if (TableSize == 0) {
1035 DEBUG ((DEBUG_VERBOSE,
"not found; marking fw_cfg blob as opaque\n"));
1036 Blob2->HostsOnlyTableData =
FALSE;
1040 if (*NumInstalled == INSTALLED_TABLES_MAX) {
1043 "%a: can't install more than %d tables\n",
1045 INSTALLED_TABLES_MAX
1047 Status = EFI_OUT_OF_RESOURCES;
1048 goto RollbackSeenPointer;
1051 Status = AcpiProtocol->InstallAcpiTable (
1053 (VOID *)(
UINTN)PointerValue,
1055 &InstalledKey[*NumInstalled]
1057 if (EFI_ERROR (Status)) {
1060 "%a: InstallAcpiTable(): %r\n",
1064 goto RollbackSeenPointer;
1104 FIRMWARE_CONFIG_ITEM FwCfgItem;
1110 UINTN OriginalPciAttributesCount;
1114 UINTN *InstalledKey;
1122 if (EFI_ERROR (Status)) {
1126 if (FwCfgSize %
sizeof *LoaderEntry != 0) {
1129 "%a: \"etc/table-loader\" has invalid size 0x%Lx\n",
1133 return EFI_PROTOCOL_ERROR;
1137 if (LoaderStart ==
NULL) {
1138 return EFI_OUT_OF_RESOURCES;
1153 EV_PLATFORM_CONFIG_FLAGS,
1154 EV_POSTCODE_INFO_ACPI_DATA,
1156 (VOID *)(
UINTN)LoaderStart,
1160 LoaderEnd = LoaderStart + FwCfgSize /
sizeof *LoaderEntry;
1162 AllocationsRestrictedTo32Bit =
NULL;
1164 &AllocationsRestrictedTo32Bit,
1168 if (EFI_ERROR (Status)) {
1179 if (EFI_ERROR (Status)) {
1180 goto FreeAllocationsRestrictedTo32Bit;
1185 if (Tracker ==
NULL) {
1186 Status = EFI_OUT_OF_RESOURCES;
1197 WritePointerSubsetEnd = LoaderStart;
1198 for (LoaderEntry = LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry) {
1199 switch (LoaderEntry->Type) {
1200 case QemuLoaderCmdAllocate:
1202 &LoaderEntry->Command.Allocate,
1204 AllocationsRestrictedTo32Bit
1208 case QemuLoaderCmdAddPointer:
1210 &LoaderEntry->Command.AddPointer,
1215 case QemuLoaderCmdAddChecksum:
1217 &LoaderEntry->Command.AddChecksum,
1222 case QemuLoaderCmdWritePointer:
1224 &LoaderEntry->Command.WritePointer,
1228 if (!EFI_ERROR (Status)) {
1229 WritePointerSubsetEnd = LoaderEntry + 1;
1237 "%a: unknown loader command: 0x%x\n",
1244 if (EFI_ERROR (Status)) {
1245 goto RollbackWritePointersAndFreeTracker;
1249 InstalledKey =
AllocatePool (INSTALLED_TABLES_MAX *
sizeof *InstalledKey);
1250 if (InstalledKey ==
NULL) {
1251 Status = EFI_OUT_OF_RESOURCES;
1252 goto RollbackWritePointersAndFreeTracker;
1256 if (SeenPointers ==
NULL) {
1257 Status = EFI_OUT_OF_RESOURCES;
1265 for (LoaderEntry = LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry) {
1266 if (LoaderEntry->Type == QemuLoaderCmdAddPointer) {
1268 &LoaderEntry->Command.AddPointer,
1275 if (EFI_ERROR (Status)) {
1276 goto UninstallAcpiTables;
1285 QemuAcpiHandle =
NULL;
1286 Status =
gBS->InstallProtocolInterface (
1288 &gQemuAcpiTableNotifyProtocolGuid,
1292 if (EFI_ERROR (Status)) {
1293 goto UninstallAcpiTables;
1301 if (S3Context !=
NULL) {
1303 if (EFI_ERROR (Status)) {
1304 goto UninstallQemuAcpiTableNotifyProtocol;
1313 DEBUG ((DEBUG_INFO,
"%a: installed %d tables\n", __func__, Installed));
1315UninstallQemuAcpiTableNotifyProtocol:
1316 if (EFI_ERROR (Status)) {
1317 gBS->UninstallProtocolInterface (
1319 &gQemuAcpiTableNotifyProtocolGuid,
1325 if (EFI_ERROR (Status)) {
1329 while (Installed > 0) {
1331 AcpiProtocol->UninstallAcpiTable (AcpiProtocol, InstalledKey[Installed]);
1336 SeenPointerEntry !=
NULL;
1337 SeenPointerEntry = SeenPointerEntry2)
1348RollbackWritePointersAndFreeTracker:
1353 if (EFI_ERROR (Status)) {
1354 LoaderEntry = WritePointerSubsetEnd;
1355 while (LoaderEntry > LoaderStart) {
1357 if (LoaderEntry->Type == QemuLoaderCmdWritePointer) {
1369 TrackerEntry = TrackerEntry2)
1378 if (EFI_ERROR (Status) || Blob->HostsOnlyTableData) {
1381 "%a: freeing \"%a\"\n",
1394 if (S3Context !=
NULL) {
1398FreeAllocationsRestrictedTo32Bit:
#define EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
#define EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
INTN EFIAPI AsciiStrCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
UINT8 EFIAPI CalculateSum8(IN CONST UINT8 *Buffer, IN UINTN Length)
UINT8 EFIAPI CalculateCheckSum8(IN CONST UINT8 *Buffer, IN UINTN Length)
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID EFIAPI FreePages(IN VOID *Buffer, IN UINTN Pages)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define RETURN_ERROR(StatusCode)
#define RETURN_ALREADY_STARTED
#define ASSERT_RETURN_ERROR(StatusParameter)
#define DEBUG(Expression)
ORDERED_COLLECTION_ENTRY *EFIAPI OrderedCollectionFind(IN CONST ORDERED_COLLECTION *Collection, IN CONST VOID *StandaloneKey)
ORDERED_COLLECTION_ENTRY *EFIAPI OrderedCollectionMin(IN CONST ORDERED_COLLECTION *Collection)
VOID *EFIAPI OrderedCollectionUserStruct(IN CONST ORDERED_COLLECTION_ENTRY *Entry)
RETURN_STATUS EFIAPI OrderedCollectionInsert(IN OUT ORDERED_COLLECTION *Collection, OUT ORDERED_COLLECTION_ENTRY **Entry OPTIONAL, IN VOID *UserStruct)
VOID EFIAPI OrderedCollectionUninit(IN ORDERED_COLLECTION *Collection)
ORDERED_COLLECTION *EFIAPI OrderedCollectionInit(IN ORDERED_COLLECTION_USER_COMPARE UserStructCompare, IN ORDERED_COLLECTION_KEY_COMPARE KeyCompare)
ORDERED_COLLECTION_ENTRY *EFIAPI OrderedCollectionNext(IN CONST ORDERED_COLLECTION_ENTRY *Entry)
VOID EFIAPI OrderedCollectionDelete(IN OUT ORDERED_COLLECTION *Collection, IN ORDERED_COLLECTION_ENTRY *Entry, OUT VOID **UserStruct OPTIONAL)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
STATIC INTN EFIAPI BlobKeyCompare(IN CONST VOID *StandaloneKey, IN CONST VOID *UserStruct)
STATIC EFI_STATUS EFIAPI ProcessCmdAddPointer(IN CONST QEMU_LOADER_ADD_POINTER *AddPointer, IN CONST ORDERED_COLLECTION *Tracker)
STATIC EFI_STATUS EFIAPI ProcessCmdAddChecksum(IN CONST QEMU_LOADER_ADD_CHECKSUM *AddChecksum, IN CONST ORDERED_COLLECTION *Tracker)
STATIC EFI_STATUS ProcessCmdWritePointer(IN CONST QEMU_LOADER_WRITE_POINTER *WritePointer, IN CONST ORDERED_COLLECTION *Tracker, IN OUT S3_CONTEXT *S3Context OPTIONAL)
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, IN OUT ORDERED_COLLECTION *SeenPointers)
STATIC VOID UndoCmdWritePointer(IN CONST QEMU_LOADER_WRITE_POINTER *WritePointer)
STATIC INTN EFIAPI BlobCompare(IN CONST VOID *UserStruct1, IN CONST VOID *UserStruct2)
STATIC INTN EFIAPI PointerCompare(IN CONST VOID *Pointer1, IN CONST VOID *Pointer2)
STATIC EFI_STATUS CollectAllocationsRestrictedTo32Bit(OUT ORDERED_COLLECTION **AllocationsRestrictedTo32Bit, IN CONST QEMU_LOADER_ENTRY *LoaderStart, IN CONST QEMU_LOADER_ENTRY *LoaderEnd)
STATIC VOID ReleaseAllocationsRestrictedTo32Bit(IN ORDERED_COLLECTION *AllocationsRestrictedTo32Bit)
STATIC INTN EFIAPI AsciiStringCompare(IN CONST VOID *AsciiString1, IN CONST VOID *AsciiString2)
EFI_STATUS EFIAPI InstallQemuFwCfgTables(IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol)
STATIC EFI_STATUS EFIAPI ProcessCmdAllocate(IN CONST QEMU_LOADER_ALLOCATE *Allocate, IN OUT ORDERED_COLLECTION *Tracker, IN ORDERED_COLLECTION *AllocationsRestrictedTo32Bit)
VOID EFIAPI QemuFwCfgWriteBytes(IN UINTN Size, IN VOID *Buffer)
RETURN_STATUS EFIAPI QemuFwCfgFindFile(IN CONST CHAR8 *Name, OUT FIRMWARE_CONFIG_ITEM *Item, OUT UINTN *Size)
VOID EFIAPI QemuFwCfgReadBytes(IN UINTN Size, IN VOID *Buffer OPTIONAL)
VOID EFIAPI QemuFwCfgSelectItem(IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem)
VOID EFIAPI QemuFwCfgSkipBytes(IN UINTN Size)
BOOLEAN EFIAPI QemuFwCfgS3Enabled(VOID)
EFI_STATUS EFIAPI TpmMeasureAndLogData(IN UINT32 PcrIndex, IN UINT32 EventType, IN VOID *EventLog, IN UINT32 LogLen, IN VOID *HashData, IN UINT64 HashDataLen)
UINT64 EFI_PHYSICAL_ADDRESS
#define EFI_PAGES_TO_SIZE(Pages)
#define EFI_SIZE_TO_PAGES(Size)