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