1 /** @file 2 Populate the BIOS_TABLES_TEST structure. 3 4 Copyright (C) 2019, Red Hat, Inc. 5 6 This program and the accompanying materials are licensed and made available 7 under the terms and conditions of the BSD License that accompanies this 8 distribution. The full text of the license may be found at 9 <http://opensource.org/licenses/bsd-license.php>. 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT 12 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 **/ 14 15 #include <Guid/Acpi.h> 16 #include <Guid/BiosTablesTest.h> 17 #include <Guid/SmBios.h> 18 #include <Library/BaseLib.h> 19 #include <Library/BaseMemoryLib.h> 20 #include <Library/MemoryAllocationLib.h> 21 #include <Library/UefiBootServicesTableLib.h> 22 #include <Library/UefiLib.h> 23 24 /** 25 Wait for a keypress with a message that the application is about to exit. 26 **/ 27 STATIC 28 VOID 29 WaitForExitKeyPress ( 30 VOID 31 ) 32 { 33 EFI_STATUS Status; 34 UINTN Idx; 35 EFI_INPUT_KEY Key; 36 37 if (gST->ConIn == NULL) { 38 return; 39 } 40 AsciiPrint ("%a: press any key to exit\n", gEfiCallerBaseName); 41 Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Idx); 42 if (EFI_ERROR (Status)) { 43 return; 44 } 45 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); 46 } 47 48 EFI_STATUS 49 EFIAPI 50 BiosTablesTestMain ( 51 IN EFI_HANDLE ImageHandle, 52 IN EFI_SYSTEM_TABLE *SystemTable 53 ) 54 { 55 VOID *Pages; 56 volatile BIOS_TABLES_TEST *BiosTablesTest; 57 CONST VOID *Rsdp10; 58 CONST VOID *Rsdp20; 59 CONST VOID *Smbios21; 60 CONST VOID *Smbios30; 61 CONST EFI_CONFIGURATION_TABLE *ConfigTable; 62 CONST EFI_CONFIGURATION_TABLE *ConfigTablesEnd; 63 volatile EFI_GUID *InverseSignature; 64 UINTN Idx; 65 66 Pages = AllocateAlignedPages (EFI_SIZE_TO_PAGES (sizeof *BiosTablesTest), 67 SIZE_1MB); 68 if (Pages == NULL) { 69 AsciiErrorPrint ("%a: AllocateAlignedPages() failed\n", 70 gEfiCallerBaseName); 71 // 72 // Assuming the application was launched by the boot manager as a boot 73 // loader, exiting with error will cause the boot manager to proceed with 74 // the remaining boot options. If there are no other boot options, the boot 75 // manager menu will be pulled up. Give the user a chance to read the error 76 // message. 77 // 78 WaitForExitKeyPress (); 79 return EFI_OUT_OF_RESOURCES; 80 } 81 82 // 83 // Locate all the gEfiAcpi10TableGuid, gEfiAcpi20TableGuid, 84 // gEfiSmbiosTableGuid, gEfiSmbios3TableGuid config tables in one go. 85 // 86 Rsdp10 = NULL; 87 Rsdp20 = NULL; 88 Smbios21 = NULL; 89 Smbios30 = NULL; 90 ConfigTable = gST->ConfigurationTable; 91 ConfigTablesEnd = gST->ConfigurationTable + gST->NumberOfTableEntries; 92 while ((Rsdp10 == NULL || Rsdp20 == NULL || 93 Smbios21 == NULL || Smbios30 == NULL) && 94 ConfigTable < ConfigTablesEnd) { 95 if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi10TableGuid)) { 96 Rsdp10 = ConfigTable->VendorTable; 97 } else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi20TableGuid)) { 98 Rsdp20 = ConfigTable->VendorTable; 99 } else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiSmbiosTableGuid)) { 100 Smbios21 = ConfigTable->VendorTable; 101 } else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiSmbios3TableGuid)) { 102 Smbios30 = ConfigTable->VendorTable; 103 } 104 ++ConfigTable; 105 } 106 107 AsciiPrint ("%a: BiosTablesTest=%p Rsdp10=%p Rsdp20=%p\n", 108 gEfiCallerBaseName, Pages, Rsdp10, Rsdp20); 109 AsciiPrint ("%a: Smbios21=%p Smbios30=%p\n", gEfiCallerBaseName, Smbios21, 110 Smbios30); 111 112 // 113 // Store the config table addresses first, then the signature second. 114 // 115 BiosTablesTest = Pages; 116 BiosTablesTest->Rsdp10 = (UINTN)Rsdp10; 117 BiosTablesTest->Rsdp20 = (UINTN)Rsdp20; 118 BiosTablesTest->Smbios21 = (UINTN)Smbios21; 119 BiosTablesTest->Smbios30 = (UINTN)Smbios30; 120 121 MemoryFence(); 122 123 InverseSignature = &BiosTablesTest->InverseSignatureGuid; 124 InverseSignature->Data1 = gBiosTablesTestGuid.Data1; 125 InverseSignature->Data1 ^= MAX_UINT32; 126 InverseSignature->Data2 = gBiosTablesTestGuid.Data2; 127 InverseSignature->Data2 ^= MAX_UINT16; 128 InverseSignature->Data3 = gBiosTablesTestGuid.Data3; 129 InverseSignature->Data3 ^= MAX_UINT16; 130 for (Idx = 0; Idx < sizeof InverseSignature->Data4; ++Idx) { 131 InverseSignature->Data4[Idx] = gBiosTablesTestGuid.Data4[Idx]; 132 InverseSignature->Data4[Idx] ^= MAX_UINT8; 133 } 134 135 // 136 // The wait below has dual purpose. First, it blocks the application without 137 // wasting VCPU cycles while the hypervisor is scanning guest RAM. Second, 138 // assuming the application was launched by the boot manager as a boot 139 // loader, exiting the app with success causes the boot manager to pull up 140 // the boot manager menu at once (regardless of other boot options); the wait 141 // gives the user a chance to read the info printed above. 142 // 143 WaitForExitKeyPress (); 144 return EFI_SUCCESS; 145 } 146