Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

383 Commits   1 Branch   1 Tag
Index: radix-1.9/boot/edk2/orange-pi5/0.9.1.1/Makefile
===================================================================
--- radix-1.9/boot/edk2/orange-pi5/0.9.1.1/Makefile	(nonexistent)
+++ radix-1.9/boot/edk2/orange-pi5/0.9.1.1/Makefile	(revision 220)
@@ -0,0 +1,165 @@
+
+COMPONENT_TARGETS  = $(HARDWARE_ORANGE_PI5)
+
+NEED_ABS_PATH      = true
+
+COMPONENT_IS_3PP   = true
+
+
+include ../../../../build-system/constants.mk
+
+
+SOURCE_REQUIRES    = sources/U-Boot/OrangePi/edk2
+
+REQUIRES           = boot/u-boot/orange-pi5/2023.07
+
+# ======= __END_OF_REQUIRES__ =======
+
+
+version            = 0.9.1.1
+tar_xz_archive     = $(SRC_PACKAGE_PATH)/U-Boot/OrangePi/edk2/edk2-rk3588-$(version).tar.xz
+SRC_ARCHIVE        = $(tar_xz_archive)
+SRC_DIR            = $(TARGET_BUILD_DIR)/edk2-rk3588-$(version)
+src_done           = $(TARGET_BUILD_DIR)/.source_done
+
+PATCHES = PATCHES
+
+spi_flash_img           = $(HARDWARE).spi-flash.image
+spi_flash_image         = $(TARGET_BUILD_DIR)/$(spi_flash_img)
+install_spi_flash_image = $(TARGET_BUILD_DIR)/.spi_flash_image_done
+
+spi_flash_image_sum         = $(TARGET_BUILD_DIR)/$(HARDWARE).spi-flash.image.md5
+install_spi_flash_image_sum = $(TARGET_BUILD_DIR)/.spi_flash_image_sum_done
+
+
+####### Targets
+
+PKG_GROUP = boot
+
+EDK2_BIN_PKG_NAME                = edk2
+EDK2_BIN_PKG_VERSION             = 0.9.1.1
+EDK2_BIN_PKG_ARCH                = $(PKGARCH)
+EDK2_BIN_PKG_DISTRO_NAME         = $(DISTRO_NAME)
+EDK2_BIN_PKG_DISTRO_VERSION      = $(DISTRO_VERSION)
+EDK2_BIN_PKG_GROUP               = $(PKG_GROUP)
+###                               |---handy-ruler-------------------------------|
+EDK2_BIN_PKG_SHORT_DESCRIPTION   = EDK2 UEFI firmware
+EDK2_BIN_PKG_URL                 = $(BUG_URL)
+EDK2_BIN_PKG_LICENSE             = custom
+EDK2_BIN_PKG_DESCRIPTION_FILE    = $(TARGET_BUILD_DIR)/$(EDK2_BIN_PKG_NAME)-pkg-description
+EDK2_BIN_PKG_DESCRIPTION_FILE_IN = $(EDK2_BIN_PKG_NAME)-pkg-description.in
+EDK2_BIN_PKG_INSTALL_SCRIPT      = $(EDK2_BIN_PKG_NAME)-pkg-install.sh
+
+EDK2_BIN_PKG       = $(CURDIR)/$(TARGET_BUILD_DIR)/$(EDK2_BIN_PKG_NAME)-package
+
+build_edk2_pkg     = $(TARGET_BUILD_DIR)/.edk2_pkg_done
+
+pkg_basename       = $(EDK2_BIN_PKG_NAME)-$(EDK2_BIN_PKG_VERSION)-$(EDK2_BIN_PKG_ARCH)-$(EDK2_BIN_PKG_DISTRO_NAME)-$(EDK2_BIN_PKG_DISTRO_VERSION)
+
+pkg_archive        = $(TARGET_BUILD_DIR)/$(PKG_GROUP)/$(pkg_basename).$(pkg_arch_suffix)
+
+pkg_certificate    = $(call cert-name,$(pkg_archive))
+pkg_signature      = $(call sign-name,$(pkg_archive))
+pkg_description    = $(call desc-name,$(pkg_archive))
+products           = $(call pkg-files,$(pkg_archive))
+
+BUILD_TARGETS     += $(spi_flash_image)
+BUILD_TARGETS     += $(install_spi_flash_image)
+BUILD_TARGETS     += $(install_spi_flash_image_sum)
+BUILD_TARGETS     += $(build_edk2_pkg)
+
+PRODUCT_TARGETS    = $(products)
+
+ROOTFS_TARGETS     = $(pkg_archive)
+
+
+include ../../../../build-system/core.mk
+
+
+####### Dependencies
+
+$(src_done): $(SRC_ARCHIVE) $(PATCHES_DEP)
+	$(UNPACK_SRC_ARCHIVE)
+	$(APPLY_PATCHES)
+	@touch $@
+
+$(spi_flash_image): $(src_done)
+	@( cd $(SRC_DIR) ; \
+	   PKG_CONFIG_PATH= \
+	   CROSS_COMPILE='$(CROSS_PREFIX)' \
+	   ./build.sh --device orangepi-5 --skip-rootfs-gen ; \
+	   cp RK3588_NOR_FLASH.img ../$(spi_flash_img) ; \
+	 )
+	@touch $@
+
+$(install_spi_flash_image): $(spi_flash_image)
+	@$(BUILDSYSTEM)/install_targets         \
+	   --destination=$(PRODUCTS_DEST_DIR)   \
+	   --toolchain=$(TOOLCHAIN)             \
+	   --hardware=$(HARDWARE)               \
+	   --flavour=$(FLAVOUR)                 \
+	   $^
+	@touch $@
+
+$(spi_flash_image_sum): $(spi_flash_image)
+	@( cd $(TARGET_BUILD_DIR) ; \
+	   md5sum -b $(HARDWARE).spi-flash.image > $(HARDWARE).spi-flash.image.md5 ; \
+	 )
+	@touch $@
+
+$(install_spi_flash_image_sum): $(spi_flash_image_sum)
+	@$(BUILDSYSTEM)/install_targets         \
+	   --destination=$(PRODUCTS_DEST_DIR)   \
+	   --toolchain=$(TOOLCHAIN)             \
+	   --hardware=$(HARDWARE)               \
+	   --flavour=$(FLAVOUR)                 \
+	   $^
+	@touch $@
+
+$(build_edk2_pkg): $(install_spi_flash_image_sum)
+	@mkdir -p $(TARGET_DEST_DIR)/bootfs/edk2
+	@mkdir -p $(EDK2_BIN_PKG)/boot/edk2
+	# ======= install EDK2 image =======
+	@cp -a $(spi_flash_image) $(spi_flash_image_sum)  $(TARGET_DEST_DIR)/bootfs/edk2/
+	@cp -a $(spi_flash_image)  $(EDK2_BIN_PKG)/boot/edk2/spi-flash.image
+	@( cd $(EDK2_BIN_PKG)/boot/edk2/ ; \
+	   md5sum -b spi-flash.image > spi-flash.image.md5 ; \
+	 )
+	# ======= install Documentation =======
+	@mkdir -p $(EDK2_BIN_PKG)/usr/doc/edk2-$(EDK2_BIN_PKG_VERSION)
+	@mkdir -p $(EDK2_BIN_PKG)/usr/share/doc/edk2-$(EDK2_BIN_PKG_VERSION)
+	@( cd $(SRC_DIR)/edk2 ; \
+	   cat License.txt | tr -d '\r' \
+	       > $(EDK2_BIN_PKG)/usr/doc/edk2-$(EDK2_BIN_PKG_VERSION)/LICENSE ; \
+	   cat License.txt | tr -d '\r' \
+	       > $(EDK2_BIN_PKG)/usr/share/doc/edk2-$(EDK2_BIN_PKG_VERSION)/LICENSE ; \
+	 )
+	@cp -a $(SRC_DIR)/README.md \
+	       $(EDK2_BIN_PKG)/usr/share/doc/edk2-$(EDK2_BIN_PKG_VERSION)
+	@touch $@
+
+$(EDK2_BIN_PKG_DESCRIPTION_FILE): $(EDK2_BIN_PKG_DESCRIPTION_FILE_IN)
+	@cat $< | $(SED) -e "s/@VERSION@/$(EDK2_BIN_PKG_VERSION)/g" | \
+	          $(SED) -e "s/@HARDWARE_SPEC@/$(HW_SPEC)/g"> $@
+
+$(pkg_certificate) : $(pkg_archive) ;
+$(pkg_signature)   : $(pkg_archive) ;
+$(pkg_description) : $(pkg_archive) ;
+
+$(pkg_archive): $(build_edk2_pkg) $(EDK2_BIN_PKG_DESCRIPTION_FILE) $(EDK2_BIN_PKG_INSTALL_SCRIPT)
+	@cp $(EDK2_BIN_PKG_DESCRIPTION_FILE) $(EDK2_BIN_PKG)/.DESCRIPTION
+	@cp $(EDK2_BIN_PKG_INSTALL_SCRIPT) $(EDK2_BIN_PKG)/.INSTALL
+	@chmod a+x $(EDK2_BIN_PKG)/.INSTALL
+	@$(BUILD_PKG_REQUIRES) $(EDK2_BIN_PKG)/.REQUIRES
+	@echo "pkgname=$(EDK2_BIN_PKG_NAME)"                            >  $(EDK2_BIN_PKG)/.PKGINFO ; \
+	 echo "pkgver=$(EDK2_BIN_PKG_VERSION)"                          >> $(EDK2_BIN_PKG)/.PKGINFO ; \
+	 echo "arch=$(EDK2_BIN_PKG_ARCH)"                               >> $(EDK2_BIN_PKG)/.PKGINFO ; \
+	 echo "distroname=$(EDK2_BIN_PKG_DISTRO_NAME)"                  >> $(EDK2_BIN_PKG)/.PKGINFO ; \
+	 echo "distrover=$(EDK2_BIN_PKG_DISTRO_VERSION)"                >> $(EDK2_BIN_PKG)/.PKGINFO ; \
+	 echo "group=$(EDK2_BIN_PKG_GROUP)"                             >> $(EDK2_BIN_PKG)/.PKGINFO ; \
+	 echo "short_description=\"$(EDK2_BIN_PKG_SHORT_DESCRIPTION)\"" >> $(EDK2_BIN_PKG)/.PKGINFO ; \
+	 echo "url=$(EDK2_BIN_PKG_URL)"                                 >> $(EDK2_BIN_PKG)/.PKGINFO ; \
+	 echo "license=$(EDK2_BIN_PKG_LICENSE)"                         >> $(EDK2_BIN_PKG)/.PKGINFO
+	@$(PSEUDO) sh -c "cd $(EDK2_BIN_PKG) && \
+	                  chown -R root:root . && \
+	                  $(MAKE_PACKAGE) -J --linkadd=yes $(GNUPG_OPTIONS) -m -d .. ."
Index: radix-1.9/boot/edk2/orange-pi5/0.9.1.1/PATCHES
===================================================================
--- radix-1.9/boot/edk2/orange-pi5/0.9.1.1/PATCHES	(nonexistent)
+++ radix-1.9/boot/edk2/orange-pi5/0.9.1.1/PATCHES	(revision 220)
@@ -0,0 +1,2 @@
+
+../../../../sources/U-Boot/OrangePi/edk2/patches/edk2-rk3588-0.9.1.1-f2.patch -p0
Index: radix-1.9/boot/edk2/orange-pi5/0.9.1.1/edk2-pkg-description.in
===================================================================
--- radix-1.9/boot/edk2/orange-pi5/0.9.1.1/edk2-pkg-description.in	(nonexistent)
+++ radix-1.9/boot/edk2/orange-pi5/0.9.1.1/edk2-pkg-description.in	(revision 220)
@@ -0,0 +1,19 @@
+# HOW TO EDIT THIS FILE:
+# The "handy ruler" below makes it easier to edit a package description.  Line
+# up the first '|' above the ':' following the base package name, and the '|'
+# on the right side marks the last column you can put a character in.  You must
+# make exactly 11 lines for the formatting to be correct.  It's also
+# customary to leave one space after the ':'.
+
+    |-----handy-ruler------------------------------------------------------|
+edk2: EDK2 UEFI firmware @VERSION@ (for @HARDWARE_SPEC@ board)
+edk2:
+edk2: TianoCore is the open source implementation of the Unified
+edk2: Extensible Firmware Interface (UEFI). EDK II is a modern,
+edk2: feature-rich, cross-platform firmware development environment
+edk2: for the UEFI and UEFI Platform Initialization (PI) specifications.
+edk2:
+edk2: This package contains the firmware for Rockchip RK3588 platforms.
+edk2:
+edk2: GitHub: https://github.com/edk2-porting/edk2-rk3588
+edk2:
Index: radix-1.9/boot/edk2/orange-pi5/0.9.1.1/edk2-pkg-install.sh
===================================================================
--- radix-1.9/boot/edk2/orange-pi5/0.9.1.1/edk2-pkg-install.sh	(nonexistent)
+++ radix-1.9/boot/edk2/orange-pi5/0.9.1.1/edk2-pkg-install.sh	(revision 220)
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# Preserve new files
+install_file() {
+  NEW="$1"
+  OLD="`dirname $NEW`/`basename $NEW .new`"
+  # If there's no file by that name, mv it over:
+  if [ ! -r $OLD ]; then
+    mv $NEW $OLD
+  elif [ "`cat $OLD | md5sum`" = "`cat $NEW | md5sum`" ]; then
+    # toss the redundant copy:
+    rm $NEW
+  fi
+  # Otherwise, we leave the .new copy for the admin to consider...
+}
+
+
+# arg 1:  the new package version
+pre_install() {
+  /bin/true
+}
+
+# arg 1:  the new package version
+post_install() {
+  /bin/true
+}
+
+# arg 1:  the new package version
+# arg 2:  the old package version
+pre_update() {
+  /bin/true
+}
+
+# arg 1:  the new package version
+# arg 2:  the old package version
+post_update() {
+  post_install
+}
+
+# arg 1:  the old package version
+pre_remove() {
+  /bin/true
+}
+
+# arg 1:  the old package version
+post_remove() {
+  /bin/true
+}
+
+
+operation=$1
+shift
+
+$operation $*

