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
WaitForExitKeyPress(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
BiosTablesTestMain(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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