diff --git a/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.c b/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.c new file mode 100644 index 0000000000..996d1a6036 --- /dev/null +++ b/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.c @@ -0,0 +1,293 @@ +/** @file +* +* Copyright (c) 2017, Linaro, Ltd. All rights reserved. +* +* This program and the accompanying materials are licensed and made available +* under the terms and conditions of the BSD License which accompanies this +* distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ConsolePrefDxe.h" + +#define SPCR_SIG EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE + +extern UINT8 ConsolePrefHiiBin[]; +extern UINT8 ConsolePrefDxeStrings[]; + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +STATIC HII_VENDOR_DEVICE_PATH mConsolePrefDxeVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + CONSOLE_PREF_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +STATIC EFI_EVENT mReadyToBootEvent; + +STATIC +EFI_STATUS +InstallHiiPages ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + + DriverHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces (&DriverHandle, + &gEfiDevicePathProtocolGuid, + &mConsolePrefDxeVendorDevicePath, + NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + HiiHandle = HiiAddPackages (&gConsolePrefFormSetGuid, + DriverHandle, + ConsolePrefDxeStrings, + ConsolePrefHiiBin, + NULL); + + if (HiiHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces (DriverHandle, + &gEfiDevicePathProtocolGuid, + &mConsolePrefDxeVendorDevicePath, + NULL); + return EFI_OUT_OF_RESOURCES; + } + return EFI_SUCCESS; +} + +STATIC +VOID +RemoveDtStdoutPath ( + VOID +) +{ + VOID *Dtb; + INT32 Node; + INT32 Error; + EFI_STATUS Status; + + Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &Dtb); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: could not retrieve DT blob - %r\n", __FUNCTION__, + Status)); + return; + } + + Node = fdt_path_offset (Dtb, "/chosen"); + if (Node < 0) { + return; + } + + Error = fdt_delprop (Dtb, Node, "stdout-path"); + if (Error) { + DEBUG ((DEBUG_INFO, "%a: Failed to delete 'stdout-path' property: %a\n", + __FUNCTION__, fdt_strerror (Error))); + } +} + +STATIC +VOID +RemoveSpcrTable ( + VOID + ) +{ + EFI_ACPI_SDT_PROTOCOL *Sdt; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + EFI_STATUS Status; + UINTN TableIndex; + EFI_ACPI_SDT_HEADER *TableHeader; + EFI_ACPI_TABLE_VERSION TableVersion; + UINTN TableKey; + + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, + (VOID **)&AcpiTable); + if (EFI_ERROR (Status)) { + return; + } + + Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&Sdt); + if (EFI_ERROR (Status)) { + return; + } + + TableIndex = 0; + TableKey = 0; + TableHeader = NULL; + + do { + Status = Sdt->GetAcpiTable (TableIndex++, &TableHeader, &TableVersion, + &TableKey); + if (EFI_ERROR (Status)) { + break; + } + + if (TableHeader->Signature != SPCR_SIG) { + continue; + } + + Status = AcpiTable->UninstallAcpiTable (AcpiTable, TableKey); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "%a: failed to uninstall SPCR table - %r\n", + __FUNCTION__, Status)); + } + break; + } while (TRUE); +} + +STATIC +VOID +OnReadyToBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + CONSOLE_PREF_VARSTORE_DATA ConsolePref; + UINTN BufferSize; + EFI_STATUS Status; + VOID *Gop; + + BufferSize = sizeof (ConsolePref); + Status = gRT->GetVariable (CONSOLE_PREF_VARIABLE_NAME, + &gConsolePrefFormSetGuid, NULL, &BufferSize, &ConsolePref); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a: variable '%s' could not be read - bailing!\n", __FUNCTION__, + CONSOLE_PREF_VARIABLE_NAME)); + return; + } + + if (ConsolePref.Console == CONSOLE_PREF_SERIAL) { + DEBUG ((DEBUG_INFO, + "%a: serial console preferred - doing nothing\n", __FUNCTION__)); + return; + } + + // + // Check if any GOP instances exist: if so, disable stdout-path and SPCR + // + Status = gBS->LocateProtocol (&gEfiGraphicsOutputProtocolGuid, NULL, &Gop); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, + "%a: no GOP instances found - doing nothing (%r)\n", __FUNCTION__, + Status)); + return; + } + + RemoveDtStdoutPath (); + RemoveSpcrTable (); +} + +/** + The entry point for ConsolePrefDxe driver. + + @param[in] ImageHandle The image handle of the driver. + @param[in] SystemTable The system table. + + @retval EFI_ALREADY_STARTED The driver already exists in system. + @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of + resources. + @retval EFI_SUCCES All the related protocols are installed on + the driver. + +**/ +EFI_STATUS +EFIAPI +ConsolePrefDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + CONSOLE_PREF_VARSTORE_DATA ConsolePref; + UINTN BufferSize; + + // + // Get the current console preference from the ConsolePref variable. + // + BufferSize = sizeof (ConsolePref); + Status = gRT->GetVariable (CONSOLE_PREF_VARIABLE_NAME, + &gConsolePrefFormSetGuid, NULL, &BufferSize, &ConsolePref); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, + "%a: no console preference found, defaulting to graphical\n", + __FUNCTION__)); + ConsolePref.Console = CONSOLE_PREF_GRAPHICAL; + } + + if (!EFI_ERROR (Status) && + ConsolePref.Console != CONSOLE_PREF_GRAPHICAL && + ConsolePref.Console != CONSOLE_PREF_SERIAL) { + DEBUG ((DEBUG_WARN, "%a: invalid value for %s, defaulting to graphical\n", + __FUNCTION__, CONSOLE_PREF_VARIABLE_NAME)); + ConsolePref.Console = CONSOLE_PREF_GRAPHICAL; + Status = EFI_INVALID_PARAMETER; // trigger setvar below + } + + // + // Write the newly selected value back to the variable store. + // + if (EFI_ERROR (Status)) { + ZeroMem (&ConsolePref.Reserved, sizeof (ConsolePref.Reserved)); + Status = gRT->SetVariable (CONSOLE_PREF_VARIABLE_NAME, + &gConsolePrefFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (ConsolePref), &ConsolePref); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: gRT->SetVariable () failed - %r\n", + __FUNCTION__, Status)); + return Status; + } + } + + Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, + OnReadyToBoot, NULL, &gEfiEventReadyToBootGuid, + &mReadyToBootEvent); + ASSERT_EFI_ERROR (Status); + + return InstallHiiPages (); +} diff --git a/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.h b/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.h new file mode 100644 index 0000000000..8315e739d3 --- /dev/null +++ b/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.h @@ -0,0 +1,31 @@ +/** @file +* +* Copyright (c) 2017, Linaro Limited. All rights reserved. +* +* This program and the accompanying materials are licensed and made available +* under the terms and conditions of the BSD License which accompanies this +* distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#ifndef __CONSOLE_PREF_DXE_H__ +#define __CONSOLE_PREF_DXE_H__ + +#include +#include + +#define CONSOLE_PREF_GRAPHICAL 0x0 +#define CONSOLE_PREF_SERIAL 0x1 + +#define CONSOLE_PREF_VARIABLE_NAME L"ConsolePref" + +typedef struct { + UINT8 Console; + UINT8 Reserved[3]; +} CONSOLE_PREF_VARSTORE_DATA; + +#endif diff --git a/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.inf b/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.inf new file mode 100644 index 0000000000..d8b412b920 --- /dev/null +++ b/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.inf @@ -0,0 +1,62 @@ +## @file +# +# Copyright (c) 2017, Linaro, Ltd. All rights reserved.
+# +# This program and the accompanying materials are licensed and made +# available under the terms and conditions of the BSD License which +# accompanies this distribution. The full text of the license may be +# found at http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR +# IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = ConsolePrefDxe + FILE_GUID = bbe2668c-0efc-46fb-9137-4f2da8f419f3 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = ConsolePrefDxeEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + ConsolePrefDxe.c + ConsolePrefHii.vfr + ConsolePrefHii.uni + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + FdtLib + HiiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + UefiRuntimeServicesTableLib + +[Guids] + gConsolePrefFormSetGuid + gFdtTableGuid + gEfiEventReadyToBootGuid + +[Protocols] + gEfiAcpiTableProtocolGuid + gEfiAcpiSdtProtocolGuid + gEfiGraphicsOutputProtocolGuid + +[Depex] + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid diff --git a/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefHii.uni b/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefHii.uni new file mode 100644 index 0000000000..947cf70a48 --- /dev/null +++ b/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefHii.uni @@ -0,0 +1,27 @@ +/** @file +* +* Copyright (c) 2017, Linaro, Ltd. All rights reserved. +* +* This program and the accompanying materials are licensed and made available +* under the terms and conditions of the BSD License which accompanies this +* distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#langdef en-US "English" + +#string STR_FORM_SET_TITLE #language en-US "Console Preference Selection" +#string STR_FORM_SET_TITLE_HELP #language en-US "Press to choose between graphical and serial console." + +#string STR_MAIN_FORM_TITLE #language en-US "Console Preference Selection" +#string STR_NULL_STRING #language en-US "" + +#string STR_CONSOLE_PREF_SELECT_PROMPT #language en-US "Preferred console" +#string STR_CONSOLE_PREF_SELECT_HELP #language en-US "Select the preferred console if both graphical and serial are available." + +#string STR_CONSOLE_PREF_GRAPHICAL #language en-US "Graphical" +#string STR_CONSOLE_PREF_SERIAL #language en-US "Serial" diff --git a/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefHii.vfr b/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefHii.vfr new file mode 100644 index 0000000000..a1e603abf0 --- /dev/null +++ b/EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefHii.vfr @@ -0,0 +1,51 @@ +/** @file +* +* Copyright (c) 2017, Linaro, Ltd. All rights reserved. +* +* This program and the accompanying materials are licensed and made available +* under the terms and conditions of the BSD License which accompanies this +* distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include "ConsolePrefDxe.h" + +// +// EFI Variable attributes +// +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +#define EFI_VARIABLE_READ_ONLY 0x00000008 + +formset + guid = CONSOLE_PREF_FORMSET_GUID, + title = STRING_TOKEN(STR_FORM_SET_TITLE), + help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP), + classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID, + + efivarstore CONSOLE_PREF_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, // EFI variable attributes + name = ConsolePref, + guid = CONSOLE_PREF_FORMSET_GUID; + + form formid = 0x1000, + title = STRING_TOKEN(STR_MAIN_FORM_TITLE); + + oneof varid = ConsolePref.Console, + prompt = STRING_TOKEN(STR_CONSOLE_PREF_SELECT_PROMPT), + help = STRING_TOKEN(STR_CONSOLE_PREF_SELECT_HELP), + flags = NUMERIC_SIZE_1 | INTERACTIVE, + option text = STRING_TOKEN(STR_CONSOLE_PREF_GRAPHICAL), value = CONSOLE_PREF_GRAPHICAL, flags = DEFAULT; + option text = STRING_TOKEN(STR_CONSOLE_PREF_SERIAL), value = CONSOLE_PREF_SERIAL, flags = 0; + endoneof; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + endform; + +endformset; diff --git a/EmbeddedPkg/EmbeddedPkg.dec b/EmbeddedPkg/EmbeddedPkg.dec index 151b1d503d..52482af13a 100644 --- a/EmbeddedPkg/EmbeddedPkg.dec +++ b/EmbeddedPkg/EmbeddedPkg.dec @@ -67,6 +67,9 @@ # File GUID for default DTB image embedded in the firmware volume gDtPlatformDefaultDtbFileGuid = { 0x25462cda, 0x221f, 0x47df, { 0xac, 0x1d, 0x25, 0x9c, 0xfa, 0xa4, 0xe3, 0x26 } } + # HII form set GUID for ConsolePrefDxe driver + gConsolePrefFormSetGuid = { 0x2d2358b4, 0xe96c, 0x484d, { 0xb2, 0xdd, 0x7c, 0x2e, 0xdf, 0xc7, 0xd5, 0x6f } } + [Protocols.common] gHardwareInterruptProtocolGuid = { 0x2890B3EA, 0x053D, 0x1643, { 0xAD, 0x0C, 0xD6, 0x48, 0x08, 0xDA, 0x3F, 0xF1 } } gHardwareInterrupt2ProtocolGuid = { 0x32898322, 0x2da1, 0x474a, { 0xba, 0xaa, 0xf3, 0xf7, 0xcf, 0x56, 0x94, 0x70 } } diff --git a/EmbeddedPkg/Include/Guid/ConsolePrefFormSet.h b/EmbeddedPkg/Include/Guid/ConsolePrefFormSet.h new file mode 100644 index 0000000000..f3cca1d15d --- /dev/null +++ b/EmbeddedPkg/Include/Guid/ConsolePrefFormSet.h @@ -0,0 +1,23 @@ +/** @file +* +* Copyright (c) 2017, Linaro Limited. All rights reserved. +* +* This program and the accompanying materials are licensed and made available +* under the terms and conditions of the BSD License which accompanies this +* distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#ifndef __CONSOLE_PREF_FORMSET_H__ +#define __CONSOLE_PREF_FORMSET_H__ + +#define CONSOLE_PREF_FORMSET_GUID \ + { 0x2d2358b4, 0xe96c, 0x484d, { 0xb2, 0xdd, 0x7c, 0x2e, 0xdf, 0xc7, 0xd5, 0x6f } } + +extern EFI_GUID gConsolePrefFormSetGuid; + +#endif