From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: None (no SPF record) identity=mailfrom; client-ip=2a00:1450:4864:20::541; helo=mail-ed1-x541.google.com; envelope-from=pete@akeo.ie; receiver=edk2-devel@lists.01.org Received: from mail-ed1-x541.google.com (mail-ed1-x541.google.com [IPv6:2a00:1450:4864:20::541]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A1E962194D387 for ; Tue, 5 Feb 2019 08:26:31 -0800 (PST) Received: by mail-ed1-x541.google.com with SMTP id g22so3352695edr.7 for ; Tue, 05 Feb 2019 08:26:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=akeo-ie.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=DUW6qpZd8OM1XZiKFSXsvNE/DtNZkk2dSAT/vO+313U=; b=NY22E5VjCSBkDLO9YUfBpsCiGM+CfsiEy6en7MS3y5uF/qM8NsHRsuCGlPNGrw5Sz1 iohOlsn43f97S2Z2qDbpeZkb7Ap9AlzQheKzIubp9b7OtRts2KKKEhPaz4WuZIpD+bIM 68C5eBFu3ECeNEy4361xcvFfCSlcKXk2k2FAgXOP9hFD7DSslaNUhfdOR7m2RBz477GK NTA0cKiaLRQHvzvk6I2LYLI2uRSL1FQoCN/ZT4U/9E4neIBSLr0pbFYGqS4RGeTPpoNe iG9mthJ+DLA9qCfZUcho77EzE83eJe3fN9R99Acv6n2xcGG78vs4BjAV/2hJ8o1r9N2B An+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=DUW6qpZd8OM1XZiKFSXsvNE/DtNZkk2dSAT/vO+313U=; b=jDE9L8bLj7TV9R0itcKWUgl0EunpNw0jmMDFGA65ZL8FGtPKZ+jjiss9A/i+gGLg3a W88LHgj2mnN6h+7xHWE/0W4prH9gk/71TcyOQXtjxgB2UfMZX5uZTjq5UgIbOA8H4apN s0S/maEu9/1TT3wAs2UvJ/oOK97lEZ6vuEBoSl516dbkNHNEKY0R+vzOo2pH0ssgxQT2 ZG54aELFI8zhX221D2ZwvQsU+PDN7qj7XMkjon+4mHfz8Li+nxBmHLwIfMCF+rZpQU1Q LJgJHH4q0BSz4218y+VsB4PSGKrfwuwwQXb6Xf4rqaJg3HtFAX0WjKQGkFjEiYakd69d a8aA== X-Gm-Message-State: AHQUAubuZ6Icye7NlRNjGWNNH9oq6B/sQmgz2JeG3rsbW6MxDXC2mkrz hWKw68h/V/ypYTRUSODB4pnIhTKUZKI= X-Google-Smtp-Source: AHgI3IbFuIZFxDUy0WULVof1a2JI5eMXHxj5JW8nu9zuWafj7nBBS+uW8EvmxL74m4jzMAsAD/j0Ag== X-Received: by 2002:a17:906:6855:: with SMTP id a21mr4103440ejs.83.1549383989337; Tue, 05 Feb 2019 08:26:29 -0800 (PST) Received: from localhost.localdomain ([84.203.58.139]) by smtp.gmail.com with ESMTPSA id j16sm3191430ejq.59.2019.02.05.08.26.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 05 Feb 2019 08:26:28 -0800 (PST) From: Pete Batard To: edk2-devel@lists.01.org Date: Tue, 5 Feb 2019 16:25:31 +0000 Message-Id: <20190205162537.6472-17-pete@akeo.ie> X-Mailer: git-send-email 2.17.0.windows.1 In-Reply-To: <20190205162537.6472-1-pete@akeo.ie> References: <20190205162537.6472-1-pete@akeo.ie> Subject: [PATCH v5 edk2-platforms 16/22] Platform/RaspberryPi/RPi3: Add platform boot manager and helper libs X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 X-List-Received-Date: Tue, 05 Feb 2019 16:26:32 -0000 The libraries decide and set the boot order between UEFI Shell, SD media and/or USB media and allow for user configuration and override. Stale boot options (non present media) are automatically removed on boot. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Pete Batard --- Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBm.c | 793 ++++++++++++++++++++ Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBm.h | 60 ++ Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf | 90 +++ Platform/RaspberryPi/RPi3/Library/PlatformUiAppLib/PlatformUiAppLib.c | 120 +++ Platform/RaspberryPi/RPi3/Library/PlatformUiAppLib/PlatformUiAppLib.inf | 34 + 5 files changed, 1097 insertions(+) diff --git a/Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBm.c b/Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBm.c new file mode 100644 index 000000000000..9bbe0db64950 --- /dev/null +++ b/Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBm.c @@ -0,0 +1,793 @@ +/** @file + * + * Copyright (c) 2018, Pete Batard + * Copyright (c) 2017-2018, Andrei Warkentin + * Copyright (c) 2016, Linaro Ltd. All rights reserved. + * Copyright (c) 2015-2016, Red Hat, Inc. + * Copyright (c) 2014, ARM Ltd. All rights reserved. + * Copyright (c) 2004-2016, Intel Corporation. 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 + +#include "PlatformBm.h" + +#define BOOT_PROMPT L"ESC (setup), F1 (shell), ENTER (boot)" + +#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) } + +#pragma pack (1) +typedef struct { + VENDOR_DEVICE_PATH SerialDxe; + UART_DEVICE_PATH Uart; + VENDOR_DEFINED_DEVICE_PATH TermType; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_SERIAL_CONSOLE; +#pragma pack () + +typedef struct { + VENDOR_DEVICE_PATH Custom; + USB_DEVICE_PATH Hub; + USB_DEVICE_PATH Dev; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} PLATFORM_USB_DEV; + +typedef struct { + VENDOR_DEVICE_PATH Custom; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} PLATFORM_SD_DEV; + +#define ARASAN_MMC_DXE_FILE_GUID \ + { 0x100c2cfa, 0xb586, 0x4198, { 0x9b, 0x4c, 0x16, 0x83, 0xd1, 0x95, 0xb1, 0xda } } + +#define SDHOST_MMC_DXE_FILE_GUID \ + { 0x58abd787, 0xf64d, 0x4ca2, { 0xa0, 0x34, 0xb9, 0xac, 0x2d, 0x5a, 0xd0, 0xcf } } + +#define SERIAL_DXE_FILE_GUID \ + { 0xD3987D4B, 0x971A, 0x435F, { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } } + +STATIC PLATFORM_SD_DEV mArasan = { + // + // VENDOR_DEVICE_PATH ArasanMMCHostDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, + ARASAN_MMC_DXE_FILE_GUID + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +STATIC PLATFORM_SD_DEV mSDHost = { + // + // VENDOR_DEVICE_PATH SdHostDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, + SDHOST_MMC_DXE_FILE_GUID + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = { + // + // VENDOR_DEVICE_PATH SerialDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, + SERIAL_DXE_FILE_GUID + }, + + // + // UART_DEVICE_PATH Uart + // + { + { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) }, + 0, // Reserved + FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate + FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits + FixedPcdGet8 (PcdUartDefaultParity), // Parity + FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits + }, + + // + // VENDOR_DEFINED_DEVICE_PATH TermType + // + { + { + MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, + DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH) + } + // + // Guid to be filled in dynamically + // + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + + +#pragma pack (1) +typedef struct { + USB_CLASS_DEVICE_PATH Keyboard; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_USB_KEYBOARD; +#pragma pack () + +STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = { + // + // USB_CLASS_DEVICE_PATH Keyboard + // + { + { + MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, + DP_NODE_LEN (USB_CLASS_DEVICE_PATH) + }, + 0xFFFF, // VendorId: any + 0xFFFF, // ProductId: any + 3, // DeviceClass: HID + 1, // DeviceSubClass: boot + 1 // DeviceProtocol: keyboard + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +STATIC EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *mSerialConProtocol; + +/** + Check if the handle satisfies a particular condition. + + @param[in] Handle The handle to check. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. + + @retval TRUE The condition is satisfied. + @retval FALSE Otherwise. This includes the case when the condition could not + be fully evaluated due to an error. +**/ +typedef +BOOLEAN +(EFIAPI *FILTER_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + + +/** + Process a handle. + + @param[in] Handle The handle to process. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. +**/ +typedef +VOID +(EFIAPI *CALLBACK_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + +/** + Locate all handles that carry the specified protocol, filter them with a + callback function, and pass each handle that passes the filter to another + callback. + + @param[in] ProtocolGuid The protocol to look for. + + @param[in] Filter The filter function to pass each handle to. If this + parameter is NULL, then all handles are processed. + + @param[in] Process The callback function to pass each handle to that + clears the filter. +**/ +STATIC +VOID +FilterAndProcess ( + IN EFI_GUID *ProtocolGuid, + IN FILTER_FUNCTION Filter OPTIONAL, + IN CALLBACK_FUNCTION Process + ) +{ + EFI_STATUS Status; + EFI_HANDLE *Handles; + UINTN NoHandles; + UINTN Idx; + + Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid, + NULL /* SearchKey */, &NoHandles, &Handles); + if (EFI_ERROR (Status)) { + // + // This is not an error, just an informative condition. + // + DEBUG ((DEBUG_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid, + Status)); + return; + } + + ASSERT (NoHandles > 0); + for (Idx = 0; Idx < NoHandles; ++Idx) { + CHAR16 *DevicePathText; + STATIC CHAR16 Fallback[] = L""; + + // + // The ConvertDevicePathToText() function handles NULL input transparently. + // + DevicePathText = ConvertDevicePathToText ( + DevicePathFromHandle (Handles[Idx]), + FALSE, // DisplayOnly + FALSE // AllowShortcuts + ); + if (DevicePathText == NULL) { + DevicePathText = Fallback; + } + + if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) { + Process (Handles[Idx], DevicePathText); + } + + if (DevicePathText != Fallback) { + FreePool (DevicePathText); + } + } + gBS->FreePool (Handles); +} + +/** + This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the + handle, and adds it to ConOut and ErrOut. +**/ +STATIC +VOID +EFIAPI +AddOutput ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = DevicePathFromHandle (Handle); + if (DevicePath == NULL) { + DEBUG ((DEBUG_ERROR, "%a: %s: handle %p: device path not found\n", + __FUNCTION__, ReportText, Handle)); + return; + } + + Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + DEBUG ((DEBUG_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__, + ReportText)); +} + +STATIC +INTN +PlatformRegisterBootOption ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath, + CHAR16 *Description, + UINT32 Attributes + ) +{ + EFI_STATUS Status; + INTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + + Status = EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + + BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); + + OptionIndex = EfiBootManagerFindLoadOption (&NewOption, BootOptions, BootOptionCount); + + if (OptionIndex == -1) { + Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN); + ASSERT_EFI_ERROR (Status); + OptionIndex = BootOptionCount; + } + + EfiBootManagerFreeLoadOption (&NewOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); + + return OptionIndex; +} + +STATIC +INTN +PlatformRegisterFvBootOption ( + CONST EFI_GUID *FileGuid, + CHAR16 *Description, + UINT32 Attributes + ) +{ + EFI_STATUS Status; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + INTN OptionIndex; + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID**)&LoadedImage + ); + ASSERT_EFI_ERROR (Status); + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle); + ASSERT (DevicePath != NULL); + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&FileNode); + ASSERT (DevicePath != NULL); + + OptionIndex = PlatformRegisterBootOption (DevicePath, Description, Attributes); + FreePool (DevicePath); + + return OptionIndex; +} + +STATIC +VOID +RemoveStaleBootOptions ( + VOID +) +{ + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + UINTN Index; + EFI_STATUS Status; + + BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, + LoadOptionTypeBoot); + + for (Index = 0; Index < BootOptionCount; ++Index) { + EFI_DEVICE_PATH_PROTOCOL *DevicePath = BootOptions[Index].FilePath; + + if (CompareMem (&mArasan, DevicePath, GetDevicePathSize (DevicePath)) == 0) { + if (PcdGet32 (PcdSdIsArasan)) { + continue; + } + } else if (CompareMem (&mSDHost, DevicePath, GetDevicePathSize (DevicePath)) == 0) { + if (!PcdGet32 (PcdSdIsArasan)) { + continue; + } + } else { + continue; + } + + // + // Delete the boot options corresponding to stale SD controllers. + // + Status = EfiBootManagerDeleteLoadOptionVariable ( + BootOptions[Index].OptionNumber, LoadOptionTypeBoot); + DEBUG_CODE ( + CHAR16 *DevicePathString; + + DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath, FALSE, FALSE); + DEBUG (( + EFI_ERROR (Status) ? EFI_D_WARN : EFI_D_INFO, + "%a: removing stale Boot#%04x %s: %r\n", + __FUNCTION__, + (UINT32)BootOptions[Index].OptionNumber, + DevicePathString == NULL ? L"" : DevicePathString, + Status + )); + if (DevicePathString != NULL) { + FreePool (DevicePathString); + } + ); + } + + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); +} + +STATIC +VOID +PlatformRegisterOptionsAndKeys ( + VOID + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Enter; + EFI_INPUT_KEY F1; + EFI_INPUT_KEY Esc; + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + INTN ShellOption; + + RemoveStaleBootOptions (); + + ShellOption = PlatformRegisterFvBootOption (&gUefiShellFileGuid, L"UEFI Shell", LOAD_OPTION_ACTIVE); + if (ShellOption != -1) { + // + // F1 boots Shell. + // + F1.ScanCode = SCAN_F1; + F1.UnicodeChar = CHAR_NULL; + Status = EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)ShellOption, 0, &F1, NULL); + ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); + } + + // + // Register ENTER as CONTINUE key + // + Enter.ScanCode = SCAN_NULL; + Enter.UnicodeChar = CHAR_CARRIAGE_RETURN; + Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); + ASSERT_EFI_ERROR (Status); + + // + // Map ESC to Boot Manager Menu + // + Esc.ScanCode = SCAN_ESC; + Esc.UnicodeChar = CHAR_NULL; + Status = EfiBootManagerGetBootManagerMenu (&BootOption); + ASSERT_EFI_ERROR (Status); + Status = EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)BootOption.OptionNumber, 0, &Esc, NULL); + ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); +} + +STATIC VOID +SerialConPrint ( + IN CHAR16 *Text + ) +{ + if (mSerialConProtocol != NULL) { + mSerialConProtocol->OutputString (mSerialConProtocol, Text); + } +} + +STATIC +VOID +EFIAPI +ExitBootServicesHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + // + // Long enough to occlude the string printed + // in PlatformBootManagerWaitCallback. + // + STATIC CHAR16 *OsBootStr = L"Exiting UEFI and booting EL2 OS kernel!\r\n"; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Green; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Yellow; + + if (!PcdGet32 (PcdDebugShowUEFIExit)) { + return; + } + + Green.Raw = 0x00007F00; + Black.Raw = 0x00000000; + Yellow.Raw = 0x00FFFF00; + + Status = BootLogoUpdateProgress (Yellow.Pixel, + Black.Pixel, + OsBootStr, + Green.Pixel, + 100, 0); + if (Status == EFI_SUCCESS) { + SerialConPrint (OsBootStr); + } else { + Print (L"\n"); + Print (OsBootStr); + Print (L"\n"); + } +} + +// +// BDS Platform Functions +// +/** + Do the platform init, can be customized by OEM/IBV + Possible things that can be done in PlatformBootManagerBeforeConsole: + > Update console variable: 1. include hot-plug devices; + > 2. Clear ConIn and add SOL for AMT + > Register new Driver#### or Boot#### + > Register new Key####: e.g.: F12 + > Signal ReadyToLock event + > Authentication action: 1. connect Auth devices; + > 2. Identify auto logon user. +**/ +VOID +EFIAPI +PlatformBootManagerBeforeConsole ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT ExitBSEvent; + ESRT_MANAGEMENT_PROTOCOL *EsrtManagement; + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + ExitBootServicesHandler, + NULL, + &gEfiEventExitBootServicesGuid, + &ExitBSEvent + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: failed to register ExitBootServices handler\n", __FUNCTION__)); + } + + if (GetBootModeHob () == BOOT_ON_FLASH_UPDATE) { + DEBUG ((DEBUG_INFO, "ProcessCapsules Before EndOfDxe ......\n")); + Status = ProcessCapsules (); + DEBUG ((DEBUG_INFO, "ProcessCapsules returned %r\n", Status)); + } else { + Status = gBS->LocateProtocol (&gEsrtManagementProtocolGuid, NULL, (VOID**)&EsrtManagement); + if (!EFI_ERROR (Status)) { + EsrtManagement->SyncEsrtFmp (); + } + } + + // + // Now add the device path of all handles with GOP on them to ConOut and + // ErrOut. + // + FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput); + + // + // Add the hardcoded short-form USB keyboard device path to ConIn. + // + EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL*)&mUsbKeyboard, NULL); + + // + // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut. + // + ASSERT (FixedPcdGet8 (PcdDefaultTerminalType) == 4); + CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid); + + EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL*)&mSerialConsole, NULL); + EfiBootManagerUpdateConsoleVariable (ConOut, (EFI_DEVICE_PATH_PROTOCOL*)&mSerialConsole, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, (EFI_DEVICE_PATH_PROTOCOL*)&mSerialConsole, NULL); + + // + // Signal EndOfDxe PI Event + // + EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); + + // + // Dispatch deferred images after EndOfDxe event and ReadyToLock installation. + // + EfiBootManagerDispatchDeferredImages (); +} + +/** + Do the platform specific action after the console is ready + Possible things that can be done in PlatformBootManagerAfterConsole: + > Console post action: + > Dynamically switch output mode from 100x31 to 80x25 for certain senarino + > Signal console ready platform customized event + > Run diagnostics like memory testing + > Connect certain devices + > Dispatch aditional option roms + > Special boot: e.g.: USB boot, enter UI +**/ +VOID +EFIAPI +PlatformBootManagerAfterConsole ( + VOID + ) +{ + ESRT_MANAGEMENT_PROTOCOL *EsrtManagement; + EFI_STATUS Status; + EFI_HANDLE SerialHandle; + + Status = EfiBootManagerConnectDevicePath ((EFI_DEVICE_PATH_PROTOCOL*)&mSerialConsole, &SerialHandle); + if (Status == EFI_SUCCESS) { + gBS->HandleProtocol (SerialHandle, &gEfiSimpleTextOutProtocolGuid, (VOID**)&mSerialConProtocol); + } + + // + // Show the splash screen. + // + Status = BootLogoEnableLogo (); + if (Status == EFI_SUCCESS) { + SerialConPrint (BOOT_PROMPT); + } else { + Print (BOOT_PROMPT); + } + + // + // Connect the rest of the devices. + // + EfiBootManagerConnectAll (); + + Status = gBS->LocateProtocol (&gEsrtManagementProtocolGuid, NULL, (VOID**)&EsrtManagement); + if (!EFI_ERROR (Status)) { + EsrtManagement->SyncEsrtFmp (); + } + + if (GetBootModeHob () == BOOT_ON_FLASH_UPDATE) { + DEBUG ((DEBUG_INFO, "ProcessCapsules After EndOfDxe ......\n")); + Status = ProcessCapsules (); + DEBUG ((DEBUG_INFO, "ProcessCapsules returned %r\n", Status)); + } + + PlatformRegisterOptionsAndKeys (); +} + +/** + This function is called each second during the boot manager waits the + timeout. + + @param TimeoutRemain The remaining timeout. +**/ +VOID +EFIAPI +PlatformBootManagerWaitCallback ( + IN UINT16 TimeoutRemain + ) +{ + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White; + UINT16 Timeout; + EFI_STATUS Status; + EFI_BOOT_LOGO_PROTOCOL *BootLogo; + + Timeout = PcdGet16 (PcdPlatformBootTimeOut); + + Black.Raw = 0x00000000; + White.Raw = 0x00FFFFFF; + + Status = BootLogoUpdateProgress ( + White.Pixel, + Black.Pixel, + BOOT_PROMPT, + White.Pixel, + (Timeout - TimeoutRemain) * 100 / Timeout, + 0 + ); + if (Status == EFI_SUCCESS) { + SerialConPrint (L"."); + } else { + Print (L"."); + } + + if (TimeoutRemain == 0) { + BootLogo = NULL; + + // + // Clear out the boot logo so that Windows displays its own logo + // instead of ours. + // + Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID**)&BootLogo); + if (!EFI_ERROR (Status) && (BootLogo != NULL)) { + Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0); + ASSERT_EFI_ERROR (Status); + }; + + gST->ConOut->ClearScreen (gST->ConOut); + } +} + +/** + The function is called when no boot option could be launched, + including platform recovery options and options pointing to applications + built into firmware volumes. + If this function returns, BDS attempts to enter an infinite loop. +**/ +VOID +EFIAPI +PlatformBootManagerUnableToBoot ( + VOID + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu; + UINTN Index; + + // + // BootManagerMenu doesn't contain the correct information when return status + // is EFI_NOT_FOUND. + // + Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu); + if (EFI_ERROR (Status)) { + return; + } + // + // Normally BdsDxe does not print anything to the system console, but this is + // a last resort -- the end-user will likely not see any DEBUG messages + // logged in this situation. + // + // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn + // here to see if it makes sense to request and wait for a keypress. + // + if (gST->ConIn != NULL) { + AsciiPrint ( + "%a: No bootable option or device was found.\n" + "%a: Press any key to enter the Boot Manager Menu.\n", + gEfiCallerBaseName, + gEfiCallerBaseName); + Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index); + ASSERT_EFI_ERROR (Status); + ASSERT (Index == 0); + + // + // Drain any queued keys. + // + while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) { + // + // just throw away Key + // + } + } + + for (;;) { + EfiBootManagerBoot (&BootManagerMenu); + } +} diff --git a/Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBm.h b/Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBm.h new file mode 100644 index 000000000000..3717ba6174df --- /dev/null +++ b/Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBm.h @@ -0,0 +1,60 @@ +/** @file + * + * Copyright (c) 2017-2018, Andrei Warkentin + * Copyright (c) 2016, Linaro Ltd. All rights reserved. + * Copyright (c) 2015-2016, Red Hat, Inc. + * Copyright (c) 2014, ARM Ltd. All rights reserved. + * Copyright (c) 2004-2016, Intel Corporation. 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 _PLATFORM_BM_H_ +#define _PLATFORM_BM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Use SystemTable Conout to stop video based Simple Text Out consoles from + going to the video device. Put up LogoFile on every video device that is a + console. + + @param[in] LogoFile File name of logo to display on the center of the + screen. + + @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo + displayed. + @retval EFI_UNSUPPORTED Logo not found +**/ +EFI_STATUS +EnableQuietBoot ( + IN EFI_GUID *LogoFile + ); + +/** + Use SystemTable Conout to turn on video based Simple Text Out consoles. The + Simple Text Out screens will now be synced up with all non video output + devices + + @retval EFI_SUCCESS UGA devices are back in text mode and synced up. +**/ +EFI_STATUS +DisableQuietBoot ( + VOID + ); + +#endif // _PLATFORM_BM_H_ diff --git a/Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf new file mode 100644 index 000000000000..b30772d5a123 --- /dev/null +++ b/Platform/RaspberryPi/RPi3/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -0,0 +1,90 @@ +#/** @file +# +# Copyright (c) 2017-2018, Andrei Warkentin +# Copyright (c) 2016, Linaro Ltd. All rights reserved. +# Copyright (c) 2015-2016, Red Hat, Inc. +# Copyright (c) 2014, ARM Ltd. All rights reserved. +# Copyright (c) 2007-2014, Intel Corporation. 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 = 0x0001001A + BASE_NAME = PlatformBootManagerLib + FILE_GUID = 92FD2DE3-B9CB-4B35-8141-42AD34D73C9F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = AARCH64 +# + +[Sources] + PlatformBm.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + Platform/RaspberryPi/RPi3/RPi3.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + BootLogoLib + CapsuleLib + DebugLib + DevicePathLib + DxeServicesLib + HobLib + MemoryAllocationLib + PcdLib + PrintLib + UefiBootManagerLib + UefiBootServicesTableLib + UefiLib + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport + +[FixedPcd] + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut + gRaspberryPiTokenSpaceGuid.PcdDebugShowUEFIExit + gRaspberryPiTokenSpaceGuid.PcdSdIsArasan + +[Guids] + gEfiFileInfoGuid + gEfiFileSystemInfoGuid + gEfiFileSystemVolumeLabelInfoIdGuid + gEfiEndOfDxeEventGroupGuid + gEfiTtyTermGuid + gUefiShellFileGuid + gEfiEventExitBootServicesGuid + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiGraphicsOutputProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEsrtManagementProtocolGuid + gEfiUsb2HcProtocolGuid + gEfiBootLogoProtocolGuid diff --git a/Platform/RaspberryPi/RPi3/Library/PlatformUiAppLib/PlatformUiAppLib.c b/Platform/RaspberryPi/RPi3/Library/PlatformUiAppLib/PlatformUiAppLib.c new file mode 100644 index 000000000000..3f8521a35190 --- /dev/null +++ b/Platform/RaspberryPi/RPi3/Library/PlatformUiAppLib/PlatformUiAppLib.c @@ -0,0 +1,120 @@ +/** @file + * + * Copyright (c) 2019, Andrey Warkentin + * + * 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 + +#define ARASAN_MMC_DXE_FILE_GUID \ + { 0x100c2cfa, 0xb586, 0x4198, { 0x9b, 0x4c, 0x16, 0x83, 0xd1, 0x95, 0xb1, 0xda } } + +#define SDHOST_MMC_DXE_FILE_GUID \ + { 0x58abd787, 0xf64d, 0x4ca2, { 0xa0, 0x34, 0xb9, 0xac, 0x2d, 0x5a, 0xd0, 0xcf } } + +#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) } + +typedef struct { + VENDOR_DEVICE_PATH Custom; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} PLATFORM_SD_DEV; + +STATIC PLATFORM_SD_DEV mArasan = { + // + // VENDOR_DEVICE_PATH ArasanMMCHostDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, + ARASAN_MMC_DXE_FILE_GUID + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +STATIC PLATFORM_SD_DEV mSDHost = { + // + // VENDOR_DEVICE_PATH SdHostDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, + SDHOST_MMC_DXE_FILE_GUID + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +STATIC +CHAR16* +EFIAPI +BootDescriptionHandler ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *DefaultDescription + ) +{ + CHAR16 *Name; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = DevicePathFromHandle (Handle); + if (CompareMem (&mArasan, DevicePath, GetDevicePathSize (DevicePath)) == 0) { + Name = L"SD/MMC on Arasan SDHCI"; + } else if (CompareMem (&mSDHost, DevicePath, GetDevicePathSize (DevicePath)) == 0) { + Name = L"SD/MMC on Broadcom SDHOST"; + } else { + return NULL; + } + + return AllocateCopyPool(StrSize (Name), Name); +} + +EFI_STATUS +EFIAPI +PlatformUiAppLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = EfiBootManagerRegisterBootDescriptionHandler(BootDescriptionHandler); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PlatformUiAppLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} diff --git a/Platform/RaspberryPi/RPi3/Library/PlatformUiAppLib/PlatformUiAppLib.inf b/Platform/RaspberryPi/RPi3/Library/PlatformUiAppLib/PlatformUiAppLib.inf new file mode 100644 index 000000000000..cacf55f02a14 --- /dev/null +++ b/Platform/RaspberryPi/RPi3/Library/PlatformUiAppLib/PlatformUiAppLib.inf @@ -0,0 +1,34 @@ +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = PlatformUiAppLib + FILE_GUID = CCB2DCE1-5EC9-42CB-88C5-D349E134C9FC + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|DXE_DRIVER UEFI_APPLICATION + CONSTRUCTOR = PlatformUiAppLibConstructor + DESTRUCTOR = PlatformUiAppLibDestructor + +[Sources] + PlatformUiAppLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Platform/RaspberryPi/RPi3/RPi3.dec + +[LibraryClasses] + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + PrintLib + UefiBootManagerLib + MemoryAllocationLib + +[Guids] + +[Protocols] + +[FeaturePcd] + +[Pcd] -- 2.17.0.windows.1