Property changes on: radix-1.9/boot/edk2/orange-pi5/0.9.1.1/edk2-pkg-install.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: radix-1.9/boot/edk2/orange-pi5/0.9.1.1
===================================================================
--- radix-1.9/boot/edk2/orange-pi5/0.9.1.1	(nonexistent)
+++ radix-1.9/boot/edk2/orange-pi5/0.9.1.1	(revision 220)

Property changes on: radix-1.9/boot/edk2/orange-pi5/0.9.1.1
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,74 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.rk358x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: radix-1.9/products/base/Makefile
===================================================================
--- radix-1.9/products/base/Makefile	(revision 219)
+++ radix-1.9/products/base/Makefile	(revision 220)
@@ -74,6 +74,7 @@
 ifneq ($(filter $(HARDWARE),$(HARDWARE_ORANGE_PI5)),)
 REQUIRES  = boot/kernel/orange-pi5/5.10.110
 REQUIRES += boot/u-boot/orange-pi5/2023.07
+REQUIRES += boot/edk2/orange-pi5/0.9.1.1
 endif
 
 ifneq ($(filter $(HARDWARE),$(HARDWARE_VISIONFIVE2)),)
Index: radix-1.9/sources/U-Boot/OrangePi/Makefile
===================================================================
--- radix-1.9/sources/U-Boot/OrangePi/Makefile	(nonexistent)
+++ radix-1.9/sources/U-Boot/OrangePi/Makefile	(revision 220)
@@ -0,0 +1,13 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+SOURCE_REQUIRES += ALL_DIRS
+
+
+include ../../../build-system/core.mk
+
+
+download_clean:
+	@true
+
+.PHONY: download_clean
Index: radix-1.9/sources/U-Boot/OrangePi/edk2/Makefile
===================================================================
--- radix-1.9/sources/U-Boot/OrangePi/edk2/Makefile	(nonexistent)
+++ radix-1.9/sources/U-Boot/OrangePi/edk2/Makefile	(revision 220)
@@ -0,0 +1,54 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/U-Boot/OrangePi/edk2
+
+versions    = 0.9.1.1
+
+tarballs    = $(addsuffix .tar.xz, $(addprefix edk2-rk3588-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+patches     = $(CURDIR)/patches/edk2-rk3588-0.9.1.1-f2.patch
+
+.NOTPARALLEL: $(patches)
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s) $(patches)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+$(patches): $(sha1s)
+	@echo -e "\n======= Create Patches =======\n" ; \
+	 ( cd create-0.9.1.1-f2-patch ; ./create.patch.sh ) ; \
+	 echo -e "\n"
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s) $(patches)
Index: radix-1.9/sources/U-Boot/OrangePi/edk2/create-0.9.1.1-f2-patch/create.patch.sh
===================================================================
--- radix-1.9/sources/U-Boot/OrangePi/edk2/create-0.9.1.1-f2-patch/create.patch.sh	(nonexistent)
+++ radix-1.9/sources/U-Boot/OrangePi/edk2/create-0.9.1.1-f2-patch/create.patch.sh	(revision 220)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=0.9.1.1
+
+tar --files-from=file.list -xJvf ../edk2-rk3588-$VERSION.tar.xz
+mv edk2-rk3588-$VERSION edk2-rk3588-$VERSION-orig
+
+cp -rf ./edk2-rk3588-$VERSION-new ./edk2-rk3588-$VERSION
+
+diff --unified -Nr  edk2-rk3588-$VERSION-orig  edk2-rk3588-$VERSION > edk2-rk3588-$VERSION-f2.patch
+
+mv edk2-rk3588-$VERSION-f2.patch ../patches
+
+rm -rf ./edk2-rk3588-$VERSION
+rm -rf ./edk2-rk3588-$VERSION-orig

