TianoCore EDK2 master
Loading...
Searching...
No Matches
ConsolePrefDxe.c
Go to the documentation of this file.
1
9#include <Uefi.h>
11#include <libfdt.h>
12#include <Library/BaseLib.h>
14#include <Library/DebugLib.h>
16#include <Library/HiiLib.h>
20#include <Library/UefiLib.h>
22
23#include <Protocol/AcpiTable.h>
25
26#include "ConsolePrefDxe.h"
27
28#define SPCR_SIG EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
29
30extern UINT8 ConsolePrefHiiBin[];
31extern UINT8 ConsolePrefDxeStrings[];
32
33typedef struct {
34 VENDOR_DEVICE_PATH VendorDevicePath;
37
38STATIC HII_VENDOR_DEVICE_PATH mConsolePrefDxeVendorDevicePath = {
39 {
40 {
43 {
44 (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
45 (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
46 }
47 },
48 CONSOLE_PREF_FORMSET_GUID
49 },
50 {
51 END_DEVICE_PATH_TYPE,
52 END_ENTIRE_DEVICE_PATH_SUBTYPE,
53 {
54 (UINT8)(END_DEVICE_PATH_LENGTH),
55 (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
56 }
57 }
58};
59
60STATIC EFI_EVENT mReadyToBootEvent;
61
64InstallHiiPages (
65 VOID
66 )
67{
68 EFI_STATUS Status;
69 EFI_HII_HANDLE HiiHandle;
70 EFI_HANDLE DriverHandle;
71
72 DriverHandle = NULL;
73 Status = gBS->InstallMultipleProtocolInterfaces (
74 &DriverHandle,
75 &gEfiDevicePathProtocolGuid,
76 &mConsolePrefDxeVendorDevicePath,
77 NULL
78 );
79 if (EFI_ERROR (Status)) {
80 return Status;
81 }
82
83 HiiHandle = HiiAddPackages (
84 &gConsolePrefFormSetGuid,
85 DriverHandle,
86 ConsolePrefDxeStrings,
87 ConsolePrefHiiBin,
88 NULL
89 );
90
91 if (HiiHandle == NULL) {
92 gBS->UninstallMultipleProtocolInterfaces (
93 DriverHandle,
94 &gEfiDevicePathProtocolGuid,
95 &mConsolePrefDxeVendorDevicePath,
96 NULL
97 );
98 return EFI_OUT_OF_RESOURCES;
99 }
100
101 return EFI_SUCCESS;
102}
103
104STATIC
105VOID
106RemoveDtStdoutPath (
107 VOID
108 )
109{
110 VOID *Dtb;
111 INT32 Node;
112 INT32 Error;
113 EFI_STATUS Status;
114
115 Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &Dtb);
116 if (EFI_ERROR (Status)) {
117 DEBUG ((
118 DEBUG_INFO,
119 "%a: could not retrieve DT blob - %r\n",
120 __func__,
121 Status
122 ));
123 return;
124 }
125
126 Node = fdt_path_offset (Dtb, "/chosen");
127 if (Node < 0) {
128 return;
129 }
130
131 Error = fdt_delprop (Dtb, Node, "stdout-path");
132 if (Error) {
133 DEBUG ((
134 DEBUG_INFO,
135 "%a: Failed to delete 'stdout-path' property: %a\n",
136 __func__,
137 fdt_strerror (Error)
138 ));
139 }
140}
141
142STATIC
143VOID
144RemoveSpcrTable (
145 VOID
146 )
147{
149 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
150 EFI_STATUS Status;
151 UINTN TableIndex;
152 EFI_ACPI_SDT_HEADER *TableHeader;
153 EFI_ACPI_TABLE_VERSION TableVersion;
154 UINTN TableKey;
155
156 Status = gBS->LocateProtocol (
157 &gEfiAcpiTableProtocolGuid,
158 NULL,
159 (VOID **)&AcpiTable
160 );
161 if (EFI_ERROR (Status)) {
162 return;
163 }
164
165 Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&Sdt);
166 if (EFI_ERROR (Status)) {
167 return;
168 }
169
170 TableIndex = 0;
171 TableKey = 0;
172 TableHeader = NULL;
173
174 do {
175 Status = Sdt->GetAcpiTable (
176 TableIndex++,
177 &TableHeader,
178 &TableVersion,
179 &TableKey
180 );
181 if (EFI_ERROR (Status)) {
182 break;
183 }
184
185 if (TableHeader->Signature != SPCR_SIG) {
186 continue;
187 }
188
189 Status = AcpiTable->UninstallAcpiTable (AcpiTable, TableKey);
190 if (EFI_ERROR (Status)) {
191 DEBUG ((
192 DEBUG_WARN,
193 "%a: failed to uninstall SPCR table - %r\n",
194 __func__,
195 Status
196 ));
197 }
198
199 break;
200 } while (TRUE);
201}
202
203STATIC
204VOID
205EFIAPI
206OnReadyToBoot (
207 IN EFI_EVENT Event,
208 IN VOID *Context
209 )
210{
211 CONSOLE_PREF_VARSTORE_DATA ConsolePref;
212 UINTN BufferSize;
213 EFI_STATUS Status;
214 VOID *Gop;
215
216 BufferSize = sizeof (ConsolePref);
217 Status = gRT->GetVariable (
218 CONSOLE_PREF_VARIABLE_NAME,
219 &gConsolePrefFormSetGuid,
220 NULL,
221 &BufferSize,
222 &ConsolePref
223 );
224 if (EFI_ERROR (Status)) {
225 DEBUG ((
226 DEBUG_ERROR,
227 "%a: variable '%s' could not be read - bailing!\n",
228 __func__,
229 CONSOLE_PREF_VARIABLE_NAME
230 ));
231 return;
232 }
233
234 if (ConsolePref.Console == CONSOLE_PREF_SERIAL) {
235 DEBUG ((
236 DEBUG_INFO,
237 "%a: serial console preferred - doing nothing\n",
238 __func__
239 ));
240 return;
241 }
242
243 //
244 // Check if any GOP instances exist: if so, disable stdout-path and SPCR
245 //
246 Status = gBS->LocateProtocol (&gEfiGraphicsOutputProtocolGuid, NULL, &Gop);
247 if (EFI_ERROR (Status)) {
248 DEBUG ((
249 DEBUG_INFO,
250 "%a: no GOP instances found - doing nothing (%r)\n",
251 __func__,
252 Status
253 ));
254 return;
255 }
256
257 RemoveDtStdoutPath ();
258 RemoveSpcrTable ();
259}
260
275EFIAPI
277 IN EFI_HANDLE ImageHandle,
278 IN EFI_SYSTEM_TABLE *SystemTable
279 )
280{
281 EFI_STATUS Status;
282 CONSOLE_PREF_VARSTORE_DATA ConsolePref;
283 UINTN BufferSize;
284
285 //
286 // Get the current console preference from the ConsolePref variable.
287 //
288 BufferSize = sizeof (ConsolePref);
289 Status = gRT->GetVariable (
290 CONSOLE_PREF_VARIABLE_NAME,
291 &gConsolePrefFormSetGuid,
292 NULL,
293 &BufferSize,
294 &ConsolePref
295 );
296 if (EFI_ERROR (Status)) {
297 DEBUG ((
298 DEBUG_INFO,
299 "%a: no console preference found, defaulting to graphical\n",
300 __func__
301 ));
302 ConsolePref.Console = CONSOLE_PREF_GRAPHICAL;
303 }
304
305 if (!EFI_ERROR (Status) &&
306 (ConsolePref.Console != CONSOLE_PREF_GRAPHICAL) &&
307 (ConsolePref.Console != CONSOLE_PREF_SERIAL))
308 {
309 DEBUG ((
310 DEBUG_WARN,
311 "%a: invalid value for %s, defaulting to graphical\n",
312 __func__,
313 CONSOLE_PREF_VARIABLE_NAME
314 ));
315 ConsolePref.Console = CONSOLE_PREF_GRAPHICAL;
316 Status = EFI_INVALID_PARAMETER; // trigger setvar below
317 }
318
319 //
320 // Write the newly selected value back to the variable store.
321 //
322 if (EFI_ERROR (Status)) {
323 ZeroMem (&ConsolePref.Reserved, sizeof (ConsolePref.Reserved));
324 Status = gRT->SetVariable (
325 CONSOLE_PREF_VARIABLE_NAME,
326 &gConsolePrefFormSetGuid,
327 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
328 sizeof (ConsolePref),
329 &ConsolePref
330 );
331
332 if (EFI_ERROR (Status)) {
333 DEBUG ((
334 DEBUG_ERROR,
335 "%a: gRT->SetVariable () failed - %r\n",
336 __func__,
337 Status
338 ));
339 return Status;
340 }
341 }
342
343 Status = gBS->CreateEventEx (
344 EVT_NOTIFY_SIGNAL,
345 TPL_CALLBACK,
346 OnReadyToBoot,
347 NULL,
348 &gEfiEventReadyToBootGuid,
349 &mReadyToBootEvent
350 );
351 ASSERT_EFI_ERROR (Status);
352
353 return InstallHiiPages ();
354}
UINT64 UINTN
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS EFIAPI ConsolePrefDxeEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
#define HARDWARE_DEVICE_PATH
Definition: DevicePath.h:68
#define HW_VENDOR_DP
Definition: DevicePath.h:133
EFI_HII_HANDLE EFIAPI HiiAddPackages(IN CONST EFI_GUID *PackageListGuid, IN EFI_HANDLE DeviceHandle OPTIONAL,...)
Definition: HiiLib.c:141
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
VOID * EFI_HII_HANDLE
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable(IN EFI_GUID *TableGuid, OUT VOID **Table)
Definition: UefiLib.c:82
#define EFI_VARIABLE_NON_VOLATILE