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 <Library/BaseLib.h> 18 #include <Library/BaseMemoryLib.h> 19 #include <Library/MemoryAllocationLib.h> 20 #include <Library/UefiBootServicesTableLib.h> 21 #include <Library/UefiLib.h> 22 23 /** 24 Wait for a keypress with a message that the application is about to exit. 25 **/ 26 STATIC 27 VOID 28 WaitForExitKeyPress ( 29 VOID 30 ) 31 { 32 EFI_STATUS Status; 33 UINTN Idx; 34 EFI_INPUT_KEY Key; 35 36 if (gST->ConIn == NULL) { 37 return; 38 } 39 AsciiPrint ("%a: press any key to exit\n", gEfiCallerBaseName); 40 Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Idx); 41 if (EFI_ERROR (Status)) { 42 return; 43 } 44 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); 45 } 46 47 EFI_STATUS 48 EFIAPI 49 BiosTablesTestMain ( 50 IN EFI_HANDLE ImageHandle, 51 IN EFI_SYSTEM_TABLE *SystemTable 52 ) 53 { 54 VOID *Pages; 55 volatile BIOS_TABLES_TEST *BiosTablesTest; 56 CONST VOID *Rsdp10; 57 CONST VOID *Rsdp20; 58 CONST EFI_CONFIGURATION_TABLE *ConfigTable; 59 CONST EFI_CONFIGURATION_TABLE *ConfigTablesEnd; 60 volatile EFI_GUID *InverseSignature; 61 UINTN Idx; 62 63 Pages = AllocateAlignedPages (EFI_SIZE_TO_PAGES (sizeof *BiosTablesTest), 64 SIZE_1MB); 65 if (Pages == NULL) { 66 AsciiErrorPrint ("%a: AllocateAlignedPages() failed\n", 67 gEfiCallerBaseName); 68 // 69 // Assuming the application was launched by the boot manager as a boot 70 // loader, exiting with error will cause the boot manager to proceed with 71 // the remaining boot options. If there are no other boot options, the boot 72 // manager menu will be pulled up. Give the user a chance to read the error 73 // message. 74 // 75 WaitForExitKeyPress (); 76 return EFI_OUT_OF_RESOURCES; 77 } 78 79 // 80 // Locate both gEfiAcpi10TableGuid and gEfiAcpi20TableGuid config tables in 81 // one go. 82 // 83 Rsdp10 = NULL; 84 Rsdp20 = NULL; 85 ConfigTable = gST->ConfigurationTable; 86 ConfigTablesEnd = gST->ConfigurationTable + gST->NumberOfTableEntries; 87 while ((Rsdp10 == NULL || Rsdp20 == NULL) && ConfigTable < ConfigTablesEnd) { 88 if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi10TableGuid)) { 89 Rsdp10 = ConfigTable->VendorTable; 90 } else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi20TableGuid)) { 91 Rsdp20 = ConfigTable->VendorTable; 92 } 93 ++ConfigTable; 94 } 95 96 AsciiPrint ("%a: BiosTablesTest=%p Rsdp10=%p Rsdp20=%p\n", 97 gEfiCallerBaseName, Pages, Rsdp10, Rsdp20); 98 99 // 100 // Store the RSD PTR address(es) first, then the signature second. 101 // 102 BiosTablesTest = Pages; 103 BiosTablesTest->Rsdp10 = (UINTN)Rsdp10; 104 BiosTablesTest->Rsdp20 = (UINTN)Rsdp20; 105 106 MemoryFence(); 107 108 InverseSignature = &BiosTablesTest->InverseSignatureGuid; 109 InverseSignature->Data1 = gBiosTablesTestGuid.Data1; 110 InverseSignature->Data1 ^= MAX_UINT32; 111 InverseSignature->Data2 = gBiosTablesTestGuid.Data2; 112 InverseSignature->Data2 ^= MAX_UINT16; 113 InverseSignature->Data3 = gBiosTablesTestGuid.Data3; 114 InverseSignature->Data3 ^= MAX_UINT16; 115 for (Idx = 0; Idx < sizeof InverseSignature->Data4; ++Idx) { 116 InverseSignature->Data4[Idx] = gBiosTablesTestGuid.Data4[Idx]; 117 InverseSignature->Data4[Idx] ^= MAX_UINT8; 118 } 119 120 // 121 // The wait below has dual purpose. First, it blocks the application without 122 // wasting VCPU cycles while the hypervisor is scanning guest RAM. Second, 123 // assuming the application was launched by the boot manager as a boot 124 // loader, exiting the app with success causes the boot manager to pull up 125 // the boot manager menu at once (regardless of other boot options); the wait 126 // gives the user a chance to read the info printed above. 127 // 128 WaitForExitKeyPress (); 129 return EFI_SUCCESS; 130 } 131