]>
Commit | Line | Data |
---|---|---|
09a274d8 LE |
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> | |
b097ba37 | 17 | #include <Guid/SmBios.h> |
09a274d8 LE |
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; | |
b097ba37 LE |
59 | CONST VOID *Smbios21; |
60 | CONST VOID *Smbios30; | |
09a274d8 LE |
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 | // | |
b097ba37 LE |
83 | // Locate all the gEfiAcpi10TableGuid, gEfiAcpi20TableGuid, |
84 | // gEfiSmbiosTableGuid, gEfiSmbios3TableGuid config tables in one go. | |
09a274d8 LE |
85 | // |
86 | Rsdp10 = NULL; | |
87 | Rsdp20 = NULL; | |
b097ba37 LE |
88 | Smbios21 = NULL; |
89 | Smbios30 = NULL; | |
09a274d8 LE |
90 | ConfigTable = gST->ConfigurationTable; |
91 | ConfigTablesEnd = gST->ConfigurationTable + gST->NumberOfTableEntries; | |
b097ba37 LE |
92 | while ((Rsdp10 == NULL || Rsdp20 == NULL || |
93 | Smbios21 == NULL || Smbios30 == NULL) && | |
94 | ConfigTable < ConfigTablesEnd) { | |
09a274d8 LE |
95 | if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi10TableGuid)) { |
96 | Rsdp10 = ConfigTable->VendorTable; | |
97 | } else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi20TableGuid)) { | |
98 | Rsdp20 = ConfigTable->VendorTable; | |
b097ba37 LE |
99 | } else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiSmbiosTableGuid)) { |
100 | Smbios21 = ConfigTable->VendorTable; | |
101 | } else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiSmbios3TableGuid)) { | |
102 | Smbios30 = ConfigTable->VendorTable; | |
09a274d8 LE |
103 | } |
104 | ++ConfigTable; | |
105 | } | |
106 | ||
107 | AsciiPrint ("%a: BiosTablesTest=%p Rsdp10=%p Rsdp20=%p\n", | |
108 | gEfiCallerBaseName, Pages, Rsdp10, Rsdp20); | |
b097ba37 LE |
109 | AsciiPrint ("%a: Smbios21=%p Smbios30=%p\n", gEfiCallerBaseName, Smbios21, |
110 | Smbios30); | |
09a274d8 LE |
111 | |
112 | // | |
b097ba37 | 113 | // Store the config table addresses first, then the signature second. |
09a274d8 LE |
114 | // |
115 | BiosTablesTest = Pages; | |
116 | BiosTablesTest->Rsdp10 = (UINTN)Rsdp10; | |
117 | BiosTablesTest->Rsdp20 = (UINTN)Rsdp20; | |
b097ba37 LE |
118 | BiosTablesTest->Smbios21 = (UINTN)Smbios21; |
119 | BiosTablesTest->Smbios30 = (UINTN)Smbios30; | |
09a274d8 LE |
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 | } |