Property changes on: radix-1.9/sources/U-Boot/OrangePi/edk2/create-0.9.1.1-f2-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: radix-1.9/sources/U-Boot/OrangePi/edk2/create-0.9.1.1-f2-patch/edk2-rk3588-0.9.1.1-new/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBm.c
===================================================================
--- radix-1.9/sources/U-Boot/OrangePi/edk2/create-0.9.1.1-f2-patch/edk2-rk3588-0.9.1.1-new/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBm.c	(nonexistent)
+++ radix-1.9/sources/U-Boot/OrangePi/edk2/create-0.9.1.1-f2-patch/edk2-rk3588-0.9.1.1-new/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBm.c	(revision 220)
@@ -0,0 +1,1321 @@
+/** @file
+  Implementation for PlatformBootManagerLib library class interfaces.
+
+  Copyright (C) 2015-2016, Red Hat, Inc.
+  Copyright (c) 2014 - 2021, ARM Ltd. All rights reserved.<BR>
+  Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
+  Copyright (c) 2021, Semihalf All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/Pci22.h>
+#include <Library/BootLogoLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/RkAtagsLib.h>
+#include <Protocol/BootManagerPolicy.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/EsrtManagement.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/NonDiscoverableDevice.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PlatformBootManager.h>
+#include <Guid/BootDiscoveryPolicy.h>
+#include <Guid/EventGroup.h>
+#include <Guid/NonDiscoverableDevice.h>
+#include <Guid/TtyTerm.h>
+#include <Guid/SerialPortLibVendor.h>
+#include <Protocol/FirmwareVolume2.h>
+
+#include "PlatformBm.h"
+
+#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 ()
+
+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",
+      __FUNCTION__,
+      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", __FUNCTION__, ReportText, Status));
+    return FALSE;
+  }
+
+  return IS_PCI_DISPLAY (&Pci);
+}
+
+/**
+  This FILTER_FUNCTION checks if a handle corresponds to a non-discoverable
+  USB host controller.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+IsUsbHost (
+  IN EFI_HANDLE    Handle,
+  IN CONST CHAR16  *ReportText
+  )
+{
+  NON_DISCOVERABLE_DEVICE  *Device;
+  EFI_STATUS               Status;
+
+  Status = gBS->HandleProtocol (
+                  Handle,
+                  &gEdkiiNonDiscoverableDeviceProtocolGuid,
+                  (VOID **)&Device
+                  );
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  }
+
+  if (CompareGuid (Device->Type, &gEdkiiNonDiscoverableUhciDeviceGuid) ||
+      CompareGuid (Device->Type, &gEdkiiNonDiscoverableEhciDeviceGuid) ||
+      CompareGuid (Device->Type, &gEdkiiNonDiscoverableXhciDeviceGuid))
+  {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  This FILTER_FUNCTION checks if the Block I/O protocol handle
+  corresponds to that of the boot SD/eMMC device.
+
+  This code is almost identical to FvbCheckIsBootDevice from RkFvbDxe.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+IsSdBootBlockIo (
+  IN EFI_HANDLE    Handle,
+  IN CONST CHAR16  *ReportText
+  )
+{
+  EFI_STATUS                          Status;
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
+  EFI_HANDLE                          DeviceHandle;
+  NON_DISCOVERABLE_DEVICE             *Device;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Descriptor;
+  RKATAG_BOOTDEV                      *BootDevice;
+
+  BootDevice = RkAtagsGetBootDev ();
+  if (BootDevice == NULL) {
+    return FALSE;
+  }
+
+  DevicePath = DevicePathFromHandle (Handle);
+
+  if (DevicePath->Type != HARDWARE_DEVICE_PATH
+      || DevicePath->SubType != HW_VENDOR_DP) {
+    return FALSE;
+  }
+
+  Status = gBS->LocateDevicePath (&gEdkiiNonDiscoverableDeviceProtocolGuid,
+                   &DevicePath, &DeviceHandle);
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  }
+
+  Status = gBS->HandleProtocol (DeviceHandle,
+                   &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **) &Device);
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  }
+
+  Descriptor = &Device->Resources[0];
+
+  if (Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR ||
+      Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
+    return FALSE;
+  }
+
+  if (BootDevice->DevType == RkAtagBootDevTypeEmmc) {
+    return Descriptor->AddrRangeMin == PcdGet32 (PcdDwcSdhciBaseAddress);
+  }
+  if (BootDevice->DevType == RkAtagBootDevTypeSd0) {
+    return Descriptor->AddrRangeMin == PcdGet32 (PcdRkSdmmcBaseAddress);
+  }
+
+  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",
+    __FUNCTION__,
+    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",
+      __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
+VOID
+PlatformRegisterFvBootOption (
+  CONST EFI_GUID  *FileGuid,
+  CHAR16          *Description,
+  UINT32          Attributes,
+  EFI_INPUT_KEY   *Key
+  )
+{
+  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);
+    Status = EfiBootManagerAddKeyOptionVariable (
+               NULL,
+               (UINT16)NewOption.OptionNumber,
+               0,
+               Key,
+               NULL
+               );
+    ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
+  }
+
+  EfiBootManagerFreeLoadOption (&NewOption);
+  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+STATIC
+VOID
+GetPlatformOptions (
+  VOID
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_BOOT_MANAGER_LOAD_OPTION    *CurrentBootOptions;
+  EFI_BOOT_MANAGER_LOAD_OPTION    *BootOptions;
+  EFI_INPUT_KEY                   *BootKeys;
+  PLATFORM_BOOT_MANAGER_PROTOCOL  *PlatformBootManager;
+  UINTN                           CurrentBootOptionCount;
+  UINTN                           Index;
+  UINTN                           BootCount;
+
+  Status = gBS->LocateProtocol (
+                  &gPlatformBootManagerProtocolGuid,
+                  NULL,
+                  (VOID **)&PlatformBootManager
+                  );
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  Status = PlatformBootManager->GetPlatformBootOptionsAndKeys (
+                                  &BootCount,
+                                  &BootOptions,
+                                  &BootKeys
+                                  );
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  //
+  // Fetch the existent boot options. If there are none, CurrentBootCount
+  // will be zeroed.
+  //
+  CurrentBootOptions = EfiBootManagerGetLoadOptions (
+                         &CurrentBootOptionCount,
+                         LoadOptionTypeBoot
+                         );
+  //
+  // Process the platform boot options.
+  //
+  for (Index = 0; Index < BootCount; Index++) {
+    INTN   Match;
+    UINTN  BootOptionNumber;
+
+    //
+    // If there are any preexistent boot options, and the subject platform boot
+    // option is already among them, then don't try to add it. Just get its
+    // assigned boot option number so we can associate a hotkey with it. Note
+    // that EfiBootManagerFindLoadOption() deals fine with (CurrentBootOptions
+    // == NULL) if (CurrentBootCount == 0).
+    //
+    Match = EfiBootManagerFindLoadOption (
+              &BootOptions[Index],
+              CurrentBootOptions,
+              CurrentBootOptionCount
+              );
+    if (Match >= 0) {
+      BootOptionNumber = CurrentBootOptions[Match].OptionNumber;
+    } else {
+      //
+      // Add the platform boot options as a new one, at the end of the boot
+      // order. Note that if the platform provided this boot option with an
+      // unassigned option number, then the below function call will assign a
+      // number.
+      //
+      Status = EfiBootManagerAddLoadOptionVariable (
+                 &BootOptions[Index],
+                 MAX_UINTN
+                 );
+      if (EFI_ERROR (Status)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "%a: failed to register \"%s\": %r\n",
+          __FUNCTION__,
+          BootOptions[Index].Description,
+          Status
+          ));
+        continue;
+      }
+
+      BootOptionNumber = BootOptions[Index].OptionNumber;
+    }
+
+    //
+    // Register a hotkey with the boot option, if requested.
+    //
+    if (BootKeys[Index].UnicodeChar == L'\0') {
+      continue;
+    }
+
+    Status = EfiBootManagerAddKeyOptionVariable (
+               NULL,
+               BootOptionNumber,
+               0,
+               &BootKeys[Index],
+               NULL
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "%a: failed to register hotkey for \"%s\": %r\n",
+        __FUNCTION__,
+        BootOptions[Index].Description,
+        Status
+        ));
+    }
+  }
+
+  EfiBootManagerFreeLoadOptions (CurrentBootOptions, CurrentBootOptionCount);
+  EfiBootManagerFreeLoadOptions (BootOptions, BootCount);
+  FreePool (BootKeys);
+}
+
+/**
+  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:
+  - DXEFV's base address or size changed (historical),
+  - DXEFV'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.
+**/
+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 (
+      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",
+        __FUNCTION__,
+        (UINT32)BootOptions[Index].OptionNumber,
+        DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
+        Status
+        ));
+      if (DevicePathString != NULL) {
+        FreePool (DevicePathString);
+      }
+      );
+  }
+
+  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;
+
+  GetPlatformOptions ();
+
+  //
+  // 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
+  )
+{
+  //
+  // 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);
+
+  //
+  // 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);
+
+  //
+  // The core BDS code connects short-form USB device paths by explicitly
+  // looking for handles with PCI I/O installed, and checking the PCI class
+  // code whether it matches the one for a USB host controller. This means
+  // non-discoverable USB host controllers need to have the non-discoverable
+  // PCI driver attached first.
+  //
+  FilterAndProcess (&gEdkiiNonDiscoverableDeviceProtocolGuid, IsUsbHost, Connect);
+
+  //
+  // Connect USB OHCI controller(s)
+  //
+  FilterAndProcess (&gOhciDeviceProtocolGuid, NULL, Connect);
+
+  //
+  // Connect the Block I/O device produced by the SD/eMMC device that
+  // booted UEFI. We don't want BDS to ignore this device as it would
+  // prevent RkFvbDxe from detecting it and dumping the NVRAM variables
+  // in time.
+  //
+  FilterAndProcess (&gEfiBlockIoProtocolGuid, IsSdBootBlockIo, Connect);
+
+  //
+  // 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.
+  //
+  STATIC_ASSERT (
+    FixedPcdGet8 (PcdDefaultTerminalType) == 4,
+    "PcdDefaultTerminalType must be TTYTERM"
+    );
+  STATIC_ASSERT (
+    FixedPcdGet8 (PcdUartDefaultParity) != 0,
+    "PcdUartDefaultParity must be set to an actual value, not 'default'"
+    );
+  STATIC_ASSERT (
+    FixedPcdGet8 (PcdUartDefaultStopBits) != 0,
+    "PcdUartDefaultStopBits must be set to an actual value, not 'default'"
+    );
+
+  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
+    );
+
+  //
+  // Register platform-specific boot options and keyboard shortcuts.
+  //
+  PlatformRegisterOptionsAndKeys ();
+}
+
+STATIC
+VOID
+HandleCapsules (
+  VOID
+  )
+{
+  ESRT_MANAGEMENT_PROTOCOL  *EsrtManagement;
+  EFI_PEI_HOB_POINTERS      HobPointer;
+  EFI_CAPSULE_HEADER        *CapsuleHeader;
+  BOOLEAN                   NeedReset;
+  EFI_STATUS                Status;
+
+  DEBUG ((DEBUG_INFO, "%a: processing capsules ...\n", __FUNCTION__));
+
+  Status = gBS->LocateProtocol (
+                  &gEsrtManagementProtocolGuid,
+                  NULL,
+                  (VOID **)&EsrtManagement
+                  );
+  if (!EFI_ERROR (Status)) {
+    EsrtManagement->SyncEsrtFmp ();
+  }
+
+  //
+  // Find all capsule images from hob
+  //
+  HobPointer.Raw = GetHobList ();
+  NeedReset      = FALSE;
+  while ((HobPointer.Raw = GetNextHob (
+                             EFI_HOB_TYPE_UEFI_CAPSULE,
+                             HobPointer.Raw
+                             )) != NULL)
+  {
+    CapsuleHeader = (VOID *)(UINTN)HobPointer.Capsule->BaseAddress;
+
+    Status = ProcessCapsuleImage (CapsuleHeader);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "%a: failed to process capsule %p - %r\n",
+        __FUNCTION__,
+        CapsuleHeader,
+        Status
+        ));
+      return;
+    }
+
+    NeedReset      = TRUE;
+    HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+  }
+
+  if (NeedReset) {
+    DEBUG ((
+      DEBUG_WARN,
+      "%a: capsule update successful, resetting ...\n",
+      __FUNCTION__
+      ));
+
+    gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+    CpuDeadLoop ();
+  }
+}
+
+#define VERSION_STRING_PREFIX  L"Tianocore/EDK2 firmware version "
+
+/**
+  This functions checks the value of BootDiscoverPolicy variable and
+  connect devices of class specified by that variable. Then it refreshes
+  Boot order for newly discovered boot device.
+
+  @retval  EFI_SUCCESS  Devices connected successfully or connection
+                        not required.
+  @retval  others       Return values from GetVariable(), LocateProtocol()
+                        and ConnectDeviceClass().
+**/
+STATIC
+EFI_STATUS
+BootDiscoveryPolicyHandler (
+  VOID
+  )
+{
+  EFI_STATUS                        Status;
+  UINT32                            DiscoveryPolicy;
+  UINT32                            DiscoveryPolicyOld;
+  UINTN                             Size;
+  EFI_BOOT_MANAGER_POLICY_PROTOCOL  *BMPolicy;
+  EFI_GUID                          *Class;
+
+  Size   = sizeof (DiscoveryPolicy);
+  Status = gRT->GetVariable (
+                  BOOT_DISCOVERY_POLICY_VAR,
+                  &gBootDiscoveryPolicyMgrFormsetGuid,
+                  NULL,
+                  &Size,
+                  &DiscoveryPolicy
+                  );
+  if (Status == EFI_NOT_FOUND) {
+    DiscoveryPolicy = PcdGet32 (PcdBootDiscoveryPolicy);
+    Status          = PcdSet32S (PcdBootDiscoveryPolicy, DiscoveryPolicy);
+    if (Status == EFI_NOT_FOUND) {
+      return EFI_SUCCESS;
+    } else if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  } else if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (DiscoveryPolicy == BDP_CONNECT_MINIMAL) {
+    return EFI_SUCCESS;
+  }
+
+  switch (DiscoveryPolicy) {
+    case BDP_CONNECT_NET:
+      Class = &gEfiBootManagerPolicyNetworkGuid;
+      break;
+    case BDP_CONNECT_ALL:
+      Class = &gEfiBootManagerPolicyConnectAllGuid;
+      break;
+    default:
+      DEBUG ((
+        DEBUG_INFO,
+        "%a - Unexpected DiscoveryPolicy (0x%x). Run Minimal Discovery Policy\n",
+        __FUNCTION__,
+        DiscoveryPolicy
+        ));
+      return EFI_SUCCESS;
+  }
+
+  Status = gBS->LocateProtocol (
+                  &gEfiBootManagerPolicyProtocolGuid,
+                  NULL,
+                  (VOID **)&BMPolicy
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_INFO,
+      "%a - Failed to locate gEfiBootManagerPolicyProtocolGuid."
+      "Driver connect will be skipped.\n",
+      __FUNCTION__
+      ));
+    return Status;
+  }
+
+  Status = BMPolicy->ConnectDeviceClass (BMPolicy, Class);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a - ConnectDeviceClass returns - %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  //
+  // Refresh Boot Options if Boot Discovery Policy has been changed
+  //
+  Size   = sizeof (DiscoveryPolicyOld);
+  Status = gRT->GetVariable (
+                  BOOT_DISCOVERY_POLICY_OLD_VAR,
+                  &gBootDiscoveryPolicyMgrFormsetGuid,
+                  NULL,
+                  &Size,
+                  &DiscoveryPolicyOld
+                  );
+  if ((Status == EFI_NOT_FOUND) || (DiscoveryPolicyOld != DiscoveryPolicy)) {
+    EfiBootManagerRefreshAllBootOption ();
+
+    Status = gRT->SetVariable (
+                    BOOT_DISCOVERY_POLICY_OLD_VAR,
+                    &gBootDiscoveryPolicyMgrFormsetGuid,
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                    sizeof (DiscoveryPolicyOld),
+                    &DiscoveryPolicy
+                    );
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  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
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;
+  UINTN                         FirmwareVerLength;
+  UINTN                         PosX;
+  UINTN                         PosY;
+  EFI_INPUT_KEY                 Key;
+
+  EfiEventGroupSignal (&gRockchipEventPlatformBmAfterConsoleGuid);
+
+  FirmwareVerLength = StrLen (PcdGetPtr (PcdFirmwareVersionString));
+
+  //
+  // Show the splash screen.
+  //
+  Status = BootLogoEnableLogo ();
+  if (EFI_ERROR (Status)) {
+    if (FirmwareVerLength > 0) {
+      Print (
+        VERSION_STRING_PREFIX L"%s\n",
+        PcdGetPtr (PcdFirmwareVersionString)
+        );
+    }
+    Print (L"Press F2 for boot options");
+  } else if (FirmwareVerLength > 0) {
+    Status = gBS->HandleProtocol (
+                    gST->ConsoleOutHandle,
+                    &gEfiGraphicsOutputProtocolGuid,
+                    (VOID **)&GraphicsOutput
+                    );
+    if (!EFI_ERROR (Status)) {
+      PosX = (GraphicsOutput->Mode->Info->HorizontalResolution -
+              (StrLen (VERSION_STRING_PREFIX) + FirmwareVerLength) *
+              EFI_GLYPH_WIDTH) / 2;
+      PosY = 0;
+
+      PrintXY (
+        PosX,
+        PosY,
+        NULL,
+        NULL,
+        VERSION_STRING_PREFIX L"%s",
+        PcdGetPtr (PcdFirmwareVersionString)
+        );
+    }
+  }
+
+  //
+  // Connect device specified by BootDiscoverPolicy variable and
+  // refresh Boot order for newly discovered boot devices
+  //
+  BootDiscoveryPolicyHandler ();
+
+  //
+  // On ARM, there is currently no reason to use the phased capsule
+  // update approach where some capsules are dispatched before EndOfDxe
+  // and some are dispatched after. So just handle all capsules here,
+  // when the console is up and we can actually give the user some
+  // feedback about what is going on.
+  //
+  HandleCapsules ();
+
+  //
+  // Register UEFI Shell
+  //
+  Key.ScanCode    = SCAN_NULL;
+  Key.UnicodeChar = L's';
+  PlatformRegisterFvBootOption (&gUefiShellFileGuid, L"UEFI Shell", 0, &Key);
+
+  RemoveStaleFvFileOptions ();
+}
+
+/**
+  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                               Timeout;
+  EFI_STATUS                           Status;
+
+  Timeout = PcdGet16 (PcdPlatformBootTimeOut);
+
+  Black.Raw = 0x00000000;
+  White.Raw = 0x00FFFFFF;
+
+  Status = BootLogoUpdateProgress (
+             White.Pixel,
+             Black.Pixel,
+             L"Press F2 for boot options",
+             White.Pixel,
+             (Timeout - TimeoutRemain) * 100 / Timeout,
+             0
+             );
+  if (EFI_ERROR (Status)) {
+    Print (L".");
+  }
+}
+
+/**
+  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_BOOT_MANAGER_LOAD_OPTION  BootManagerMenu;
+  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions;
+  UINTN                         OldBootOptionCount;
+  UINTN                         NewBootOptionCount;
+
+  //
+  // Record the total number of boot configured boot options
+  //
+  BootOptions = EfiBootManagerGetLoadOptions (
+                  &OldBootOptionCount,
+                  LoadOptionTypeBoot
+                  );
+  EfiBootManagerFreeLoadOptions (BootOptions, OldBootOptionCount);
+
+  //
+  // Connect all devices, and regenerate all boot options
+  //
+  EfiBootManagerConnectAll ();
+  EfiBootManagerRefreshAllBootOption ();
+
+  //
+  // Record the updated number of boot configured boot options
+  //
+  BootOptions = EfiBootManagerGetLoadOptions (
+                  &NewBootOptionCount,
+                  LoadOptionTypeBoot
+                  );
+  EfiBootManagerFreeLoadOptions (BootOptions, NewBootOptionCount);
+
+  //
+  // If the number of configured boot options has changed, reboot
+  // the system so the new boot options will be taken into account
+  // while executing the ordinary BDS bootflow sequence.
+  // *Unless* persistent varstore is being emulated, since we would
+  // then end up in an endless reboot loop.
+  //
+  if (!PcdGetBool (PcdEmuVariableNvModeEnable)) {
+    if (NewBootOptionCount != OldBootOptionCount) {
+      DEBUG ((
+        DEBUG_WARN,
+        "%a: rebooting after refreshing all boot options\n",
+        __FUNCTION__
+        ));
+      gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+    }
+  }
+
+  Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  for ( ; ;) {
+    EfiBootManagerBoot (&BootManagerMenu);
+  }
+}
Index: radix-1.9/sources/U-Boot/OrangePi/edk2/create-0.9.1.1-f2-patch/file.list
===================================================================
--- radix-1.9/sources/U-Boot/OrangePi/edk2/create-0.9.1.1-f2-patch/file.list	(nonexistent)
+++ radix-1.9/sources/U-Boot/OrangePi/edk2/create-0.9.1.1-f2-patch/file.list	(revision 220)
@@ -0,0 +1 @@
+edk2-rk3588-0.9.1.1/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBm.c
Index: radix-1.9/sources/U-Boot/OrangePi/edk2/patches/README
===================================================================
--- radix-1.9/sources/U-Boot/OrangePi/edk2/patches/README	(nonexistent)
+++ radix-1.9/sources/U-Boot/OrangePi/edk2/patches/README	(revision 220)
@@ -0,0 +1,6 @@
+
+/* begin *
+
+   TODO: Leave some comment here.
+
+ * end */
Index: radix-1.9/sources/U-Boot/OrangePi/edk2/patches
===================================================================
--- radix-1.9/sources/U-Boot/OrangePi/edk2/patches	(nonexistent)
+++ radix-1.9/sources/U-Boot/OrangePi/edk2/patches	(revision 220)

Property changes on: radix-1.9/sources/U-Boot/OrangePi/edk2/patches
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,74 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.rk358x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: radix-1.9/sources/U-Boot/OrangePi/edk2
===================================================================
--- radix-1.9/sources/U-Boot/OrangePi/edk2	(nonexistent)
+++ radix-1.9/sources/U-Boot/OrangePi/edk2	(revision 220)

Property changes on: radix-1.9/sources/U-Boot/OrangePi/edk2
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,74 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.rk358x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: radix-1.9/sources/U-Boot/OrangePi
===================================================================
--- radix-1.9/sources/U-Boot/OrangePi	(nonexistent)
+++ radix-1.9/sources/U-Boot/OrangePi	(revision 220)

Property changes on: radix-1.9/sources/U-Boot/OrangePi
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,74 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.rk358x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~