3 * Copyright (c) 2017, Linaro, Ltd. All rights reserved.
5 * SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <IndustryStandard/Acpi.h>
12 #include <Library/BaseLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/DevicePathLib.h>
15 #include <Library/HiiLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
17 #include <Library/UefiBootServicesTableLib.h>
18 #include <Library/UefiDriverEntryPoint.h>
19 #include <Library/UefiLib.h>
20 #include <Library/UefiRuntimeServicesTableLib.h>
22 #include <Protocol/AcpiTable.h>
23 #include <Protocol/AcpiSystemDescriptionTable.h>
25 #include "ConsolePrefDxe.h"
27 #define SPCR_SIG EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
29 extern UINT8 ConsolePrefHiiBin
[];
30 extern UINT8 ConsolePrefDxeStrings
[];
33 VENDOR_DEVICE_PATH VendorDevicePath
;
34 EFI_DEVICE_PATH_PROTOCOL End
;
35 } HII_VENDOR_DEVICE_PATH
;
37 STATIC HII_VENDOR_DEVICE_PATH mConsolePrefDxeVendorDevicePath
= {
43 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
44 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
47 CONSOLE_PREF_FORMSET_GUID
51 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
53 (UINT8
) (END_DEVICE_PATH_LENGTH
),
54 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
59 STATIC EFI_EVENT mReadyToBootEvent
;
68 EFI_HII_HANDLE HiiHandle
;
69 EFI_HANDLE DriverHandle
;
72 Status
= gBS
->InstallMultipleProtocolInterfaces (&DriverHandle
,
73 &gEfiDevicePathProtocolGuid
,
74 &mConsolePrefDxeVendorDevicePath
,
76 if (EFI_ERROR (Status
)) {
80 HiiHandle
= HiiAddPackages (&gConsolePrefFormSetGuid
,
82 ConsolePrefDxeStrings
,
86 if (HiiHandle
== NULL
) {
87 gBS
->UninstallMultipleProtocolInterfaces (DriverHandle
,
88 &gEfiDevicePathProtocolGuid
,
89 &mConsolePrefDxeVendorDevicePath
,
91 return EFI_OUT_OF_RESOURCES
;
107 Status
= EfiGetSystemConfigurationTable (&gFdtTableGuid
, &Dtb
);
108 if (EFI_ERROR (Status
)) {
109 DEBUG ((DEBUG_INFO
, "%a: could not retrieve DT blob - %r\n", __FUNCTION__
,
114 Node
= fdt_path_offset (Dtb
, "/chosen");
119 Error
= fdt_delprop (Dtb
, Node
, "stdout-path");
121 DEBUG ((DEBUG_INFO
, "%a: Failed to delete 'stdout-path' property: %a\n",
122 __FUNCTION__
, fdt_strerror (Error
)));
132 EFI_ACPI_SDT_PROTOCOL
*Sdt
;
133 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
136 EFI_ACPI_SDT_HEADER
*TableHeader
;
137 EFI_ACPI_TABLE_VERSION TableVersion
;
140 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
,
141 (VOID
**)&AcpiTable
);
142 if (EFI_ERROR (Status
)) {
146 Status
= gBS
->LocateProtocol (&gEfiAcpiSdtProtocolGuid
, NULL
, (VOID
**)&Sdt
);
147 if (EFI_ERROR (Status
)) {
156 Status
= Sdt
->GetAcpiTable (TableIndex
++, &TableHeader
, &TableVersion
,
158 if (EFI_ERROR (Status
)) {
162 if (TableHeader
->Signature
!= SPCR_SIG
) {
166 Status
= AcpiTable
->UninstallAcpiTable (AcpiTable
, TableKey
);
167 if (EFI_ERROR (Status
)) {
168 DEBUG ((DEBUG_WARN
, "%a: failed to uninstall SPCR table - %r\n",
169 __FUNCTION__
, Status
));
183 CONSOLE_PREF_VARSTORE_DATA ConsolePref
;
188 BufferSize
= sizeof (ConsolePref
);
189 Status
= gRT
->GetVariable (CONSOLE_PREF_VARIABLE_NAME
,
190 &gConsolePrefFormSetGuid
, NULL
, &BufferSize
, &ConsolePref
);
191 if (EFI_ERROR (Status
)) {
193 "%a: variable '%s' could not be read - bailing!\n", __FUNCTION__
,
194 CONSOLE_PREF_VARIABLE_NAME
));
198 if (ConsolePref
.Console
== CONSOLE_PREF_SERIAL
) {
200 "%a: serial console preferred - doing nothing\n", __FUNCTION__
));
205 // Check if any GOP instances exist: if so, disable stdout-path and SPCR
207 Status
= gBS
->LocateProtocol (&gEfiGraphicsOutputProtocolGuid
, NULL
, &Gop
);
208 if (EFI_ERROR (Status
)) {
210 "%a: no GOP instances found - doing nothing (%r)\n", __FUNCTION__
,
215 RemoveDtStdoutPath ();
220 The entry point for ConsolePrefDxe driver.
222 @param[in] ImageHandle The image handle of the driver.
223 @param[in] SystemTable The system table.
225 @retval EFI_ALREADY_STARTED The driver already exists in system.
226 @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of
228 @retval EFI_SUCCESS All the related protocols are installed on
234 ConsolePrefDxeEntryPoint (
235 IN EFI_HANDLE ImageHandle
,
236 IN EFI_SYSTEM_TABLE
*SystemTable
240 CONSOLE_PREF_VARSTORE_DATA ConsolePref
;
244 // Get the current console preference from the ConsolePref variable.
246 BufferSize
= sizeof (ConsolePref
);
247 Status
= gRT
->GetVariable (CONSOLE_PREF_VARIABLE_NAME
,
248 &gConsolePrefFormSetGuid
, NULL
, &BufferSize
, &ConsolePref
);
249 if (EFI_ERROR (Status
)) {
251 "%a: no console preference found, defaulting to graphical\n",
253 ConsolePref
.Console
= CONSOLE_PREF_GRAPHICAL
;
256 if (!EFI_ERROR (Status
) &&
257 ConsolePref
.Console
!= CONSOLE_PREF_GRAPHICAL
&&
258 ConsolePref
.Console
!= CONSOLE_PREF_SERIAL
) {
259 DEBUG ((DEBUG_WARN
, "%a: invalid value for %s, defaulting to graphical\n",
260 __FUNCTION__
, CONSOLE_PREF_VARIABLE_NAME
));
261 ConsolePref
.Console
= CONSOLE_PREF_GRAPHICAL
;
262 Status
= EFI_INVALID_PARAMETER
; // trigger setvar below
266 // Write the newly selected value back to the variable store.
268 if (EFI_ERROR (Status
)) {
269 ZeroMem (&ConsolePref
.Reserved
, sizeof (ConsolePref
.Reserved
));
270 Status
= gRT
->SetVariable (CONSOLE_PREF_VARIABLE_NAME
,
271 &gConsolePrefFormSetGuid
,
272 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
273 sizeof (ConsolePref
), &ConsolePref
);
275 if (EFI_ERROR (Status
)) {
276 DEBUG ((DEBUG_ERROR
, "%a: gRT->SetVariable () failed - %r\n",
277 __FUNCTION__
, Status
));
282 Status
= gBS
->CreateEventEx (EVT_NOTIFY_SIGNAL
, TPL_CALLBACK
,
283 OnReadyToBoot
, NULL
, &gEfiEventReadyToBootGuid
,
285 ASSERT_EFI_ERROR (Status
);
287 return InstallHiiPages ();