public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Sunil V L" <sunilvl@ventanamicro.com>
To: John Chew <yuinyee.chew@starfivetech.com>
Cc: devel@edk2.groups.io, Yong Li <yong.li@intel.com>
Subject: Re: [edk2-devel] [PATCH v1 4/6] StarFive/JH7110Pkg: Add PlatformBootManagerLib library
Date: Thu, 19 Oct 2023 17:42:32 +0530	[thread overview]
Message-ID: <ZTEdMEjZM0IDle6l@sunil-laptop> (raw)
In-Reply-To: <20231019025921.1593-4-yuinyee.chew@starfivetech.com>

Hi John,

On Thu, Oct 19, 2023 at 10:59:19AM +0800, John Chew wrote:
> From: JohnChew <yuinyee.chew@starfivetech.com>
> 
> For JH7110 with graphic console
>
This commit message needs to be improved. From the code, I can't find
why this library needs to be copied for your platform. Why not migrate
and use the library in ArmPkg to MdePkg?

> Cc: Sunil V L <sunilvl@ventanamicro.com>
> Co-authored-by: Yong Li <yong.li@intel.com>
> Signed-off-by: John Chew <yuinyee.chew@starfivetech.com>
> ---
>  Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBm.c               | 1014 ++++++++++++++++++++
>  Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBm.h               |   46 +
>  Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf |   71 ++
>  3 files changed, 1131 insertions(+)
> 
> diff --git a/Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBm.c b/Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBm.c
> new file mode 100755
> index 000000000000..b58d2c7cbcd5
> --- /dev/null
> +++ b/Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBm.c
> @@ -0,0 +1,1014 @@
> +/** @file
> +*  Implementation for PlatformBootManagerLib library class interfaces.
> +*
> +*  Copyright (C) 2015-2016, Red Hat, Inc.
> +*  Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
> +*  Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
> +*  Copyright (c) 2023, StarFive Technology Co., Ltd. All rights reserved.<BR>
> +*
> +*  SPDX-License-Identifier: BSD-2-Clause-Patent
> +*
> +**/
> +
> +#include <IndustryStandard/Pci22.h>
> +#include <IndustryStandard/Virtio095.h>
> +#include <Library/BootLogoLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PlatformBmPrintScLib.h>
> +#include <Library/QemuBootOrderLib.h>
> +#include <Library/TpmPlatformHierarchyLib.h>
> +#include <Library/UefiBootManagerLib.h>
> +#include <Protocol/DevicePath.h>
> +#include <Protocol/FirmwareVolume2.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/PciIo.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +#include <Protocol/VirtioDevice.h>
> +#include <Guid/EventGroup.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/RootBridgesConnectedEventGroup.h>
> +#include <Guid/SerialPortLibVendor.h>
> +#include <Guid/TtyTerm.h>
> +
> +#include "PlatformBm.h"
> +
> +#define DP_NODE_LEN(Type)  { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
> +
> +#define VERSION_STRING_PREFIX  L"RISC-V EDK2 firmware version "
> +
> +#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 ()
> +
> +STATIC PLATFORM_SERIAL_CONSOLE  mSerialConsole = {
> +  //
> +  // VENDOR_DEVICE_PATH SerialDxe
> +  //
> +  {
> +    { HARDWARE_DEVICE_PATH,  HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },
> +    EDKII_SERIAL_PORT_LIB_VENDOR_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)
> +  }
> +};
> +
> +/**
> +  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",
> +      __func__,
> +      ProtocolGuid,
> +      Status
> +      ));
> +    return;
> +  }
> +
> +  ASSERT (NoHandles > 0);
> +  for (Idx = 0; Idx < NoHandles; ++Idx) {
> +    CHAR16         *DevicePathText;
> +    STATIC CHAR16  Fallback[] = L"<device path unavailable>";
> +
> +    //
> +    // 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 FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
> +**/
> +STATIC
> +BOOLEAN
> +EFIAPI
> +IsPciDisplay (
> +  IN EFI_HANDLE    Handle,
> +  IN CONST CHAR16  *ReportText
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EFI_PCI_IO_PROTOCOL  *PciIo;
> +  PCI_TYPE00           Pci;
> +
> +  Status = gBS->HandleProtocol (
> +                  Handle,
> +                  &gEfiPciIoProtocolGuid,
> +                  (VOID **)&PciIo
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    //
> +    // This is not an error worth reporting.
> +    //
> +    return FALSE;
> +  }
> +
> +  Status = PciIo->Pci.Read (
> +                        PciIo,
> +                        EfiPciIoWidthUint32,
> +                        0 /* Offset */,
> +                        sizeof Pci / sizeof (UINT32),
> +                        &Pci
> +                        );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __func__, ReportText, Status));
> +    return FALSE;
> +  }
> +
> +  return IS_PCI_DISPLAY (&Pci);
> +}
> +
> +
> +/**
> +  This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
> +  the EFI_PCI_IO_PROTOCOL level.
> +**/
> +STATIC
> +BOOLEAN
> +EFIAPI
> +IsVirtioPciRng (

Is this required?

Thanks,
Sunil
> +  IN EFI_HANDLE    Handle,
> +  IN CONST CHAR16  *ReportText
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EFI_PCI_IO_PROTOCOL  *PciIo;
> +  UINT16               VendorId;
> +  UINT16               DeviceId;
> +  UINT8                RevisionId;
> +  BOOLEAN              Virtio10;
> +  UINT16               SubsystemId;
> +
> +  Status = gBS->HandleProtocol (
> +                  Handle,
> +                  &gEfiPciIoProtocolGuid,
> +                  (VOID **)&PciIo
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Read and check VendorId.
> +  //
> +  Status = PciIo->Pci.Read (
> +                        PciIo,
> +                        EfiPciIoWidthUint16,
> +                        PCI_VENDOR_ID_OFFSET,
> +                        1,
> +                        &VendorId
> +                        );
> +  if (EFI_ERROR (Status)) {
> +    goto PciError;
> +  }
> +
> +  if (VendorId != VIRTIO_VENDOR_ID) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Read DeviceId and RevisionId.
> +  //
> +  Status = PciIo->Pci.Read (
> +                        PciIo,
> +                        EfiPciIoWidthUint16,
> +                        PCI_DEVICE_ID_OFFSET,
> +                        1,
> +                        &DeviceId
> +                        );
> +  if (EFI_ERROR (Status)) {
> +    goto PciError;
> +  }
> +
> +  Status = PciIo->Pci.Read (
> +                        PciIo,
> +                        EfiPciIoWidthUint8,
> +                        PCI_REVISION_ID_OFFSET,
> +                        1,
> +                        &RevisionId
> +                        );
> +  if (EFI_ERROR (Status)) {
> +    goto PciError;
> +  }
> +
> +  //
> +  // From DeviceId and RevisionId, determine whether the device is a
> +  // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
> +  // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
> +  // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
> +  // only be sanity-checked, and SubsystemId will decide.
> +  //
> +  if ((DeviceId == 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE) &&
> +      (RevisionId >= 0x01))
> +  {
> +    Virtio10 = TRUE;
> +  } else if ((DeviceId >= 0x1000) && (DeviceId <= 0x103F) && (RevisionId == 0x00)) {
> +    Virtio10 = FALSE;
> +  } else {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Read and check SubsystemId as dictated by Virtio10.
> +  //
> +  Status = PciIo->Pci.Read (
> +                        PciIo,
> +                        EfiPciIoWidthUint16,
> +                        PCI_SUBSYSTEM_ID_OFFSET,
> +                        1,
> +                        &SubsystemId
> +                        );
> +  if (EFI_ERROR (Status)) {
> +    goto PciError;
> +  }
> +
> +  if (Virtio10 && (SubsystemId >= 0x40)) {
> +    return TRUE;
> +  }
> +
> +  if (!Virtio10 && (SubsystemId == VIRTIO_SUBSYSTEM_ENTROPY_SOURCE)) {
> +    return TRUE;
> +  }
> +
> +  return FALSE;
> +
> +PciError:
> +  DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __func__, ReportText, Status));
> +  return FALSE;
> +}
> +
> +/**
> +  This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
> +  the matching driver to produce all first-level child handles.
> +**/
> +STATIC
> +VOID
> +EFIAPI
> +Connect (
> +  IN EFI_HANDLE    Handle,
> +  IN CONST CHAR16  *ReportText
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = gBS->ConnectController (
> +                  Handle, // ControllerHandle
> +                  NULL,   // DriverImageHandle
> +                  NULL,   // RemainingDevicePath -- produce all children
> +                  FALSE   // Recursive
> +                  );
> +  DEBUG ((
> +    EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
> +    "%a: %s: %r\n",
> +    __func__,
> +    ReportText,
> +    Status
> +    ));
> +}
> +
> +/**
> +  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",
> +      __func__,
> +      ReportText,
> +      Handle
> +      ));
> +    return;
> +  }
> +
> +  Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: %s: adding to ConOut: %r\n",
> +      __func__,
> +      ReportText,
> +      Status
> +      ));
> +    return;
> +  }
> +
> +  Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: %s: adding to ErrOut: %r\n",
> +      __func__,
> +      ReportText,
> +      Status
> +      ));
> +    return;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_VERBOSE,
> +    "%a: %s: added to ConOut and ErrOut\n",
> +    __func__,
> +    ReportText
> +    ));
> +}
> +
> +STATIC
> +VOID
> +PlatformRegisterFvBootOption (
> +  EFI_GUID  *FileGuid,
> +  CHAR16    *Description,
> +  UINT32    Attributes
> +  )
> +{
> +  EFI_STATUS                         Status;
> +  INTN                               OptionIndex;
> +  EFI_BOOT_MANAGER_LOAD_OPTION       NewOption;
> +  EFI_BOOT_MANAGER_LOAD_OPTION       *BootOptions;
> +  UINTN                              BootOptionCount;
> +  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;
> +  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
> +  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;
> +
> +  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);
> +
> +  Status = EfiBootManagerInitializeLoadOption (
> +             &NewOption,
> +             LoadOptionNumberUnassigned,
> +             LoadOptionTypeBoot,
> +             Attributes,
> +             Description,
> +             DevicePath,
> +             NULL,
> +             0
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +  FreePool (DevicePath);
> +
> +  BootOptions = EfiBootManagerGetLoadOptions (
> +                  &BootOptionCount,
> +                  LoadOptionTypeBoot
> +                  );
> +
> +  OptionIndex = EfiBootManagerFindLoadOption (
> +                  &NewOption,
> +                  BootOptions,
> +                  BootOptionCount
> +                  );
> +
> +  if (OptionIndex == -1) {
> +    Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +
> +  EfiBootManagerFreeLoadOption (&NewOption);
> +  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
> +}
> +
> +/**
> +  Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
> +  whose device paths do not resolve exactly to an FvFile in the system.
> +
> +  This removes any boot options that point to binaries built into the firmware
> +  and have become stale due to any of the following:
> +  - FvMain's base address or size changed (historical),
> +  - FvMain's FvNameGuid changed,
> +  - the FILE_GUID of the pointed-to binary changed,
> +  - the referenced binary is no longer built into the firmware.
> +
> +  EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
> +  avoids exact duplicates.
> +**/
> +STATIC
> +VOID
> +RemoveStaleFvFileOptions (
> +  VOID
> +  )
> +{
> +  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions;
> +  UINTN                         BootOptionCount;
> +  UINTN                         Index;
> +
> +  BootOptions = EfiBootManagerGetLoadOptions (
> +                  &BootOptionCount,
> +                  LoadOptionTypeBoot
> +                  );
> +
> +  for (Index = 0; Index < BootOptionCount; ++Index) {
> +    EFI_DEVICE_PATH_PROTOCOL  *Node1, *Node2, *SearchNode;
> +    EFI_STATUS                Status;
> +    EFI_HANDLE                FvHandle;
> +
> +    //
> +    // If the device path starts with neither MemoryMapped(...) nor Fv(...),
> +    // then keep the boot option.
> +    //
> +    Node1 = BootOptions[Index].FilePath;
> +    if (!((DevicePathType (Node1) == HARDWARE_DEVICE_PATH) &&
> +          (DevicePathSubType (Node1) == HW_MEMMAP_DP)) &&
> +        !((DevicePathType (Node1) == MEDIA_DEVICE_PATH) &&
> +          (DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)))
> +    {
> +      continue;
> +    }
> +
> +    //
> +    // If the second device path node is not FvFile(...), then keep the boot
> +    // option.
> +    //
> +    Node2 = NextDevicePathNode (Node1);
> +    if ((DevicePathType (Node2) != MEDIA_DEVICE_PATH) ||
> +        (DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP))
> +    {
> +      continue;
> +    }
> +
> +    //
> +    // Locate the Firmware Volume2 protocol instance that is denoted by the
> +    // boot option. If this lookup fails (i.e., the boot option references a
> +    // firmware volume that doesn't exist), then we'll proceed to delete the
> +    // boot option.
> +    //
> +    SearchNode = Node1;
> +    Status     = gBS->LocateDevicePath (
> +                        &gEfiFirmwareVolume2ProtocolGuid,
> +                        &SearchNode,
> +                        &FvHandle
> +                        );
> +
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // The firmware volume was found; now let's see if it contains the FvFile
> +      // identified by GUID.
> +      //
> +      EFI_FIRMWARE_VOLUME2_PROTOCOL      *FvProtocol;
> +      MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvFileNode;
> +      UINTN                              BufferSize;
> +      EFI_FV_FILETYPE                    FoundType;
> +      EFI_FV_FILE_ATTRIBUTES             FileAttributes;
> +      UINT32                             AuthenticationStatus;
> +
> +      Status = gBS->HandleProtocol (
> +                      FvHandle,
> +                      &gEfiFirmwareVolume2ProtocolGuid,
> +                      (VOID **)&FvProtocol
> +                      );
> +      ASSERT_EFI_ERROR (Status);
> +
> +      FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
> +      //
> +      // Buffer==NULL means we request metadata only: BufferSize, FoundType,
> +      // FileAttributes.
> +      //
> +      Status = FvProtocol->ReadFile (
> +                             FvProtocol,
> +                             &FvFileNode->FvFileName, // NameGuid
> +                             NULL,                    // Buffer
> +                             &BufferSize,
> +                             &FoundType,
> +                             &FileAttributes,
> +                             &AuthenticationStatus
> +                             );
> +      if (!EFI_ERROR (Status)) {
> +        //
> +        // The FvFile was found. Keep the boot option.
> +        //
> +        continue;
> +      }
> +    }
> +
> +    //
> +    // Delete the boot option.
> +    //
> +    Status = EfiBootManagerDeleteLoadOptionVariable (
> +               BootOptions[Index].OptionNumber,
> +               LoadOptionTypeBoot
> +               );
> +    DEBUG_CODE_BEGIN ();
> +    CHAR16  *DevicePathString;
> +
> +    DevicePathString = ConvertDevicePathToText (
> +                         BootOptions[Index].FilePath,
> +                         FALSE,
> +                         FALSE
> +                         );
> +    DEBUG ((
> +      EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_VERBOSE,
> +      "%a: removing stale Boot#%04x %s: %r\n",
> +      __func__,
> +      (UINT32)BootOptions[Index].OptionNumber,
> +      DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
> +      Status
> +      ));
> +    if (DevicePathString != NULL) {
> +      FreePool (DevicePathString);
> +    }
> +
> +    DEBUG_CODE_END ();
> +  }
> +
> +  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
> +}
> +
> +STATIC
> +VOID
> +PlatformRegisterOptionsAndKeys (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_INPUT_KEY                 Enter;
> +  EFI_INPUT_KEY                 F2;
> +  EFI_INPUT_KEY                 Esc;
> +  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
> +
> +  //
> +  // Register ENTER as CONTINUE key
> +  //
> +  Enter.ScanCode    = SCAN_NULL;
> +  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
> +  Status            = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Map F2 and ESC to Boot Manager Menu
> +  //
> +  F2.ScanCode     = SCAN_F2;
> +  F2.UnicodeChar  = CHAR_NULL;
> +  Esc.ScanCode    = SCAN_ESC;
> +  Esc.UnicodeChar = CHAR_NULL;
> +  Status          = EfiBootManagerGetBootManagerMenu (&BootOption);
> +  ASSERT_EFI_ERROR (Status);
> +  Status = EfiBootManagerAddKeyOptionVariable (
> +             NULL,
> +             (UINT16)BootOption.OptionNumber,
> +             0,
> +             &F2,
> +             NULL
> +             );
> +  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
> +  Status = EfiBootManagerAddKeyOptionVariable (
> +             NULL,
> +             (UINT16)BootOption.OptionNumber,
> +             0,
> +             &Esc,
> +             NULL
> +             );
> +  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
> +}
> +
> +//
> +// 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
> +  )
> +{
> +  UINT16         FrontPageTimeout;
> +  EFI_STATUS     Status;
> +
> +  //
> +  // Signal EndOfDxe PI Event
> +  //
> +  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
> +
> +  //
> +  // Dispatch deferred images after EndOfDxe event.
> +  //
> +  EfiBootManagerDispatchDeferredImages ();
> +
> +  //
> +  // Locate the PCI root bridges and make the PCI bus driver connect each,
> +  // non-recursively. This will produce a number of child handles with PciIo on
> +  // them.
> +  //
> +  FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);
> +
> +  //
> +  // Signal the ACPI platform driver that it can download QEMU ACPI tables.
> +  //
> +  EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);
> +
> +  //
> +  // Find all display class PCI devices (using the handles from the previous
> +  // step), and connect them non-recursively. This should produce a number of
> +  // child handles with GOPs on them.
> +  //
> +  FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);
> +
> +  //
> +  // 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.
> +  //
> +  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
> +    );
> +
> +  //
> +  // Reflect the PCD in the standard Timeout variable.
> +  //
> +  Status = gRT->SetVariable (
> +                  EFI_TIME_OUT_VARIABLE_NAME,
> +                  &gEfiGlobalVariableGuid,
> +                  (EFI_VARIABLE_NON_VOLATILE |
> +                   EFI_VARIABLE_BOOTSERVICE_ACCESS |
> +                   EFI_VARIABLE_RUNTIME_ACCESS),
> +                  sizeof FrontPageTimeout,
> +                  &FrontPageTimeout
> +                  );
> +  DEBUG ((
> +    EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
> +    "%a: SetVariable(%s, %u): %r\n",
> +    __func__,
> +    EFI_TIME_OUT_VARIABLE_NAME,
> +    FrontPageTimeout,
> +    Status
> +    ));
> +
> +  //
> +  // Register platform-specific boot options and keyboard shortcuts.
> +  //
> +  PlatformRegisterOptionsAndKeys ();
> +
> +  //
> +  // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
> +  // instances on Virtio PCI RNG devices.
> +  //
> +  FilterAndProcess (&gEfiPciIoProtocolGuid, IsVirtioPciRng, Connect);
> +}
> +
> +/**
> +  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 scenario
> +    > Signal console ready platform customized event
> +  > Run diagnostics like memory testing
> +  > Connect certain devices
> +  > Dispatch additional option roms
> +  > Special boot: e.g.: USB boot, enter UI
> +**/
> +VOID
> +EFIAPI
> +PlatformBootManagerAfterConsole (
> +  VOID
> +  )
> +{
> +  UINTN          FirmwareVerLength;
> +
> +  FirmwareVerLength = StrLen (PcdGetPtr (PcdFirmwareVersionString));
> +  //
> +  // Show the splash screen.
> +  //
> +  BootLogoEnableLogo ();
> +
> +  if (FirmwareVerLength > 0) {
> +    Print (
> +      VERSION_STRING_PREFIX L"%s\n",
> +      PcdGetPtr (PcdFirmwareVersionString)
> +      );
> +  }
> +
> +  Print (L"Press ESCAPE within 10 seconds for boot options ");
> +
> +  //
> +  // Enumerate all possible boot options, then filter and reorder them based on
> +  // the QEMU configuration.
> +  //
> +  EfiBootManagerRefreshAllBootOption ();
> +
> +  //
> +  // Register UEFI Shell
> +  //
> +  PlatformRegisterFvBootOption (
> +    &gUefiShellFileGuid,
> +    L"EFI Internal Shell",
> +    LOAD_OPTION_ACTIVE
> +    );
> +
> +  RemoveStaleFvFileOptions ();
> +
> +  PlatformBmPrintScRegisterHandler ();
> +}
> +
> +/**
> +  This function is called each second during the boot manager waits the
> +  timeout.
> +
> +  @param TimeoutRemain  The remaining timeout.
> +**/
> +VOID
> +EFIAPI
> +PlatformBootManagerWaitCallback (
> +  UINT16  TimeoutRemain
> +  )
> +{
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION  Black;
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION  White;
> +  UINT16                               TimeoutInitial;
> +
> +  TimeoutInitial = PcdGet16 (PcdPlatformBootTimeOut);
> +
> +  //
> +  // If PcdPlatformBootTimeOut is set to zero, then we consider
> +  // that no progress update should be enacted.
> +  //
> +  if (TimeoutInitial == 0) {
> +    return;
> +  }
> +
> +  Black.Raw = 0x00000000;
> +  White.Raw = 0x00FFFFFF;
> +
> +  BootLogoUpdateProgress (
> +    White.Pixel,
> +    Black.Pixel,
> +    L"Start boot option",
> +    White.Pixel,
> +    (TimeoutInitial - TimeoutRemain) * 100 / TimeoutInitial,
> +    0
> +    );
> +}
> +
> +/**
> +  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/Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBm.h b/Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBm.h
> new file mode 100755
> index 000000000000..067af555ad31
> --- /dev/null
> +++ b/Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBm.h
> @@ -0,0 +1,46 @@
> +/** @file
> +*  Head file for BDS Platform specific code
> +*
> +*  Copyright (C) 2015-2016, Red Hat, Inc.
> +*  Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
> +*  Copyright (c) 2023, StarFive Technology Co., Ltd. All rights reserved.<BR>
> +*
> +*  SPDX-License-Identifier: BSD-2-Clause-Patent
> +*
> +**/
> +
> +#ifndef _PLATFORM_BM_H_
> +#define _PLATFORM_BM_H_
> +
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +
> +/**
> +  Download the kernel, the initial ramdisk, and the kernel command line from
> +  QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two
> +  image files, and load and start the kernel from it.
> +
> +  The kernel will be instructed via its command line to load the initrd from
> +  the same Simple FileSystem.
> +
> +  @retval EFI_NOT_FOUND         Kernel image was not found.
> +  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +  @retval EFI_PROTOCOL_ERROR    Unterminated kernel command line.
> +
> +  @return                       Error codes from any of the underlying
> +                                functions. On success, the function doesn't
> +                                return.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TryRunningQemuKernel (
> +  VOID
> +  );
> +
> +#endif // _PLATFORM_BM_H_
> diff --git a/Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
> new file mode 100755
> index 000000000000..d967f808cf7f
> --- /dev/null
> +++ b/Silicon/StarFive/JH7110Pkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
> @@ -0,0 +1,71 @@
> +## @file
> +#  Implementation for PlatformBootManagerLib library class interfaces for RISC-V.
> +#
> +#  Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
> +#  Copyright (c) 2023, StarFive Technology Co., Ltd. All rights reserved.<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = DxeRiscV64PlatformBootManagerLib
> +  FILE_GUID                      = 900C3D64-E5EA-0F56-1F51-64D593F374D2
> +  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           = RISCV64
> +#
> +
> +[Sources]
> +  PlatformBm.c
> +  PlatformBm.h
> +
> +[Packages]
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +  SecurityPkg/SecurityPkg.dec
> +  ShellPkg/ShellPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  BaseMemoryLib
> +  BootLogoLib
> +  DebugLib
> +  DevicePathLib
> +  MemoryAllocationLib
> +  PcdLib
> +  PlatformBmPrintScLib
> +  ReportStatusCodeLib
> +  UefiBootManagerLib
> +  UefiBootServicesTableLib
> +  UefiLib
> +  UefiRuntimeServicesTableLib
> +
> +[FixedPcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
> +
> +[Pcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
> +
> +[Guids]
> +  gEfiEndOfDxeEventGroupGuid
> +  gEfiGlobalVariableGuid
> +  gRootBridgesConnectedEventGroupGuid
> +  gUefiShellFileGuid
> +  gEfiTtyTermGuid
> +
> +[Protocols]
> +  gEfiGenericMemTestProtocolGuid  ## CONSUMES
> +  gEfiGraphicsOutputProtocolGuid  ## CONSUMES
> +  gEfiPciRootBridgeIoProtocolGuid
> -- 
> 2.34.1
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#109800): https://edk2.groups.io/g/devel/message/109800
Mute This Topic: https://groups.io/mt/102053683/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  reply	other threads:[~2023-10-19 12:12 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-19  2:59 [edk2-devel] [PATCH v1 1/6] StarFive/JH7110Pkg: Add Pci controller driver John Chew
2023-10-19  2:59 ` [edk2-devel] [PATCH v1 2/6] StarFive/JH7110Pkg: Add SPI protocol and driver support John Chew
2023-10-19  2:59 ` [edk2-devel] [PATCH v1 3/6] StarFive/JH7110Pkg: Add firmware volume block protocol John Chew
2023-10-19  2:59 ` [edk2-devel] [PATCH v1 4/6] StarFive/JH7110Pkg: Add PlatformBootManagerLib library John Chew
2023-10-19 12:12   ` Sunil V L [this message]
2023-10-20  9:34     ` John Chew
2023-10-19  2:59 ` [edk2-devel] [PATCH v1 5/6] StarFive/JH7110Pkg: Implement boot services memory allocation driver John Chew
2023-10-19 12:14   ` Sunil V L
2023-10-20  8:45     ` John Chew
2023-10-19  2:59 ` [edk2-devel] [PATCH v1 6/6] StarFive/JH7110Pkg: Add JH7110 Silicon Package John Chew
2023-10-19 12:34   ` Sunil V L
2023-10-20  8:58     ` John Chew

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZTEdMEjZM0IDle6l@sunil-laptop \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox