diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree.fdf.inc b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree.fdf.inc
new file mode 100644
index 00000000000..dae829db513
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree.fdf.inc
@@ -0,0 +1,35 @@
+## @file
+# FDF include file with Layout Regions that define an empty variable store.
+#
+# Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+$(DTB_OFFSET)|$(DTB_SIZE)
+gUefiRiscVPlatformPkgTokenSpaceGuid.PcdRiscVDtbFvBase|gUefiRiscVPlatformPkgTokenSpaceGuid.PcdRiscVDtbFvSize
+FV = DTBFV
+
+[FV.DTBFV]
+BlockSize = 0x1000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+INF RuleOverride = DTB Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/U740DeviceTree.inf
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/U740DeviceTree.inf b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/U740DeviceTree.inf
new file mode 100644
index 00000000000..71cd467a539
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/U740DeviceTree.inf
@@ -0,0 +1,25 @@
+## @file
+#
+# Device tree description of the Hifive Unleashed platform
+#
+# Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = U740DeviceTree
+ FILE_GUID = 0FFA746F-9B5D-48F7-A561-E47D555C5E3E
+ MODULE_TYPE = USER_DEFINED
+ VERSION_STRING = 1.0
+
+[Sources]
+ gpio.h
+ hifive-unleashed-a00.dts
+ fu540-c000.dtsi
+ sifive-fu540-prci.h
+
+[Packages]
+ MdePkg/MdePkg.dec
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/fu540-c000.dtsi b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/fu540-c000.dtsi
new file mode 100644
index 00000000000..b4fc06b25ba
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/fu540-c000.dtsi
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2018-2019 SiFive, Inc */
+
+/dts-v1/;
+
+/**@file
+ SiFive U540 platform Device Tree
+
+ Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "sifive-fu540-prci.h"
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "sifive,fu540-c000", "sifive,fu540";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ ethernet0 = ð0;
+ };
+
+ chosen {
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu0: cpu@0 {
+ compatible = "sifive,e51", "sifive,rocket0", "riscv";
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <128>;
+ i-cache-size = <16384>;
+ reg = <0>;
+ riscv,isa = "rv64imac";
+ status = "disabled";
+ cpu0_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
+ cpu1: cpu@1 {
+ compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+ d-cache-block-size = <64>;
+ d-cache-sets = <64>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <64>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv39";
+ reg = <1>;
+ riscv,isa = "rv64imafdc";
+ tlb-split;
+ next-level-cache = <&l2cache>;
+ cpu1_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
+ cpu2: cpu@2 {
+ compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+ d-cache-block-size = <64>;
+ d-cache-sets = <64>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <64>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv39";
+ reg = <2>;
+ riscv,isa = "rv64imafdc";
+ tlb-split;
+ next-level-cache = <&l2cache>;
+ cpu2_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
+ cpu3: cpu@3 {
+ compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+ d-cache-block-size = <64>;
+ d-cache-sets = <64>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <64>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv39";
+ reg = <3>;
+ riscv,isa = "rv64imafdc";
+ tlb-split;
+ next-level-cache = <&l2cache>;
+ cpu3_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
+ cpu4: cpu@4 {
+ compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+ d-cache-block-size = <64>;
+ d-cache-sets = <64>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <32>;
+ device_type = "cpu";
+ i-cache-block-size = <64>;
+ i-cache-sets = <64>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <32>;
+ mmu-type = "riscv,sv39";
+ reg = <4>;
+ riscv,isa = "rv64imafdc";
+ tlb-split;
+ next-level-cache = <&l2cache>;
+ cpu4_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
+ };
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "sifive,fu540-c000", "sifive,fu540", "simple-bus";
+ ranges;
+ plic0: interrupt-controller@c000000 {
+ #interrupt-cells = <1>;
+ compatible = "sifive,plic-1.0.0";
+ reg = <0x0 0xc000000 0x0 0x4000000>;
+ riscv,ndev = <53>;
+ interrupt-controller;
+ interrupts-extended = <
+ &cpu0_intc 0xffffffff
+ &cpu1_intc 0xffffffff &cpu1_intc 9
+ &cpu2_intc 0xffffffff &cpu2_intc 9
+ &cpu3_intc 0xffffffff &cpu3_intc 9
+ &cpu4_intc 0xffffffff &cpu4_intc 9>;
+ };
+ prci: clock-controller@10000000 {
+ compatible = "sifive,fu540-c000-prci";
+ reg = <0x0 0x10000000 0x0 0x1000>;
+ clocks = <&hfclk>, <&rtcclk>;
+ #clock-cells = <1>;
+ };
+ uart0: serial@10010000 {
+ compatible = "sifive,fu540-c000-uart", "sifive,uart0";
+ reg = <0x0 0x10010000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <4>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ status = "disabled";
+ };
+ dma: dma@3000000 {
+ compatible = "sifive,fu540-c000-pdma";
+ reg = <0x0 0x3000000 0x0 0x8000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <23 24 25 26 27 28 29 30>;
+ #dma-cells = <1>;
+ };
+ uart1: serial@10011000 {
+ compatible = "sifive,fu540-c000-uart", "sifive,uart0";
+ reg = <0x0 0x10011000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <5>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ status = "disabled";
+ };
+ i2c0: i2c@10030000 {
+ compatible = "sifive,fu540-c000-i2c", "sifive,i2c0";
+ reg = <0x0 0x10030000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <50>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ qspi0: spi@10040000 {
+ compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+ reg = <0x0 0x10040000 0x0 0x1000
+ 0x0 0x20000000 0x0 0x10000000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <51>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ qspi1: spi@10041000 {
+ compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+ reg = <0x0 0x10041000 0x0 0x1000
+ 0x0 0x30000000 0x0 0x10000000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <52>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ qspi2: spi@10050000 {
+ compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+ reg = <0x0 0x10050000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <6>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ eth0: ethernet@10090000 {
+ compatible = "sifive,fu540-c000-gem";
+ interrupt-parent = <&plic0>;
+ interrupts = <53>;
+ reg = <0x0 0x10090000 0x0 0x2000
+ 0x0 0x100a0000 0x0 0x1000>;
+ local-mac-address = [00 00 00 00 00 00];
+ clock-names = "pclk", "hclk";
+ clocks = <&prci PRCI_CLK_GEMGXLPLL>,
+ <&prci PRCI_CLK_GEMGXLPLL>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ pwm0: pwm@10020000 {
+ compatible = "sifive,fu540-c000-pwm", "sifive,pwm0";
+ reg = <0x0 0x10020000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <42 43 44 45>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+ pwm1: pwm@10021000 {
+ compatible = "sifive,fu540-c000-pwm", "sifive,pwm0";
+ reg = <0x0 0x10021000 0x0 0x1000>;
+ interrupt-parent = <&plic0>;
+ interrupts = <46 47 48 49>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+ l2cache: cache-controller@2010000 {
+ compatible = "sifive,fu540-c000-ccache", "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-sets = <1024>;
+ cache-size = <2097152>;
+ cache-unified;
+ interrupt-parent = <&plic0>;
+ interrupts = <1 2 3>;
+ reg = <0x0 0x2010000 0x0 0x1000>;
+ };
+ gpio: gpio@10060000 {
+ compatible = "sifive,fu540-c000-gpio", "sifive,gpio0";
+ interrupt-parent = <&plic0>;
+ interrupts = <7>, <8>, <9>, <10>, <11>, <12>, <13>,
+ <14>, <15>, <16>, <17>, <18>, <19>, <20>,
+ <21>, <22>;
+ reg = <0x0 0x10060000 0x0 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&prci PRCI_CLK_TLCLK>;
+ status = "disabled";
+ };
+ clint: clint@2000000 {
+ compatible = "riscv,clint0";
+ interrupts-extended = <&cpu0_intc 3 &cpu0_intc 7
+ &cpu1_intc 3 &cpu1_intc 7
+ &cpu2_intc 3 &cpu2_intc 7
+ &cpu3_intc 3 &cpu3_intc 7
+ &cpu4_intc 3 &cpu4_intc 7>;
+ reg = <0x0 0x2000000 0x0 0xc0000>;
+ };
+ };
+};
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/gpio.h b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/gpio.h
new file mode 100644
index 00000000000..1ad335d693b
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/gpio.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * This header provides constants for most GPIO bindings.
+ *
+ * Most GPIO bindings include a flags cell as part of the GPIO specifier.
+ * In most cases, the format of the flags cell uses the standard values
+ * defined in this header.
+ */
+
+#ifndef _DT_BINDINGS_GPIO_GPIO_H
+#define _DT_BINDINGS_GPIO_GPIO_H
+
+/* Bit 0 express polarity */
+#define GPIO_ACTIVE_HIGH 0
+#define GPIO_ACTIVE_LOW 1
+
+/* Bit 1 express single-endedness */
+#define GPIO_PUSH_PULL 0
+#define GPIO_SINGLE_ENDED 2
+
+/* Bit 2 express Open drain or open source */
+#define GPIO_LINE_OPEN_SOURCE 0
+#define GPIO_LINE_OPEN_DRAIN 4
+
+/*
+ * Open Drain/Collector is the combination of single-ended open drain interface.
+ * Open Source/Emitter is the combination of single-ended open source interface.
+ */
+#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN)
+#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE)
+
+/* Bit 3 express GPIO suspend/resume and reset persistence */
+#define GPIO_PERSISTENT 0
+#define GPIO_TRANSITORY 8
+
+/* Bit 4 express pull up */
+#define GPIO_PULL_UP 16
+
+/* Bit 5 express pull down */
+#define GPIO_PULL_DOWN 32
+
+#endif
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/hifive-unleashed-a00.dts b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/hifive-unleashed-a00.dts
new file mode 100644
index 00000000000..df06f1c8c43
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/hifive-unleashed-a00.dts
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2018-2019 SiFive, Inc */
+
+#include "fu540-c000.dtsi"
+/*#include */
+#include "gpio.h"
+
+/* Clock frequency (in Hz) of the PCB crystal for rtcclk */
+#define RTCCLK_FREQ 1000000
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "SiFive HiFive Unleashed A00";
+ compatible = "sifive,hifive-unleashed-a00", "sifive,fu540-c000";
+
+ chosen {
+ stdout-path = "serial0";
+ };
+
+ cpus {
+ timebase-frequency = ;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x2 0x00000000>;
+ };
+
+ soc {
+ };
+
+ hfclk: hfclk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <33333333>;
+ clock-output-names = "hfclk";
+ };
+
+ rtcclk: rtcclk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = ;
+ clock-output-names = "rtcclk";
+ };
+ gpio-restart {
+ compatible = "gpio-restart";
+ gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&qspi0 {
+ status = "okay";
+ flash@0 {
+ compatible = "issi,is25wp256", "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
+ m25p,fast-read;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ };
+};
+
+&qspi2 {
+ status = "okay";
+ mmc@0 {
+ compatible = "mmc-spi-slot";
+ reg = <0>;
+ spi-max-frequency = <20000000>;
+ voltage-ranges = <3300 3300>;
+ disable-wp;
+ };
+};
+
+ð0 {
+ status = "okay";
+ phy-mode = "gmii";
+ phy-handle = <&phy0>;
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+};
+
+&pwm0 {
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&gpio {
+ status = "okay";
+};
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/sifive-fu540-prci.h b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/sifive-fu540-prci.h
new file mode 100644
index 00000000000..4446b28548e
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/sifive-fu540-prci.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ * Wesley Terpstra
+ * Paul Walmsley
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_SIFIVE_FU540_PRCI_H
+#define __DT_BINDINGS_CLOCK_SIFIVE_FU540_PRCI_H
+
+/* Clock indexes for use by Device Tree data and the PRCI driver */
+
+#define PRCI_CLK_COREPLL 0
+#define PRCI_CLK_DDRPLL 1
+#define PRCI_CLK_GEMGXLPLL 2
+#define PRCI_CLK_TLCLK 3
+
+#endif
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/Library/RiscVSpecialPlatformLib/RiscVSpecialPlatformLib.inf b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/Library/RiscVSpecialPlatformLib/RiscVSpecialPlatformLib.inf
new file mode 100644
index 00000000000..5a95e28dbd3
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/Library/RiscVSpecialPlatformLib/RiscVSpecialPlatformLib.inf
@@ -0,0 +1,36 @@
+## @file
+# Null library instance to provide platform_override for the
+# special RISC-V platform. This module incorporates with
+# OpensbiPlatformLib and RISC-V Opensbi library.
+#
+# Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RiscVSpecialPlatformLib
+ FILE_GUID = FE0AE3E6-90A4-421D-851D-E092CBEEE645
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RiscVSpecialPlatformLib|SEC
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = RISCV64
+#
+
+[Sources]
+ SifiveFu740.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
+ Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
+
+[LibraryClasses]
+ BaseLib
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/Library/RiscVSpecialPlatformLib/SifiveFu740.c b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/Library/RiscVSpecialPlatformLib/SifiveFu740.c
new file mode 100644
index 00000000000..871608db485
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/Library/RiscVSpecialPlatformLib/SifiveFu740.c
@@ -0,0 +1,63 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ *
+ * Authors:
+ * Anup Patel
+
+ Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+#include
+#include
+#include
+
+static u64
+sifive_fu540_tlbr_flush_limit (
+ const struct fdt_match *match
+ )
+{
+ /*
+ * The sfence.vma by virtual address does not work on
+ * SiFive FU540 so we return remote TLB flush limit as zero.
+ */
+ return 0;
+}
+
+static int
+sifive_fu540_fdt_fixup (
+ void *fdt,
+ const struct fdt_match *match
+ )
+{
+ /*
+ * SiFive Freedom U540 has an erratum that prevents S-mode software
+ * to access a PMP protected region using 1GB page table mapping, so
+ * always add the no-map attribute on this platform.
+ */
+ fdt_reserved_memory_nomap_fixup (fdt);
+
+ return 0;
+}
+
+static const struct fdt_match sifive_fu540_match[] = {
+ { .compatible = "sifive,fu540" },
+ { .compatible = "sifive,fu540g" },
+ { .compatible = "sifive,fu540-c000" },
+ { .compatible = "sifive,hifive-unleashed-a00" },
+ { },
+};
+
+const struct platform_override sifive_fu540 = {
+ .match_table = sifive_fu540_match,
+ .tlbr_flush_limit = sifive_fu540_tlbr_flush_limit,
+ .fdt_fixup = sifive_fu540_fdt_fixup,
+};
+
+const struct platform_override *special_platforms[] = {
+ &sifive_fu540,
+};
+INTN NumberOfPlaformsInArray = array_size (special_platforms);
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.dec b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.dec
new file mode 100644
index 00000000000..f3b714172a0
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.dec
@@ -0,0 +1,26 @@
+## @file U740.dec
+# This Package provides SiFive U740 modules and libraries.
+#
+# Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+# Copyright (c) 2022, Boyang Han
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x0001001b
+ PACKAGE_NAME = U740
+ PACKAGE_UNI_FILE = U740.uni
+ PACKAGE_GUID = 0E5F5459-20DF-4748-BCE8-F8CBDC5C41DB
+ PACKAGE_VERSION = 1.0
+
+[Includes]
+
+[LibraryClasses]
+
+[Guids]
+ gUefiRiscVPlatformU740PkgTokenSpaceGuid = {0xF73592FF, 0xD846, 0x445B, { 0xBD, 0x19, 0x2D, 0xD5, 0x72, 0x8B, 0xDE, 0x61 }}
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ U740PkgExtra.uni
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.dsc b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.dsc
new file mode 100644
index 00000000000..2af45f87390
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.dsc
@@ -0,0 +1,571 @@
+## @file
+# RISC-V EFI on SiFive Freedom U740 HiFive Unmatched RISC-V platform
+#
+# Copyright (c) 2019-2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+# Copyright (c) 2022, Boyang Han
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ PLATFORM_NAME = FreedomU740HiFiveUnmatched
+ PLATFORM_GUID = 5035C873-6747-4548-BDB3-21E11903911F
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x0001001c
+ OUTPUT_DIRECTORY = Build/$(PLATFORM_NAME)
+ SUPPORTED_ARCHITECTURES = RISCV64
+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+ FLASH_DEFINITION = Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.fdf
+
+ #
+ # Enable below options may cause build error or may not work on
+ # the initial version of RISC-V package
+ # Defines for default states. These can be changed on the command line.
+ # -D FLAG=VALUE
+ #
+ DEFINE SECURE_BOOT_ENABLE = FALSE
+ DEFINE DEBUG_ON_SERIAL_PORT = TRUE
+
+ #
+ # Network definition
+ #
+ DEFINE NETWORK_SNP_ENABLE = FALSE
+ DEFINE NETWORK_IP6_ENABLE = FALSE
+ DEFINE NETWORK_TLS_ENABLE = FALSE
+ DEFINE NETWORK_HTTP_BOOT_ENABLE = FALSE
+ DEFINE NETWORK_ISCSI_ENABLE = FALSE
+
+[BuildOptions]
+ GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ GCC:*_*_RISCV64_GENFW_FLAGS = --keepexceptiontable
+!endif
+
+################################################################################
+#
+# SKU Identification section - list of all SKU IDs supported by this Platform.
+#
+################################################################################
+[SkuIds]
+ 0|DEFAULT
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
+[LibraryClasses]
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ SerialPortLib|Platform/SiFive/U7SeriesPkg/Library/SerialIoLib/SerialIoLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf
+ FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
+ UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
+ SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
+
+# RISC-V Platform Library
+ TimeBaseLib|EmbeddedPkg//Library/TimeBaseLib/TimeBaseLib.inf
+ RealTimeClockLib|EmbeddedPkg//Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
+
+# RISC-V Core Library
+ RiscVOpensbiLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf
+
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+ DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
+!else
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+!endif
+
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
+ TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
+ AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
+ SecureBootVariableProvisionLib|SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.inf
+!else
+ TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+ AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
+!endif
+ VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+
+!if $(HTTP_BOOT_ENABLE) == TRUE
+ HttpLib|MdeModulePkg/Library/DxeHttpLib/DxeHttpLib.inf
+!endif
+
+# ACPI not supported yet.
+ #S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
+ SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
+ OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
+
+[LibraryClasses.common]
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+!endif
+ RiscVCpuLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVCpuLib/RiscVCpuLib.inf
+ RiscVEdk2SbiLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf
+ RiscVPlatformTimerLib|Platform/SiFive/U7SeriesPkg/Library/RiscVPlatformTimerLib/RiscVPlatformTimerLib.inf
+ #MachineModeTimerLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVReadMachineModeTimer/MachineModeTimerLib/MachineModeTimerLib.inf
+ MachineModeTimerLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVReadMachineModeTimer/EmulatedMachineModeTimerLib/EmulatedMachineModeTimerLib.inf
+ CpuExceptionHandlerLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVExceptionLib/CpuExceptionHandlerDxeLib.inf
+
+
+ # Flattened Device Tree (FDT) access library
+ FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
+
+[LibraryClasses.common.SEC]
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf
+ Edk2OpensbiPlatformWrapperLib|Platform/RISC-V/PlatformPkg/Library/Edk2OpensbiPlatformWrapperLib/Edk2OpensbiPlatformWrapperLib.inf
+ RiscVSpecialPlatformLib|Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/Library/RiscVSpecialPlatformLib/RiscVSpecialPlatformLib.inf
+
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+
+#
+# OpenSBi Platform Library
+#
+ RiscVOpensbiPlatformLib|Platform/RISC-V/PlatformPkg/Library/OpensbiPlatformLib/OpensbiPlatformLib.inf
+
+[LibraryClasses.common.PEI_CORE]
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib|Silicon/RISC-V/ProcessorPkg/Library/PeiServicesTablePointerLibOpenSbi/PeiServicesTablePointerLibOpenSbi.inf
+ RiscVFirmwareContextLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVFirmwareContextSscratchLib/RiscVFirmwareContextSscratchLib.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ # RISC-V platform PEI core entry point.
+ PeiCoreEntryPoint|Platform/RISC-V/PlatformPkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+ PlatformSecPpiLib|Platform/SiFive/U7SeriesPkg/Library/PlatformSecPpiLib/PlatformSecPpiLib.inf
+
+[LibraryClasses.common.PEIM]
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib|Silicon/RISC-V/ProcessorPkg/Library/PeiServicesTablePointerLibOpenSbi/PeiServicesTablePointerLibOpenSbi.inf
+ RiscVFirmwareContextLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVFirmwareContextSscratchLib/RiscVFirmwareContextSscratchLib.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PeiResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+ FirmwareContextProcessorSpecificLib|Platform/RISC-V/PlatformPkg/Library/FirmwareContextProcessorSpecificLib/FirmwareContextProcessorSpecificLib.inf
+
+#
+# RISC-V core libraries
+#
+# SiliconSiFiveU74CoreInfoLib|Silicon/SiFive/U74/Library/PeiCoreInfoHobLib/PeiCoreInfoHobLibNull.inf
+# RiscVCoreplexInfoLib|Platform/SiFive/U7SeriesPkg/Library/PeiCoreInfoHobLib/PeiCoreInfoHobLibNull.inf
+RiscVCoreplexInfoLib|Platform/RISC-V/PlatformPkg/Library/PeiCoreInfoHobLibNull/PeiCoreInfoHobLib.inf
+
+[LibraryClasses.common.DXE_CORE]
+ TimerLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVTimerLib/BaseRiscVTimerLib.inf
+ HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+ ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVTimerLib/BaseRiscVTimerLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+ ResetSystemLib|Platform/RISC-V/PlatformPkg/Library/ResetSystemLib/ResetSystemLib.inf
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+!endif
+ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
+
+[LibraryClasses.common.UEFI_DRIVER]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVTimerLib/BaseRiscVTimerLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVTimerLib/BaseRiscVTimerLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ PlatformBootManagerLib|Platform/RISC-V/PlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+ PlatformMemoryTestLib|Platform/RISC-V/PlatformPkg/Library/PlatformMemoryTestLibNull/PlatformMemoryTestLibNull.inf
+ PlatformUpdateProgressLib|Platform/RISC-V/PlatformPkg/Library/PlatformUpdateProgressLibNull/PlatformUpdateProgressLibNull.inf
+
+[LibraryClasses.common.UEFI_APPLICATION]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib|Silicon/RISC-V/ProcessorPkg/Library/RiscVTimerLib/BaseRiscVTimerLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!endif
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform.
+#
+################################################################################
+[PcdsFeatureFlag]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
+
+[PcdsFixedAtBuild]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1
+ gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x8000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+
+ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
+!endif
+
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2
+!endif
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot
+ gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x04
+ gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy|0x04
+ gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x04
+!endif
+
+ #
+ # F2 for UI APP
+ #
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
+
+################################################################################
+#
+# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsDynamicDefault]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|800
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|600
+
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0
+
+ # Set video resolution for text setup.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|640
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|480
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0208
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosDocRev|0x0
+
+################################################################################
+#
+# Components Section - list of all EDK II Modules needed by this Platform.
+#
+################################################################################
+[Components]
+
+ #
+ # SEC Phase modules
+ #
+ Platform/RISC-V/PlatformPkg/Universal/Sec/SecMain.inf
+
+ #
+ # PEI Phase modules
+ #
+ MdeModulePkg/Core/Pei/PeiMain.inf
+ MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
+
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+ MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+ MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
+
+ NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ }
+
+ Platform/RISC-V/PlatformPkg/Universal/Pei/PlatformPei/PlatformPei.inf {
+
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ }
+ Platform/RISC-V/PlatformPkg/Universal/FdtPeim/FdtPeim.inf
+
+ #
+ # DXE Phase modules
+ #
+ MdeModulePkg/Core/Dxe/DxeMain.inf {
+
+ NULL|MdeModulePkg//Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ }
+
+ MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+ MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+
+ MdeModulePkg/Universal/PCD/Dxe/Pcd.inf {
+
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+
+ MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf {
+
+ NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
+ }
+!else
+ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+!endif
+
+ UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+ MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
+
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ MdeModulePkg/Universal/Metronome/Metronome.inf
+ MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+ MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf {
+
+ ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
+ }
+ EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+
+ #
+ # RISC-V Platform module
+ #
+ Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/TimerDxe.inf
+ Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+
+ #
+ # RISC-V Core module
+ #
+ Silicon/RISC-V/ProcessorPkg/Universal/CpuDxe/CpuDxe.inf
+ Silicon/RISC-V/ProcessorPkg/Universal/SmbiosDxe/RiscVSmbiosDxe.inf
+ MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+
+ MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
+
+ NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
+ }
+ MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+ MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+ MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+ MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+
+# No graphic console supported yet.
+# MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf {
+#
+# PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+# }
+ MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+ MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf {
+
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+ MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+ MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+ MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+ MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+ MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
+
+ Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/DeviceTree/U740DeviceTree.inf
+
+ #
+ # SMBIOS Support
+ #
+ MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+
+ #
+ # Network Support
+ #
+ !include NetworkPkg/Network.dsc.inc
+
+ #
+ # Usb Support
+ #
+ MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
+ MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+ MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
+ MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+ MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+ MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+
+ Silicon/RISC-V/ProcessorPkg/Universal/FdtDxe/FdtDxe.inf
+
+ #
+ # FAT filesystem + GPT/MBR partitioning + UDF filesystem
+ #
+ FatPkg/EnhancedFatDxe/Fat.inf
+ MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+
+ OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
+
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ }
+
+ ShellPkg/Application/Shell/Shell.inf {
+
+ ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
+ HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+ FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
+
+
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
+ }
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+!endif
+
+ MdeModulePkg/Application/UiApp/UiApp.inf
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.fdf b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.fdf
new file mode 100644
index 00000000000..8f5ef2658da
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.fdf
@@ -0,0 +1,336 @@
+# @file
+# Flash definition file on SiFive Freedom U740 HiFive Unmatched RISC-V platform
+#
+# Copyright (c) 2019-2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+# Copyright (c) 2022, Boyang Han
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# Platform definitions
+#
+!include U740.fdf.inc
+
+#
+# Build the variable store and the firmware code as one unified flash device
+# image.
+#
+[FD.U740]
+BaseAddress = $(FW_BASE_ADDRESS)
+Size = $(FW_SIZE)
+ErasePolarity = 1
+BlockSize = $(BLOCK_SIZE)
+NumBlocks = $(FW_BLOCKS)
+
+$(SECFV_OFFSET)|$(SECFV_SIZE)
+gUefiRiscVPlatformPkgTokenSpaceGuid.PcdRiscVSecFvBase|gUefiRiscVPlatformPkgTokenSpaceGuid.PcdRiscVSecFvSize
+FV = SECFV
+
+$(PEIFV_OFFSET)|$(PEIFV_SIZE)
+gUefiRiscVPlatformPkgTokenSpaceGuid.PcdRiscVPeiFvBase|gUefiRiscVPlatformPkgTokenSpaceGuid.PcdRiscVPeiFvSize
+FV = PEIFV
+
+$(FVMAIN_OFFSET)|$(FVMAIN_SIZE)
+gUefiRiscVPlatformPkgTokenSpaceGuid.PcdRiscVDxeFvBase|gUefiRiscVPlatformPkgTokenSpaceGuid.PcdRiscVDxeFvSize
+FV = FVMAIN_COMPACT
+
+!include VarStore.fdf.inc
+!include DeviceTree.fdf.inc
+
+################################################################################
+
+[FV.SECFV]
+BlockSize = 0x1000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+#
+# SEC Phase modules
+#
+# The code in this FV handles the initial firmware startup, and
+# decompresses the PEI and DXE FVs which handles the rest of the boot sequence.
+#
+INF Platform/RISC-V/PlatformPkg/Universal/Sec/SecMain.inf
+
+################################################################################
+[FV.PEIFV]
+BlockSize = 0x10000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+APRIORI PEI {
+ INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+ INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+ INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+}
+
+#
+# PEI Phase modules
+#
+INF MdeModulePkg/Core/Pei/PeiMain.inf
+INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+
+# RISC-V Platform PEI Driver
+INF Platform/RISC-V/PlatformPkg/Universal/Pei/PlatformPei/PlatformPei.inf
+INF Platform/RISC-V/PlatformPkg/Universal/FdtPeim/FdtPeim.inf
+
+################################################################################
+
+[FV.DXEFV]
+BlockSize = 0x10000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+APRIORI DXE {
+ INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+ INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+ INF Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+}
+
+#
+# DXE Phase modules
+#
+INF MdeModulePkg/Core/Dxe/DxeMain.inf
+
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+
+INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+INF MdeModulePkg/Universal/Metronome/Metronome.inf
+INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+
+# RISC-V Platform Drivers
+INF Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+
+# RISC-V Core Drivers
+INF Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/TimerDxe.inf
+INF Silicon/RISC-V/ProcessorPkg/Universal/CpuDxe/CpuDxe.inf
+INF Silicon/RISC-V/ProcessorPkg/Universal/SmbiosDxe/RiscVSmbiosDxe.inf
+
+INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+
+INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+!endif
+
+INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+INF MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+INF FatPkg/EnhancedFatDxe/Fat.inf
+INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+INF Silicon/RISC-V/ProcessorPkg/Universal/FdtDxe/FdtDxe.inf
+
+!ifndef $(SOURCE_DEBUG_ENABLE)
+INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
+!endif
+
+INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+
+INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
+INF ShellPkg/Application/Shell/Shell.inf
+
+#
+# Network modules
+#
+!if $(E1000_ENABLE)
+ FILE DRIVER = 5D695E11-9B3F-4b83-B25F-4A8D5D69BE07 {
+ SECTION PE32 = Intel3.5/EFIX64/E3507X2.EFI
+ }
+!endif
+
+!include NetworkPkg/Network.fdf.inc
+
+#
+# Usb Support
+#
+INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
+INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+INF MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+
+INF MdeModulePkg/Application/UiApp/UiApp.inf
+
+################################################################################
+
+[FV.FVMAIN_COMPACT]
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+FvNameGuid = 27A72E80-3118-4c0c-8673-AA5B4EFA9613
+
+FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
+ SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
+ #
+ # These firmware volumes will have files placed in them uncompressed,
+ # and then both firmware volumes will be compressed in a single
+ # compression operation in order to achieve better overall compression.
+ #
+ SECTION FV_IMAGE = DXEFV
+ }
+ }
+
+[Rule.Common.SEC]
+ FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED {
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING ="$(MODULE_NAME)" Optional
+ VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEI_CORE]
+ FILE PEI_CORE = $(NAMED_GUID) {
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING ="$(MODULE_NAME)" Optional
+ VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEIM]
+ FILE PEIM = $(NAMED_GUID) {
+ PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_CORE]
+ FILE DXE_CORE = $(NAMED_GUID) {
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align = 4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_DRIVER.BINARY]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional |.depex
+ PE32 PE32 Align=4K |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_APPLICATION]
+ FILE APPLICATION = $(NAMED_GUID) {
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_APPLICATION.BINARY]
+ FILE APPLICATION = $(NAMED_GUID) {
+ PE32 PE32 Align=4K |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.USER_DEFINED.ACPITABLE]
+ FILE FREEFORM = $(NAMED_GUID) {
+ RAW ACPI |.acpi
+ RAW ASL |.aml
+ }
+
+[Rule.Common.USER_DEFINED.DTB]
+ FILE FREEFORM = $(NAMED_GUID) {
+ RAW BIN |.dtb
+ }
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.fdf.inc b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.fdf.inc
new file mode 100644
index 00000000000..537b76d0f3c
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.fdf.inc
@@ -0,0 +1,108 @@
+## @file
+# Definitions of Flash definition file on SiFive Freedom U740 HiFive Unmatched RISC-V platform
+#
+# Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+# Copyright (c) 2022, Boyang Han
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+[Defines]
+DEFINE BLOCK_SIZE = 0x1000
+
+DEFINE FW_BASE_ADDRESS = 0x80000000
+DEFINE FW_SIZE = 0x00900000
+DEFINE FW_BLOCKS = 0x900
+
+#
+# 0x000000-0x7DFFFF code
+# 0x7E0000-0x800000 variables
+#
+DEFINE CODE_BASE_ADDRESS = 0x80000000
+DEFINE CODE_SIZE = 0x00800000
+DEFINE CODE_BLOCKS = 0x800
+DEFINE VARS_BLOCKS = 0x20
+
+#
+# SEC + opensbi library is the root FW domain.
+# The base address must be round up to log2.
+#
+DEFINE SECFV_OFFSET = 0x00000000
+DEFINE SECFV_SIZE = 0x00040000
+DEFINE ROOT_FW_DOMAIN_SIZE = $(SECFV_SIZE)
+
+#
+# Other FV regions are in the second FW domain.
+# The size of memory region must be power of 2.
+# The base address must be aligned with the size.
+#
+# FW memory region
+#
+DEFINE PEIFV_OFFSET = 0x00400000
+DEFINE PEIFV_SIZE = 0x00180000
+DEFINE FVMAIN_OFFSET = 0x00580000
+DEFINE FVMAIN_SIZE = 0x00280000
+
+#
+# EFI Variable memory region.
+# The total size of EFI Variable FD must include
+# all of sub regions of EFI Variable
+#
+DEFINE VARS_OFFSET = 0x00800000
+DEFINE VARS_SIZE = 0x00007000
+DEFINE VARS_FTW_WORKING_OFFSET = 0x00807000
+DEFINE VARS_FTW_WORKING_SIZE = 0x00001000
+DEFINE VARS_FTW_SPARE_OFFSET = 0x00808000
+DEFINE VARS_FTW_SPARE_SIZE = 0x00018000
+
+#
+# Device Tree memory region
+#
+DEFINE DTB_OFFSET = 0x00840000
+DEFINE DTB_SIZE = 0x00002000
+
+#
+# Scratch area memory region
+#
+DEFINE SCRATCH_OFFSET = 0x00880000
+DEFINE SCRATCH_SIZE = 0x00010000
+
+
+DEFINE FW_DOMAIN_SIZE = $(FVMAIN_OFFSET) + $(FVMAIN_SIZE) - $(PEIFV_OFFSET)
+DEFINE VARIABLE_FW_SIZE = $(VARS_FTW_SPARE_OFFSET) + $(VARS_FTW_SPARE_SIZE) - $(VARS_OFFSET)
+
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdRootFirmwareDomainBaseAddress = $(CODE_BASE_ADDRESS) + $(SECFV_OFFSET)
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdRootFirmwareDomainSize = $(ROOT_FW_DOMAIN_SIZE)
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdFirmwareDomainBaseAddress = $(CODE_BASE_ADDRESS) + $(PEIFV_OFFSET)
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdFirmwareDomainSize = $(FW_DOMAIN_SIZE)
+
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdVariableFdBaseAddress = $(FW_BASE_ADDRESS) + $(VARS_OFFSET)
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdVariableFdSize = $(VARS_SIZE) + $(VARS_FTW_WORKING_SIZE) + $(VARS_FTW_SPARE_SIZE)
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdVariableFdBlockSize = $(BLOCK_SIZE)
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdVariableFirmwareRegionBaseAddress = $(CODE_BASE_ADDRESS) + $(VARS_OFFSET)
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdVariableFirmwareRegionSize = $(VARIABLE_FW_SIZE)
+
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdOpenSbiStackSize = 8192
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdScratchRamBase = $(CODE_BASE_ADDRESS) + $(SCRATCH_OFFSET)
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdScratchRamSize = $(SCRATCH_SIZE)
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdTemporaryRamBase = $(CODE_BASE_ADDRESS) + $(FW_SIZE)
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdTemporaryRamSize = 0x10000
+
+
+SET gUefiRiscVPkgTokenSpaceGuid.PcdRiscVMachineTimerFrequencyInHerz = 1000000
+SET gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdU7PlatformSystemClock = 250250000 # 250.250MHz system clock
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdBootHartId = 1 # Boot hart ID
+
+#
+# The bootable hart number the platform would like to use during boot.
+#
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdBootableHartNumber = 1
+#
+# Only use hart ID 1, 2, 3, 4
+#
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdBootableHartIndexToId = {0x1}
+ # during boot
+SET gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdNumberofU7Cores = 1 # Total U7 cores enabled on U740 platform
+SET gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdE5MCSupported = True # E51 MC exists.
+SET gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdU7UartBase = 0x10010000 # Serial port base address
+SET gUefiRiscVPlatformPkgTokenSpaceGuid.PcdPeiCorePrivilegeMode = 1 # Set PeiCore to S-Mode
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.uni b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.uni
new file mode 100644
index 00000000000..4f386b131ce
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740.uni
@@ -0,0 +1,14 @@
+// /** @file
+// SiFive U740 HiFive Unmatched Package Localized Strings and Content.
+//
+// Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+// Copyright (c) 2022, Boyang Han
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_PACKAGE_ABSTRACT #language en-US "Provides SiFIve Freedom U740 HiFive Unmatched platform modules and libraries"
+
+#string STR_PACKAGE_DESCRIPTION #language en-US "This Package SiFIve Freedom U740 HiFive Unmatched platform modules and libraries."
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740PkgExtra.uni b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740PkgExtra.uni
new file mode 100644
index 00000000000..cf42e1e6518
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/U740PkgExtra.uni
@@ -0,0 +1,13 @@
+// /** @file
+// SiFive U740 Package Localized Strings and Content.
+//
+// Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+// Copyright (c) 2022, Boyang Han
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_PACKAGE_NAME
+#language en-US
+"SiFive Freedom U740 HiFive Unmatcheded board package"
diff --git a/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/VarStore.fdf.inc b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/VarStore.fdf.inc
new file mode 100644
index 00000000000..ba93c17a168
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchedBoard/VarStore.fdf.inc
@@ -0,0 +1,78 @@
+## @file
+# FDF include file with Layout Regions that define an empty variable store.
+#
+# Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+$(VARS_OFFSET)|$(VARS_SIZE)
+gUefiRiscVPlatformPkgTokenSpaceGuid.PcdPlatformFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+#
+# NV_VARIABLE_STORE
+#
+DATA = {
+ ## This is the EFI_FIRMWARE_VOLUME_HEADER
+ # ZeroVector []
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ # FileSystemGuid: gEfiSystemNvDataFvGuid =
+ # { 0xFFF12B8D, 0x7696, 0x4C8B,
+ # { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
+ 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
+ 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
+ # FvLength: 0x20000
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ # Signature "_FVH" # Attributes
+ 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00,
+ # HeaderLength # CheckSum # ExtHeaderOffset #Reserved #Revision
+ 0x48, 0x00, 0x39, 0xF1, 0x00, 0x00, 0x00, 0x02,
+ # Blockmap[0]: 0x20 Blocks * 0x1000 Bytes / Block
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ # Blockmap[1]: End
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is the VARIABLE_STORE_HEADER
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ # Signature: gEfiAuthenticatedVariableGuid =
+ # { 0xaaf32c78, 0x947b, 0x439a,
+ # { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }}
+ 0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43,
+ 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92,
+!else
+ # Signature: gEfiVariableGuid =
+ # { 0xddcf3616, 0x3275, 0x4164,
+ # { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }}
+ 0x16, 0x36, 0xcf, 0xdd, 0x75, 0x32, 0x64, 0x41,
+ 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d,
+!endif
+ # Size: 0x7000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) -
+ # 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0x6fb8
+ # This can speed up the Variable Dispatch a bit.
+ 0xB8, 0x6F, 0x00, 0x00,
+ # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
+ 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+$(VARS_FTW_WORKING_OFFSET)|$(VARS_FTW_WORKING_SIZE)
+gUefiRiscVPlatformPkgTokenSpaceGuid.PcdPlatformFlashNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+#
+#NV_FTW_WROK
+#
+DATA = {
+ # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid =
+ # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
+ 0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49,
+ 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95,
+ # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved
+ 0x2c, 0xaf, 0x2c, 0x64, 0xFE, 0xFF, 0xFF, 0xFF,
+ # WriteQueueSize: UINT64
+ 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+$(VARS_FTW_SPARE_OFFSET)|$(VARS_FTW_SPARE_SIZE)
+gUefiRiscVPlatformPkgTokenSpaceGuid.PcdPlatformFlashNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+#
+#NV_FTW_SPARE
diff --git a/Platform/SiFive/U7SeriesPkg/Include/SiFiveU5MCCoreplex.h b/Platform/SiFive/U7SeriesPkg/Include/SiFiveU5MCCoreplex.h
new file mode 100644
index 00000000000..9ce0922791b
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Include/SiFiveU5MCCoreplex.h
@@ -0,0 +1,32 @@
+/** @file
+ SiFive U74 Coreplex library definitions.
+
+ Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (c) 2022, Boyang Han
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SIFIVE_U7MC_COREPLEX_H_
+#define SIFIVE_U7MC_COREPLEX_H_
+
+#include
+
+#include
+#include
+
+#define SIFIVE_U7MC_COREPLEX_MC_HART_ID 0
+
+/**
+ Build processor and platform information for the U7 platform
+
+ @return EFI_SUCCESS Status.
+
+**/
+EFI_STATUS
+BuildRiscVSmbiosHobs (
+ VOID
+ );
+
+#endif
diff --git a/Platform/SiFive/U7SeriesPkg/Include/SifiveU7Uart.h b/Platform/SiFive/U7SeriesPkg/Include/SifiveU7Uart.h
new file mode 100644
index 00000000000..b9025f6f966
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Include/SifiveU7Uart.h
@@ -0,0 +1,18 @@
+/** @file
+ SiFive U7 series UART header file. This is the wrapper file
+ of sifive-uart.h under opensib include/sbi_utils/serial.
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (c) 2022, Boyang Han
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SIFIVE_U7_SERIES_UART_H_
+#define SIFIVE_U7_SERIES_UART_H_
+
+#include
+#include
+
+#endif
diff --git a/Platform/SiFive/U7SeriesPkg/Include/U5Clint.h b/Platform/SiFive/U7SeriesPkg/Include/U5Clint.h
new file mode 100644
index 00000000000..35f35f23804
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Include/U5Clint.h
@@ -0,0 +1,22 @@
+/** @file
+ RISC-V Timer Architectural definition for U700 platform.
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (c) 2022, Boyang Han
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef U7_CLINT_H_
+#define U7_CLINT_H_
+
+#define CLINT_REG_BASE_ADDR 0x02000000
+#define CLINT_REG_MTIME 0x0200BFF8
+#define CLINT_REG_MTIMECMP0 0x02004000
+#define CLINT_REG_MTIMECMP1 0x02004008
+#define CLINT_REG_MTIMECMP2 0x02004010
+#define CLINT_REG_MTIMECMP3 0x02004018
+#define CLINT_REG_MTIMECMP4 0x02004020
+
+#endif
diff --git a/Platform/SiFive/U7SeriesPkg/Library/PeiCoreInfoHobLib/CoreInfoHob.c b/Platform/SiFive/U7SeriesPkg/Library/PeiCoreInfoHobLib/CoreInfoHob.c
new file mode 100644
index 00000000000..c7ce0ea09c3
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Library/PeiCoreInfoHobLib/CoreInfoHob.c
@@ -0,0 +1,193 @@
+/**@file
+ Build up platform processor information.
+
+ Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include
+
+//
+// The Library classes this module consumes
+//
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+/**
+ Build up processor-specific HOB for U5MC Coreplex
+
+ @param UniqueId Unique ID of this U5MC Coreplex processor
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CreateU5MCCoreplexProcessorSpecificDataHob (
+ IN UINTN UniqueId
+ )
+{
+ EFI_STATUS Status;
+ UINT32 HartIdNumber;
+ RISC_V_PROCESSOR_SPECIFIC_HOB_DATA *GuidHobData;
+ EFI_GUID *ParentCoreGuid;
+ BOOLEAN MCSupport;
+
+ DEBUG ((DEBUG_INFO, "Building U5 Coreplex processor information HOB\n"));
+
+ HartIdNumber = 0;
+ ParentCoreGuid = PcdGetPtr (PcdSiFiveU5MCCoreplexGuid);
+ MCSupport = PcdGetBool (PcdE5MCSupported);
+ if (MCSupport == TRUE) {
+ Status = CreateU54E51CoreProcessorSpecificDataHob (ParentCoreGuid, UniqueId, HartIdNumber, FALSE, TRUE, &GuidHobData);
+ if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) {
+ DEBUG ((DEBUG_ERROR, "Faile to build U5MC processor informatino HOB\n"));
+ ASSERT (FALSE);
+ } else {
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "Support E5 Monitor core on U5 platform, HOB at address 0x%x\n", GuidHobData));
+ }
+ }
+
+ HartIdNumber++;
+ }
+
+ for ( ; HartIdNumber < (FixedPcdGet32 (PcdNumberofU5Cores) + (UINT32)MCSupport); HartIdNumber++) {
+ Status = CreateU54E51CoreProcessorSpecificDataHob (ParentCoreGuid, UniqueId, HartIdNumber, (HartIdNumber == FixedPcdGet32 (PcdBootHartId)), FALSE, &GuidHobData);
+ if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) {
+ DEBUG ((DEBUG_ERROR, "Faile to build U5MC processor informatino HOB\n"));
+ ASSERT (FALSE);
+ } else {
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "Support U5 application core on U5 platform, HOB Data at address 0x%x\n", GuidHobData));
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "Support %d U5 application cores on U5 platform\n", HartIdNumber - (UINT32)MCSupport));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to build processor related SMBIOS information. RISC-V SMBIOS DXE driver collect
+ this information and build SMBIOS Type4 and Type7 record.
+
+ @param ProcessorUid Unique ID of physical processor which owns this core.
+ @param SmbiosHobPtr Pointer to receive RISC_V_PROCESSOR_SMBIOS_HOB_DATA. The pointers
+ maintained in this structure is only valid before memory is discovered.
+ Access to those pointers after memory is installed will cause unexpected issues.
+
+ @return EFI_SUCCESS The SMBIOS Hobs were created successfully.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CreateU5MCProcessorSmbiosDataHob (
+ IN UINTN ProcessorUid,
+ OUT RISC_V_PROCESSOR_SMBIOS_HOB_DATA **SmbiosHobPtr
+ )
+{
+ EFI_GUID *GuidPtr;
+ RISC_V_PROCESSOR_TYPE7_HOB_DATA L2CacheDataHob;
+ RISC_V_PROCESSOR_SMBIOS_HOB_DATA SmbiosDataHob;
+ RISC_V_PROCESSOR_TYPE4_HOB_DATA *ProcessorDataHobPtr;
+ RISC_V_PROCESSOR_TYPE7_HOB_DATA *L1CacheDataHobPtr;
+ RISC_V_PROCESSOR_TYPE7_HOB_DATA *L2CacheDataHobPtr;
+ RISC_V_PROCESSOR_SMBIOS_HOB_DATA *SmbiosDataHobPtr;
+
+ DEBUG ((DEBUG_INFO, "%a: Entry\n", __FUNCTION__));
+
+ if (SmbiosHobPtr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CreateU54SmbiosType7L1DataHob (ProcessorUid, &L1CacheDataHobPtr);
+ CreateU54SmbiosType4DataHob (ProcessorUid, &ProcessorDataHobPtr);
+
+ //
+ // Build up SMBIOS type 7 L2 cache record.
+ //
+ ZeroMem ((VOID *)&L2CacheDataHob, sizeof (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
+ L2CacheDataHob.PrcessorGuid = *((EFI_GUID *)PcdGetPtr (PcdSiFiveU5MCCoreplexGuid));
+ L2CacheDataHob.ProcessorUid = ProcessorUid;
+ L2CacheDataHob.SmbiosType7Cache.SocketDesignation = TO_BE_FILLED_BY_VENDOR;
+ L2CacheDataHob.SmbiosType7Cache.CacheConfiguration = RISC_V_CACHE_CONFIGURATION_CACHE_LEVEL_2 | \
+ RISC_V_CACHE_CONFIGURATION_LOCATION_EXTERNAL | \
+ RISC_V_CACHE_CONFIGURATION_ENABLED | \
+ RISC_V_CACHE_CONFIGURATION_MODE_UNKNOWN;
+ L2CacheDataHob.SmbiosType7Cache.MaximumCacheSize = TO_BE_FILLED_BY_VENDOR;
+ L2CacheDataHob.SmbiosType7Cache.InstalledSize = TO_BE_FILLED_BY_VENDOR;
+ L2CacheDataHob.SmbiosType7Cache.SupportedSRAMType.Unknown = 1;
+ L2CacheDataHob.SmbiosType7Cache.CurrentSRAMType.Unknown = 1;
+ L2CacheDataHob.SmbiosType7Cache.CacheSpeed = TO_BE_FILLED_BY_VENDOR;
+ L2CacheDataHob.SmbiosType7Cache.ErrorCorrectionType = TO_BE_FILLED_BY_VENDOR;
+ L2CacheDataHob.SmbiosType7Cache.SystemCacheType = CacheTypeUnified;
+ L2CacheDataHob.SmbiosType7Cache.Associativity = TO_BE_FILLED_BY_VENDOR;
+ GuidPtr = (EFI_GUID *)PcdGetPtr (PcdProcessorSmbiosType7GuidHobGuid);
+ L2CacheDataHobPtr = (RISC_V_PROCESSOR_TYPE7_HOB_DATA *)BuildGuidDataHob (GuidPtr, (VOID *)&L2CacheDataHob, sizeof (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
+ if (L2CacheDataHobPtr == NULL) {
+ DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U5 MC Coreplex L2 cache RISC_V_PROCESSOR_TYPE7_HOB_DATA.\n"));
+ ASSERT (FALSE);
+ }
+
+ ZeroMem ((VOID *)&SmbiosDataHob, sizeof (RISC_V_PROCESSOR_SMBIOS_HOB_DATA));
+ SmbiosDataHob.Processor = ProcessorDataHobPtr;
+ SmbiosDataHob.L1Cache = L1CacheDataHobPtr;
+ SmbiosDataHob.L2Cache = L2CacheDataHobPtr;
+ SmbiosDataHob.L3Cache = NULL;
+
+ GuidPtr = (EFI_GUID *)PcdGetPtr (PcdProcessorSmbiosGuidHobGuid);
+ SmbiosDataHobPtr = (RISC_V_PROCESSOR_SMBIOS_HOB_DATA *)BuildGuidDataHob (GuidPtr, (VOID *)&SmbiosDataHob, sizeof (RISC_V_PROCESSOR_SMBIOS_HOB_DATA));
+ if (SmbiosDataHobPtr == NULL) {
+ DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U5MC Coreplex RISC_V_PROCESSOR_SMBIOS_HOB_DATA.\n"));
+ ASSERT (FALSE);
+ }
+
+ *SmbiosHobPtr = SmbiosDataHobPtr;
+ DEBUG ((DEBUG_INFO, "%a: Exit\n", __FUNCTION__));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Build processor and platform information for the U5 platform
+
+ @return EFI_SUCCESS Status.
+
+**/
+EFI_STATUS
+BuildRiscVSmbiosHobs (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ RISC_V_PROCESSOR_SMBIOS_HOB_DATA *SmbiosHobPtr;
+
+ Status = CreateU5MCCoreplexProcessorSpecificDataHob (0);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ }
+
+ Status = CreateU5MCProcessorSmbiosDataHob (0, &SmbiosHobPtr);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ }
+
+ DEBUG ((DEBUG_INFO, "U5 MC Coreplex SMBIOS DATA HOB at address 0x%x\n", SmbiosHobPtr));
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/SiFive/U7SeriesPkg/Library/PeiCoreInfoHobLib/PeiCoreInfoHobLib.inf b/Platform/SiFive/U7SeriesPkg/Library/PeiCoreInfoHobLib/PeiCoreInfoHobLib.inf
new file mode 100644
index 00000000000..dc9cb122766
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Library/PeiCoreInfoHobLib/PeiCoreInfoHobLib.inf
@@ -0,0 +1,58 @@
+## @file
+# Library instance to create core information HOB
+#
+# Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = SiliconSiFiveU7MCCoreplexInfoLib
+ FILE_GUID = ABB3DECE-488D-4381-83FE-E32FF1C1427A
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RiscVCoreplexInfoLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = RISCV64
+#
+
+[Sources]
+ CoreInfoHob.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Platform/SiFive/U7SeriesPkg/U7SeriesPkg.dec
+ Silicon/SiFive/SiFive.dec
+ Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
+ Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ PcdLib
+ PrintLib
+ RiscVFirmwareContextLib
+ SiliconSiFiveU74CoreInfoLib
+
+[Guids]
+ gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid
+
+[Ppis]
+
+[FixedPcd]
+ gUefiRiscVPkgTokenSpaceGuid.PcdProcessorSmbiosGuidHobGuid
+ gUefiRiscVPkgTokenSpaceGuid.PcdProcessorSmbiosType4GuidHobGuid
+ gUefiRiscVPkgTokenSpaceGuid.PcdProcessorSmbiosType7GuidHobGuid
+ gEfiSiFiveSiliconTokenSpaceGuid.PcdSiFiveU74CoreGuid
+ gEfiSiFiveSiliconTokenSpaceGuid.PcdSiFiveE51CoreGuid
+ gEfiSiFiveSiliconTokenSpaceGuid.PcdSiFiveU7MCCoreplexGuid
+ gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdNumberofU7Cores
+ gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdE5MCSupported
+ gUefiRiscVPlatformPkgTokenSpaceGuid.PcdHartCount
+ gUefiRiscVPlatformPkgTokenSpaceGuid.PcdBootHartId
diff --git a/Platform/SiFive/U7SeriesPkg/Library/PlatformSecPpiLib/PlatformSecPpiLib.c b/Platform/SiFive/U7SeriesPkg/Library/PlatformSecPpiLib/PlatformSecPpiLib.c
new file mode 100644
index 00000000000..245d54966f3
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Library/PlatformSecPpiLib/PlatformSecPpiLib.c
@@ -0,0 +1,151 @@
+/**@file
+ Library to install platform PPI before PEI Core
+
+ Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ );
+
+EFI_STATUS
+EFIAPI
+TemporaryRamDone (
+ VOID
+ );
+
+STATIC EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {
+ TemporaryRamMigration
+};
+
+STATIC EFI_PEI_TEMPORARY_RAM_DONE_PPI mTemporaryRamDonePpi = {
+ TemporaryRamDone
+};
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gEfiTemporaryRamSupportPpiGuid,
+ &mTemporaryRamSupportPpi
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiTemporaryRamDonePpiGuid,
+ &mTemporaryRamDonePpi
+ },
+};
+
+/** Temporary RAM migration function.
+
+ This function migrates the data from temporary RAM to permanent
+ memory.
+
+ @param[in] PeiServices PEI service
+ @param[in] TemporaryMemoryBase Temporary memory base address
+ @param[in] PermanentMemoryBase Permanent memory base address
+ @param[in] CopySize Size to copy
+
+**/
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ )
+{
+ VOID *OldHeap;
+ VOID *NewHeap;
+ VOID *OldStack;
+ VOID *NewStack;
+ EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext;
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Temp Mem Base:0x%Lx, Permanent Mem Base:0x%Lx, CopySize:0x%Lx\n",
+ __FUNCTION__,
+ TemporaryMemoryBase,
+ PermanentMemoryBase,
+ (UINT64)CopySize
+ ));
+
+ OldHeap = (VOID *)(UINTN)TemporaryMemoryBase;
+ NewHeap = (VOID *)((UINTN)PermanentMemoryBase + (CopySize >> 1));
+
+ OldStack = (VOID *)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
+ NewStack = (VOID *)(UINTN)PermanentMemoryBase;
+
+ CopyMem (NewHeap, OldHeap, CopySize >> 1); // Migrate Heap
+ CopyMem (NewStack, OldStack, CopySize >> 1); // Migrate Stack
+
+ //
+ // Reset firmware context pointer
+ //
+ GetFirmwareContextPointer (&FirmwareContext);
+ FirmwareContext = (VOID *)FirmwareContext + (unsigned long)((UINTN)NewStack - (UINTN)OldStack);
+ SetFirmwareContextPointer (FirmwareContext);
+
+ //
+ // Relocate PEI Service **
+ //
+ FirmwareContext->PeiServiceTable += (unsigned long)((UINTN)NewStack - (UINTN)OldStack);
+ DEBUG ((DEBUG_INFO, "%a: OpenSBI Firmware Context is relocated to 0x%x\n", __FUNCTION__, FirmwareContext));
+ DEBUG ((DEBUG_INFO, "OpenSBI Firmware Context at 0x%x\n", FirmwareContext));
+ DEBUG ((DEBUG_INFO, " PEI Service at 0x%x\n\n", FirmwareContext->PeiServiceTable));
+
+ register uintptr_t a0 asm ("a0") = (uintptr_t)((UINTN)NewStack - (UINTN)OldStack);
+
+ asm volatile ("add sp, sp, a0"::"r"(a0):);
+ return EFI_SUCCESS;
+}
+
+/** Temprary RAM done function.
+
+**/
+EFI_STATUS EFIAPI
+TemporaryRamDone (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "%a: 2nd time PEI core, temporary ram done.\n", __FUNCTION__));
+ return EFI_SUCCESS;
+}
+
+/** Return platform SEC PPI before PEI Core
+
+ @param[in,out] ThisPpiList Pointer to retrieve EFI_PEI_PPI_DESCRIPTOR.
+
+**/
+EFI_STATUS
+GetPlatformPrePeiCorePpiDescriptor (
+ IN OUT EFI_PEI_PPI_DESCRIPTOR **ThisPpiList
+ )
+{
+ *ThisPpiList = mPrivateDispatchTable;
+ return EFI_SUCCESS;
+}
diff --git a/Platform/SiFive/U7SeriesPkg/Library/PlatformSecPpiLib/PlatformSecPpiLib.inf b/Platform/SiFive/U7SeriesPkg/Library/PlatformSecPpiLib/PlatformSecPpiLib.inf
new file mode 100644
index 00000000000..a3b0aad050c
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Library/PlatformSecPpiLib/PlatformSecPpiLib.inf
@@ -0,0 +1,43 @@
+## @file
+# Library instance to to provide PPI before PEI Core
+#
+# Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = PlatformSecPpiLib
+ FILE_GUID = 8F8E049E-F193-427C-998E-1E8FE2612D94
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformSecPpiLib|PEI_CORE
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = RISCV64
+#
+
+[Sources]
+ PlatformSecPpiLib.c
+
+[Ppis]
+[Ppis]
+ gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
+ gEfiTemporaryRamDonePpiGuid # PPI ALWAYS_PRODUCED
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
+ Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ MemoryAllocationLib
+ PrintLib
+ RiscVFirmwareContextLib
diff --git a/Platform/SiFive/U7SeriesPkg/Library/RiscVPlatformTimerLib/RiscVPlatformTimerLib.S b/Platform/SiFive/U7SeriesPkg/Library/RiscVPlatformTimerLib/RiscVPlatformTimerLib.S
new file mode 100644
index 00000000000..9582a6d9203
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Library/RiscVPlatformTimerLib/RiscVPlatformTimerLib.S
@@ -0,0 +1,49 @@
+//------------------------------------------------------------------------------
+//
+// SiFive U7 Series Timer CSR functions.
+//
+// Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+// Copyright (c) 2022, Boyang Han
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//------------------------------------------------------------------------------
+#include
+#include
+#include
+
+.data
+
+.text
+.align 3
+
+.global ASM_PFX(RiscVReadMachineTimer)
+.global ASM_PFX(RiscVSetMachineTimerCmp)
+.global ASM_PFX(RiscVReadMachineTimerCmp)
+
+//
+// Read machine timer CSR.
+// @retval a0 : 64-bit machine timer.
+//
+ASM_PFX (RiscVReadMachineTimer):
+ li t1, CLINT_REG_MTIME
+ ld a0, (t1)
+ ret
+
+//
+// Set machine timer compare CSR.
+// @param a0 : UINT64
+//
+ASM_PFX (RiscVSetMachineTimerCmp):
+ li t1, CLINT_REG_MTIMECMP0
+ sd a0, (t1)
+ ret
+
+//
+// Read machine timer compare CSR.
+// @param a0 : UINT64
+//
+ASM_PFX (RiscVReadMachineTimerCmp):
+ li t1, CLINT_REG_MTIMECMP0
+ ld a0, (t1)
+ ret
diff --git a/Platform/SiFive/U7SeriesPkg/Library/RiscVPlatformTimerLib/RiscVPlatformTimerLib.inf b/Platform/SiFive/U7SeriesPkg/Library/RiscVPlatformTimerLib/RiscVPlatformTimerLib.inf
new file mode 100644
index 00000000000..503abb9d148
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Library/RiscVPlatformTimerLib/RiscVPlatformTimerLib.inf
@@ -0,0 +1,37 @@
+## @file
+# RISC-V CPU lib to override timer mechanism for U7 series platform.
+#
+# Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+# Copyright (c) 2022, Boyang Han
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RiscVPlatformTimerLib
+ FILE_GUID = C7FD58B3-F645-4268-90F8-BD301BD7EA49
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RiscVPlatformTimerLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = RISCV64
+#
+
+[Sources]
+
+[Sources.RISCV64]
+ RiscVPlatformTimerLib.S
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Platform/SiFive/U7SeriesPkg/U7SeriesPkg.dec
+ Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
+
+
+
diff --git a/Platform/SiFive/U7SeriesPkg/Library/SerialIoLib/SerialIoLib.inf b/Platform/SiFive/U7SeriesPkg/Library/SerialIoLib/SerialIoLib.inf
new file mode 100644
index 00000000000..b56d65e949d
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Library/SerialIoLib/SerialIoLib.inf
@@ -0,0 +1,39 @@
+## @file
+# Library instance for SerialIo library class
+#
+# Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = U7SerialPortLib
+ MODULE_UNI_FILE = U7SerialPortLib.uni
+ FILE_GUID = E610093B-BB19-42D7-8F98-1FFEE128FAA6
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = RISCV64
+#
+[Packages]
+ MdePkg/MdePkg.dec
+ Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
+ Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
+ Platform/SiFive/U7SeriesPkg/U7SeriesPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ RiscVOpensbiLib
+
+[FixedPcd]
+ gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdU7UartBase
+ gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdU7PlatformSystemClock
+
+[Sources]
+ SerialPortLib.c
diff --git a/Platform/SiFive/U7SeriesPkg/Library/SerialIoLib/SerialPortLib.c b/Platform/SiFive/U7SeriesPkg/Library/SerialIoLib/SerialPortLib.c
new file mode 100644
index 00000000000..6699e799337
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Library/SerialIoLib/SerialPortLib.c
@@ -0,0 +1,382 @@
+/** @file
+ UART Serial Port library functions
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include
+#include
+#include
+#include
+#include
+
+// ---------------------------------------------
+// UART Register Offsets
+// ---------------------------------------------
+
+#define UART_REG_IP 5
+#define UART_IP_RXWM 0x02
+
+#define UART_REG_TXFIFO 0
+#define UART_REG_RXFIFO 1
+#define UART_REG_TXCTRL 2
+#define UART_REG_RXCTRL 3
+#define UART_REG_IE 4
+#define UART_REG_IP 5
+#define UART_REG_DIV 6
+
+#define UART_TXFIFO_FULL 0x80000000
+#define UART_RXFIFO_EMPTY 0x80000000
+#define UART_RXFIFO_DATA 0x000000ff
+#define UART_TXCTRL_TXEN 0x1
+#define UART_RXCTRL_RXEN 0x1
+
+// ---------------------------------------------
+// UART Settings
+// ---------------------------------------------
+
+#define UART_BAUDRATE 115200
+#define SYS_CLK FixedPcdGet32(PcdU7PlatformSystemClock)
+
+BOOLEAN Initiated = TRUE;
+
+/**
+ Get value from serial port register.
+
+ @param RegIndex Register index
+
+ @retval Vale returned from from serial port.
+
+**/
+UINT32
+GetReg (
+ IN UINT32 RegIndex
+ )
+{
+ STATIC volatile UINT32 *const uart = (UINT32 *)FixedPcdGet32 (PcdU7UartBase);
+
+ return readl ((volatile void *)(uart + RegIndex));
+}
+
+/**
+ Set serial port register.
+
+ @param RegIndex Register index
+ @param Value Value write to Register
+
+**/
+VOID
+SetReg (
+ IN UINT32 RegIndex,
+ IN UINT32 Value
+ )
+{
+ STATIC volatile UINT32 *const uart = (UINT32 *)FixedPcdGet32 (PcdU7UartBase);
+
+ writel (Value, (volatile void *)(uart + RegIndex));
+}
+
+/**
+ Character output to serial port.
+
+ @param Ch The character to serial port.
+
+**/
+VOID
+SifiveUartPutChar (
+ IN UINT8 Ch
+ )
+{
+ while (GetReg (UART_REG_TXFIFO) & UART_TXFIFO_FULL) {
+ }
+
+ SetReg (UART_REG_TXFIFO, Ch);
+}
+
+/**
+ Get character from serial port.
+
+ @retval character The character from serial port.
+
+**/
+UINT32
+SifiveUartGetChar (
+ VOID
+ )
+{
+ UINT32 Ret;
+
+ Ret = GetReg (UART_REG_RXFIFO);
+ if (!(Ret & UART_RXFIFO_EMPTY)) {
+ return Ret & UART_RXFIFO_DATA;
+ }
+
+ return -1;
+}
+
+/**
+ Find minimum divisor divides in_freq to max_target_hz;
+ Based on uart driver n SiFive FSBL.
+
+ f_baud = f_in / (div + 1) => div = (f_in / f_baud) - 1
+ The nearest integer solution requires rounding up as to not exceed max_target_hz.
+ div = ceil(f_in / f_baud) - 1
+ = floor((f_in - 1 + f_baud) / f_baud) - 1
+ This should not overflow as long as (f_in - 1 + f_baud) does not exceed
+ 2^32 - 1, which is unlikely since we represent frequencies in kHz.
+
+ @param Freq The given clock to UART.
+ @param MaxTargetHZ Target baudrate.
+
+**/
+UINT32
+UartMinClkDivisor (
+ IN UINT64 Freq,
+ IN UINT64 MaxTargetHZ
+ )
+{
+ UINT64 Quotient;
+
+ Quotient = (Freq + MaxTargetHZ - 1) / (MaxTargetHZ);
+ if (Quotient == 0) {
+ return 0;
+ } else {
+ return Quotient - 1;
+ }
+}
+
+/**
+ Initialize the serial device hardware.
+
+ If no initialization is required, then return RETURN_SUCCESS.
+ If the serial device was successfuly initialized, then return RETURN_SUCCESS.
+ If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.
+
+ @retval RETURN_SUCCESS The serial device was initialized.
+ @retval RETURN_DEVICE_ERROR The serail device could not be initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+SerialPortInitialize (
+ VOID
+ )
+{
+ UINT32 Divisor;
+ UINT32 CurrentDivisor;
+
+ Divisor = UartMinClkDivisor (SYS_CLK / 2, UART_BAUDRATE);
+ if (Divisor == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CurrentDivisor = GetReg (UART_REG_DIV);
+ if (Divisor != CurrentDivisor) {
+ sifive_uart_init (FixedPcdGet32 (PcdU7UartBase), SYS_CLK / 2, UART_BAUDRATE);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write data from buffer to serial device.
+
+ Writes NumberOfBytes data bytes from Buffer to the serial device.
+ The number of bytes actually written to the serial device is returned.
+ If the return value is less than NumberOfBytes, then the write operation failed.
+
+ If Buffer is NULL, then ASSERT().
+
+ If NumberOfBytes is zero, then return 0.
+
+ @param Buffer Pointer to the data buffer to be written.
+ @param NumberOfBytes Number of bytes to written to the serial device.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes written to the serial device.
+ If this value is less than NumberOfBytes, then the write operation failed.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ UINTN Index;
+
+ if ((Buffer == NULL) || (Initiated == FALSE)) {
+ return 0;
+ }
+
+ for (Index = 0; Index < NumberOfBytes; Index++) {
+ SifiveUartPutChar (Buffer[Index]);
+ }
+
+ return Index;
+}
+
+/**
+ Reads data from a serial device into a buffer.
+
+ @param Buffer Pointer to the data buffer to store the data read from the serial device.
+ @param NumberOfBytes Number of bytes to read from the serial device.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes read from the serial device.
+ If this value is less than NumberOfBytes, then the read operation failed.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ UINTN Index;
+
+ if ((NULL == Buffer) || (Initiated == FALSE)) {
+ return 0;
+ }
+
+ for (Index = 0; Index < NumberOfBytes; Index++) {
+ Buffer[Index] = (UINT8)SifiveUartGetChar ();
+ }
+
+ return Index;
+}
+
+/**
+ Polls a serial device to see if there is any data waiting to be read.
+
+ Polls aserial device to see if there is any data waiting to be read.
+ If there is data waiting to be read from the serial device, then TRUE is returned.
+ If there is no data waiting to be read from the serial device, then FALSE is returned.
+
+ @retval TRUE Data is waiting to be read from the serial device.
+ @retval FALSE There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+ VOID
+ )
+{
+ STATIC volatile UINT32 *const uart = (UINT32 *)FixedPcdGet32 (PcdU7UartBase);
+ UINT32 IP;
+
+ if (Initiated == FALSE) {
+ return FALSE;
+ }
+
+ IP = MmioRead32 ((UINTN)(uart + UART_REG_IP));
+ if (IP & UART_IP_RXWM) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Sets the control bits on a serial device.
+
+ @param Control Sets the bits of Control that are settable.
+
+ @retval RETURN_SUCCESS The new control bits were set on the serial device.
+ @retval RETURN_UNSUPPORTED The serial device does not support this operation.
+ @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortSetControl (
+ IN UINT32 Control
+ )
+{
+ if (Initiated == FALSE) {
+ return EFI_NOT_READY;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Retrieve the status of the control bits on a serial device.
+
+ @param Control A pointer to return the current control signals from the serial device.
+
+ @retval RETURN_SUCCESS The control bits were read from the serial device.
+ @retval RETURN_UNSUPPORTED The serial device does not support this operation.
+ @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortGetControl (
+ OUT UINT32 *Control
+ )
+{
+ if (Initiated == FALSE) {
+ return EFI_NOT_READY;
+ }
+
+ *Control = 0;
+ return RETURN_SUCCESS;
+}
+
+/**
+ Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
+ data bits, and stop bits on a serial device.
+
+ @param BaudRate The requested baud rate. A BaudRate value of 0 will use the
+ device's default interface speed.
+ On output, the value actually set.
+ @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the
+ serial interface. A ReceiveFifoDepth value of 0 will use
+ the device's default FIFO depth.
+ On output, the value actually set.
+ @param Timeout The requested time out for a single character in microseconds.
+ This timeout applies to both the transmit and receive side of the
+ interface. A Timeout value of 0 will use the device's default time
+ out value.
+ On output, the value actually set.
+ @param Parity The type of parity to use on this serial device. A Parity value of
+ DefaultParity will use the device's default parity value.
+ On output, the value actually set.
+ @param DataBits The number of data bits to use on the serial device. A DataBits
+ vaule of 0 will use the device's default data bit setting.
+ On output, the value actually set.
+ @param StopBits The number of stop bits to use on this serial device. A StopBits
+ value of DefaultStopBits will use the device's default number of
+ stop bits.
+ On output, the value actually set.
+
+ @retval RETURN_SUCCESS The new attributes were set on the serial device.
+ @retval RETURN_UNSUPPORTED The serial device does not support this operation.
+ @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value.
+ @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortSetAttributes (
+ IN OUT UINT64 *BaudRate,
+ IN OUT UINT32 *ReceiveFifoDepth,
+ IN OUT UINT32 *Timeout,
+ IN OUT EFI_PARITY_TYPE *Parity,
+ IN OUT UINT8 *DataBits,
+ IN OUT EFI_STOP_BITS_TYPE *StopBits
+ )
+{
+ if (Initiated == FALSE) {
+ return EFI_NOT_READY;
+ }
+
+ return RETURN_SUCCESS;
+}
diff --git a/Platform/SiFive/U7SeriesPkg/Library/SerialIoLib/U5SerialPortLib.uni b/Platform/SiFive/U7SeriesPkg/Library/SerialIoLib/U5SerialPortLib.uni
new file mode 100644
index 00000000000..dcc8507095e
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Library/SerialIoLib/U5SerialPortLib.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Library instance for SerialIo library class
+//
+// Library instance for SerialIO library class.
+//
+// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Library instance for SerialIO library class"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Library instance for SerialIO library class."
+
diff --git a/Platform/SiFive/U7SeriesPkg/Readme.md b/Platform/SiFive/U7SeriesPkg/Readme.md
new file mode 100644
index 00000000000..039c04d05a1
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Readme.md
@@ -0,0 +1,39 @@
+# Introduction of SiFive U7 Series Platforms
+U7SeriesPkg provides the common EDK2 libraries and drivers for SiFive U7 series
+platforms. Currently the supported platforms are Freedom U740 HiFive Unmatched
+platform.
+
+## U740 Platform
+This is a platform package used for the SiFive Freedom U740 HiFive Unmatched
+development board.
+
+To test this package on hardware, first build EDK2 with:
+```
+build -a RISCV64 -t GCC5 -p Platform/SiFive/U7SeriesPkg/FreedomU740HiFiveUnmatchBoard/U740.dsc
+```
+The produced image is located at
+```
+./Build/FreedomU740HiFiveUnmatched/DEBUG_GCC5/FV/U740.fd
+```
+
+Then clone and build the fsbl (first stage bootloader, I think this will
+eventually reside in the UEFI PEI stage?):
+```
+git clone https://github.com/yqszxx/freedom-u740-c000-bootloader
+cd freedom-u740-c000-bootloader
+CROSSCOMPILE=riscv64-unknown-elf- make
+```
+And you will get the fsbl image as `fsbl.bin`.
+
+Next prepare a micro-SD card, properly partition it, and write the images.
+```
+sudo sgdisk -g --clear -a 1 \
+ --new=1:34:2081 --change-name=1:fsbl --typecode=1:5B193300-FC78-40CD-8002-E86C45580B47 \
+ --new=2:2082:34849 --change-name=2:edk2 --typecode=2:2E54B353-1271-4842-806F-E436D6AF6985
+ /dev/sdX
+sudo dd if=fsbl.bin of=/dev/sdX1
+sudo dd if=U740.fd of=/dev/sdX2
+```
+
+Insert the card into the slot on the unmatched board, press power button, expect
+to see the UEFI shell on serial console.
diff --git a/Platform/SiFive/U7SeriesPkg/U7SeriesPkg.dec b/Platform/SiFive/U7SeriesPkg/U7SeriesPkg.dec
new file mode 100644
index 00000000000..8ae7fa46984
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/U7SeriesPkg.dec
@@ -0,0 +1,35 @@
+## @file U7SeriesPkg.dec
+# This Package provides modules and libraries.for SiFive U7 series platforms.
+#
+# Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+# Copyright (c) 2022, Boyang Han
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x0001001b
+ PACKAGE_NAME = U7SeriesPkg
+ PACKAGE_UNI_FILE = U7SeriesPkg.uni
+ PACKAGE_GUID = 402E1931-A807-4100-B119-5C7415D878AC
+ PACKAGE_VERSION = 1.0
+
+[Includes]
+ Include
+
+[LibraryClasses]
+
+[Guids]
+ gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid = {0x9034A58E, 0x759E, 0x41E2, { 0xAB, 0x11, 0xF5, 0xAC, 0x32, 0x33, 0x61, 0x00 }}
+
+[PcdsFixedAtBuild]
+ gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdU7PlatformSystemClock|0x0|UINT32|0x00001000
+ gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdNumberofU7Cores|0x8|UINT32|0x00001001
+ gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdE5MCSupported|TRUE|BOOLEAN|0x00001002
+ gSiFiveU7SeriesPlatformsPkgTokenSpaceGuid.PcdU7UartBase|0x0|UINT32|0x00001003
+
+[PcdsPatchableInModule]
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ U7SeriesPkg.uni
diff --git a/Platform/SiFive/U7SeriesPkg/U7SeriesPkg.uni b/Platform/SiFive/U7SeriesPkg/U7SeriesPkg.uni
new file mode 100644
index 00000000000..b348d9bebaa
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/U7SeriesPkg.uni
@@ -0,0 +1,14 @@
+// /** @file
+// SiFive U7 Series Package Localized Strings and Content.
+//
+// Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+// Copyright (c) 2022, Boyang Han
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_PACKAGE_ABSTRACT #language en-US "Provides SiFIve RISC-V U7 series platform modules and libraries"
+
+#string STR_PACKAGE_DESCRIPTION #language en-US "This Package SiFIve RISC-V U7 series platform modules and libraries."
diff --git a/Platform/SiFive/U7SeriesPkg/U7SeriesPkgExtra.uni b/Platform/SiFive/U7SeriesPkg/U7SeriesPkgExtra.uni
new file mode 100644
index 00000000000..83275f55eef
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/U7SeriesPkgExtra.uni
@@ -0,0 +1,13 @@
+// /** @file
+// SiFive U7 Series Package Localized Strings and Content.
+//
+// Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+// Copyright (c) 2022, Boyang Han
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_PACKAGE_NAME
+#language en-US
+"SiFive U7 series platform package"
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbInfo.c b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbInfo.c
new file mode 100644
index 00000000000..fc0646665dd
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbInfo.c
@@ -0,0 +1,130 @@
+/**@file
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (c) 2006, Intel Corporation. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ Module Name:
+
+ FvbInfo.c
+
+ Abstract:
+
+ Defines data structure that is the volume header found.These data is intent
+ to decouple FVB driver with FV header.
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include
+
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include
+//
+// The Library classes this module consumes
+//
+#include
+#include
+
+typedef struct {
+ UINT64 FvLength;
+ EFI_FIRMWARE_VOLUME_HEADER FvbInfo;
+ //
+ // EFI_FV_BLOCK_MAP_ENTRY ExtraBlockMap[n];//n=0
+ //
+ EFI_FV_BLOCK_MAP_ENTRY End[1];
+} EFI_FVB_MEDIA_INFO;
+
+EFI_FVB_MEDIA_INFO mPlatformFvbMediaInfo[] = {
+ //
+ // Systen NvStorage FVB
+ //
+ {
+ FixedPcdGet32 (PcdFlashNvStorageVariableSize) +
+ FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
+ FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize),
+ {
+ {
+ 0,
+ }, // ZeroVector[16]
+ EFI_SYSTEM_NV_DATA_FV_GUID,
+ FixedPcdGet32 (PcdFlashNvStorageVariableSize) +
+ FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
+ FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize),
+ EFI_FVH_SIGNATURE,
+ EFI_FVB2_MEMORY_MAPPED |
+ EFI_FVB2_READ_ENABLED_CAP |
+ EFI_FVB2_READ_STATUS |
+ EFI_FVB2_WRITE_ENABLED_CAP |
+ EFI_FVB2_WRITE_STATUS |
+ EFI_FVB2_ERASE_POLARITY |
+ EFI_FVB2_ALIGNMENT_16,
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),
+ 0, // CheckSum
+ 0, // ExtHeaderOffset
+ {
+ 0,
+ }, // Reserved[1]
+ 2, // Revision
+ {
+ {
+ (FixedPcdGet32 (PcdFlashNvStorageVariableSize) +
+ FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
+ FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize)) /
+ FixedPcdGet32 (PcdVariableFdBlockSize),
+ FixedPcdGet32 (PcdVariableFdBlockSize),
+ }
+ } // BlockMap[1]
+ },
+ {
+ {
+ 0,
+ 0
+ }
+ } // End[1]
+ }
+};
+
+EFI_STATUS
+GetFvbInfo (
+ IN UINT64 FvLength,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo
+ )
+{
+ STATIC BOOLEAN Checksummed = FALSE;
+ UINTN Index;
+
+ if (!Checksummed) {
+ for (Index = 0;
+ Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_INFO);
+ Index += 1)
+ {
+ UINT16 Checksum;
+ mPlatformFvbMediaInfo[Index].FvbInfo.Checksum = 0;
+ Checksum = CalculateCheckSum16 (
+ (UINT16 *)&mPlatformFvbMediaInfo[Index].FvbInfo,
+ mPlatformFvbMediaInfo[Index].FvbInfo.HeaderLength
+ );
+ mPlatformFvbMediaInfo[Index].FvbInfo.Checksum = Checksum;
+ }
+
+ Checksummed = TRUE;
+ }
+
+ for (Index = 0;
+ Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_INFO);
+ Index += 1)
+ {
+ if (mPlatformFvbMediaInfo[Index].FvLength == FvLength) {
+ *FvbInfo = &mPlatformFvbMediaInfo[Index].FvbInfo;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
new file mode 100644
index 00000000000..8b71eca173c
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
@@ -0,0 +1,84 @@
+## @file
+# Component description file for RAM Flash Fimware Volume Block DXE driver
+# module.
+#
+# This DXE runtime driver implements and produces the Fimware Volue Block
+# Protocol for a RAM flash device.
+#
+# Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = FvbServicesRuntimeDxe
+ FILE_GUID = B04036D3-4C60-43D6-9850-0FCC090FF054
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = FvbInitialize
+
+#
+# The following information is for reference only and not required by the build
+# tools.
+#
+# VALID_ARCHITECTURES = RISCV64
+#
+
+[Sources]
+ FvbInfo.c
+ FwBlockService.c
+ FwBlockServiceDxe.c
+ RamFlash.c
+ RamFlashDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ PcdLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeLib
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED
+ # gEfiEventVirtualAddressChangeGuid # Create Event: EVENT_GROUP_GUID
+
+[Protocols]
+ gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
+ gEfiDevicePathProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
+ gPcdProtocolGuid # SOMETIMES_CONSUMES
+ gEfiPcdProtocolGuid # CONSUMES
+ gGetPcdInfoProtocolGuid # SOMETIMES_CONSUMES
+ gEfiGetPcdInfoProtocolGuid # SOMETIMES_CONSUMES
+
+[FixedPcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+ gUefiRiscVPlatformPkgTokenSpaceGuid.PcdPlatformFlashNvStorageVariableBase
+ gUefiRiscVPlatformPkgTokenSpaceGuid.PcdPlatformFlashNvStorageFtwWorkingBase
+ gUefiRiscVPlatformPkgTokenSpaceGuid.PcdPlatformFlashNvStorageFtwSpareBase
+ gUefiRiscVPlatformPkgTokenSpaceGuid.PcdVariableFdBaseAddress
+ gUefiRiscVPlatformPkgTokenSpaceGuid.PcdVariableFdSize
+ gUefiRiscVPlatformPkgTokenSpaceGuid.PcdVariableFdBlockSize
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
+
+[Depex]
+ gEfiPcdProtocolGuid
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.c b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.c
new file mode 100644
index 00000000000..c1721abe7aa
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.c
@@ -0,0 +1,1163 @@
+/**@file
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ Module Name:
+
+ FWBlockService.c
+
+ Abstract:
+
+ Revision History
+
+**/
+
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include
+#include
+
+//
+// The Library classes this module consumes
+//
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "FwBlockService.h"
+#include "RamFlash.h"
+
+#define EFI_FVB2_STATUS \
+ (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)
+
+ESAL_FWB_GLOBAL *mFvbModuleGlobal;
+
+FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_MEMMAP_DP,
+ {
+ (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
+ (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)
+ }
+ },
+ EfiMemoryMappedIO,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+};
+
+FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {
+ {
+ {
+ MEDIA_DEVICE_PATH,
+ MEDIA_PIWG_FW_VOL_DP,
+ {
+ (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),
+ (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)
+ }
+ },
+ { 0 }
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+};
+
+EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {
+ FVB_DEVICE_SIGNATURE,
+ NULL,
+ 0,
+ {
+ FvbProtocolGetAttributes,
+ FvbProtocolSetAttributes,
+ FvbProtocolGetPhysicalAddress,
+ FvbProtocolGetBlockSize,
+ FvbProtocolRead,
+ FvbProtocolWrite,
+ FvbProtocolEraseBlocks,
+ NULL
+ }
+};
+
+/*++
+
+ Routine Description:
+ Retrieves the physical address of a memory mapped FV
+
+ Arguments:
+ Instance - The FV instance whose base address is going to be
+ returned
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+ FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure
+
+ Returns:
+ EFI_SUCCESS - Successfully returns
+ EFI_INVALID_PARAMETER - Instance not found
+
+--*/
+EFI_STATUS
+GetFvbInstance (
+ IN UINTN Instance,
+ IN ESAL_FWB_GLOBAL *Global,
+ OUT EFI_FW_VOL_INSTANCE **FwhInstance
+ )
+{
+ EFI_FW_VOL_INSTANCE *FwhRecord;
+
+ *FwhInstance = NULL;
+ if (Instance >= Global->NumFv) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Find the right instance of the FVB private data
+ //
+ FwhRecord = Global->FvInstance;
+ while (Instance > 0) {
+ FwhRecord = (EFI_FW_VOL_INSTANCE *)
+ (
+ (UINTN)FwhRecord + FwhRecord->VolumeHeader.HeaderLength +
+ (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
+ );
+ Instance--;
+ }
+
+ *FwhInstance = FwhRecord;
+
+ return EFI_SUCCESS;
+}
+
+/*++
+
+ Routine Description:
+ Retrieves the physical address of a memory mapped FV
+
+ Arguments:
+ Instance - The FV instance whose base address is going to be
+ returned
+ Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
+ that on successful return, contains the base
+ address of the firmware volume.
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+
+ Returns:
+ EFI_SUCCESS - Successfully returns
+ EFI_INVALID_PARAMETER - Instance not found
+
+--*/
+EFI_STATUS
+FvbGetPhysicalAddress (
+ IN UINTN Instance,
+ OUT EFI_PHYSICAL_ADDRESS *Address,
+ IN ESAL_FWB_GLOBAL *Global
+ )
+{
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ EFI_STATUS Status;
+
+ //
+ // Find the right instance of the FVB private data
+ //
+ Status = GetFvbInstance (Instance, Global, &FwhInstance);
+ ASSERT_EFI_ERROR (Status);
+ *Address = FwhInstance->FvBase;
+
+ return EFI_SUCCESS;
+}
+
+/*++
+
+ Routine Description:
+ Retrieves attributes, insures positive polarity of attribute bits, returns
+ resulting attributes in output parameter
+
+ Arguments:
+ Instance - The FV instance whose attributes is going to be
+ returned
+ Attributes - Output buffer which contains attributes
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+
+ Returns:
+ EFI_SUCCESS - Successfully returns
+ EFI_INVALID_PARAMETER - Instance not found
+
+--*/
+EFI_STATUS
+FvbGetVolumeAttributes (
+ IN UINTN Instance,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
+ IN ESAL_FWB_GLOBAL *Global
+ )
+{
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ EFI_STATUS Status;
+
+ //
+ // Find the right instance of the FVB private data
+ //
+ Status = GetFvbInstance (Instance, Global, &FwhInstance);
+ ASSERT_EFI_ERROR (Status);
+ *Attributes = FwhInstance->VolumeHeader.Attributes;
+
+ return EFI_SUCCESS;
+}
+
+/*++
+
+ Routine Description:
+ Retrieves the starting address of an LBA in an FV
+
+ Arguments:
+ Instance - The FV instance which the Lba belongs to
+ Lba - The logical block address
+ LbaAddress - On output, contains the physical starting address
+ of the Lba
+ LbaLength - On output, contains the length of the block
+ NumOfBlocks - A pointer to a caller allocated UINTN in which the
+ number of consecutive blocks starting with Lba is
+ returned. All blocks in this range have a size of
+ BlockSize
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+
+ Returns:
+ EFI_SUCCESS - Successfully returns
+ EFI_INVALID_PARAMETER - Instance not found
+
+--*/
+EFI_STATUS
+FvbGetLbaAddress (
+ IN UINTN Instance,
+ IN EFI_LBA Lba,
+ OUT UINTN *LbaAddress,
+ OUT UINTN *LbaLength,
+ OUT UINTN *NumOfBlocks,
+ IN ESAL_FWB_GLOBAL *Global
+ )
+{
+ UINT32 NumBlocks;
+ UINT32 BlockLength;
+ UINTN Offset;
+ EFI_LBA StartLba;
+ EFI_LBA NextLba;
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
+ EFI_STATUS Status;
+
+ //
+ // Find the right instance of the FVB private data
+ //
+ Status = GetFvbInstance (Instance, Global, &FwhInstance);
+ ASSERT_EFI_ERROR (Status);
+
+ StartLba = 0;
+ Offset = 0;
+ BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]);
+
+ //
+ // Parse the blockmap of the FV to find which map entry the Lba belongs to
+ //
+ while (TRUE) {
+ NumBlocks = BlockMap->NumBlocks;
+ BlockLength = BlockMap->Length;
+
+ if ((NumBlocks == 0) || (BlockLength == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NextLba = StartLba + NumBlocks;
+
+ //
+ // The map entry found
+ //
+ if ((Lba >= StartLba) && (Lba < NextLba)) {
+ Offset = Offset + (UINTN)MultU64x32 ((Lba - StartLba), BlockLength);
+ if (LbaAddress != NULL) {
+ *LbaAddress = FwhInstance->FvBase + Offset;
+ }
+
+ if (LbaLength != NULL) {
+ *LbaLength = BlockLength;
+ }
+
+ if (NumOfBlocks != NULL) {
+ *NumOfBlocks = (UINTN)(NextLba - Lba);
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ StartLba = NextLba;
+ Offset = Offset + NumBlocks * BlockLength;
+ BlockMap++;
+ }
+}
+
+/*++
+
+ Routine Description:
+ Modifies the current settings of the firmware volume according to the
+ input parameter, and returns the new setting of the volume
+
+ Arguments:
+ Instance - The FV instance whose attributes is going to be
+ modified
+ Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
+ containing the desired firmware volume settings.
+ On successful return, it contains the new settings
+ of the firmware volume
+ Global - Pointer to ESAL_FWB_GLOBAL that contains all
+ instance data
+
+ Returns:
+ EFI_SUCCESS - Successfully returns
+ EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified
+ EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
+ in conflict with the capabilities as declared in
+ the firmware volume header
+
+--*/
+EFI_STATUS
+FvbSetVolumeAttributes (
+ IN UINTN Instance,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
+ IN ESAL_FWB_GLOBAL *Global
+ )
+{
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ EFI_FVB_ATTRIBUTES_2 OldAttributes;
+ EFI_FVB_ATTRIBUTES_2 *AttribPtr;
+ UINT32 Capabilities;
+ UINT32 OldStatus;
+ UINT32 NewStatus;
+ EFI_STATUS Status;
+ EFI_FVB_ATTRIBUTES_2 UnchangedAttributes;
+
+ //
+ // Find the right instance of the FVB private data
+ //
+ Status = GetFvbInstance (Instance, Global, &FwhInstance);
+ ASSERT_EFI_ERROR (Status);
+
+ AttribPtr =
+ (EFI_FVB_ATTRIBUTES_2 *)&(FwhInstance->VolumeHeader.Attributes);
+ OldAttributes = *AttribPtr;
+ Capabilities = OldAttributes & (EFI_FVB2_READ_DISABLED_CAP | \
+ EFI_FVB2_READ_ENABLED_CAP | \
+ EFI_FVB2_WRITE_DISABLED_CAP | \
+ EFI_FVB2_WRITE_ENABLED_CAP | \
+ EFI_FVB2_LOCK_CAP \
+ );
+ OldStatus = OldAttributes & EFI_FVB2_STATUS;
+ NewStatus = *Attributes & EFI_FVB2_STATUS;
+
+ UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP | \
+ EFI_FVB2_READ_ENABLED_CAP | \
+ EFI_FVB2_WRITE_DISABLED_CAP | \
+ EFI_FVB2_WRITE_ENABLED_CAP | \
+ EFI_FVB2_LOCK_CAP | \
+ EFI_FVB2_STICKY_WRITE | \
+ EFI_FVB2_MEMORY_MAPPED | \
+ EFI_FVB2_ERASE_POLARITY | \
+ EFI_FVB2_READ_LOCK_CAP | \
+ EFI_FVB2_WRITE_LOCK_CAP | \
+ EFI_FVB2_ALIGNMENT;
+
+ //
+ // Some attributes of FV is read only can *not* be set
+ //
+ if ((OldAttributes & UnchangedAttributes) ^
+ (*Attributes & UnchangedAttributes))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If firmware volume is locked, no status bit can be updated
+ //
+ if (OldAttributes & EFI_FVB2_LOCK_STATUS) {
+ if (OldStatus ^ NewStatus) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+
+ //
+ // Test read disable
+ //
+ if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {
+ if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Test read enable
+ //
+ if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {
+ if (NewStatus & EFI_FVB2_READ_STATUS) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Test write disable
+ //
+ if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {
+ if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Test write enable
+ //
+ if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {
+ if (NewStatus & EFI_FVB2_WRITE_STATUS) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Test lock
+ //
+ if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {
+ if (NewStatus & EFI_FVB2_LOCK_STATUS) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));
+ *AttribPtr = (*AttribPtr) | NewStatus;
+ *Attributes = *AttribPtr;
+
+ return EFI_SUCCESS;
+}
+
+/*++
+
+ Routine Description:
+
+ Retrieves the physical address of the device.
+
+ Arguments:
+
+ This - Calling context
+ Address - Output buffer containing the address.
+
+ Returns:
+ EFI_SUCCESS - Successfully returns
+
+--*/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ return FvbGetPhysicalAddress (
+ FvbDevice->Instance,
+ Address,
+ mFvbModuleGlobal
+ );
+}
+
+/*++
+
+ Routine Description:
+ Retrieve the size of a logical block
+
+ Arguments:
+ This - Calling context
+ Lba - Indicates which block to return the size for.
+ BlockSize - A pointer to a caller allocated UINTN in which
+ the size of the block is returned
+ NumOfBlocks - a pointer to a caller allocated UINTN in which the
+ number of consecutive blocks starting with Lba is
+ returned. All blocks in this range have a size of
+ BlockSize
+
+ Returns:
+ EFI_SUCCESS - The firmware volume was read successfully and
+ contents are in Buffer
+
+--*/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN CONST EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumOfBlocks
+ )
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ return FvbGetLbaAddress (
+ FvbDevice->Instance,
+ Lba,
+ NULL,
+ BlockSize,
+ NumOfBlocks,
+ mFvbModuleGlobal
+ );
+}
+
+/*++
+
+ Routine Description:
+ Retrieves Volume attributes. No polarity translations are done.
+
+ Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+ Returns:
+ EFI_SUCCESS - Successfully returns
+
+--*/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ return FvbGetVolumeAttributes (
+ FvbDevice->Instance,
+ Attributes,
+ mFvbModuleGlobal
+ );
+}
+
+/*++
+
+ Routine Description:
+ Sets Volume attributes. No polarity translations are done.
+
+ Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+ Returns:
+ EFI_SUCCESS - Successfully returns
+
+--*/
+EFI_STATUS
+EFIAPI
+FvbProtocolSetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ return FvbSetVolumeAttributes (
+ FvbDevice->Instance,
+ Attributes,
+ mFvbModuleGlobal
+ );
+}
+
+/*++
+
+ Routine Description:
+
+ The EraseBlock() function erases one or more blocks as denoted by the
+ variable argument list. The entire parameter list of blocks must be
+ verified prior to erasing any blocks. If a block is requested that does
+ not exist within the associated firmware volume (it has a larger index than
+ the last block of the firmware volume), the EraseBlock() function must
+ return EFI_INVALID_PARAMETER without modifying the contents of the firmware
+ volume.
+
+ Arguments:
+ This - Calling context
+ ... - Starting LBA followed by Number of Lba to erase.
+ a -1 to terminate the list.
+
+ Returns:
+ EFI_SUCCESS - The erase request was successfully completed
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and
+ could not be written. Firmware device may have been
+ partially erased
+
+--*/
+EFI_STATUS
+EFIAPI
+FvbProtocolEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ ...
+ )
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ UINTN NumOfBlocks;
+ VA_LIST args;
+ EFI_LBA StartingLba;
+ UINTN NumOfLba;
+ EFI_STATUS Status;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ Status = GetFvbInstance (
+ FvbDevice->Instance,
+ mFvbModuleGlobal,
+ &FwhInstance
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ NumOfBlocks = FwhInstance->NumOfBlocks;
+
+ VA_START (args, This);
+
+ do {
+ StartingLba = VA_ARG (args, EFI_LBA);
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ break;
+ }
+
+ NumOfLba = VA_ARG (args, UINT32);
+
+ //
+ // Check input parameters
+ //
+ if ((NumOfLba == 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) {
+ VA_END (args);
+ return EFI_INVALID_PARAMETER;
+ }
+ } while (1);
+
+ VA_END (args);
+
+ VA_START (args, This);
+ do {
+ StartingLba = VA_ARG (args, EFI_LBA);
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ break;
+ }
+
+ NumOfLba = VA_ARG (args, UINT32);
+
+ while (NumOfLba > 0) {
+ Status = RamFlashEraseBlock (StartingLba);
+ if (EFI_ERROR (Status)) {
+ VA_END (args);
+ return Status;
+ }
+
+ StartingLba++;
+ NumOfLba--;
+ }
+ } while (1);
+
+ VA_END (args);
+
+ return EFI_SUCCESS;
+}
+
+/*++
+
+ Routine Description:
+
+ Writes data beginning at Lba:Offset from FV. The write terminates either
+ when *NumBytes of data have been written, or when a block boundary is
+ reached. *NumBytes is updated to reflect the actual number of bytes
+ written. The write opertion does not include erase. This routine will
+ attempt to write only the specified bytes. If the writes do not stick,
+ it will return an error.
+
+ Arguments:
+ This - Calling context
+ Lba - Block in which to begin write
+ Offset - Offset in the block at which to begin write
+ NumBytes - On input, indicates the requested write size. On
+ output, indicates the actual number of bytes
+ written
+ Buffer - Buffer containing source data for the write.
+
+ Returns:
+ EFI_SUCCESS - The firmware volume was written successfully
+ EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,
+ NumBytes contains the total number of bytes
+ actually written
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and
+ could not be written
+ EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
+
+--*/
+EFI_STATUS
+EFIAPI
+FvbProtocolWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ return RamFlashWrite (Lba, Offset, NumBytes, Buffer);
+}
+
+/*++
+
+ Routine Description:
+
+ Reads data beginning at Lba:Offset from FV. The Read terminates either
+ when *NumBytes of data have been read, or when a block boundary is
+ reached. *NumBytes is updated to reflect the actual number of bytes
+ written. The write opertion does not include erase. This routine will
+ attempt to write only the specified bytes. If the writes do not stick,
+ it will return an error.
+
+ Arguments:
+ This - Calling context
+ Lba - Block in which to begin Read
+ Offset - Offset in the block at which to begin Read
+ NumBytes - On input, indicates the requested write size. On
+ output, indicates the actual number of bytes Read
+ Buffer - Buffer containing source data for the Read.
+
+ Returns:
+ EFI_SUCCESS - The firmware volume was read successfully and
+ contents are in Buffer
+ EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,
+ NumBytes contains the total number of bytes
+ returned in Buffer
+ EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and
+ could not be read
+ EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
+
+--*/
+EFI_STATUS
+EFIAPI
+FvbProtocolRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN CONST EFI_LBA Lba,
+ IN CONST UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ return RamFlashRead (Lba, Offset, NumBytes, Buffer);
+}
+
+/*++
+
+ Routine Description:
+ Check the integrity of firmware volume header
+
+ Arguments:
+ FwVolHeader - A pointer to a firmware volume header
+
+ Returns:
+ EFI_SUCCESS - The firmware volume is consistent
+ EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an
+ FV
+
+--*/
+EFI_STATUS
+ValidateFvHeader (
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
+ )
+{
+ UINT16 Checksum;
+
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
+ (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
+ (FwVolHeader->FvLength == ((UINTN)-1)) ||
+ ((FwVolHeader->HeaderLength & 0x01) != 0)
+ )
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Verify the header checksum
+ //
+
+ Checksum = CalculateSum16 (
+ (UINT16 *)FwVolHeader,
+ FwVolHeader->HeaderLength
+ );
+ if (Checksum != 0) {
+ UINT16 Expected;
+
+ Expected =
+ (UINT16)(((UINTN)FwVolHeader->Checksum + 0x10000 - Checksum) & 0xffff);
+
+ DEBUG ((
+ DEBUG_INFO,
+ "FV@%p Checksum is 0x%x, expected 0x%x\n",
+ FwVolHeader,
+ FwVolHeader->Checksum,
+ Expected
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+MarkMemoryRangeForRuntimeAccess (
+ EFI_PHYSICAL_ADDRESS BaseAddress,
+ UINTN Length
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Mark flash region as runtime memory
+ //
+ Status = gDS->RemoveMemorySpace (
+ BaseAddress,
+ Length
+ );
+
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeSystemMemory,
+ BaseAddress,
+ Length,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->AllocatePages (
+ AllocateAddress,
+ EfiRuntimeServicesData,
+ EFI_SIZE_TO_PAGES (Length),
+ &BaseAddress
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+InitializeVariableFvHeader (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_HEADER *GoodFwVolHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ UINTN Length;
+ UINTN WriteLength;
+ UINTN BlockSize;
+
+ FwVolHeader =
+ (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)
+ PcdGet32 (PcdPlatformFlashNvStorageVariableBase);
+
+ Length =
+ (FixedPcdGet32 (PcdFlashNvStorageVariableSize) +
+ FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
+ FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize));
+
+ BlockSize = PcdGet32 (PcdVariableFdBlockSize);
+
+ Status = ValidateFvHeader (FwVolHeader);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "ValidateFvHeader() return ok\n"));
+ if ((FwVolHeader->FvLength != Length) ||
+ (FwVolHeader->BlockMap[0].Length != BlockSize))
+ {
+ Status = EFI_VOLUME_CORRUPTED;
+ DEBUG ((DEBUG_INFO, "FwVolHeader->FvLength(%x) != Length(%x) || FwVolHeader->BlockMap[0].Length(%x) != BlockSize(%x)\n", FwVolHeader->FvLength, Length, FwVolHeader->BlockMap[0].Length, BlockSize));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "ValidateFvHeader() return failed\n"));
+ }
+
+ if (EFI_ERROR (Status)) {
+ UINTN Offset;
+ UINTN Start;
+
+ DEBUG ((
+ DEBUG_INFO,
+ "Variable FV header is not valid. It will be reinitialized.\n"
+ ));
+
+ //
+ // Get FvbInfo to provide in FwhInstance.
+ //
+ Status = GetFvbInfo (Length, &GoodFwVolHeader);
+ ASSERT (!EFI_ERROR (Status));
+
+ Start = (UINTN)(UINT8 *)FwVolHeader - PcdGet32 (PcdVariableFdBaseAddress);
+ ASSERT (Start % BlockSize == 0 && Length % BlockSize == 0);
+ ASSERT (GoodFwVolHeader->HeaderLength <= BlockSize);
+
+ //
+ // Erase all the blocks
+ //
+ for (Offset = Start; Offset < Start + Length; Offset += BlockSize) {
+ Status = RamFlashEraseBlock (Offset / BlockSize);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Write good FV header
+ //
+ WriteLength = GoodFwVolHeader->HeaderLength;
+ Status = RamFlashWrite (
+ Start / BlockSize,
+ 0,
+ &WriteLength,
+ (UINT8 *)GoodFwVolHeader
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (WriteLength == GoodFwVolHeader->HeaderLength);
+ }
+
+ return Status;
+}
+
+/*++
+
+ Routine Description:
+ This function does common initialization for FVB services
+
+ Arguments:
+
+ Returns:
+
+--*/
+EFI_STATUS
+EFIAPI
+FvbInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ UINT32 BufferSize;
+ EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ UINT32 MaxLbaSize;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINTN Length;
+ UINTN NumOfBlocks;
+
+ if (EFI_ERROR (RamFlashInitialize ())) {
+ //
+ // Return an error so image will be unloaded
+ //
+ DEBUG ((
+ DEBUG_INFO,
+ "RAM flash was not detected. Writable FVB is not being installed.\n"
+ ));
+ return EFI_WRITE_PROTECTED;
+ }
+
+ //
+ // Allocate runtime services data for global variable, which contains
+ // the private data of all firmware volume block instances
+ //
+ mFvbModuleGlobal = AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL));
+ ASSERT (mFvbModuleGlobal != NULL);
+
+ BaseAddress = (UINTN)PcdGet32 (PcdVariableFdBaseAddress);
+ Length = PcdGet32 (PcdVariableFdSize);
+ DEBUG ((DEBUG_INFO, "FvbInitialize(): BaseAddress: 0x%lx Length:0x%x\n", BaseAddress, Length));
+ Status = InitializeVariableFvHeader ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_INFO,
+ "RAM Flash: Unable to initialize variable FV header\n"
+ ));
+ return EFI_WRITE_PROTECTED;
+ }
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
+ Status = ValidateFvHeader (FwVolHeader);
+ if (EFI_ERROR (Status)) {
+ //
+ // Get FvbInfo
+ //
+ DEBUG ((DEBUG_INFO, "FvbInitialize(): ValidateFvHeader() return error(%r)\n", Status));
+
+ Status = GetFvbInfo (Length, &FwVolHeader);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "FvbInitialize(): GetFvbInfo (Length, &FwVolHeader) return error(%r)\n", Status));
+ return EFI_WRITE_PROTECTED;
+ }
+ }
+
+ BufferSize = (sizeof (EFI_FW_VOL_INSTANCE) +
+ FwVolHeader->HeaderLength -
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER)
+ );
+ mFvbModuleGlobal->FvInstance = AllocateRuntimePool (BufferSize);
+ ASSERT (mFvbModuleGlobal->FvInstance != NULL);
+
+ FwhInstance = mFvbModuleGlobal->FvInstance;
+
+ mFvbModuleGlobal->NumFv = 0;
+ MaxLbaSize = 0;
+
+ FwVolHeader =
+ (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)
+ PcdGet32 (PcdPlatformFlashNvStorageVariableBase);
+
+ FwhInstance->FvBase = (UINTN)BaseAddress;
+
+ CopyMem (
+ (UINTN *)&(FwhInstance->VolumeHeader),
+ (UINTN *)FwVolHeader,
+ FwVolHeader->HeaderLength
+ );
+ FwVolHeader = &(FwhInstance->VolumeHeader);
+
+ NumOfBlocks = 0;
+
+ for (PtrBlockMapEntry = FwVolHeader->BlockMap;
+ PtrBlockMapEntry->NumBlocks != 0;
+ PtrBlockMapEntry++)
+ {
+ //
+ // Get the maximum size of a block.
+ //
+ if (MaxLbaSize < PtrBlockMapEntry->Length) {
+ MaxLbaSize = PtrBlockMapEntry->Length;
+ }
+
+ NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks;
+ }
+
+ //
+ // The total number of blocks in the FV.
+ //
+ FwhInstance->NumOfBlocks = NumOfBlocks;
+
+ //
+ // Add a FVB Protocol Instance
+ //
+ FvbDevice = AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE));
+ ASSERT (FvbDevice != NULL);
+
+ CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE));
+
+ FvbDevice->Instance = mFvbModuleGlobal->NumFv;
+ mFvbModuleGlobal->NumFv++;
+
+ //
+ // Set up the devicepath
+ //
+ if (FwVolHeader->ExtHeaderOffset == 0) {
+ FV_MEMMAP_DEVICE_PATH *FvMemmapDevicePath;
+
+ //
+ // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH
+ //
+ FvMemmapDevicePath = AllocateCopyPool (
+ sizeof (FV_MEMMAP_DEVICE_PATH),
+ &mFvMemmapDevicePathTemplate
+ );
+ FvMemmapDevicePath->MemMapDevPath.StartingAddress = BaseAddress;
+ FvMemmapDevicePath->MemMapDevPath.EndingAddress =
+ BaseAddress + FwVolHeader->FvLength - 1;
+ FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)FvMemmapDevicePath;
+ } else {
+ FV_PIWG_DEVICE_PATH *FvPiwgDevicePath;
+
+ FvPiwgDevicePath = AllocateCopyPool (
+ sizeof (FV_PIWG_DEVICE_PATH),
+ &mFvPIWGDevicePathTemplate
+ );
+ CopyGuid (
+ &FvPiwgDevicePath->FvDevPath.FvName,
+ (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset)
+ );
+ FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)FvPiwgDevicePath;
+ }
+
+ //
+ // Module type specific hook.
+ //
+ InstallProtocolInterfaces (FvbDevice);
+
+ MarkMemoryRangeForRuntimeAccess (BaseAddress, Length);
+
+ //
+ // Set several PCD values to point to flash
+ //
+ Status = PcdSet64S (
+ PcdFlashNvStorageVariableBase64,
+ (UINTN)PcdGet32 (PcdPlatformFlashNvStorageVariableBase)
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet32S (
+ PcdFlashNvStorageFtwWorkingBase,
+ PcdGet32 (PcdPlatformFlashNvStorageFtwWorkingBase)
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet32S (
+ PcdFlashNvStorageFtwSpareBase,
+ PcdGet32 (PcdPlatformFlashNvStorageFtwSpareBase)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ FwhInstance = (EFI_FW_VOL_INSTANCE *)
+ (
+ (UINTN)FwhInstance + FwVolHeader->HeaderLength +
+ (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
+ );
+
+ //
+ // Module type specific hook.
+ //
+ InstallVirtualAddressChangeHandler ();
+ return EFI_SUCCESS;
+}
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.h b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.h
new file mode 100644
index 00000000000..dc4afbf9ce0
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.h
@@ -0,0 +1,187 @@
+/**@file
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (c) 2006, Intel Corporation. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ Module Name:
+
+ FwBlockService.h
+
+ Abstract:
+
+ Firmware volume block driver for RAM based firmware volume block.
+
+**/
+
+#ifndef FW_BLOCK_SERVICE_H_
+#define FW_BLOCK_SERVICE_H_
+
+typedef struct {
+ UINTN FvBase;
+ UINTN NumOfBlocks;
+ EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
+} EFI_FW_VOL_INSTANCE;
+
+typedef struct {
+ UINT32 NumFv;
+ EFI_FW_VOL_INSTANCE *FvInstance;
+} ESAL_FWB_GLOBAL;
+
+extern ESAL_FWB_GLOBAL *mFvbModuleGlobal;
+
+//
+// Fvb Protocol instance data
+//
+#define FVB_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE,\
+ FwVolBlockInstance, FVB_DEVICE_SIGNATURE)
+
+#define FVB_EXTEND_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE,\
+ FvbExtension, FVB_DEVICE_SIGNATURE)
+
+#define FVB_DEVICE_SIGNATURE SIGNATURE_32 ('F', 'V', 'B', 'N')
+
+typedef struct {
+ MEDIA_FW_VOL_DEVICE_PATH FvDevPath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevPath;
+} FV_PIWG_DEVICE_PATH;
+
+typedef struct {
+ MEMMAP_DEVICE_PATH MemMapDevPath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevPath;
+} FV_MEMMAP_DEVICE_PATH;
+
+typedef struct {
+ UINTN Signature;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN Instance;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance;
+} EFI_FW_VOL_BLOCK_DEVICE;
+
+EFI_STATUS
+GetFvbInfo (
+ IN UINT64 FvLength,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo
+ );
+
+EFI_STATUS
+FvbSetVolumeAttributes (
+ IN UINTN Instance,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
+ IN ESAL_FWB_GLOBAL *Global
+ );
+
+EFI_STATUS
+FvbGetVolumeAttributes (
+ IN UINTN Instance,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
+ IN ESAL_FWB_GLOBAL *Global
+ );
+
+EFI_STATUS
+FvbGetPhysicalAddress (
+ IN UINTN Instance,
+ OUT EFI_PHYSICAL_ADDRESS *Address,
+ IN ESAL_FWB_GLOBAL *Global
+ );
+
+EFI_STATUS
+EFIAPI
+FvbInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+VOID
+EFIAPI
+FvbClassAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+FvbGetLbaAddress (
+ IN UINTN Instance,
+ IN EFI_LBA Lba,
+ OUT UINTN *LbaAddress,
+ OUT UINTN *LbaLength,
+ OUT UINTN *NumOfBlocks,
+ IN ESAL_FWB_GLOBAL *Global
+ );
+
+//
+// Protocol APIs
+//
+EFI_STATUS
+EFIAPI
+FvbProtocolGetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbProtocolSetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbProtocolGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ );
+
+EFI_STATUS
+EFIAPI
+FvbProtocolGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN CONST EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumOfBlocks
+ );
+
+EFI_STATUS
+EFIAPI
+FvbProtocolRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN CONST EFI_LBA Lba,
+ IN CONST UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbProtocolWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbProtocolEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ ...
+ );
+
+//
+// The following functions have different implementations dependent on the
+// module type chosen for building this driver.
+//
+VOID
+InstallProtocolInterfaces (
+ IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice
+ );
+
+VOID
+InstallVirtualAddressChangeHandler (
+ VOID
+ );
+
+#endif
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockServiceDxe.c b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockServiceDxe.c
new file mode 100644
index 00000000000..36b518e9a25
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockServiceDxe.c
@@ -0,0 +1,152 @@
+/**@file
+ Functions related to the Firmware Volume Block service whose
+ implementation is specific to the runtime DXE driver build.
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (C) 2015, Red Hat, Inc.
+ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "FwBlockService.h"
+#include "RamFlash.h"
+
+VOID
+InstallProtocolInterfaces (
+ IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE FwbHandle;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface;
+
+ //
+ // Find a handle with a matching device path that has supports FW Block
+ // protocol
+ //
+ Status = gBS->LocateDevicePath (
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ &FvbDevice->DevicePath,
+ &FwbHandle
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // LocateDevicePath fails so install a new interface and device path
+ //
+ FwbHandle = NULL;
+ DEBUG ((DEBUG_INFO, "Installing RAM FVB\n"));
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &FwbHandle,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ &FvbDevice->FwVolBlockInstance,
+ &gEfiDevicePathProtocolGuid,
+ FvbDevice->DevicePath,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else if (IsDevicePathEnd (FvbDevice->DevicePath)) {
+ //
+ // Device already exists, so reinstall the FVB protocol
+ //
+ Status = gBS->HandleProtocol (
+ FwbHandle,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ (VOID **)&OldFwbInterface
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "Reinstalling FVB for Ram flash region\n"));
+ Status = gBS->ReinstallProtocolInterface (
+ FwbHandle,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ OldFwbInterface,
+ &FvbDevice->FwVolBlockInstance
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ //
+ // There was a FVB protocol on an End Device Path node
+ //
+ ASSERT (FALSE);
+ }
+}
+
+/*++
+
+ Routine Description:
+
+ Fixup internal data so that EFI and SAL can be call in virtual mode.
+ Call the passed in Child Notify event and convert the mFvbModuleGlobal
+ date items to there virtual address.
+
+ Arguments:
+
+ (Standard EFI notify event - EFI_EVENT_NOTIFY)
+
+ Returns:
+
+ None
+
+--*/
+STATIC
+VOID
+EFIAPI
+FvbVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_FW_VOL_INSTANCE *FwhInstance;
+ UINTN Index;
+
+ FwhInstance = mFvbModuleGlobal->FvInstance;
+ EfiConvertPointer (0x0, (VOID **)&mFvbModuleGlobal->FvInstance);
+
+ //
+ // Convert the base address of all the instances
+ //
+ Index = 0;
+ while (Index < mFvbModuleGlobal->NumFv) {
+ EfiConvertPointer (0x0, (VOID **)&FwhInstance->FvBase);
+ FwhInstance = (EFI_FW_VOL_INSTANCE *)
+ (
+ (UINTN)FwhInstance +
+ FwhInstance->VolumeHeader.HeaderLength +
+ (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
+ );
+ Index++;
+ }
+
+ EfiConvertPointer (0x0, (VOID **)&mFvbModuleGlobal);
+ RamFlashConvertPointers ();
+}
+
+VOID
+InstallVirtualAddressChangeHandler (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT VirtualAddressChangeEvent;
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ FvbVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &VirtualAddressChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+}
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.c b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.c
new file mode 100644
index 00000000000..0f96e1a47d7
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.c
@@ -0,0 +1,141 @@
+/** @file
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include
+#include
+#include
+#include
+
+#include "RamFlash.h"
+
+VOID *mFlashBase;
+
+STATIC UINTN mFdBlockSize = 0;
+STATIC UINTN mFdBlockCount = 0;
+
+STATIC
+UINT8 *
+RamFlashPtr (
+ IN EFI_LBA Lba,
+ IN UINTN Offset
+ )
+{
+ return mFlashBase + ((UINTN)Lba * mFdBlockSize) + Offset;
+}
+
+/**
+ Read from Ram Flash
+
+ @param[in] Lba The starting logical block index to read from.
+ @param[in] Offset Offset into the block at which to begin reading.
+ @param[in] NumBytes On input, indicates the requested read size. On
+ output, indicates the actual number of bytes read
+ @param[in] Buffer Pointer to the buffer to read into.
+
+**/
+EFI_STATUS
+RamFlashRead (
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ UINT8 *Ptr;
+
+ //
+ // Only write to the first 64k. We don't bother saving the FTW Spare
+ // block into the flash memory.
+ //
+ if (Lba >= mFdBlockCount) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get flash address
+ //
+ Ptr = (UINT8 *)RamFlashPtr (Lba, Offset);
+
+ CopyMem (Buffer, Ptr, *NumBytes);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write to Ram Flash
+
+ @param[in] Lba The starting logical block index to write to.
+ @param[in] Offset Offset into the block at which to begin writing.
+ @param[in] NumBytes On input, indicates the requested write size. On
+ output, indicates the actual number of bytes written
+ @param[in] Buffer Pointer to the data to write.
+
+**/
+EFI_STATUS
+RamFlashWrite (
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ UINT8 *Ptr;
+ UINTN i;
+
+ //
+ // Only write to the first 64k. We don't bother saving the FTW Spare
+ // block into the flash memory.
+ //
+ if (Lba >= mFdBlockCount) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Program flash
+ //
+ Ptr = RamFlashPtr (Lba, Offset);
+ for (i = 0; i < *NumBytes; i++) {
+ MmioWrite8 ((UINTN)Ptr, Buffer[i]);
+ Ptr++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Erase a Ram Flash block
+
+ @param Lba The logical block index to erase.
+
+**/
+EFI_STATUS
+RamFlashEraseBlock (
+ IN EFI_LBA Lba
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Initializes Ram flash memory support
+
+ @retval EFI_WRITE_PROTECTED The Ram flash device is not present.
+ @retval EFI_SUCCESS The Ram flash device is supported.
+
+**/
+EFI_STATUS
+RamFlashInitialize (
+ VOID
+ )
+{
+ mFlashBase = (UINT8 *)(UINTN)PcdGet32 (PcdVariableFdBaseAddress);
+ mFdBlockSize = PcdGet32 (PcdVariableFdBlockSize);
+ ASSERT (PcdGet32 (PcdVariableFdSize) % mFdBlockSize == 0);
+ mFdBlockCount = PcdGet32 (PcdVariableFdSize) / mFdBlockSize;
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.h b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.h
new file mode 100644
index 00000000000..e26246400f8
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.h
@@ -0,0 +1,81 @@
+/** @file
+ Ram flash device for EFI variable
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef RAM_FLASH_H_
+#define RAM_FLASH_H_
+
+#include
+
+extern VOID *mFlashBase;
+
+/**
+ Read from Ram Flash
+
+ @param[in] Lba The starting logical block index to read from.
+ @param[in] Offset Offset into the block at which to begin reading.
+ @param[in] NumBytes On input, indicates the requested read size. On
+ output, indicates the actual number of bytes read
+ @param[in] Buffer Pointer to the buffer to read into.
+
+**/
+EFI_STATUS
+RamFlashRead (
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+/**
+ Write to Ram Flash
+
+ @param[in] Lba The starting logical block index to write to.
+ @param[in] Offset Offset into the block at which to begin writing.
+ @param[in] NumBytes On input, indicates the requested write size. On
+ output, indicates the actual number of bytes written
+ @param[in] Buffer Pointer to the data to write.
+
+**/
+EFI_STATUS
+RamFlashWrite (
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+/**
+ Erase a Ram Flash block
+
+ @param Lba The logical block index to erase.
+
+**/
+EFI_STATUS
+RamFlashEraseBlock (
+ IN EFI_LBA Lba
+ );
+
+/**
+ Initializes Ram flash memory support
+
+ @retval EFI_WRITE_PROTECTED The Ram flash device is not present.
+ @retval EFI_SUCCESS The Ram flash device is supported.
+
+**/
+EFI_STATUS
+RamFlashInitialize (
+ VOID
+ );
+
+VOID
+RamFlashConvertPointers (
+ VOID
+ );
+
+#endif
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlashDxe.c b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlashDxe.c
new file mode 100644
index 00000000000..1fef9b70162
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlashDxe.c
@@ -0,0 +1,20 @@
+/** @file
+ Ram flash device for EFI variable
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include
+
+#include "RamFlash.h"
+
+VOID
+RamFlashConvertPointers (
+ VOID
+ )
+{
+ EfiConvertPointer (0x0, (VOID **)&mFlashBase);
+}
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/Timer.c b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/Timer.c
new file mode 100644
index 00000000000..5c82a3cd0f5
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/Timer.c
@@ -0,0 +1,315 @@
+/** @file
+ RISC-V Timer Architectural Protocol for U7 series platform.
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (c) 2022, Boyang Han
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Timer.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+BOOLEAN TimerHandlerReentry = FALSE;
+
+//
+// The handle onto which the Timer Architectural Protocol will be installed
+//
+STATIC EFI_HANDLE mTimerHandle = NULL;
+
+//
+// The Timer Architectural Protocol that this driver produces
+//
+EFI_TIMER_ARCH_PROTOCOL mTimer = {
+ TimerDriverRegisterHandler,
+ TimerDriverSetTimerPeriod,
+ TimerDriverGetTimerPeriod,
+ TimerDriverGenerateSoftInterrupt
+};
+
+//
+// Pointer to the CPU Architectural Protocol instance
+//
+EFI_CPU_ARCH_PROTOCOL *mCpu;
+
+//
+// The notification function to call on every timer interrupt.
+// A bug in the compiler prevents us from initializing this here.
+//
+STATIC EFI_TIMER_NOTIFY mTimerNotifyFunction;
+
+//
+// The current period of the timer interrupt
+//
+STATIC UINT64 mTimerPeriod = 0;
+
+/**
+ U7 Series Timer Interrupt Handler.
+
+ @param InterruptType The type of interrupt that occured
+ @param SystemContext A pointer to the system context when the interrupt occured
+**/
+VOID
+EFIAPI
+TimerInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ EFI_TPL OriginalTPL;
+ UINT64 RiscvTimer;
+
+ if (TimerHandlerReentry) {
+ //
+ // MMode timer occurred when processing
+ // SMode timer handler.
+ //
+ RiscvTimer = RiscVReadMachineTimerInterface ();
+ SbiSetTimer (RiscvTimer += mTimerPeriod);
+ csr_clear (CSR_SIP, MIP_STIP);
+ return;
+ }
+
+ TimerHandlerReentry = TRUE;
+
+ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ csr_clear (CSR_SIE, MIP_STIP); // Disable SMode timer int
+ csr_clear (CSR_SIP, MIP_STIP);
+ if (mTimerPeriod == 0) {
+ gBS->RestoreTPL (OriginalTPL);
+ csr_clear (CSR_SIE, MIP_STIP); // Disable SMode timer int
+ return;
+ }
+
+ if (mTimerNotifyFunction != NULL) {
+ mTimerNotifyFunction (mTimerPeriod);
+ }
+
+ RiscvTimer = RiscVReadMachineTimerInterface ();
+ SbiSetTimer (RiscvTimer += mTimerPeriod);
+ gBS->RestoreTPL (OriginalTPL);
+ csr_set (CSR_SIE, MIP_STIP); // enable SMode timer int
+ TimerHandlerReentry = FALSE;
+}
+
+/**
+
+ This function registers the handler NotifyFunction so it is called every time
+ the timer interrupt fires. It also passes the amount of time since the last
+ handler call to the NotifyFunction. If NotifyFunction is NULL, then the
+ handler is unregistered. If the handler is registered, then EFI_SUCCESS is
+ returned. If the CPU does not support registering a timer interrupt handler,
+ then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
+ when a handler is already registered, then EFI_ALREADY_STARTED is returned.
+ If an attempt is made to unregister a handler when a handler is not registered,
+ then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
+ register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
+ is returned.
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param NotifyFunction The function to call when a timer interrupt fires. This
+ function executes at TPL_HIGH_LEVEL. The DXE Core will
+ register a handler for the timer interrupt, so it can know
+ how much time has passed. This information is used to
+ signal timer based events. NULL will unregister the handler.
+
+ @retval EFI_SUCCESS The timer handler was registered.
+ @retval EFI_UNSUPPORTED The platform does not support timer interrupts.
+ @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
+ registered.
+ @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
+ previously registered.
+ @retval EFI_DEVICE_ERROR The timer handler could not be registered.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverRegisterHandler (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN EFI_TIMER_NOTIFY NotifyFunction
+ )
+{
+ DEBUG ((DEBUG_INFO, "TimerDriverRegisterHandler(0x%lx) called\n", NotifyFunction));
+ mTimerNotifyFunction = NotifyFunction;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function adjusts the period of timer interrupts to the value specified
+ by TimerPeriod. If the timer period is updated, then the selected timer
+ period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
+ If an error occurs while attempting to update the timer period, then the
+ timer hardware will be put back in its state prior to this call, and
+ EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
+ is disabled. This is not the same as disabling the CPU's interrupts.
+ Instead, it must either turn off the timer hardware, or it must adjust the
+ interrupt controller so that a CPU interrupt is not generated when the timer
+ interrupt fires.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is
+ returned. If the timer is programmable, then the timer period
+ will be rounded up to the nearest timer period that is supported
+ by the timer hardware. If TimerPeriod is set to 0, then the
+ timer interrupts will be disabled.
+
+ @retval EFI_SUCCESS The timer period was changed.
+ @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
+ @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverSetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN UINT64 TimerPeriod
+ )
+{
+ UINT64 RiscvTimer;
+
+ DEBUG ((DEBUG_INFO, "TimerDriverSetTimerPeriod(0x%lx)\n", TimerPeriod));
+
+ if (TimerPeriod == 0) {
+ mTimerPeriod = 0;
+ csr_clear (CSR_SIE, MIP_STIP); // disable timer int
+ return EFI_SUCCESS;
+ }
+
+ mTimerPeriod = TimerPeriod; // convert unit from 100ns to 1us
+ RiscvTimer = RiscVReadMachineTimerInterface ();
+ SbiSetTimer (RiscvTimer + mTimerPeriod / 10);
+
+ mCpu->EnableInterrupt (mCpu);
+ csr_set (CSR_SIE, MIP_STIP); // enable timer int
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function retrieves the period of timer interrupts in 100 ns units,
+ returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
+ is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
+ returned, then the timer is currently disabled.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
+ 0 is returned, then the timer is currently disabled.
+
+ @retval EFI_SUCCESS The timer period was returned in TimerPeriod.
+ @retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ OUT UINT64 *TimerPeriod
+ )
+{
+ *TimerPeriod = mTimerPeriod;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function generates a soft timer interrupt. If the platform does not support soft
+ timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
+ If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
+ service, then a soft timer interrupt will be generated. If the timer interrupt is
+ enabled when this service is called, then the registered handler will be invoked. The
+ registered handler should not be able to distinguish a hardware-generated timer
+ interrupt from a software-generated timer interrupt.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The soft timer interrupt was generated.
+ @retval EFI_UNSUPPORTEDT The platform does not support the generation of soft timer interrupts.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGenerateSoftInterrupt (
+ IN EFI_TIMER_ARCH_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize the Timer Architectural Protocol driver
+
+ @param ImageHandle ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Timer Architectural Protocol created
+ @retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver.
+ @retval EFI_DEVICE_ERROR A device error occured attempting to initialize the driver.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Initialize the pointer to our notify function.
+ //
+ mTimerNotifyFunction = NULL;
+
+ //
+ // Make sure the Timer Architectural Protocol is not already installed in the system
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid);
+
+ //
+ // Find the CPU architectural protocol.
+ //
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Force the timer to be disabled
+ //
+ Status = TimerDriverSetTimerPeriod (&mTimer, 0);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install interrupt handler for RISC-V Timer.
+ //
+ Status = mCpu->RegisterInterruptHandler (mCpu, EXCEPT_RISCV_TIMER_INT, TimerInterruptHandler);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Force the timer to be enabled at its default period
+ //
+ Status = TimerDriverSetTimerPeriod (&mTimer, DEFAULT_TIMER_TICK_DURATION);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install the Timer Architectural Protocol onto a new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mTimerHandle,
+ &gEfiTimerArchProtocolGuid,
+ &mTimer,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/Timer.h b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/Timer.h
new file mode 100644
index 00000000000..4b00951519b
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/Timer.h
@@ -0,0 +1,179 @@
+/** @file
+ RISC-V Timer Architectural Protocol definitions for U7 Series platform,
+
+ Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (c) 2022, Boyang Han
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef U7_SERIES_TIMER_H_
+#define U7_SERIES_TIMER_H_
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+//
+// RISC-V use 100us timer.
+// The default timer tick duration is set to 10 ms = 10 * 1000 * 10 100 ns units
+//
+#define DEFAULT_TIMER_TICK_DURATION 100000
+
+extern VOID
+RiscvSetTimerPeriod (
+ UINT32 TimerPeriod
+ );
+
+//
+// Function Prototypes
+//
+
+/**
+ Initialize the Timer Architectural Protocol driver
+
+ @param ImageHandle ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Timer Architectural Protocol created
+ @retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver.
+ @retval EFI_DEVICE_ERROR A device error occured attempting to initialize the driver.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+;
+
+/**
+
+ This function adjusts the period of timer interrupts to the value specified
+ by TimerPeriod. If the timer period is updated, then the selected timer
+ period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
+ If an error occurs while attempting to update the timer period, then the
+ timer hardware will be put back in its state prior to this call, and
+ EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
+ is disabled. This is not the same as disabling the CPU's interrupts.
+ Instead, it must either turn off the timer hardware, or it must adjust the
+ interrupt controller so that a CPU interrupt is not generated when the timer
+ interrupt fires.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param NotifyFunction The rate to program the timer interrupt in 100 nS units. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is
+ returned. If the timer is programmable, then the timer period
+ will be rounded up to the nearest timer period that is supported
+ by the timer hardware. If TimerPeriod is set to 0, then the
+ timer interrupts will be disabled.
+
+ @retval EFI_SUCCESS The timer period was changed.
+ @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
+ @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverRegisterHandler (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN EFI_TIMER_NOTIFY NotifyFunction
+ )
+;
+
+/**
+
+ This function adjusts the period of timer interrupts to the value specified
+ by TimerPeriod. If the timer period is updated, then the selected timer
+ period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
+ If an error occurs while attempting to update the timer period, then the
+ timer hardware will be put back in its state prior to this call, and
+ EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
+ is disabled. This is not the same as disabling the CPU's interrupts.
+ Instead, it must either turn off the timer hardware, or it must adjust the
+ interrupt controller so that a CPU interrupt is not generated when the timer
+ interrupt fires.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is
+ returned. If the timer is programmable, then the timer period
+ will be rounded up to the nearest timer period that is supported
+ by the timer hardware. If TimerPeriod is set to 0, then the
+ timer interrupts will be disabled.
+
+ @retval EFI_SUCCESS The timer period was changed.
+ @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
+ @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverSetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN UINT64 TimerPeriod
+ )
+;
+
+/**
+
+ This function retrieves the period of timer interrupts in 100 ns units,
+ returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
+ is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
+ returned, then the timer is currently disabled.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
+ 0 is returned, then the timer is currently disabled.
+
+ @retval EFI_SUCCESS The timer period was returned in TimerPeriod.
+ @retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ OUT UINT64 *TimerPeriod
+ )
+;
+
+/**
+
+ This function generates a soft timer interrupt. If the platform does not support soft
+ timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
+ If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
+ service, then a soft timer interrupt will be generated. If the timer interrupt is
+ enabled when this service is called, then the registered handler will be invoked. The
+ registered handler should not be able to distinguish a hardware-generated timer
+ interrupt from a software-generated timer interrupt.
+
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The soft timer interrupt was generated.
+ @retval EFI_UNSUPPORTEDT The platform does not support the generation of soft timer interrupts.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGenerateSoftInterrupt (
+ IN EFI_TIMER_ARCH_PROTOCOL *This
+ )
+;
+
+#endif
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/Timer.uni b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/Timer.uni
new file mode 100644
index 00000000000..08d8ac7ecdd
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/Timer.uni
@@ -0,0 +1,14 @@
+// /** @file
+//
+// RISC-V Timer Arch protocol strings.
+//
+// Copyright (c) 2016, Hewlett Packard Enterprise Development LP. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "RISC-V timer driver that provides Timer Arch protocol"
+
+#string STR_MODULE_DESCRIPTION #language en-US "RISC-V timer driver that provides Timer Arch protocol."
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/TimerDxe.inf b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/TimerDxe.inf
new file mode 100644
index 00000000000..e6fd874c249
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/TimerDxe.inf
@@ -0,0 +1,55 @@
+## @file
+# RISC-V Timer Arch protocol module for U7 Series platform
+#
+# Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+# Copyright (c) 2022, Boyang Han
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = Timer
+ MODULE_UNI_FILE = Timer.uni
+ FILE_GUID = 182C47AC-8D8F-4E96-BE26-AEDD96F3BD80
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = TimerDriverInitialize
+#
+# The following information is for reference only and not required by the build
+# tools.
+#
+# VALID_ARCHITECTURES = RISCV64
+#
+[Packages]
+ MdePkg/MdePkg.dec
+ Platform/SiFive/U7SeriesPkg/U7SeriesPkg.dec
+ Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ IoLib
+ MachineModeTimerLib
+ RiscVCpuLib
+ RiscVEdk2SbiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Sources]
+ Timer.h
+ Timer.c
+
+[Protocols]
+ gEfiCpuArchProtocolGuid ## CONSUMES
+ gEfiTimerArchProtocolGuid ## PRODUCES
+
+[Pcd]
+ gUefiRiscVPkgTokenSpaceGuid.PcdRiscVMachineTimerFrequencyInHerz
+
+[Depex]
+ gEfiCpuArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ TimerExtra.uni
diff --git a/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/TimerExtra.uni b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/TimerExtra.uni
new file mode 100644
index 00000000000..7d7cc40b5e5
--- /dev/null
+++ b/Platform/SiFive/U7SeriesPkg/Universal/Dxe/TimerDxe/TimerExtra.uni
@@ -0,0 +1,12 @@
+// /** @file
+// Timer Localized Strings and Content
+//
+// Copyright (c) 2016, Hewlett Packard Enterprise Development LP. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"RISC-V Timer DXE Driver"
diff --git a/Silicon/SiFive/SiFive.dec b/Silicon/SiFive/SiFive.dec
index bf280864be6..90fe4e07da4 100644
--- a/Silicon/SiFive/SiFive.dec
+++ b/Silicon/SiFive/SiFive.dec
@@ -30,6 +30,8 @@
gEfiSiFiveSiliconTokenSpaceGuid.PcdSiFiveU54CoreGuid |{0x64, 0x70, 0xF6, 0x90, 0x11, 0x59, 0x47, 0xF1, 0xB8, 0xD5, 0xCF, 0x89, 0x10, 0xC5, 0x30, 0x20}|VOID*|0x00001001
# U5 MC Coreplex GUID
gEfiSiFiveSiliconTokenSpaceGuid.PcdSiFiveU5MCCoreplexGuid |{0x06, 0x38, 0x9F, 0x33, 0xF9, 0xDB, 0x43, 0x13, 0x9A, 0x9B, 0x1C, 0x68, 0xD6, 0x04, 0xEA, 0xFF}|VOID*|0x00001003
+ # U74 Core GUID
+ gEfiSiFiveSiliconTokenSpaceGuid.PcdSiFiveU74CoreGuid |{0x24, 0xB4, 0x19, 0xC7, 0x20, 0x46, 0x48, 0x27, 0x9F, 0x60, 0x1E, 0xEC, 0x38, 0x3D, 0xAE, 0x26}|VOID*|0x00001005
[PcdsDynamic, PcdsDynamicEx]
diff --git a/Silicon/SiFive/U74/Library/PeiCoreInfoHobLib/CoreInfoHob.c b/Silicon/SiFive/U74/Library/PeiCoreInfoHobLib/CoreInfoHob.c
new file mode 100644
index 00000000000..e7e31afd2f7
--- /dev/null
+++ b/Silicon/SiFive/U74/Library/PeiCoreInfoHobLib/CoreInfoHob.c
@@ -0,0 +1,234 @@
+/**@file
+ Build up platform processor information of SiFive U54 core.
+
+ Copyright (c) 2019 - 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include
+
+//
+// The Library classes this module consumes
+//
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+/**
+ Function to build core specific information HOB for U54 or E51 core.
+
+ @param ParentProcessorGuid Parent processor of this core. ParentProcessorGuid
+ could be the same as CoreGuid if one processor has
+ only one core.
+ @param ParentProcessorUid Unique ID of pysical processor which owns this core.
+ @param HartId Hart ID of this core.
+ @param IsBootHart TRUE means this is the boot HART.
+ @param IsManagementCore TRUE means this is for the E51 management core, not U54
+ @param GuidHobData Pointer to RISC_V_PROCESSOR_SPECIFIC_HOB_DATA.
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+ EFI_UNSUPPORTED HART is ignored by platform.
+ EFI_NOT_FOUND Processor specific data hob is not available.
+**/
+EFI_STATUS
+EFIAPI
+CreateU54E51CoreProcessorSpecificDataHob (
+ IN EFI_GUID *ParentProcessorGuid,
+ IN UINTN ParentProcessorUid,
+ IN UINTN HartId,
+ IN BOOLEAN IsBootHart,
+ IN BOOLEAN IsManagementCore,
+ OUT RISC_V_PROCESSOR_SPECIFIC_HOB_DATA **GuidHobData
+ )
+{
+ RISC_V_PROCESSOR_SPECIFIC_HOB_DATA *CoreGuidHob;
+ EFI_GUID *ProcessorSpecDataHobGuid;
+ RISC_V_PROCESSOR_SPECIFIC_HOB_DATA ProcessorSpecDataHob;
+ EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext;
+ EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC *FirmwareContextHartSpecific;
+
+ DEBUG ((DEBUG_INFO, "%a: Entry.\n", __FUNCTION__));
+
+ if (GuidHobData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GetFirmwareContextPointer (&FirmwareContext);
+ ASSERT (FirmwareContext != NULL);
+ if (FirmwareContext == NULL) {
+ DEBUG ((DEBUG_ERROR, "Failed to get the pointer of EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT of hart %d\n", HartId));
+ return EFI_NOT_FOUND;
+ }
+
+ DEBUG ((DEBUG_INFO, " Firmware Context is at 0x%x.\n", FirmwareContext));
+
+ FirmwareContextHartSpecific = FirmwareContext->HartSpecific[HartId];
+ DEBUG ((DEBUG_INFO, " Firmware Context Hart specific is at 0x%x.\n", FirmwareContextHartSpecific));
+ if (FirmwareContextHartSpecific == NULL) {
+ DEBUG ((DEBUG_INFO, " This hart: %d is ignored by platform.\n", HartId));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Build up RISC_V_PROCESSOR_SPECIFIC_HOB_DATA.
+ //
+ CommonFirmwareContextHartSpecificInfo (
+ FirmwareContextHartSpecific,
+ ParentProcessorGuid,
+ ParentProcessorUid,
+ (EFI_GUID *)PcdGetPtr (PcdSiFiveU54CoreGuid),
+ HartId,
+ IsBootHart,
+ &ProcessorSpecDataHob
+ );
+
+ ProcessorSpecDataHob.ProcessorSpecificData.MModeExcepDelegation.Value64_L = TO_BE_FILLED;
+ ProcessorSpecDataHob.ProcessorSpecificData.MModeExcepDelegation.Value64_H = TO_BE_FILLED;
+ ProcessorSpecDataHob.ProcessorSpecificData.MModeInterruptDelegation.Value64_L = TO_BE_FILLED;
+ ProcessorSpecDataHob.ProcessorSpecificData.MModeInterruptDelegation.Value64_H = TO_BE_FILLED;
+ ProcessorSpecDataHob.ProcessorSpecificData.HartXlen = RegisterLen64;
+ ProcessorSpecDataHob.ProcessorSpecificData.MachineModeXlen = RegisterLen64;
+ ProcessorSpecDataHob.ProcessorSpecificData.UserModeXlen = RegisterLen64;
+
+ if (IsManagementCore) {
+ // Configuration for E51
+ ProcessorSpecDataHob.ProcessorSpecificData.SupervisorModeXlen = RegisterUnsupported;
+ } else {
+ // Configuration for U54
+ ProcessorSpecDataHob.ProcessorSpecificData.SupervisorModeXlen = RegisterLen64;
+ }
+
+ DebugPrintHartSpecificInfo (&ProcessorSpecDataHob);
+
+ //
+ // Build GUID HOB for core, this is for SMBIOS type 44
+ //
+ ProcessorSpecDataHobGuid = PcdGetPtr (PcdProcessorSpecificDataGuidHobGuid);
+ CoreGuidHob = (RISC_V_PROCESSOR_SPECIFIC_HOB_DATA *)BuildGuidDataHob (ProcessorSpecDataHobGuid, (VOID *)&ProcessorSpecDataHob, sizeof (RISC_V_PROCESSOR_SPECIFIC_HOB_DATA));
+ if (CoreGuidHob == NULL) {
+ DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U54 core.\n"));
+ ASSERT (FALSE);
+ }
+
+ *GuidHobData = CoreGuidHob;
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to build cache related SMBIOS information. RISC-V SMBIOS DXE driver collects
+ this information and builds SMBIOS Type 7 record.
+
+ The caller can adjust the allocated hob data to their needs.
+
+ @param ProcessorUid Unique ID of physical processor which owns this core.
+ @param L1CacheDataHobPtr Pointer to allocated HOB data.
+
+**/
+VOID
+EFIAPI
+CreateU54SmbiosType7L1DataHob (
+ IN UINTN ProcessorUid,
+ OUT RISC_V_PROCESSOR_TYPE7_HOB_DATA **L1CacheDataHobPtr
+ )
+{
+ EFI_GUID *GuidPtr;
+ RISC_V_PROCESSOR_TYPE7_HOB_DATA L1CacheDataHob;
+
+ //
+ // Build up SMBIOS type 7 L1 cache record.
+ //
+ ZeroMem ((VOID *)&L1CacheDataHob, sizeof (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
+ L1CacheDataHob.PrcessorGuid = *((EFI_GUID *)PcdGetPtr (PcdSiFiveU5MCCoreplexGuid));
+ L1CacheDataHob.ProcessorUid = ProcessorUid;
+ L1CacheDataHob.SmbiosType7Cache.SocketDesignation = TO_BE_FILLED_BY_VENDOR;
+ L1CacheDataHob.SmbiosType7Cache.CacheConfiguration = RISC_V_CACHE_CONFIGURATION_CACHE_LEVEL_1 | \
+ RISC_V_CACHE_CONFIGURATION_LOCATION_INTERNAL | \
+ RISC_V_CACHE_CONFIGURATION_ENABLED | \
+ RISC_V_CACHE_CONFIGURATION_MODE_UNKNOWN;
+ L1CacheDataHob.SmbiosType7Cache.MaximumCacheSize = TO_BE_FILLED_BY_VENDOR;
+ L1CacheDataHob.SmbiosType7Cache.InstalledSize = TO_BE_FILLED_BY_VENDOR;
+ L1CacheDataHob.SmbiosType7Cache.SupportedSRAMType.Unknown = 1;
+ L1CacheDataHob.SmbiosType7Cache.CurrentSRAMType.Unknown = 1;
+ L1CacheDataHob.SmbiosType7Cache.CacheSpeed = TO_BE_FILLED_BY_VENDOR;
+ L1CacheDataHob.SmbiosType7Cache.ErrorCorrectionType = TO_BE_FILLED_BY_VENDOR;
+ L1CacheDataHob.SmbiosType7Cache.SystemCacheType = CacheTypeUnified;
+ L1CacheDataHob.SmbiosType7Cache.Associativity = TO_BE_FILLED_BY_VENDOR;
+
+ GuidPtr = (EFI_GUID *)PcdGetPtr (PcdProcessorSmbiosType7GuidHobGuid);
+ *L1CacheDataHobPtr = (RISC_V_PROCESSOR_TYPE7_HOB_DATA *)BuildGuidDataHob (GuidPtr, (VOID *)&L1CacheDataHob, sizeof (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
+ if (L1CacheDataHobPtr == NULL) {
+ DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U5 MC Coreplex L1 cache RISC_V_PROCESSOR_TYPE7_HOB_DATA.\n"));
+ ASSERT (FALSE);
+ }
+}
+
+/**
+ Function to build processor related SMBIOS information. RISC-V SMBIOS DXE driver collects
+ this information and builds SMBIOS Type 4 record.
+
+ The caller can adjust the allocated hob data to their needs.
+
+ @param ProcessorUid Unique ID of physical processor which owns this core.
+ @param ProcessorDataHobPtr Pointer to allocated HOB data.
+
+**/
+VOID
+EFIAPI
+CreateU54SmbiosType4DataHob (
+ IN UINTN ProcessorUid,
+ OUT RISC_V_PROCESSOR_TYPE4_HOB_DATA **ProcessorDataHobPtr
+ )
+{
+ EFI_GUID *GuidPtr;
+ RISC_V_PROCESSOR_TYPE4_HOB_DATA ProcessorDataHob;
+
+ //
+ // Build up SMBIOS type 4 record.
+ //
+ ZeroMem ((VOID *)&ProcessorDataHob, sizeof (RISC_V_PROCESSOR_TYPE4_HOB_DATA));
+ ProcessorDataHob.PrcessorGuid = *((EFI_GUID *)PcdGetPtr (PcdSiFiveU5MCCoreplexGuid));
+ ProcessorDataHob.ProcessorUid = ProcessorUid;
+ ProcessorDataHob.SmbiosType4Processor.Socket = TO_BE_FILLED_BY_VENDOR;
+ ProcessorDataHob.SmbiosType4Processor.ProcessorType = CentralProcessor;
+ ProcessorDataHob.SmbiosType4Processor.ProcessorFamily = ProcessorFamilyIndicatorFamily2;
+ ProcessorDataHob.SmbiosType4Processor.ProcessorManufacturer = TO_BE_FILLED_BY_VENDOR;
+ SetMem ((VOID *)&ProcessorDataHob.SmbiosType4Processor.ProcessorId, sizeof (PROCESSOR_ID_DATA), TO_BE_FILLED_BY_CODE);
+ ProcessorDataHob.SmbiosType4Processor.ProcessorVersion = TO_BE_FILLED_BY_VENDOR;
+ ProcessorDataHob.SmbiosType4Processor.Voltage.ProcessorVoltageCapability3_3V = 1;
+ ProcessorDataHob.SmbiosType4Processor.ExternalClock = TO_BE_FILLED_BY_VENDOR;
+ ProcessorDataHob.SmbiosType4Processor.MaxSpeed = TO_BE_FILLED_BY_VENDOR;
+ ProcessorDataHob.SmbiosType4Processor.CurrentSpeed = TO_BE_FILLED_BY_VENDOR;
+ ProcessorDataHob.SmbiosType4Processor.Status = TO_BE_FILLED_BY_CODE;
+ ProcessorDataHob.SmbiosType4Processor.ProcessorUpgrade = TO_BE_FILLED_BY_VENDOR;
+ ProcessorDataHob.SmbiosType4Processor.L1CacheHandle = TO_BE_FILLED_BY_RISC_V_SMBIOS_DXE_DRIVER;
+ ProcessorDataHob.SmbiosType4Processor.L2CacheHandle = TO_BE_FILLED_BY_RISC_V_SMBIOS_DXE_DRIVER;
+ ProcessorDataHob.SmbiosType4Processor.L3CacheHandle = 0xffff;
+ ProcessorDataHob.SmbiosType4Processor.SerialNumber = TO_BE_FILLED_BY_CODE;
+ ProcessorDataHob.SmbiosType4Processor.AssetTag = TO_BE_FILLED_BY_VENDOR;
+ ProcessorDataHob.SmbiosType4Processor.PartNumber = TO_BE_FILLED_BY_VENDOR;
+ ProcessorDataHob.SmbiosType4Processor.CoreCount = (UINT8)FixedPcdGet32 (PcdNumberofU5Cores) + (UINT8)PcdGetBool (PcdE5MCSupported);
+ ProcessorDataHob.SmbiosType4Processor.EnabledCoreCount = (UINT8)FixedPcdGet32 (PcdNumberofU5Cores) + (UINT8)PcdGetBool (PcdE5MCSupported);
+ ProcessorDataHob.SmbiosType4Processor.ThreadCount = (UINT8)FixedPcdGet32 (PcdNumberofU5Cores) + (UINT8)PcdGetBool (PcdE5MCSupported);
+ ProcessorDataHob.SmbiosType4Processor.ProcessorCharacteristics = (UINT16)(1 << 2); // 64-bit capable
+ ProcessorDataHob.SmbiosType4Processor.ProcessorFamily2 = ProcessorFamilyRiscVRV64;
+ ProcessorDataHob.SmbiosType4Processor.CoreCount2 = 0;
+ ProcessorDataHob.SmbiosType4Processor.EnabledCoreCount2 = 0;
+ ProcessorDataHob.SmbiosType4Processor.ThreadCount2 = 0;
+
+ GuidPtr = (EFI_GUID *)PcdGetPtr (PcdProcessorSmbiosType4GuidHobGuid);
+ *ProcessorDataHobPtr = (RISC_V_PROCESSOR_TYPE4_HOB_DATA *)BuildGuidDataHob (GuidPtr, (VOID *)&ProcessorDataHob, sizeof (RISC_V_PROCESSOR_TYPE4_HOB_DATA));
+ if (ProcessorDataHobPtr == NULL) {
+ DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U5MC Coreplex RISC_V_PROCESSOR_TYPE4_HOB_DATA.\n"));
+ ASSERT (FALSE);
+ }
+}
diff --git a/Silicon/SiFive/U74/Library/PeiCoreInfoHobLib/PeiCoreInfoHobLib.inf b/Silicon/SiFive/U74/Library/PeiCoreInfoHobLib/PeiCoreInfoHobLib.inf
new file mode 100644
index 00000000000..1e3d3508647
--- /dev/null
+++ b/Silicon/SiFive/U74/Library/PeiCoreInfoHobLib/PeiCoreInfoHobLib.inf
@@ -0,0 +1,51 @@
+## @file
+# Library instance to create core information HOB
+#
+# Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = SiliconSiFiveU54CoreInfoLib
+ FILE_GUID = 483DE090-267E-4278-A0A1-15D9836780EA
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SiliconSiFiveU54CoreInfoLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = RISCV64
+#
+
+[Sources]
+ CoreInfoHob.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
+ Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
+ Platform/SiFive/U5SeriesPkg/U7SeriesPkg.dec
+ Silicon/SiFive/SiFive.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ MemoryAllocationLib
+ PrintLib
+ FirmwareContextProcessorSpecificLib
+ RiscVEdk2SbiLib
+
+[FixedPcd]
+ gUefiRiscVPkgTokenSpaceGuid.PcdProcessorSpecificDataGuidHobGuid
+ gUefiRiscVPkgTokenSpaceGuid.PcdProcessorSmbiosGuidHobGuid
+ gUefiRiscVPkgTokenSpaceGuid.PcdProcessorSmbiosType4GuidHobGuid
+ gUefiRiscVPkgTokenSpaceGuid.PcdProcessorSmbiosType7GuidHobGuid
+ gEfiSiFiveSiliconTokenSpaceGuid.PcdSiFiveU54CoreGuid
+ gEfiSiFiveSiliconTokenSpaceGuid.PcdSiFiveU5MCCoreplexGuid
+ gSiFiveU5SeriesPlatformsPkgTokenSpaceGuid.PcdNumberofU5Cores
+ gSiFiveU5SeriesPlatformsPkgTokenSpaceGuid.PcdE5MCSupported