3 * Copyright (c) 2017, Linaro, Ltd. All rights reserved.
5 * This program and the accompanying materials are licensed and made available
6 * under the terms and conditions of the BSD License which accompanies this
7 * distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <IndustryStandard/Acpi.h>
18 #include <Library/BaseLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/DevicePathLib.h>
21 #include <Library/HiiLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/UefiBootServicesTableLib.h>
24 #include <Library/UefiDriverEntryPoint.h>
25 #include <Library/UefiLib.h>
26 #include <Library/UefiRuntimeServicesTableLib.h>
28 #include <Protocol/AcpiTable.h>
29 #include <Protocol/AcpiSystemDescriptionTable.h>
31 #include "ConsolePrefDxe.h"
33 #define SPCR_SIG EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
35 extern UINT8 ConsolePrefHiiBin
[];
36 extern UINT8 ConsolePrefDxeStrings
[];
39 VENDOR_DEVICE_PATH VendorDevicePath
;
40 EFI_DEVICE_PATH_PROTOCOL End
;
41 } HII_VENDOR_DEVICE_PATH
;
43 STATIC HII_VENDOR_DEVICE_PATH mConsolePrefDxeVendorDevicePath
= {
49 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
50 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
53 CONSOLE_PREF_FORMSET_GUID
57 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
59 (UINT8
) (END_DEVICE_PATH_LENGTH
),
60 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
65 STATIC EFI_EVENT mReadyToBootEvent
;
74 EFI_HII_HANDLE HiiHandle
;
75 EFI_HANDLE DriverHandle
;
78 Status
= gBS
->InstallMultipleProtocolInterfaces (&DriverHandle
,
79 &gEfiDevicePathProtocolGuid
,
80 &mConsolePrefDxeVendorDevicePath
,
82 if (EFI_ERROR (Status
)) {
86 HiiHandle
= HiiAddPackages (&gConsolePrefFormSetGuid
,
88 ConsolePrefDxeStrings
,
92 if (HiiHandle
== NULL
) {
93 gBS
->UninstallMultipleProtocolInterfaces (DriverHandle
,
94 &gEfiDevicePathProtocolGuid
,
95 &mConsolePrefDxeVendorDevicePath
,
97 return EFI_OUT_OF_RESOURCES
;
113 Status
= EfiGetSystemConfigurationTable (&gFdtTableGuid
, &Dtb
);
114 if (EFI_ERROR (Status
)) {
115 DEBUG ((DEBUG_INFO
, "%a: could not retrieve DT blob - %r\n", __FUNCTION__
,
120 Node
= fdt_path_offset (Dtb
, "/chosen");
125 Error
= fdt_delprop (Dtb
, Node
, "stdout-path");
127 DEBUG ((DEBUG_INFO
, "%a: Failed to delete 'stdout-path' property: %a\n",
128 __FUNCTION__
, fdt_strerror (Error
)));
138 EFI_ACPI_SDT_PROTOCOL
*Sdt
;
139 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
142 EFI_ACPI_SDT_HEADER
*TableHeader
;
143 EFI_ACPI_TABLE_VERSION TableVersion
;
146 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
,
147 (VOID
**)&AcpiTable
);
148 if (EFI_ERROR (Status
)) {
152 Status
= gBS
->LocateProtocol (&gEfiAcpiSdtProtocolGuid
, NULL
, (VOID
**)&Sdt
);
153 if (EFI_ERROR (Status
)) {
162 Status
= Sdt
->GetAcpiTable (TableIndex
++, &TableHeader
, &TableVersion
,
164 if (EFI_ERROR (Status
)) {
168 if (TableHeader
->Signature
!= SPCR_SIG
) {
172 Status
= AcpiTable
->UninstallAcpiTable (AcpiTable
, TableKey
);
173 if (EFI_ERROR (Status
)) {
174 DEBUG ((DEBUG_WARN
, "%a: failed to uninstall SPCR table - %r\n",
175 __FUNCTION__
, Status
));
188 CONSOLE_PREF_VARSTORE_DATA ConsolePref
;
193 BufferSize
= sizeof (ConsolePref
);
194 Status
= gRT
->GetVariable (CONSOLE_PREF_VARIABLE_NAME
,
195 &gConsolePrefFormSetGuid
, NULL
, &BufferSize
, &ConsolePref
);
196 if (EFI_ERROR (Status
)) {
198 "%a: variable '%s' could not be read - bailing!\n", __FUNCTION__
,
199 CONSOLE_PREF_VARIABLE_NAME
));
203 if (ConsolePref
.Console
== CONSOLE_PREF_SERIAL
) {
205 "%a: serial console preferred - doing nothing\n", __FUNCTION__
));
210 // Check if any GOP instances exist: if so, disable stdout-path and SPCR
212 Status
= gBS
->LocateProtocol (&gEfiGraphicsOutputProtocolGuid
, NULL
, &Gop
);
213 if (EFI_ERROR (Status
)) {
215 "%a: no GOP instances found - doing nothing (%r)\n", __FUNCTION__
,
220 RemoveDtStdoutPath ();
225 The entry point for ConsolePrefDxe driver.
227 @param[in] ImageHandle The image handle of the driver.
228 @param[in] SystemTable The system table.
230 @retval EFI_ALREADY_STARTED The driver already exists in system.
231 @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of
233 @retval EFI_SUCCES All the related protocols are installed on
239 ConsolePrefDxeEntryPoint (
240 IN EFI_HANDLE ImageHandle
,
241 IN EFI_SYSTEM_TABLE
*SystemTable
245 CONSOLE_PREF_VARSTORE_DATA ConsolePref
;
249 // Get the current console preference from the ConsolePref variable.
251 BufferSize
= sizeof (ConsolePref
);
252 Status
= gRT
->GetVariable (CONSOLE_PREF_VARIABLE_NAME
,
253 &gConsolePrefFormSetGuid
, NULL
, &BufferSize
, &ConsolePref
);
254 if (EFI_ERROR (Status
)) {
256 "%a: no console preference found, defaulting to graphical\n",
258 ConsolePref
.Console
= CONSOLE_PREF_GRAPHICAL
;
261 if (!EFI_ERROR (Status
) &&
262 ConsolePref
.Console
!= CONSOLE_PREF_GRAPHICAL
&&
263 ConsolePref
.Console
!= CONSOLE_PREF_SERIAL
) {
264 DEBUG ((DEBUG_WARN
, "%a: invalid value for %s, defaulting to graphical\n",
265 __FUNCTION__
, CONSOLE_PREF_VARIABLE_NAME
));
266 ConsolePref
.Console
= CONSOLE_PREF_GRAPHICAL
;
267 Status
= EFI_INVALID_PARAMETER
; // trigger setvar below
271 // Write the newly selected value back to the variable store.
273 if (EFI_ERROR (Status
)) {
274 ZeroMem (&ConsolePref
.Reserved
, sizeof (ConsolePref
.Reserved
));
275 Status
= gRT
->SetVariable (CONSOLE_PREF_VARIABLE_NAME
,
276 &gConsolePrefFormSetGuid
,
277 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
278 sizeof (ConsolePref
), &ConsolePref
);
280 if (EFI_ERROR (Status
)) {
281 DEBUG ((DEBUG_ERROR
, "%a: gRT->SetVariable () failed - %r\n",
282 __FUNCTION__
, Status
));
287 Status
= gBS
->CreateEventEx (EVT_NOTIFY_SIGNAL
, TPL_CALLBACK
,
288 OnReadyToBoot
, NULL
, &gEfiEventReadyToBootGuid
,
290 ASSERT_EFI_ERROR (Status
);
292 return InstallHiiPages ();