U-Boot
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
September 2018
- 161 participants
- 587 discussions
Some lsch3 based SoCs like lx2160a contains three
serdes modules.
Add support for third serdes protocol in lsch3
Signed-off-by: Priyanka Jain <priyanka.jain(a)nxp.com>
---
arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 3 +
.../cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c | 71 ++++++++++++++++++++++
.../include/asm/arch-fsl-layerscape/fsl_serdes.h | 2 +
3 files changed, 76 insertions(+)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index f2111fa..fd31ae1 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -348,6 +348,9 @@ config SYS_FSL_SRDS_1
config SYS_FSL_SRDS_2
bool
+config SYS_FSL_SRDS_3
+ bool
+
config SYS_HAS_SERDES
bool
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
index 2bef841..bfd2868 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
+ * Copyright 2018 NXP
* Copyright 2014-2015 Freescale Semiconductor, Inc.
*/
@@ -16,6 +17,9 @@ static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
#ifdef CONFIG_SYS_FSL_SRDS_2
static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+static u8 serdes3_prtcl_map[SERDES_PRCTL_COUNT];
+#endif
#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
int xfi_dpmac[XFI8 + 1];
@@ -57,6 +61,12 @@ int is_serdes_configured(enum srds_prtcl device)
ret |= serdes2_prtcl_map[device];
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ if (!serdes3_prtcl_map[NONE])
+ fsl_serdes_init();
+
+ ret |= serdes3_prtcl_map[device];
+#endif
return !!ret;
}
@@ -82,6 +92,13 @@ int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
cfg >>= FSL_CHASSIS3_SRDS2_PRTCL_SHIFT;
break;
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ case FSL_SRDS_3:
+ cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS3_REGSR - 1]);
+ cfg &= FSL_CHASSIS3_SRDS3_PRTCL_MASK;
+ cfg >>= FSL_CHASSIS3_SRDS3_PRTCL_SHIFT;
+ break;
+#endif
default:
printf("invalid SerDes%d\n", sd);
break;
@@ -201,6 +218,12 @@ struct serdes_prctl_info srds_prctl_info[] = {
.shift = FSL_CHASSIS3_SRDS2_PRTCL_SHIFT
},
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ {.id = 3,
+ .mask = FSL_CHASSIS3_SRDS3_PRTCL_MASK,
+ .shift = FSL_CHASSIS3_SRDS3_PRTCL_SHIFT
+ },
+#endif
{} /* NULL ENTRY */
};
@@ -341,6 +364,11 @@ int setup_serdes_volt(u32 svdd)
(void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x10000);
u32 cfg_rcwsrds2 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]);
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ struct ccsr_serdes __iomem *serdes3_base =
+ (void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x20000);
+ u32 cfg_rcwsrds3 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS3_REGSR - 1]);
+#endif
u32 cfg_tmp;
int svdd_cur, svdd_tar;
int ret = 1;
@@ -370,6 +398,9 @@ int setup_serdes_volt(u32 svdd)
#ifdef CONFIG_SYS_FSL_SRDS_2
do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, false);
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ do_enabled_lanes_reset(3, cfg_rcwsrds3, serdes3_base, false);
+#endif
/* Put the all enabled PLL in reset */
#ifdef CONFIG_SYS_FSL_SRDS_1
@@ -383,6 +414,12 @@ int setup_serdes_volt(u32 svdd)
do_pll_reset(cfg_tmp, serdes2_base);
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ cfg_tmp = cfg_rcwsrds3 & 0x30;
+ cfg_tmp >>= 4;
+ do_pll_reset(cfg_tmp, serdes3_base);
+#endif
+
/* Put the Rx/Tx calibration into reset */
#ifdef CONFIG_SYS_FSL_SRDS_1
do_rx_tx_cal_reset(serdes1_base);
@@ -392,6 +429,10 @@ int setup_serdes_volt(u32 svdd)
do_rx_tx_cal_reset(serdes2_base);
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ do_rx_tx_cal_reset(serdes3_base);
+#endif
+
ret = set_serdes_volt(svdd);
if (ret < 0) {
printf("could not change SVDD\n");
@@ -408,6 +449,11 @@ int setup_serdes_volt(u32 svdd)
cfg_tmp >>= 2;
do_serdes_enable(cfg_tmp, serdes2_base);
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ cfg_tmp = cfg_rcwsrds3 & 0x30;
+ cfg_tmp >>= 4;
+ do_serdes_enable(cfg_tmp, serdes3_base);
+#endif
/* Wait for at at least 625us, ensure the PLLs being reset are locked */
udelay(800);
@@ -422,6 +468,13 @@ int setup_serdes_volt(u32 svdd)
cfg_tmp >>= 2;
do_pll_lock(cfg_tmp, serdes2_base);
#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ cfg_tmp = cfg_rcwsrds3 & 0x30;
+ cfg_tmp >>= 4;
+ do_pll_lock(cfg_tmp, serdes3_base);
+#endif
+
/* Take the all enabled lanes out of reset */
#ifdef CONFIG_SYS_FSL_SRDS_1
do_enabled_lanes_reset(1, cfg_rcwsrds1, serdes1_base, true);
@@ -430,6 +483,10 @@ int setup_serdes_volt(u32 svdd)
do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, true);
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ do_enabled_lanes_reset(3, cfg_rcwsrds3, serdes3_base, true);
+#endif
+
/* For each PLL being reset, and achieved PLL lock set RST_DONE */
#ifdef CONFIG_SYS_FSL_SRDS_1
cfg_tmp = cfg_rcwsrds1 & 0x3;
@@ -441,6 +498,12 @@ int setup_serdes_volt(u32 svdd)
do_pll_reset_done(cfg_tmp, serdes2_base);
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ cfg_tmp = cfg_rcwsrds3 & 0x30;
+ cfg_tmp >>= 4;
+ do_pll_reset_done(cfg_tmp, serdes3_base);
+#endif
+
return ret;
}
@@ -472,4 +535,12 @@ void fsl_serdes_init(void)
FSL_CHASSIS3_SRDS2_PRTCL_SHIFT,
serdes2_prtcl_map);
#endif
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ serdes_init(FSL_SRDS_3,
+ CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + FSL_SRDS_3 * 0x10000,
+ FSL_CHASSIS3_SRDS3_REGSR,
+ FSL_CHASSIS3_SRDS3_PRTCL_MASK,
+ FSL_CHASSIS3_SRDS3_PRTCL_SHIFT,
+ serdes3_prtcl_map);
+#endif
}
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
index 6981076..bec35e8 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
+ * Copyright 2018 NXP
* Copyright 2015 Freescale Semiconductor, Inc.
*/
@@ -57,6 +58,7 @@ enum srds_prtcl {
enum srds {
FSL_SRDS_1 = 0,
FSL_SRDS_2 = 1,
+ FSL_SRDS_3 = 2,
};
#elif defined(CONFIG_FSL_LSCH2)
enum srds_prtcl {
--
2.7.4
2
2

24 Sep '18
This patch adds basic support for the MediaTek MT7620/88 SoCs. Parts of
the code is copied from the MediaTek GitHub repository:
https://github.com/MediaTek-Labs/linkit-smart-uboot.git
The mt7628a.dtsi file is imported from Linux v4.17.
Support for the LinkIt Smart 7688 module and the Gardena Smart Gateway
both based on the MT7688 will be added in further patches.
Signed-off-by: Stefan Roese <sr(a)denx.de>
Cc: Daniel Schwierzeck <daniel.schwierzeck(a)gmail.com>
---
v4:
- Remove dead code from debug version in lowlevel_init
- Use sX registers now for real
- Increase cache line size in ddr_calibrate() to 128 as done in the
original code
v3:
- Added dtsi file with this platforms support as suggested by Daniel
- Rebased on top of Daniels I-cache startup patches -> removed magic
with KSEG0 call of ddr_calibrate. Its now called directly and the
bootup is much faster
- Some improvements to print_cpuinfo(), use ioremap_nocache etc
- Added .set noreorder to lowlevel_init.S
- Multiple improvements to lowlevel_init.S as suggested by Daniel
v2:
- Sort Kconfig symbols alphabetically
- Use MIPS_TUNE_24KC
- Use imply for SPI support
- Dont' add LinkIt module support yet (is added with the board support)
- Move SKIP_LOWLEVEL_INIT from Kconfig to config header
- Use DT to get the base address of the system controller (for
display_cpuinfo)
- Remove _machine_restart - a separate driver is provided in a new patch
- Remove cachop_op() and cal_invalidate_dcache_range and use the
generic invalidate_dcache_range function instead
arch/mips/Kconfig | 16 ++
arch/mips/Makefile | 1 +
arch/mips/dts/mt7628a.dtsi | 135 +++++++++++
arch/mips/mach-mt7620/Kconfig | 113 +++++++++
arch/mips/mach-mt7620/Makefile | 8 +
arch/mips/mach-mt7620/cpu.c | 69 ++++++
arch/mips/mach-mt7620/ddr_calibrate.c | 308 ++++++++++++++++++++++++
arch/mips/mach-mt7620/lowlevel_init.S | 322 ++++++++++++++++++++++++++
arch/mips/mach-mt7620/mt76xx.h | 32 +++
9 files changed, 1004 insertions(+)
create mode 100644 arch/mips/dts/mt7628a.dtsi
create mode 100644 arch/mips/mach-mt7620/Kconfig
create mode 100644 arch/mips/mach-mt7620/Makefile
create mode 100644 arch/mips/mach-mt7620/cpu.c
create mode 100644 arch/mips/mach-mt7620/ddr_calibrate.c
create mode 100644 arch/mips/mach-mt7620/lowlevel_init.S
create mode 100644 arch/mips/mach-mt7620/mt76xx.h
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 6e5e0ffe65..b3981ef2e6 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -68,6 +68,21 @@ config ARCH_BMIPS
select SYSRESET
imply CMD_DM
+config ARCH_MT7620
+ bool "Support MT7620/7688 SoCs"
+ imply CMD_DM
+ select DISPLAY_CPUINFO
+ select DM
+ select DM_SERIAL
+ imply DM_SPI
+ imply DM_SPI_FLASH
+ select MIPS_TUNE_24KC
+ select OF_CONTROL
+ select ROM_EXCEPTION_VECTORS
+ select SUPPORTS_CPU_MIPS32_R1
+ select SUPPORTS_CPU_MIPS32_R2
+ select SUPPORTS_LITTLE_ENDIAN
+
config MACH_PIC32
bool "Support Microchip PIC32"
select DM
@@ -120,6 +135,7 @@ source "board/qemu-mips/Kconfig"
source "arch/mips/mach-ath79/Kconfig"
source "arch/mips/mach-bmips/Kconfig"
source "arch/mips/mach-pic32/Kconfig"
+source "arch/mips/mach-mt7620/Kconfig"
if MIPS
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index a36f5f1fb6..802244a06e 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -14,6 +14,7 @@ libs-y += arch/mips/lib/
machine-$(CONFIG_ARCH_ATH79) += ath79
machine-$(CONFIG_ARCH_BMIPS) += bmips
machine-$(CONFIG_MACH_PIC32) += pic32
+machine-$(CONFIG_ARCH_MT7620) += mt7620
machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y))
libs-y += $(machdirs)
diff --git a/arch/mips/dts/mt7628a.dtsi b/arch/mips/dts/mt7628a.dtsi
new file mode 100644
index 0000000000..d00f528e1f
--- /dev/null
+++ b/arch/mips/dts/mt7628a.dtsi
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ralink,mt7628a-soc";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "mti,mips24KEc";
+ device_type = "cpu";
+ reg = <0>;
+ };
+ };
+
+ resetc: reset-controller {
+ compatible = "ralink,rt2880-reset";
+ #reset-cells = <1>;
+ };
+
+ cpuintc: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ palmbus@10000000 {
+ compatible = "palmbus", "simple-bus";
+ reg = <0x10000000 0x200000>;
+ ranges = <0x0 0x10000000 0x1FFFFF>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ sysc: system-controller@0 {
+ compatible = "ralink,mt7620a-sysc", "syscon";
+ reg = <0x0 0x100>;
+ };
+
+ intc: interrupt-controller@200 {
+ compatible = "ralink,rt2880-intc";
+ reg = <0x200 0x100>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ resets = <&resetc 9>;
+ reset-names = "intc";
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+
+ ralink,intc-registers = <0x9c 0xa0
+ 0x6c 0xa4
+ 0x80 0x78>;
+ };
+
+ memory-controller@300 {
+ compatible = "ralink,mt7620a-memc";
+ reg = <0x300 0x100>;
+ };
+
+ spi0: spi@b00 {
+ compatible = "ralink,mt7621-spi";
+ reg = <0xb00 0x40>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ uart0: uartlite@c00 {
+ compatible = "ns16550a";
+ reg = <0xc00 0x100>;
+
+ resets = <&resetc 12>;
+ reset-names = "uart0";
+
+ interrupt-parent = <&intc>;
+ interrupts = <20>;
+
+ reg-shift = <2>;
+ };
+
+ uart1: uart1@d00 {
+ compatible = "ns16550a";
+ reg = <0xd00 0x100>;
+
+ resets = <&resetc 19>;
+ reset-names = "uart1";
+
+ interrupt-parent = <&intc>;
+ interrupts = <21>;
+
+ reg-shift = <2>;
+ };
+
+ uart2: uart2@e00 {
+ compatible = "ns16550a";
+ reg = <0xe00 0x100>;
+
+ resets = <&resetc 20>;
+ reset-names = "uart2";
+
+ interrupt-parent = <&intc>;
+ interrupts = <22>;
+
+ reg-shift = <2>;
+ };
+ };
+
+ usb_phy: usb-phy@10120000 {
+ compatible = "mediatek,mt7628-usbphy";
+ reg = <0x10120000 0x1000>;
+
+ #phy-cells = <0>;
+
+ ralink,sysctl = <&sysc>;
+ resets = <&resetc 22 &resetc 25>;
+ reset-names = "host", "device";
+ };
+
+ ehci@101c0000 {
+ compatible = "generic-ehci";
+ reg = <0x101c0000 0x1000>;
+
+ phys = <&usb_phy>;
+ phy-names = "usb";
+
+ interrupt-parent = <&intc>;
+ interrupts = <18>;
+ };
+};
diff --git a/arch/mips/mach-mt7620/Kconfig b/arch/mips/mach-mt7620/Kconfig
new file mode 100644
index 0000000000..396fbd0141
--- /dev/null
+++ b/arch/mips/mach-mt7620/Kconfig
@@ -0,0 +1,113 @@
+menu "MediaTek MIPS platforms"
+ depends on ARCH_MT7620
+
+config SYS_MALLOC_F_LEN
+ default 0x1000
+
+config SYS_SOC
+ default "mt7620" if SOC_MT7620
+
+choice
+ prompt "MediaTek MIPS SoC select"
+
+config SOC_MT7620
+ bool "MT7620/8"
+ select MIPS_L1_CACHE_SHIFT_5
+ help
+ This supports MediaTek MIPS MT7620 family.
+
+endchoice
+
+choice
+ prompt "Board select"
+
+endchoice
+
+choice
+ prompt "Boot mode"
+
+config BOOT_RAM
+ bool "RAM boot"
+ depends on SUPPORTS_BOOT_RAM
+ help
+ This builds an image that is linked to a RAM address. It can be used
+ for booting from CFE via TFTP using an ELF image, but it can also be
+ booted from RAM by other bootloaders using a BIN image.
+
+config BOOT_ROM
+ bool "ROM boot"
+ depends on SUPPORTS_BOOT_RAM
+ help
+ This builds an image that is linked to a ROM address. It can be
+ used as main bootloader image which is programmed onto the onboard
+ flash storage (SPI NOR).
+
+endchoice
+
+choice
+ prompt "DDR2 size"
+
+config ONBOARD_DDR2_SIZE_256MBIT
+ bool "256MBit (32MByte) total size"
+ depends on BOOT_ROM
+ help
+ Use 256MBit (32MByte) of DDR total size
+
+config ONBOARD_DDR2_SIZE_512MBIT
+ bool "512MBit (64MByte) total size"
+ depends on BOOT_ROM
+ help
+ Use 512MBit (64MByte) of DDR total size
+
+config ONBOARD_DDR2_SIZE_1024MBIT
+ bool "1024MBit (128MByte) total size"
+ depends on BOOT_ROM
+ help
+ Use 1024MBit (128MByte) of DDR total size
+
+config ONBOARD_DDR2_SIZE_2048MBIT
+ bool "2048MBit (256MByte) total size"
+ depends on BOOT_ROM
+ help
+ Use 2048MBit (256MByte) of DDR total size
+
+endchoice
+
+choice
+ prompt "DDR2 chip width"
+
+config ONBOARD_DDR2_CHIP_WIDTH_8BIT
+ bool "8bit DDR chip width"
+ depends on BOOT_ROM
+ help
+ Use DDR chips with 8bit width
+
+config ONBOARD_DDR2_CHIP_WIDTH_16BIT
+ bool "16bit DDR chip width"
+ depends on BOOT_ROM
+ help
+ Use DDR chips with 16bit width
+
+endchoice
+
+choice
+ prompt "DDR2 bus width"
+
+config ONBOARD_DDR2_BUS_WIDTH_16BIT
+ bool "16bit DDR bus width"
+ depends on BOOT_ROM
+ help
+ Use 16bit DDR bus width
+
+config ONBOARD_DDR2_BUS_WIDTH_32BIT
+ bool "32bit DDR bus width"
+ depends on BOOT_ROM
+ help
+ Use 32bit DDR bus width
+
+endchoice
+
+config SUPPORTS_BOOT_RAM
+ bool
+
+endmenu
diff --git a/arch/mips/mach-mt7620/Makefile b/arch/mips/mach-mt7620/Makefile
new file mode 100644
index 0000000000..1f3e65e8a5
--- /dev/null
+++ b/arch/mips/mach-mt7620/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += cpu.o
+
+ifndef CONFIG_SKIP_LOWLEVEL_INIT
+obj-y += ddr_calibrate.o
+obj-y += lowlevel_init.o
+endif
diff --git a/arch/mips/mach-mt7620/cpu.c b/arch/mips/mach-mt7620/cpu.c
new file mode 100644
index 0000000000..457f09f32c
--- /dev/null
+++ b/arch/mips/mach-mt7620/cpu.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Stefan Roese <sr(a)denx.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ram.h>
+#include <asm/io.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+#include "mt76xx.h"
+
+#define STR_LEN 6
+
+#ifdef CONFIG_BOOT_ROM
+int mach_cpu_init(void)
+{
+ ddr_calibrate();
+
+ return 0;
+}
+#endif
+
+int dram_init(void)
+{
+ gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M);
+
+ return 0;
+}
+
+int print_cpuinfo(void)
+{
+ static const char * const boot_str[] = { "PLL (3-Byte SPI Addr)",
+ "PLL (4-Byte SPI Addr)",
+ "XTAL (3-Byte SPI Addr)",
+ "XTAL (4-Byte SPI Addr)" };
+ const void *blob = gd->fdt_blob;
+ void __iomem *sysc_base;
+ char buf[STR_LEN + 1];
+ fdt_addr_t base;
+ fdt_size_t size;
+ char *str;
+ int node;
+ u32 val;
+
+ /* Get system controller base address */
+ node = fdt_node_offset_by_compatible(blob, -1, "ralink,mt7620a-sysc");
+ if (node < 0)
+ return -FDT_ERR_NOTFOUND;
+
+ base = fdtdec_get_addr_size_auto_noparent(blob, node, "reg",
+ 0, &size, true);
+ if (base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ sysc_base = ioremap_nocache(base, size);
+
+ str = (char *)sysc_base + MT76XX_CHIPID_OFFS;
+ snprintf(buf, STR_LEN + 1, "%s", str);
+ val = readl(sysc_base + MT76XX_CHIP_REV_ID_OFFS);
+ printf("CPU: %-*s Rev %ld.%ld - ", STR_LEN, buf,
+ (val & GENMASK(11, 8)) >> 8, val & GENMASK(3, 0));
+
+ val = (readl(sysc_base + MT76XX_SYSCFG0_OFFS) & GENMASK(3, 1)) >> 1;
+ printf("Boot from %s\n", boot_str[val]);
+
+ return 0;
+}
diff --git a/arch/mips/mach-mt7620/ddr_calibrate.c b/arch/mips/mach-mt7620/ddr_calibrate.c
new file mode 100644
index 0000000000..75763c4528
--- /dev/null
+++ b/arch/mips/mach-mt7620/ddr_calibrate.c
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Stefan Roese <sr(a)denx.de>
+ *
+ * This code is mostly based on the code extracted from this MediaTek
+ * github repository:
+ *
+ * https://github.com/MediaTek-Labs/linkit-smart-uboot.git
+ *
+ * I was not able to find a specific license or other developers
+ * copyrights here, so I can't add them here.
+ *
+ * Most functions in this file are copied from the MediaTek U-Boot
+ * repository. Without any documentation, it was impossible to really
+ * implement this differently. So its mostly a cleaned-up version of
+ * the original code, with only support for the MT7628 / MT7688 SoC.
+ */
+
+#include <common.h>
+#include <linux/io.h>
+#include <asm/cacheops.h>
+#include <asm/io.h>
+#include "mt76xx.h"
+
+#define NUM_OF_CACHELINE 128
+#define MIN_START 6
+#define MIN_FINE_START 0xf
+#define MAX_START 7
+#define MAX_FINE_START 0x0
+
+#define CPU_FRAC_DIV 1
+
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_256MBIT)
+#define DRAM_BUTTOM 0x02000000
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_512MBIT)
+#define DRAM_BUTTOM 0x04000000
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_1024MBIT)
+#define DRAM_BUTTOM 0x08000000
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_2048MBIT)
+#define DRAM_BUTTOM 0x10000000
+#endif
+
+static inline void cal_memcpy(void *src, void *dst, u32 size)
+{
+ u8 *psrc = (u8 *)src;
+ u8 *pdst = (u8 *)dst;
+ int i;
+
+ for (i = 0; i < size; i++, psrc++, pdst++)
+ *pdst = *psrc;
+}
+
+static inline void cal_memset(void *src, u8 pat, u32 size)
+{
+ u8 *psrc = (u8 *)src;
+ int i;
+
+ for (i = 0; i < size; i++, psrc++)
+ *psrc = pat;
+}
+
+#define pref_op(hint, addr) \
+ __asm__ __volatile__( \
+ ".set push\n" \
+ ".set noreorder\n" \
+ "pref %0, %1\n" \
+ ".set pop\n" \
+ : \
+ : "i" (hint), "R" (*(u8 *)(addr)))
+
+static inline void cal_patgen(u32 start_addr, u32 size, u32 bias)
+{
+ u32 *addr = (u32 *)start_addr;
+ int i;
+
+ for (i = 0; i < size; i++)
+ addr[i] = start_addr + i + bias;
+}
+
+static inline int test_loop(int k, int dqs, u32 test_dqs, u32 *coarse_dqs,
+ u32 offs, u32 pat, u32 val)
+{
+ u32 nc_addr;
+ u32 *c_addr;
+ int i;
+
+ for (nc_addr = 0xa0000000;
+ nc_addr < (0xa0000000 + DRAM_BUTTOM - NUM_OF_CACHELINE * 32);
+ nc_addr += (DRAM_BUTTOM >> 6) + offs) {
+ writel(0x00007474, (void *)MT76XX_MEMCTRL_BASE + 0x64);
+ wmb(); /* Make sure store if finished */
+
+ c_addr = (u32 *)(nc_addr & 0xdfffffff);
+ cal_memset(((u8 *)c_addr), 0x1F, NUM_OF_CACHELINE * 32);
+ cal_patgen(nc_addr, NUM_OF_CACHELINE * 8, pat);
+
+ if (dqs > 0)
+ writel(0x00000074 |
+ (((k == 1) ? coarse_dqs[dqs] : test_dqs) << 12) |
+ (((k == 0) ? val : test_dqs) << 8),
+ (void *)MT76XX_MEMCTRL_BASE + 0x64);
+ else
+ writel(0x00007400 |
+ (((k == 1) ? coarse_dqs[dqs] : test_dqs) << 4) |
+ (((k == 0) ? val : test_dqs) << 0),
+ (void *)MT76XX_MEMCTRL_BASE + 0x64);
+ wmb(); /* Make sure store if finished */
+
+ invalidate_dcache_range((u32)c_addr,
+ (u32)c_addr +
+ NUM_OF_CACHELINE * 32);
+ wmb(); /* Make sure store if finished */
+
+ for (i = 0; i < NUM_OF_CACHELINE * 8; i++) {
+ if (i % 8 == 0)
+ pref_op(0, &c_addr[i]);
+ }
+
+ for (i = 0; i < NUM_OF_CACHELINE * 8; i++) {
+ if (c_addr[i] != nc_addr + i + pat)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+void ddr_calibrate(void)
+{
+ u32 min_coarse_dqs[2];
+ u32 max_coarse_dqs[2];
+ u32 min_fine_dqs[2];
+ u32 max_fine_dqs[2];
+ u32 coarse_dqs[2];
+ u32 fine_dqs[2];
+ int reg = 0, ddr_cfg2_reg;
+ int flag;
+ int i, k;
+ int dqs = 0;
+ u32 min_coarse_dqs_bnd, min_fine_dqs_bnd, coarse_dqs_dll, fine_dqs_dll;
+ u32 val;
+ u32 fdiv = 0, frac = 0;
+
+ /* Setup clock to run at full speed */
+ val = readl((void *)MT76XX_DYN_CFG0_REG);
+ fdiv = (u32)((val >> 8) & 0x0F);
+ if (CPU_FRAC_DIV < 1 || CPU_FRAC_DIV > 10)
+ frac = val & 0x0f;
+ else
+ frac = CPU_FRAC_DIV;
+
+ while (frac < fdiv) {
+ val = readl((void *)MT76XX_DYN_CFG0_REG);
+ fdiv = (val >> 8) & 0x0f;
+ fdiv--;
+ val &= ~(0x0f << 8);
+ val |= (fdiv << 8);
+ writel(val, (void *)MT76XX_DYN_CFG0_REG);
+ udelay(500);
+ val = readl((void *)MT76XX_DYN_CFG0_REG);
+ fdiv = (val >> 8) & 0x0f;
+ }
+
+ clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
+ ddr_cfg2_reg = readl((void *)MT76XX_MEMCTRL_BASE + 0x48);
+ clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x48,
+ (0x3 << 28) | (0x3 << 26));
+
+ min_coarse_dqs[0] = MIN_START;
+ min_coarse_dqs[1] = MIN_START;
+ min_fine_dqs[0] = MIN_FINE_START;
+ min_fine_dqs[1] = MIN_FINE_START;
+ max_coarse_dqs[0] = MAX_START;
+ max_coarse_dqs[1] = MAX_START;
+ max_fine_dqs[0] = MAX_FINE_START;
+ max_fine_dqs[1] = MAX_FINE_START;
+ dqs = 0;
+
+ /* Add by KP, DQS MIN boundary */
+ reg = readl((void *)MT76XX_MEMCTRL_BASE + 0x20);
+ coarse_dqs_dll = (reg & 0xf00) >> 8;
+ fine_dqs_dll = (reg & 0xf0) >> 4;
+ if (coarse_dqs_dll <= 8)
+ min_coarse_dqs_bnd = 8 - coarse_dqs_dll;
+ else
+ min_coarse_dqs_bnd = 0;
+
+ if (fine_dqs_dll <= 8)
+ min_fine_dqs_bnd = 8 - fine_dqs_dll;
+ else
+ min_fine_dqs_bnd = 0;
+ /* DQS MIN boundary */
+
+DQS_CAL:
+
+ for (k = 0; k < 2; k++) {
+ u32 test_dqs;
+
+ if (k == 0)
+ test_dqs = MAX_START;
+ else
+ test_dqs = MAX_FINE_START;
+
+ do {
+ flag = test_loop(k, dqs, test_dqs, max_coarse_dqs,
+ 0x400, 0x3, 0xf);
+ if (flag == -1)
+ break;
+
+ test_dqs++;
+ } while (test_dqs <= 0xf);
+
+ if (k == 0) {
+ max_coarse_dqs[dqs] = test_dqs;
+ } else {
+ test_dqs--;
+
+ if (test_dqs == MAX_FINE_START - 1) {
+ max_coarse_dqs[dqs]--;
+ max_fine_dqs[dqs] = 0xf;
+ } else {
+ max_fine_dqs[dqs] = test_dqs;
+ }
+ }
+ }
+
+ for (k = 0; k < 2; k++) {
+ u32 test_dqs;
+
+ if (k == 0)
+ test_dqs = MIN_START;
+ else
+ test_dqs = MIN_FINE_START;
+
+ do {
+ flag = test_loop(k, dqs, test_dqs, min_coarse_dqs,
+ 0x480, 0x1, 0x0);
+ if (k == 0) {
+ if (flag == -1 ||
+ test_dqs == min_coarse_dqs_bnd)
+ break;
+
+ test_dqs--;
+
+ if (test_dqs < min_coarse_dqs_bnd)
+ break;
+ } else {
+ if (flag == -1) {
+ test_dqs++;
+ break;
+ } else if (test_dqs == min_fine_dqs_bnd) {
+ break;
+ }
+
+ test_dqs--;
+
+ if (test_dqs < min_fine_dqs_bnd)
+ break;
+ }
+ } while (test_dqs >= 0);
+
+ if (k == 0) {
+ min_coarse_dqs[dqs] = test_dqs;
+ } else {
+ if (test_dqs == MIN_FINE_START + 1) {
+ min_coarse_dqs[dqs]++;
+ min_fine_dqs[dqs] = 0x0;
+ } else {
+ min_fine_dqs[dqs] = test_dqs;
+ }
+ }
+ }
+
+ if (dqs == 0) {
+ dqs = 1;
+ goto DQS_CAL;
+ }
+
+ for (i = 0; i < 2; i++) {
+ u32 temp;
+
+ coarse_dqs[i] = (max_coarse_dqs[i] + min_coarse_dqs[i]) >> 1;
+ temp =
+ (((max_coarse_dqs[i] + min_coarse_dqs[i]) % 2) * 4) +
+ ((max_fine_dqs[i] + min_fine_dqs[i]) >> 1);
+ if (temp >= 0x10) {
+ coarse_dqs[i]++;
+ fine_dqs[i] = (temp - 0x10) + 0x8;
+ } else {
+ fine_dqs[i] = temp;
+ }
+ }
+ reg = (coarse_dqs[1] << 12) | (fine_dqs[1] << 8) |
+ (coarse_dqs[0] << 4) | fine_dqs[0];
+
+ clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
+ writel(reg, (void *)MT76XX_MEMCTRL_BASE + 0x64);
+ writel(ddr_cfg2_reg, (void *)MT76XX_MEMCTRL_BASE + 0x48);
+ setbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
+
+ for (i = 0; i < 2; i++)
+ debug("[%02X%02X%02X%02X]", min_coarse_dqs[i],
+ min_fine_dqs[i], max_coarse_dqs[i], max_fine_dqs[i]);
+ debug("\nDDR Calibration DQS reg = %08X\n", reg);
+}
diff --git a/arch/mips/mach-mt7620/lowlevel_init.S b/arch/mips/mach-mt7620/lowlevel_init.S
new file mode 100644
index 0000000000..1a50f160fe
--- /dev/null
+++ b/arch/mips/mach-mt7620/lowlevel_init.S
@@ -0,0 +1,322 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (c) 2018 Stefan Roese <sr(a)denx.de>
+ *
+ * This code is mostly based on the code extracted from this MediaTek
+ * github repository:
+ *
+ * https://github.com/MediaTek-Labs/linkit-smart-uboot.git
+ *
+ * I was not able to find a specific license or other developers
+ * copyrights here, so I can't add them here.
+ */
+
+#include <config.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include "mt76xx.h"
+
+#ifndef BIT
+#define BIT(nr) (1 << (nr))
+#endif
+
+#define DELAY_USEC(us) ((us) / 100)
+
+#define DDR_CFG1_CHIP_WIDTH_MASK (0x3 << 16)
+#define DDR_CFG1_BUS_WIDTH_MASK (0x3 << 12)
+
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_256MBIT)
+#define DDR_CFG1_SIZE_VAL 0x222e2323
+#define DDR_CFG4_SIZE_VAL 7
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_512MBIT)
+#define DDR_CFG1_SIZE_VAL 0x22322323
+#define DDR_CFG4_SIZE_VAL 9
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_1024MBIT)
+#define DDR_CFG1_SIZE_VAL 0x22362323
+#define DDR_CFG4_SIZE_VAL 9
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_2048MBIT)
+#define DDR_CFG1_SIZE_VAL 0x223a2323
+#define DDR_CFG4_SIZE_VAL 9
+#endif
+
+#if defined(CONFIG_ONBOARD_DDR2_CHIP_WIDTH_8BIT)
+#define DDR_CFG1_CHIP_WIDTH_VAL (0x1 << 16)
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_CHIP_WIDTH_16BIT)
+#define DDR_CFG1_CHIP_WIDTH_VAL (0x2 << 16)
+#endif
+
+#if defined(CONFIG_ONBOARD_DDR2_BUS_WIDTH_16BIT)
+#define DDR_CFG1_BUS_WIDTH_VAL (0x2 << 12)
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_BUS_WIDTH_32BIT)
+#define DDR_CFG1_BUS_WIDTH_VAL (0x3 << 12)
+#endif
+
+ .set noreorder
+
+LEAF(lowlevel_init)
+
+ /* Load base addresses as physical addresses for later usage */
+ li s0, CKSEG1ADDR(MT76XX_SYSCTL_BASE)
+ li s1, CKSEG1ADDR(MT76XX_MEMCTRL_BASE)
+ li s2, CKSEG1ADDR(MT76XX_RGCTRL_BASE)
+
+ /* polling CPLL is ready */
+ li t1, DELAY_USEC(1000000)
+ la t5, MT76XX_ROM_STATUS_REG
+1:
+ lw t2, 0(t5)
+ andi t2, t2, 0x1
+ bnez t2, CPLL_READY
+ subu t1, t1, 1
+ bgtz t1, 1b
+ nop
+ la t0, MT76XX_CLKCFG0_REG
+ lw t3, 0(t0)
+ ori t3, t3, 0x1
+ sw t3, 0(t0)
+ b CPLL_DONE
+ nop
+CPLL_READY:
+ la t0, MT76XX_CLKCFG0_REG
+ lw t1, 0(t0)
+ li t2, ~0x0c
+ and t1, t1, t2
+ ori t1, t1, 0xc
+ sw t1, 0(t0)
+ la t0, MT76XX_DYN_CFG0_REG
+ lw t3, 0(t0)
+ li t5, ~((0x0f << 8) | (0x0f << 0))
+ and t3, t3, t5
+ li t5, (10 << 8) | (1 << 0)
+ or t3, t3, t5
+ sw t3, 0(t0)
+ la t0, MT76XX_CLKCFG0_REG
+ lw t3, 0(t0)
+ li t4, ~0x0F
+ and t3, t3, t4
+ ori t3, t3, 0xc
+ sw t3, 0(t0)
+ lw t3, 0(t0)
+ ori t3, t3, 0x08
+ sw t3, 0(t0)
+
+CPLL_DONE:
+ /*
+ * SDR and DDR initialization: delay 200us
+ */
+ li t0, DELAY_USEC(200 + 40)
+ li t1, 0x1
+1:
+ sub t0, t0, t1
+ bnez t0, 1b
+ nop
+
+ /* set DRAM IO PAD for MT7628IC */
+ /* DDR LDO Enable */
+ lw t4, 0x100(s2)
+ li t2, BIT(31)
+ or t4, t4, t2
+ sw t4, 0x100(s2)
+ lw t4, 0x10c(s2)
+ j LDO_1P8V
+ nop
+LDO_1P8V:
+ li t2, ~BIT(6)
+ and t4, t4, t2
+ sw t4, 0x10c(s2)
+ j DDRLDO_SOFT_START
+LDO_2P5V:
+ /* suppose external DDR1 LDO 2.5V */
+ li t2, BIT(6)
+ or t4, t4, t2
+ sw t4, 0x10c(s2)
+
+DDRLDO_SOFT_START:
+ lw t2, 0x10c(s2)
+ li t3, BIT(16)
+ or t2, t2, t3
+ sw t2, 0x10c(s2)
+ li t3, DELAY_USEC(250*50)
+LDO_DELAY:
+ subu t3, t3, 1
+ bnez t3, LDO_DELAY
+ nop
+
+ lw t2, 0x10c(s2)
+ li t3, BIT(18)
+ or t2, t2, t3
+ sw t2, 0x10c(s2)
+
+SET_RG_BUCK_FPWM:
+ lw t2, 0x104(s2)
+ ori t2, t2, BIT(10)
+ sw t2, 0x104(s2)
+
+DDR_PAD_CFG:
+ /* clean CLK PAD */
+ lw t2, 0x704(s2)
+ li t8, 0xfffff0f0
+ and t2, t2, t8
+ /* clean CMD PAD */
+ lw t3, 0x70c(s2)
+ li t8, 0xfffff0f0
+ and t3, t3, t8
+ /* clean DQ IPAD */
+ lw t4, 0x710(s2)
+ li t8, 0xfffff8ff
+ and t4, t4, t8
+ /* clean DQ OPAD */
+ lw t5, 0x714(s2)
+ li t8, 0xfffff0f0
+ and t5, t5, t8
+ /* clean DQS IPAD */
+ lw t6, 0x718(s2)
+ li t8, 0xfffff8ff
+ and t6, t6, t8
+ /* clean DQS OPAD */
+ lw t7, 0x71c(s2)
+ li t8, 0xfffff0f0
+ and t7, t7, t8
+
+ lw t9, 0xc(s0)
+ srl t9, t9, 16
+ andi t9, t9, 0x1
+ bnez t9, MT7628_AN_DDR1_PAD
+MT7628_KN_PAD:
+ li t8, 0x00000303
+ or t2, t2, t8
+ or t3, t3, t8
+ or t5, t5, t8
+ or t7, t7, t8
+ li t8, 0x00000000
+ or t4, t4, t8
+ or t6, t6, t8
+ j SET_PAD_CFG
+MT7628_AN_DDR1_PAD:
+ lw t1, 0x10(s0)
+ andi t1, t1, 0x1
+ beqz t1, MT7628_AN_DDR2_PAD
+ li t8, 0x00000c0c
+ or t2, t2, t8
+ li t8, 0x00000202
+ or t3, t3, t8
+ li t8, 0x00000707
+ or t5, t5, t8
+ li t8, 0x00000c0c
+ or t7, t7, t8
+ li t8, 0x00000000
+ or t4, t4, t8
+ or t6, t6, t8
+ j SET_PAD_CFG
+MT7628_AN_DDR2_PAD:
+ li t8, 0x00000c0c
+ or t2, t2, t8
+ li t8, 0x00000202
+ or t3, t3, t8
+ li t8, 0x00000404
+ or t5, t5, t8
+ li t8, 0x00000c0c
+ or t7, t7, t8
+ li t8, 0x00000000 /* ODT off */
+ or t4, t4, t8
+ or t6, t6, t8
+
+SET_PAD_CFG:
+ sw t2, 0x704(s2)
+ sw t3, 0x70c(s2)
+ sw t4, 0x710(s2)
+ sw t5, 0x714(s2)
+ sw t6, 0x718(s2)
+ sw t7, 0x71c(s2)
+
+ /*
+ * DDR initialization: reset pin to 0
+ */
+ lw t2, 0x34(s0)
+ and t2, ~BIT(10)
+ sw t2, 0x34(s0)
+ nop
+
+ /*
+ * DDR initialization: wait til reg DDR_CFG1 bit 21 equal to 1 (ready)
+ */
+DDR_READY:
+ li t1, DDR_CFG1_REG
+ lw t0, 0(t1)
+ nop
+ and t2, t0, BIT(21)
+ beqz t2, DDR_READY
+ nop
+
+ /*
+ * DDR initialization
+ *
+ * Only DDR2 supported right now. DDR2 support can be added, once
+ * boards using it will get added to mainline U-Boot.
+ */
+ li t1, DDR_CFG2_REG
+ lw t0, 0(t1)
+ nop
+ and t0, ~BIT(30)
+ and t0, ~(7 << 4)
+ or t0, (4 << 4)
+ or t0, BIT(30)
+ or t0, BIT(11)
+ sw t0, 0(t1)
+ nop
+
+ li t1, DDR_CFG3_REG
+ lw t2, 0(t1)
+ /* Disable ODT; reference board ok, ev board fail */
+ and t2, ~BIT(6)
+ or t2, BIT(2)
+ li t0, DDR_CFG4_REG
+ lw t1, 0(t0)
+ li t2, ~(0x01f | 0x0f0)
+ and t1, t1, t2
+ ori t1, t1, DDR_CFG4_SIZE_VAL
+ sw t1, 0(t0)
+ nop
+
+ /*
+ * DDR initialization: config size and width on reg DDR_CFG1
+ */
+ li t6, DDR_CFG1_SIZE_VAL
+
+ and t6, ~DDR_CFG1_CHIP_WIDTH_MASK
+ or t6, DDR_CFG1_CHIP_WIDTH_VAL
+
+ /* CONFIG DDR_CFG1[13:12] about TOTAL WIDTH */
+ and t6, ~DDR_CFG1_BUS_WIDTH_MASK
+ or t6, DDR_CFG1_BUS_WIDTH_VAL
+
+ li t5, DDR_CFG1_REG
+ sw t6, 0(t5)
+ nop
+
+ /*
+ * DDR: enable self auto refresh for power saving
+ * enable it by default for both RAM and ROM version (for CoC)
+ */
+ lw t1, 0x14(s1)
+ nop
+ and t1, 0xff000000
+ or t1, 0x01
+ sw t1, 0x14(s1)
+ nop
+ lw t1, 0x10(s1)
+ nop
+ or t1, 0x10
+ sw t1, 0x10(s1)
+ nop
+
+ jr ra
+ nop
+ END(lowlevel_init)
diff --git a/arch/mips/mach-mt7620/mt76xx.h b/arch/mips/mach-mt7620/mt76xx.h
new file mode 100644
index 0000000000..17473ea8f1
--- /dev/null
+++ b/arch/mips/mach-mt7620/mt76xx.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Stefan Roese <sr(a)denx.de>
+ */
+
+#ifndef __MT76XX_H
+#define __MT76XX_H
+
+#define MT76XX_SYSCTL_BASE 0x10000000
+
+#define MT76XX_CHIPID_OFFS 0x00
+#define MT76XX_CHIP_REV_ID_OFFS 0x0c
+#define MT76XX_SYSCFG0_OFFS 0x10
+
+#define MT76XX_MEMCTRL_BASE (MT76XX_SYSCTL_BASE + 0x0300)
+#define MT76XX_RGCTRL_BASE (MT76XX_SYSCTL_BASE + 0x1000)
+
+#define MT76XX_ROM_STATUS_REG (MT76XX_SYSCTL_BASE + 0x0028)
+#define MT76XX_CLKCFG0_REG (MT76XX_SYSCTL_BASE + 0x002c)
+#define MT76XX_DYN_CFG0_REG (MT76XX_SYSCTL_BASE + 0x0440)
+
+#define DDR_CFG1_REG (MT76XX_MEMCTRL_BASE + 0x44)
+#define DDR_CFG2_REG (MT76XX_MEMCTRL_BASE + 0x48)
+#define DDR_CFG3_REG (MT76XX_MEMCTRL_BASE + 0x4c)
+#define DDR_CFG4_REG (MT76XX_MEMCTRL_BASE + 0x50)
+
+#ifndef __ASSEMBLY__
+/* Prototypes */
+void ddr_calibrate(void);
+#endif
+
+#endif
--
2.18.0
2
2

23 Sep '18
Remove unused import and variables.
Remove superfluous semicolons.
Reformat long lines.
Signed-off-by: Heinrich Schuchardt <xypron.glpk(a)gmx.de>
---
test/py/tests/test_efi_selftest.py | 35 ++++++++++++++++--------------
1 file changed, 19 insertions(+), 16 deletions(-)
diff --git a/test/py/tests/test_efi_selftest.py b/test/py/tests/test_efi_selftest.py
index e0833ffe22..380be0bbfd 100644
--- a/test/py/tests/test_efi_selftest.py
+++ b/test/py/tests/test_efi_selftest.py
@@ -4,7 +4,6 @@
# Test efi API implementation
import pytest
-import u_boot_utils
@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
def test_efi_selftest(u_boot_console):
@@ -13,15 +12,17 @@ def test_efi_selftest(u_boot_console):
"""
u_boot_console.run_command(cmd='setenv efi_selftest')
- u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False)
+ u_boot_console.run_command(cmd='bootefi selftest',
+ wait_for_prompt=False)
m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
if m != 0:
raise Exception('Failures occurred during the EFI selftest')
- u_boot_console.run_command(cmd='', wait_for_echo=False, wait_for_prompt=False);
+ u_boot_console.run_command(cmd='', wait_for_echo=False,
+ wait_for_prompt=False)
m = u_boot_console.p.expect(['resetting', 'U-Boot'])
if m != 0:
raise Exception('Reset failed during the EFI selftest')
- u_boot_console.restart_uboot();
+ u_boot_console.restart_uboot()
@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
@pytest.mark.buildconfigspec('of_control')
@@ -31,11 +32,12 @@ def test_efi_selftest_device_tree(u_boot_console):
assert '\'device tree\'' in output
u_boot_console.run_command(cmd='setenv efi_selftest device tree')
u_boot_console.run_command(cmd='setenv -f serial# Testing DT')
- u_boot_console.run_command(cmd='bootefi selftest ${fdtcontroladdr}', wait_for_prompt=False)
+ u_boot_console.run_command(cmd='bootefi selftest ${fdtcontroladdr}',
+ wait_for_prompt=False)
m = u_boot_console.p.expect(['serial-number: Testing DT', 'U-Boot'])
if m != 0:
raise Exception('Reset failed in \'device tree\' test')
- u_boot_console.restart_uboot();
+ u_boot_console.restart_uboot()
@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
def test_efi_selftest_watchdog_reboot(u_boot_console):
@@ -43,11 +45,12 @@ def test_efi_selftest_watchdog_reboot(u_boot_console):
output = u_boot_console.run_command('bootefi selftest')
assert '\'watchdog reboot\'' in output
u_boot_console.run_command(cmd='setenv efi_selftest watchdog reboot')
- u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False)
+ u_boot_console.run_command(cmd='bootefi selftest',
+ wait_for_prompt=False)
m = u_boot_console.p.expect(['resetting', 'U-Boot'])
if m != 0:
raise Exception('Reset failed in \'watchdog reboot\' test')
- u_boot_console.restart_uboot();
+ u_boot_console.restart_uboot()
@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
def test_efi_selftest_text_input(u_boot_console):
@@ -58,8 +61,8 @@ def test_efi_selftest_text_input(u_boot_console):
This function calls the text input EFI selftest.
"""
u_boot_console.run_command(cmd='setenv efi_selftest text input')
- output = u_boot_console.run_command(cmd='bootefi selftest',
- wait_for_prompt=False)
+ u_boot_console.run_command(cmd='bootefi selftest',
+ wait_for_prompt=False)
m = u_boot_console.p.expect(['To terminate type \'x\''])
if m != 0:
raise Exception('No prompt for \'text input\' test')
@@ -117,7 +120,7 @@ def test_efi_selftest_text_input(u_boot_console):
m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
if m != 0:
raise Exception('Failures occurred during the EFI selftest')
- u_boot_console.restart_uboot();
+ u_boot_console.restart_uboot()
@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
def test_efi_selftest_text_input_ex(u_boot_console):
@@ -128,8 +131,8 @@ def test_efi_selftest_text_input_ex(u_boot_console):
This function calls the extended text input EFI selftest.
"""
u_boot_console.run_command(cmd='setenv efi_selftest extended text input')
- output = u_boot_console.run_command(cmd='bootefi selftest',
- wait_for_prompt=False)
+ u_boot_console.run_command(cmd='bootefi selftest',
+ wait_for_prompt=False)
m = u_boot_console.p.expect(['To terminate type \'CTRL\+x\''])
if m != 0:
raise Exception('No prompt for \'text input\' test')
@@ -191,9 +194,9 @@ def test_efi_selftest_text_input_ex(u_boot_console):
if m != 0:
raise Exception('SHIFT+ALT+FN 5 failed in \'text input\' test')
u_boot_console.drain_console()
- u_boot_console.run_command(cmd=chr(24), wait_for_echo=False, send_nl=False,
- wait_for_prompt=False)
+ u_boot_console.run_command(cmd=chr(24), wait_for_echo=False,
+ send_nl=False, wait_for_prompt=False)
m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
if m != 0:
raise Exception('Failures occurred during the EFI selftest')
- u_boot_console.restart_uboot();
+ u_boot_console.restart_uboot()
--
2.19.0
1
0

23 Sep '18
When running in EL3 mode on AArch64, we have to first drop to EL2
to execute a UEFI payload. When dropping down, the arguments to
the entry point have to stay identical to the ones for normal entry
though.
In commit ea54ad59286 ("efi_loader: pass handle of loaded image")
we incorrectly changed that logic and had the el3 entry path diverge.
Fix it up by syncing it back to what it's supposed to be.
Fixes: ea54ad59286 ("efi_loader: pass handle of loaded image")
Signed-off-by: Alexander Graf <agraf(a)suse.de>
---
cmd/bootefi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 5fc054c9da..6395d4b9b0 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -408,7 +408,7 @@ static efi_status_t do_bootefi_exec(void *efi,
/* Move into EL2 and keep running there */
armv8_switch_to_el2((ulong)entry,
- (ulong)&loaded_image_info_obj.handle,
+ (ulong)loaded_image_info_obj.handle,
(ulong)&systab, 0, (ulong)efi_run_in_el2,
ES_TO_AARCH64);
--
2.12.3
2
1

23 Sep '18
This series makes it possible to run EFI applications in non-secure
mode. It allows me to run OpenBSD on the Technexion PICO-PI-IMX7 and
Banana Pi boards using the PSCI implementation provided by U-Boot.
The second version avoids using r3 to pass the original stack pointer.
For some reason that register gets clobbered on the Banana Pi. Instead
this version just migrates SP_svc to SP_hyp.
This third version avoids saving r3 on the stack and fixes an include
guard as suggested by Alexander Graf.
Mark Kettenis (3):
ARM: HYP/non-sec: migrate stack
efi_loader: ARM: run EFI payloads non-secure
Revert "efi_loader: no support for ARMV7_NONSEC=y"
arch/arm/cpu/armv7/nonsec_virt.S | 2 ++
cmd/bootefi.c | 32 ++++++++++++++++++++++++++++++++
doc/README.uefi | 2 --
lib/efi_loader/Kconfig | 2 --
4 files changed, 34 insertions(+), 4 deletions(-)
--
2.16.2
7
26

[U-Boot] [PATCH v4 1/1] efi_loader: refactor efi_setup_loaded_image()
by Heinrich Schuchardt 23 Sep '18
by Heinrich Schuchardt 23 Sep '18
23 Sep '18
Create the handle of loaded images and the EFI_LOADED_IMAGE_PROTOCOL
inside efi_setup_loaded_image(). Do not use local variables.
Currently we expect the loaded image handle to point to the loaded image
protocol. Additionally we have appended private fields to the protocol.
With the patch the handle points to a loaded image object and the private
fields are added here. This matches how we handle the net and the gop
object.
Signed-off-by: Heinrich Schuchardt <xypron.glpk(a)gmx.de>
---
v4
in EL3 mode path the handle not a pointer to the handle
evaluate return value of efi_setup_loaded_image()
v3
squashed two patches
https://lists.denx.de/pipermail/u-boot/2018-September/341130.html
https://lists.denx.de/pipermail/u-boot/2018-September/341589.html
v2
avoid unused variables if configured without CONFIG_EFI_SELFTEST
---
cmd/bootefi.c | 67 +++++++++++++---------
include/efi_api.h | 8 ---
include/efi_loader.h | 27 ++++++---
lib/efi_loader/efi_boottime.c | 92 +++++++++++++++----------------
lib/efi_loader/efi_image_loader.c | 23 ++++----
5 files changed, 117 insertions(+), 100 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 27cdc21f59..7ef3592b0e 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -325,19 +325,26 @@ static efi_status_t efi_install_fdt(ulong fdt_addr)
return ret;
}
-/*
- * Load an EFI payload into a newly allocated piece of memory, register all
- * EFI objects it would want to access and jump to it.
+/**
+ * do_bootefi_exec() - execute EFI binary
+ *
+ * @efi: address of the binary
+ * @device_path: path of the device from which the binary was loaded
+ * @image_path: device path of the binary
+ * Return: status code
+ *
+ * Load the EFI binary into a newly assigned memory unwinding the relocation
+ * information, install the loaded image protocol, and call the binary.
*/
static efi_status_t do_bootefi_exec(void *efi,
struct efi_device_path *device_path,
struct efi_device_path *image_path)
{
- struct efi_loaded_image loaded_image_info = {};
- struct efi_object loaded_image_info_obj = {};
efi_handle_t mem_handle = NULL;
struct efi_device_path *memdp = NULL;
efi_status_t ret;
+ struct efi_loaded_image_obj *image_handle = NULL;
+ struct efi_loaded_image *loaded_image_info = NULL;
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
struct efi_system_table *st);
@@ -367,8 +374,10 @@ static efi_status_t do_bootefi_exec(void *efi,
assert(device_path && image_path);
}
- efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj,
- device_path, image_path);
+ ret = efi_setup_loaded_image(device_path, image_path, &image_handle,
+ &loaded_image_info);
+ if (ret != EFI_SUCCESS)
+ goto exit;
/*
* gd lives in a fixed register which may get clobbered while we execute
@@ -377,9 +386,9 @@ static efi_status_t do_bootefi_exec(void *efi,
efi_save_gd();
/* Transfer environment variable bootargs as load options */
- set_load_options(&loaded_image_info, "bootargs");
+ set_load_options(loaded_image_info, "bootargs");
/* Load the EFI payload */
- entry = efi_load_pe(efi, &loaded_image_info);
+ entry = efi_load_pe(image_handle, efi, loaded_image_info);
if (!entry) {
ret = EFI_LOAD_ERROR;
goto exit;
@@ -387,10 +396,10 @@ static efi_status_t do_bootefi_exec(void *efi,
if (memdp) {
struct efi_device_path_memory *mdp = (void *)memdp;
- mdp->memory_type = loaded_image_info.image_code_type;
- mdp->start_address = (uintptr_t)loaded_image_info.image_base;
+ mdp->memory_type = loaded_image_info->image_code_type;
+ mdp->start_address = (uintptr_t)loaded_image_info->image_base;
mdp->end_address = mdp->start_address +
- loaded_image_info.image_size;
+ loaded_image_info->image_size;
}
/* we don't support much: */
@@ -400,8 +409,8 @@ static efi_status_t do_bootefi_exec(void *efi,
/* Call our payload! */
debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
- if (setjmp(&loaded_image_info.exit_jmp)) {
- ret = loaded_image_info.exit_status;
+ if (setjmp(&image_handle->exit_jmp)) {
+ ret = image_handle->exit_status;
goto exit;
}
@@ -413,7 +422,7 @@ static efi_status_t do_bootefi_exec(void *efi,
/* Move into EL2 and keep running there */
armv8_switch_to_el2((ulong)entry,
- (ulong)loaded_image_info_obj.handle,
+ (ulong)image_handle,
(ulong)&systab, 0, (ulong)efi_run_in_el2,
ES_TO_AARCH64);
@@ -430,7 +439,7 @@ static efi_status_t do_bootefi_exec(void *efi,
secure_ram_addr(_do_nonsec_entry)(
efi_run_in_hyp,
(uintptr_t)entry,
- (uintptr_t)loaded_image_info_obj.handle,
+ (uintptr_t)image_handle,
(uintptr_t)&systab);
/* Should never reach here, efi exits with longjmp */
@@ -438,11 +447,12 @@ static efi_status_t do_bootefi_exec(void *efi,
}
#endif
- ret = efi_do_enter(loaded_image_info_obj.handle, &systab, entry);
+ ret = efi_do_enter(image_handle, &systab, entry);
exit:
/* image has returned, loaded-image obj goes *poof*: */
- list_del(&loaded_image_info_obj.link);
+ if (image_handle)
+ efi_delete_handle(&image_handle->parent);
if (mem_handle)
efi_delete_handle(mem_handle);
@@ -527,8 +537,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#endif
#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
if (!strcmp(argv[1], "selftest")) {
- struct efi_loaded_image loaded_image_info = {};
- struct efi_object loaded_image_info_obj = {};
+ struct efi_loaded_image_obj *image_handle;
+ struct efi_loaded_image *loaded_image_info;
/* Construct a dummy device path. */
bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
@@ -536,9 +546,12 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
(uintptr_t)&efi_selftest);
bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest");
- efi_setup_loaded_image(&loaded_image_info,
- &loaded_image_info_obj,
- bootefi_device_path, bootefi_image_path);
+ r = efi_setup_loaded_image(bootefi_device_path,
+ bootefi_image_path, &image_handle,
+ &loaded_image_info);
+ if (r != EFI_SUCCESS)
+ return CMD_RET_FAILURE;
+
/*
* gd lives in a fixed register which may get clobbered while we
* execute the payload. So save it here and restore it on every
@@ -546,12 +559,12 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
*/
efi_save_gd();
/* Transfer environment variable efi_selftest as load options */
- set_load_options(&loaded_image_info, "efi_selftest");
+ set_load_options(loaded_image_info, "efi_selftest");
/* Execute the test */
- r = efi_selftest(loaded_image_info_obj.handle, &systab);
+ r = efi_selftest(image_handle, &systab);
efi_restore_gd();
- free(loaded_image_info.load_options);
- list_del(&loaded_image_info_obj.link);
+ free(loaded_image_info->load_options);
+ efi_delete_handle(&image_handle->parent);
return r != EFI_SUCCESS;
} else
#endif
diff --git a/include/efi_api.h b/include/efi_api.h
index 5004f520ff..c42df6900a 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -340,14 +340,6 @@ struct efi_loaded_image {
unsigned int image_code_type;
unsigned int image_data_type;
unsigned long unload;
-
- /* Below are efi loader private fields */
-#ifdef CONFIG_EFI_LOADER
- void *reloc_base;
- aligned_u64 reloc_size;
- efi_status_t exit_status;
- struct jmp_buf_data exit_jmp;
-#endif
};
#define DEVICE_PATH_GUID \
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 7738391aa2..74df070316 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -189,6 +189,20 @@ struct efi_object {
void *handle;
};
+/**
+ * struct efi_loaded_image_obj - handle of a loaded image
+ */
+struct efi_loaded_image_obj {
+ /* Generic EFI object parent class data */
+ struct efi_object parent;
+ void *reloc_base;
+ aligned_u64 reloc_size;
+ efi_status_t exit_status;
+ struct jmp_buf_data exit_jmp;
+ EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
+ struct efi_system_table *st);
+};
+
/**
* struct efi_event
*
@@ -270,7 +284,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout);
/* Called from places to check whether a timer expired */
void efi_timer_check(void);
/* PE loader implementation */
-void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info);
+void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
+ struct efi_loaded_image *loaded_image_info);
/* Called once to store the pristine gd pointer */
void efi_save_gd(void);
/* Special case handler for error/abort that just tries to dtrt to get
@@ -351,14 +366,12 @@ int efi_memory_init(void);
/* Adds new or overrides configuration table entry to the system table */
efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table);
/* Sets up a loaded image */
-efi_status_t efi_setup_loaded_image(
- struct efi_loaded_image *info, struct efi_object *obj,
- struct efi_device_path *device_path,
- struct efi_device_path *file_path);
+efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
+ struct efi_device_path *file_path,
+ struct efi_loaded_image_obj **handle_ptr,
+ struct efi_loaded_image **info_ptr);
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
void **buffer);
-/* Print information about a loaded image */
-efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc);
/* Print information about all loaded images */
void efi_print_image_infos(void *pc);
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 8e0e2f7f87..97eb19cd14 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1470,17 +1470,31 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
*
* Return: status code
*/
-efi_status_t efi_setup_loaded_image(
- struct efi_loaded_image *info, struct efi_object *obj,
- struct efi_device_path *device_path,
- struct efi_device_path *file_path)
+efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
+ struct efi_device_path *file_path,
+ struct efi_loaded_image_obj **handle_ptr,
+ struct efi_loaded_image **info_ptr)
{
efi_status_t ret;
+ struct efi_loaded_image *info;
+ struct efi_loaded_image_obj *obj;
+
+ info = calloc(1, sizeof(*info));
+ if (!info)
+ return EFI_OUT_OF_RESOURCES;
+ obj = calloc(1, sizeof(*obj));
+ if (!obj) {
+ free(info);
+ return EFI_OUT_OF_RESOURCES;
+ }
/* Add internal object to object list */
- efi_add_handle(obj);
- /* efi_exit() assumes that the handle points to the info */
- obj->handle = info;
+ efi_add_handle(&obj->parent);
+
+ if (info_ptr)
+ *info_ptr = info;
+ if (handle_ptr)
+ *handle_ptr = obj;
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
info->file_path = file_path;
@@ -1492,8 +1506,8 @@ efi_status_t efi_setup_loaded_image(
* When asking for the device path interface, return
* bootefi_device_path
*/
- ret = efi_add_protocol(obj->handle, &efi_guid_device_path,
- device_path);
+ ret = efi_add_protocol(obj->parent.handle,
+ &efi_guid_device_path, device_path);
if (ret != EFI_SUCCESS)
goto failure;
}
@@ -1502,7 +1516,8 @@ efi_status_t efi_setup_loaded_image(
* When asking for the loaded_image interface, just
* return handle which points to loaded_image_info
*/
- ret = efi_add_protocol(obj->handle, &efi_guid_loaded_image, info);
+ ret = efi_add_protocol(obj->parent.handle,
+ &efi_guid_loaded_image, info);
if (ret != EFI_SUCCESS)
goto failure;
@@ -1585,7 +1600,8 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
efi_handle_t *image_handle)
{
struct efi_loaded_image *info;
- struct efi_object *obj;
+ struct efi_loaded_image_obj **image_obj =
+ (struct efi_loaded_image_obj **)image_handle;
efi_status_t ret;
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
@@ -1601,18 +1617,6 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
goto error;
}
- info = calloc(1, sizeof(*info));
- if (!info) {
- ret = EFI_OUT_OF_RESOURCES;
- goto error;
- }
- obj = calloc(1, sizeof(*obj));
- if (!obj) {
- free(info);
- ret = EFI_OUT_OF_RESOURCES;
- goto error;
- }
-
if (!source_buffer) {
struct efi_device_path *dp, *fp;
@@ -1624,29 +1628,29 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
* file parts:
*/
efi_dp_split_file_path(file_path, &dp, &fp);
- ret = efi_setup_loaded_image(info, obj, dp, fp);
+ ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
if (ret != EFI_SUCCESS)
goto failure;
} else {
/* In this case, file_path is the "device" path, i.e.
* something like a HARDWARE_DEVICE:MEMORY_MAPPED
*/
- ret = efi_setup_loaded_image(info, obj, file_path, NULL);
+ ret = efi_setup_loaded_image(file_path, NULL, image_obj, &info);
if (ret != EFI_SUCCESS)
- goto failure;
+ goto error;
}
- info->reserved = efi_load_pe(source_buffer, info);
- if (!info->reserved) {
+ (*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info);
+ if (!(*image_obj)->entry) {
ret = EFI_UNSUPPORTED;
goto failure;
}
info->system_table = &systab;
info->parent_handle = parent_image;
- *image_handle = obj->handle;
return EFI_EXIT(EFI_SUCCESS);
failure:
+ efi_delete_handle(*image_handle);
+ *image_handle = NULL;
free(info);
- efi_delete_handle(obj);
error:
return EFI_EXIT(ret);
}
@@ -1668,16 +1672,14 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
unsigned long *exit_data_size,
s16 **exit_data)
{
- EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
- struct efi_system_table *st);
- struct efi_loaded_image *info = image_handle;
+ struct efi_loaded_image_obj *image_obj =
+ (struct efi_loaded_image_obj *)image_handle;
efi_status_t ret;
EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
- entry = info->reserved;
/* call the image! */
- if (setjmp(&info->exit_jmp)) {
+ if (setjmp(&image_obj->exit_jmp)) {
/*
* We called the entry point of the child image with EFI_CALL
* in the lines below. The child image called the Exit() boot
@@ -1700,12 +1702,12 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
assert(__efi_entry_check());
debug("%sEFI: %lu returned by started image\n",
__efi_nesting_dec(),
- (unsigned long)((uintptr_t)info->exit_status &
+ (unsigned long)((uintptr_t)image_obj->exit_status &
~EFI_ERROR_MASK));
- return EFI_EXIT(info->exit_status);
+ return EFI_EXIT(image_obj->exit_status);
}
- ret = EFI_CALL(entry(image_handle, &systab));
+ ret = EFI_CALL(image_obj->entry(image_handle, &systab));
/*
* Usually UEFI applications call Exit() instead of returning.
@@ -1736,17 +1738,11 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
int16_t *exit_data)
{
/*
- * We require that the handle points to the original loaded
- * image protocol interface.
- *
- * For getting the longjmp address this is safer than locating
- * the protocol because the protocol may have been reinstalled
- * pointing to another memory location.
- *
* TODO: We should call the unload procedure of the loaded
* image protocol.
*/
- struct efi_loaded_image *loaded_image_info = (void *)image_handle;
+ struct efi_loaded_image_obj *image_obj =
+ (struct efi_loaded_image_obj *)image_handle;
EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status,
exit_data_size, exit_data);
@@ -1760,8 +1756,8 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
*/
efi_restore_gd();
- loaded_image_info->exit_status = exit_status;
- longjmp(&loaded_image_info->exit_jmp, 1);
+ image_obj->exit_status = exit_status;
+ longjmp(&image_obj->exit_jmp, 1);
panic("EFI application exited");
}
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index fdf40a62c8..a18ce0a570 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -48,20 +48,21 @@ static int machines[] = {
* If the program counter is located within the image the offset to the base
* address is shown.
*
+ * @obj: EFI object
* @image: loaded image
* @pc: program counter (use NULL to suppress offset output)
* @return: status code
*/
-efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc)
+static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj,
+ struct efi_loaded_image *image,
+ void *pc)
{
- if (!image)
- return EFI_INVALID_PARAMETER;
printf("UEFI image");
printf(" [0x%p:0x%p]",
- image->reloc_base, image->reloc_base + image->reloc_size - 1);
- if (pc && pc >= image->reloc_base &&
- pc < image->reloc_base + image->reloc_size)
- printf(" pc=0x%zx", pc - image->reloc_base);
+ obj->reloc_base, obj->reloc_base + obj->reloc_size - 1);
+ if (pc && pc >= obj->reloc_base &&
+ pc < obj->reloc_base + obj->reloc_size)
+ printf(" pc=0x%zx", pc - obj->reloc_base);
if (image->file_path)
printf(" '%pD'", image->file_path);
printf("\n");
@@ -82,6 +83,7 @@ void efi_print_image_infos(void *pc)
list_for_each_entry(handler, &efiobj->protocols, link) {
if (!guidcmp(handler->guid, &efi_guid_loaded_image)) {
efi_print_image_info(
+ (struct efi_loaded_image_obj *)efiobj,
handler->protocol_interface, pc);
}
}
@@ -196,7 +198,8 @@ static void efi_set_code_and_data_type(
* piece of memory. On successful load it then returns the entry point for
* the binary. Otherwise NULL.
*/
-void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
+void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
+ struct efi_loaded_image *loaded_image_info)
{
IMAGE_NT_HEADERS32 *nt;
IMAGE_DOS_HEADER *dos;
@@ -314,8 +317,8 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
/* Populate the loaded image interface bits */
loaded_image_info->image_base = efi;
loaded_image_info->image_size = image_size;
- loaded_image_info->reloc_base = efi_reloc;
- loaded_image_info->reloc_size = virt_size;
+ handle->reloc_base = efi_reloc;
+ handle->reloc_size = virt_size;
return entry;
}
--
2.19.0
1
0

[U-Boot] [PATCH v3 1/1] efi_loader: refactor efi_setup_loaded_image()
by Heinrich Schuchardt 23 Sep '18
by Heinrich Schuchardt 23 Sep '18
23 Sep '18
Create the handle of loaded images and the EFI_LOADED_IMAGE_PROTOCOL
inside efi_setup_loaded_image(). Do not use local variables.
Currently we expect the loaded image handle to point to the loaded image
protocol. Additionally we have appended private fields to the protocol.
With the patch the handle points to a loaded image object and the private
fields are added here. This matches how we handle the net and the gop
object.
Signed-off-by: Heinrich Schuchardt <xypron.glpk(a)gmx.de>
---
v3
squashed two patches
https://lists.denx.de/pipermail/u-boot/2018-September/341130.html
https://lists.denx.de/pipermail/u-boot/2018-September/341589.html
v2
avoid unused variables if configured without CONFIG_EFI_SELFTEST
---
cmd/bootefi.c | 61 +++++++++++---------
include/efi_api.h | 8 ---
include/efi_loader.h | 27 ++++++---
lib/efi_loader/efi_boottime.c | 92 +++++++++++++++----------------
lib/efi_loader/efi_image_loader.c | 23 ++++----
5 files changed, 111 insertions(+), 100 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 8bc6fa49f5..f76f29a7b1 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -325,19 +325,26 @@ static efi_status_t efi_install_fdt(ulong fdt_addr)
return ret;
}
-/*
- * Load an EFI payload into a newly allocated piece of memory, register all
- * EFI objects it would want to access and jump to it.
+/**
+ * do_bootefi_exec() - execute EFI binary
+ *
+ * @efi: address of the binary
+ * @device_path: path of the device from which the binary was loaded
+ * @image_path: device path of the binary
+ * Return: status code
+ *
+ * Load the EFI binary into a newly assigned memory unwinding the relocation
+ * information, install the loaded image protocol, and call the binary.
*/
static efi_status_t do_bootefi_exec(void *efi,
struct efi_device_path *device_path,
struct efi_device_path *image_path)
{
- struct efi_loaded_image loaded_image_info = {};
- struct efi_object loaded_image_info_obj = {};
efi_handle_t mem_handle = NULL;
struct efi_device_path *memdp = NULL;
efi_status_t ret;
+ struct efi_loaded_image_obj *image_handle;
+ struct efi_loaded_image *loaded_image_info;
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
struct efi_system_table *st);
@@ -367,8 +374,8 @@ static efi_status_t do_bootefi_exec(void *efi,
assert(device_path && image_path);
}
- efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj,
- device_path, image_path);
+ efi_setup_loaded_image(device_path, image_path, &image_handle,
+ &loaded_image_info);
/*
* gd lives in a fixed register which may get clobbered while we execute
@@ -377,9 +384,9 @@ static efi_status_t do_bootefi_exec(void *efi,
efi_save_gd();
/* Transfer environment variable bootargs as load options */
- set_load_options(&loaded_image_info, "bootargs");
+ set_load_options(loaded_image_info, "bootargs");
/* Load the EFI payload */
- entry = efi_load_pe(efi, &loaded_image_info);
+ entry = efi_load_pe(image_handle, efi, loaded_image_info);
if (!entry) {
ret = EFI_LOAD_ERROR;
goto exit;
@@ -387,10 +394,10 @@ static efi_status_t do_bootefi_exec(void *efi,
if (memdp) {
struct efi_device_path_memory *mdp = (void *)memdp;
- mdp->memory_type = loaded_image_info.image_code_type;
- mdp->start_address = (uintptr_t)loaded_image_info.image_base;
+ mdp->memory_type = loaded_image_info->image_code_type;
+ mdp->start_address = (uintptr_t)loaded_image_info->image_base;
mdp->end_address = mdp->start_address +
- loaded_image_info.image_size;
+ loaded_image_info->image_size;
}
/* we don't support much: */
@@ -400,8 +407,8 @@ static efi_status_t do_bootefi_exec(void *efi,
/* Call our payload! */
debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
- if (setjmp(&loaded_image_info.exit_jmp)) {
- ret = loaded_image_info.exit_status;
+ if (setjmp(&image_handle->exit_jmp)) {
+ ret = image_handle->exit_status;
goto exit;
}
@@ -413,7 +420,7 @@ static efi_status_t do_bootefi_exec(void *efi,
/* Move into EL2 and keep running there */
armv8_switch_to_el2((ulong)entry,
- (ulong)&loaded_image_info_obj.handle,
+ (ulong)&image_handle,
(ulong)&systab, 0, (ulong)efi_run_in_el2,
ES_TO_AARCH64);
@@ -430,7 +437,7 @@ static efi_status_t do_bootefi_exec(void *efi,
secure_ram_addr(_do_nonsec_entry)(
efi_run_in_hyp,
(uintptr_t)entry,
- (uintptr_t)loaded_image_info_obj.handle,
+ (uintptr_t)image_handle,
(uintptr_t)&systab);
/* Should never reach here, efi exits with longjmp */
@@ -438,11 +445,12 @@ static efi_status_t do_bootefi_exec(void *efi,
}
#endif
- ret = efi_do_enter(loaded_image_info_obj.handle, &systab, entry);
+ ret = efi_do_enter(image_handle, &systab, entry);
exit:
/* image has returned, loaded-image obj goes *poof*: */
- list_del(&loaded_image_info_obj.link);
+ if (image_handle)
+ efi_delete_handle(&image_handle->parent);
if (mem_handle)
efi_delete_handle(mem_handle);
@@ -527,8 +535,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#endif
#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
if (!strcmp(argv[1], "selftest")) {
- struct efi_loaded_image loaded_image_info = {};
- struct efi_object loaded_image_info_obj = {};
+ struct efi_loaded_image_obj *image_handle;
+ struct efi_loaded_image *loaded_image_info;
/* Construct a dummy device path. */
bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
@@ -536,9 +544,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
(uintptr_t)&efi_selftest);
bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest");
- efi_setup_loaded_image(&loaded_image_info,
- &loaded_image_info_obj,
- bootefi_device_path, bootefi_image_path);
+ efi_setup_loaded_image(bootefi_device_path, bootefi_image_path,
+ &image_handle, &loaded_image_info);
/*
* gd lives in a fixed register which may get clobbered while we
* execute the payload. So save it here and restore it on every
@@ -546,12 +553,12 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
*/
efi_save_gd();
/* Transfer environment variable efi_selftest as load options */
- set_load_options(&loaded_image_info, "efi_selftest");
+ set_load_options(loaded_image_info, "efi_selftest");
/* Execute the test */
- r = efi_selftest(loaded_image_info_obj.handle, &systab);
+ r = efi_selftest(image_handle, &systab);
efi_restore_gd();
- free(loaded_image_info.load_options);
- list_del(&loaded_image_info_obj.link);
+ free(loaded_image_info->load_options);
+ efi_delete_handle(&image_handle->parent);
return r != EFI_SUCCESS;
} else
#endif
diff --git a/include/efi_api.h b/include/efi_api.h
index 5004f520ff..c42df6900a 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -340,14 +340,6 @@ struct efi_loaded_image {
unsigned int image_code_type;
unsigned int image_data_type;
unsigned long unload;
-
- /* Below are efi loader private fields */
-#ifdef CONFIG_EFI_LOADER
- void *reloc_base;
- aligned_u64 reloc_size;
- efi_status_t exit_status;
- struct jmp_buf_data exit_jmp;
-#endif
};
#define DEVICE_PATH_GUID \
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 7738391aa2..74df070316 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -189,6 +189,20 @@ struct efi_object {
void *handle;
};
+/**
+ * struct efi_loaded_image_obj - handle of a loaded image
+ */
+struct efi_loaded_image_obj {
+ /* Generic EFI object parent class data */
+ struct efi_object parent;
+ void *reloc_base;
+ aligned_u64 reloc_size;
+ efi_status_t exit_status;
+ struct jmp_buf_data exit_jmp;
+ EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
+ struct efi_system_table *st);
+};
+
/**
* struct efi_event
*
@@ -270,7 +284,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout);
/* Called from places to check whether a timer expired */
void efi_timer_check(void);
/* PE loader implementation */
-void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info);
+void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
+ struct efi_loaded_image *loaded_image_info);
/* Called once to store the pristine gd pointer */
void efi_save_gd(void);
/* Special case handler for error/abort that just tries to dtrt to get
@@ -351,14 +366,12 @@ int efi_memory_init(void);
/* Adds new or overrides configuration table entry to the system table */
efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table);
/* Sets up a loaded image */
-efi_status_t efi_setup_loaded_image(
- struct efi_loaded_image *info, struct efi_object *obj,
- struct efi_device_path *device_path,
- struct efi_device_path *file_path);
+efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
+ struct efi_device_path *file_path,
+ struct efi_loaded_image_obj **handle_ptr,
+ struct efi_loaded_image **info_ptr);
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
void **buffer);
-/* Print information about a loaded image */
-efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc);
/* Print information about all loaded images */
void efi_print_image_infos(void *pc);
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index b4de9961b8..2496608981 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1478,17 +1478,31 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
*
* Return: status code
*/
-efi_status_t efi_setup_loaded_image(
- struct efi_loaded_image *info, struct efi_object *obj,
- struct efi_device_path *device_path,
- struct efi_device_path *file_path)
+efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
+ struct efi_device_path *file_path,
+ struct efi_loaded_image_obj **handle_ptr,
+ struct efi_loaded_image **info_ptr)
{
efi_status_t ret;
+ struct efi_loaded_image *info;
+ struct efi_loaded_image_obj *obj;
+
+ info = calloc(1, sizeof(*info));
+ if (!info)
+ return EFI_OUT_OF_RESOURCES;
+ obj = calloc(1, sizeof(*obj));
+ if (!obj) {
+ free(info);
+ return EFI_OUT_OF_RESOURCES;
+ }
/* Add internal object to object list */
- efi_add_handle(obj);
- /* efi_exit() assumes that the handle points to the info */
- obj->handle = info;
+ efi_add_handle(&obj->parent);
+
+ if (info_ptr)
+ *info_ptr = info;
+ if (handle_ptr)
+ *handle_ptr = obj;
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
info->file_path = file_path;
@@ -1500,8 +1514,8 @@ efi_status_t efi_setup_loaded_image(
* When asking for the device path interface, return
* bootefi_device_path
*/
- ret = efi_add_protocol(obj->handle, &efi_guid_device_path,
- device_path);
+ ret = efi_add_protocol(obj->parent.handle,
+ &efi_guid_device_path, device_path);
if (ret != EFI_SUCCESS)
goto failure;
}
@@ -1510,7 +1524,8 @@ efi_status_t efi_setup_loaded_image(
* When asking for the loaded_image interface, just
* return handle which points to loaded_image_info
*/
- ret = efi_add_protocol(obj->handle, &efi_guid_loaded_image, info);
+ ret = efi_add_protocol(obj->parent.handle,
+ &efi_guid_loaded_image, info);
if (ret != EFI_SUCCESS)
goto failure;
@@ -1593,7 +1608,8 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
efi_handle_t *image_handle)
{
struct efi_loaded_image *info;
- struct efi_object *obj;
+ struct efi_loaded_image_obj **image_obj =
+ (struct efi_loaded_image_obj **)image_handle;
efi_status_t ret;
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
@@ -1609,18 +1625,6 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
goto error;
}
- info = calloc(1, sizeof(*info));
- if (!info) {
- ret = EFI_OUT_OF_RESOURCES;
- goto error;
- }
- obj = calloc(1, sizeof(*obj));
- if (!obj) {
- free(info);
- ret = EFI_OUT_OF_RESOURCES;
- goto error;
- }
-
if (!source_buffer) {
struct efi_device_path *dp, *fp;
@@ -1632,29 +1636,29 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
* file parts:
*/
efi_dp_split_file_path(file_path, &dp, &fp);
- ret = efi_setup_loaded_image(info, obj, dp, fp);
+ ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
if (ret != EFI_SUCCESS)
goto failure;
} else {
/* In this case, file_path is the "device" path, i.e.
* something like a HARDWARE_DEVICE:MEMORY_MAPPED
*/
- ret = efi_setup_loaded_image(info, obj, file_path, NULL);
+ ret = efi_setup_loaded_image(file_path, NULL, image_obj, &info);
if (ret != EFI_SUCCESS)
- goto failure;
+ goto error;
}
- info->reserved = efi_load_pe(source_buffer, info);
- if (!info->reserved) {
+ (*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info);
+ if (!(*image_obj)->entry) {
ret = EFI_UNSUPPORTED;
goto failure;
}
info->system_table = &systab;
info->parent_handle = parent_image;
- *image_handle = obj->handle;
return EFI_EXIT(EFI_SUCCESS);
failure:
+ efi_delete_handle(*image_handle);
+ *image_handle = NULL;
free(info);
- efi_delete_handle(obj);
error:
return EFI_EXIT(ret);
}
@@ -1676,18 +1680,16 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
unsigned long *exit_data_size,
s16 **exit_data)
{
- EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
- struct efi_system_table *st);
- struct efi_loaded_image *info = image_handle;
+ struct efi_loaded_image_obj *image_obj =
+ (struct efi_loaded_image_obj *)image_handle;
efi_status_t ret;
EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
- entry = info->reserved;
efi_is_direct_boot = false;
/* call the image! */
- if (setjmp(&info->exit_jmp)) {
+ if (setjmp(&image_obj->exit_jmp)) {
/*
* We called the entry point of the child image with EFI_CALL
* in the lines below. The child image called the Exit() boot
@@ -1710,12 +1712,12 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
assert(__efi_entry_check());
debug("%sEFI: %lu returned by started image\n",
__efi_nesting_dec(),
- (unsigned long)((uintptr_t)info->exit_status &
+ (unsigned long)((uintptr_t)image_obj->exit_status &
~EFI_ERROR_MASK));
- return EFI_EXIT(info->exit_status);
+ return EFI_EXIT(image_obj->exit_status);
}
- ret = EFI_CALL(entry(image_handle, &systab));
+ ret = EFI_CALL(image_obj->entry(image_handle, &systab));
/*
* Usually UEFI applications call Exit() instead of returning.
@@ -1746,17 +1748,11 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
int16_t *exit_data)
{
/*
- * We require that the handle points to the original loaded
- * image protocol interface.
- *
- * For getting the longjmp address this is safer than locating
- * the protocol because the protocol may have been reinstalled
- * pointing to another memory location.
- *
* TODO: We should call the unload procedure of the loaded
* image protocol.
*/
- struct efi_loaded_image *loaded_image_info = (void *)image_handle;
+ struct efi_loaded_image_obj *image_obj =
+ (struct efi_loaded_image_obj *)image_handle;
EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status,
exit_data_size, exit_data);
@@ -1770,8 +1766,8 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
*/
efi_restore_gd();
- loaded_image_info->exit_status = exit_status;
- longjmp(&loaded_image_info->exit_jmp, 1);
+ image_obj->exit_status = exit_status;
+ longjmp(&image_obj->exit_jmp, 1);
panic("EFI application exited");
}
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index fdf40a62c8..a18ce0a570 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -48,20 +48,21 @@ static int machines[] = {
* If the program counter is located within the image the offset to the base
* address is shown.
*
+ * @obj: EFI object
* @image: loaded image
* @pc: program counter (use NULL to suppress offset output)
* @return: status code
*/
-efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc)
+static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj,
+ struct efi_loaded_image *image,
+ void *pc)
{
- if (!image)
- return EFI_INVALID_PARAMETER;
printf("UEFI image");
printf(" [0x%p:0x%p]",
- image->reloc_base, image->reloc_base + image->reloc_size - 1);
- if (pc && pc >= image->reloc_base &&
- pc < image->reloc_base + image->reloc_size)
- printf(" pc=0x%zx", pc - image->reloc_base);
+ obj->reloc_base, obj->reloc_base + obj->reloc_size - 1);
+ if (pc && pc >= obj->reloc_base &&
+ pc < obj->reloc_base + obj->reloc_size)
+ printf(" pc=0x%zx", pc - obj->reloc_base);
if (image->file_path)
printf(" '%pD'", image->file_path);
printf("\n");
@@ -82,6 +83,7 @@ void efi_print_image_infos(void *pc)
list_for_each_entry(handler, &efiobj->protocols, link) {
if (!guidcmp(handler->guid, &efi_guid_loaded_image)) {
efi_print_image_info(
+ (struct efi_loaded_image_obj *)efiobj,
handler->protocol_interface, pc);
}
}
@@ -196,7 +198,8 @@ static void efi_set_code_and_data_type(
* piece of memory. On successful load it then returns the entry point for
* the binary. Otherwise NULL.
*/
-void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
+void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
+ struct efi_loaded_image *loaded_image_info)
{
IMAGE_NT_HEADERS32 *nt;
IMAGE_DOS_HEADER *dos;
@@ -314,8 +317,8 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
/* Populate the loaded image interface bits */
loaded_image_info->image_base = efi;
loaded_image_info->image_size = image_size;
- loaded_image_info->reloc_base = efi_reloc;
- loaded_image_info->reloc_size = virt_size;
+ handle->reloc_base = efi_reloc;
+ handle->reloc_size = virt_size;
return entry;
}
--
2.19.0
2
4

Re: [U-Boot] [U-Boot, V3, 2/3] ARM: tegra: reserve unmapped RAM so EFI doesn't use it
by Stephen Warren 23 Sep '18
by Stephen Warren 23 Sep '18
23 Sep '18
On 09/01/2018 03:58 AM, Alexander Graf wrote:
>> From: Stephen Warren <swarren(a)nvidia.com>
>>
>> Tegra U-Boot ensures that board_get_usable_ram_top() never returns a value
>> over 4GB, since some peripherals can't access such addresses. However, on
>> systems with more than 2GB of RAM, RAM bank 1 does describe this extra
>> RAM, so that Linux (or whatever OS) can use it, subject to DMA
>> limitations. Since board_get_usable_ram_top() points at the top of RAM
>> bank 0, the memory locations describes by RAM bank 1 are not mapped by
>> U-Boot's MMU configuration, and so cannot be used for anything.
>>
>> For some completely inexplicable reason, U-Boot's EFI support ignores the
>> value returned by board_get_usable_ram_top(), and EFI memory allocation
>> routines will return values above U-Boot's RAM top. This causes U-Boot to
>> crash when it accesses that RAM, since it isn't mapped by the MMU. One
>> use-case where this happens is TFTP download of a file on Jetson TX1
>> (p2371-2180).
>>
>> This change explicitly tells the EFI code that this extra RAM should not
>> be used, thus avoiding the crash.
>>
>> A previous attempt to make EFI honor board_get_usable_ram_top() was
>> rejected. So, this patch will need to be replicated for any board that
>> implements board_get_usable_ram_top().
>>
>> Fixes: aa909462d018 ("efi_loader: efi_allocate_pages is too restrictive")
>> Signed-off-by: Stephen Warren <swarren(a)nvidia.com>
>
> Thanks, applied to efi-next
They don't seem to have shown up in u-boot/master though...
2
1
Hello Alex,
function efi_exit_caches() is called by efi_exit_boot_services(). It
calls cleanup_before_linux() if efi_direct_boot is set.
Comments in the code say
<cite>
If we're running on nasty systems (32bit ARM booting into non-EFI Linux)
we need to do trickery with caches. Since we don't want to break the EFI
aware boot path, only apply hacks when loading exiting directly
(breaking direct Linux EFI booting along the way - oh well).
GRUB on 32bit ARM needs to have caches disabled before jumping into
a zImage, but does not know of all cache layers. Give it a hand.
</cite>
Why should this requirement depend on whether GRUB is loaded directly or
via iPXE or the EFI Shell? And why would we want to kill loading Linux
directly via bootefi?
Why should GRUB-efi load an operating system via anything but the EFI stub?
I would like to eliminate the variable efi_is_direct_boot and let
do_bootefi() call efi_start_image() removing the current code duplication.
The current implementation of efi_start_image() is incomplete as it does
not keep track of the currently running image (see the specification of
the UnloadImage() and Exit() services for the reason why we need this).
I would hesitate to program this in multiple places.
This coding in question was introduced with one of your first EFI patches:
bee91169f5b2 ("efi_loader: Add boot time services")
Best regards
Heinrich
2
1

23 Sep '18
Currently we expect the loaded image handle to point to the loaded image
protocol. Additionally we have appended private fields to the protocol.
With the patch the handle points to a loaded image object and the private
fields are added here. This matches how we handle the net and the gop
object.
Signed-off-by: Heinrich Schuchardt <xypron.glpk(a)gmx.de>
---
cmd/bootefi.c | 14 ++++----
include/efi_api.h | 8 -----
include/efi_loader.h | 21 ++++++++---
lib/efi_loader/efi_boottime.c | 58 +++++++++++++------------------
lib/efi_loader/efi_image_loader.c | 23 ++++++------
5 files changed, 62 insertions(+), 62 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 3ca0d588dd..f76f29a7b1 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -343,7 +343,7 @@ static efi_status_t do_bootefi_exec(void *efi,
efi_handle_t mem_handle = NULL;
struct efi_device_path *memdp = NULL;
efi_status_t ret;
- efi_handle_t image_handle;
+ struct efi_loaded_image_obj *image_handle;
struct efi_loaded_image *loaded_image_info;
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
@@ -386,7 +386,7 @@ static efi_status_t do_bootefi_exec(void *efi,
/* Transfer environment variable bootargs as load options */
set_load_options(loaded_image_info, "bootargs");
/* Load the EFI payload */
- entry = efi_load_pe(efi, loaded_image_info);
+ entry = efi_load_pe(image_handle, efi, loaded_image_info);
if (!entry) {
ret = EFI_LOAD_ERROR;
goto exit;
@@ -407,8 +407,8 @@ static efi_status_t do_bootefi_exec(void *efi,
/* Call our payload! */
debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
- if (setjmp(&loaded_image_info->exit_jmp)) {
- ret = loaded_image_info->exit_status;
+ if (setjmp(&image_handle->exit_jmp)) {
+ ret = image_handle->exit_status;
goto exit;
}
@@ -450,7 +450,7 @@ static efi_status_t do_bootefi_exec(void *efi,
exit:
/* image has returned, loaded-image obj goes *poof*: */
if (image_handle)
- efi_delete_handle(image_handle);
+ efi_delete_handle(&image_handle->parent);
if (mem_handle)
efi_delete_handle(mem_handle);
@@ -535,7 +535,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#endif
#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
if (!strcmp(argv[1], "selftest")) {
- efi_handle_t image_handle;
+ struct efi_loaded_image_obj *image_handle;
struct efi_loaded_image *loaded_image_info;
/* Construct a dummy device path. */
@@ -558,7 +558,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
r = efi_selftest(image_handle, &systab);
efi_restore_gd();
free(loaded_image_info->load_options);
- efi_delete_handle(image_handle);
+ efi_delete_handle(&image_handle->parent);
return r != EFI_SUCCESS;
} else
#endif
diff --git a/include/efi_api.h b/include/efi_api.h
index 5004f520ff..c42df6900a 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -340,14 +340,6 @@ struct efi_loaded_image {
unsigned int image_code_type;
unsigned int image_data_type;
unsigned long unload;
-
- /* Below are efi loader private fields */
-#ifdef CONFIG_EFI_LOADER
- void *reloc_base;
- aligned_u64 reloc_size;
- efi_status_t exit_status;
- struct jmp_buf_data exit_jmp;
-#endif
};
#define DEVICE_PATH_GUID \
diff --git a/include/efi_loader.h b/include/efi_loader.h
index d665627e91..74df070316 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -189,6 +189,20 @@ struct efi_object {
void *handle;
};
+/**
+ * struct efi_loaded_image_obj - handle of a loaded image
+ */
+struct efi_loaded_image_obj {
+ /* Generic EFI object parent class data */
+ struct efi_object parent;
+ void *reloc_base;
+ aligned_u64 reloc_size;
+ efi_status_t exit_status;
+ struct jmp_buf_data exit_jmp;
+ EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
+ struct efi_system_table *st);
+};
+
/**
* struct efi_event
*
@@ -270,7 +284,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout);
/* Called from places to check whether a timer expired */
void efi_timer_check(void);
/* PE loader implementation */
-void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info);
+void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
+ struct efi_loaded_image *loaded_image_info);
/* Called once to store the pristine gd pointer */
void efi_save_gd(void);
/* Special case handler for error/abort that just tries to dtrt to get
@@ -353,12 +368,10 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table
/* Sets up a loaded image */
efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
struct efi_device_path *file_path,
- efi_handle_t *handle_ptr,
+ struct efi_loaded_image_obj **handle_ptr,
struct efi_loaded_image **info_ptr);
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
void **buffer);
-/* Print information about a loaded image */
-efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc);
/* Print information about all loaded images */
void efi_print_image_infos(void *pc);
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index bc230f6824..2496608981 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1480,12 +1480,12 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
*/
efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
struct efi_device_path *file_path,
- efi_handle_t *handle_ptr,
+ struct efi_loaded_image_obj **handle_ptr,
struct efi_loaded_image **info_ptr)
{
efi_status_t ret;
struct efi_loaded_image *info;
- struct efi_object *obj;
+ struct efi_loaded_image_obj *obj;
info = calloc(1, sizeof(*info));
if (!info)
@@ -1497,14 +1497,12 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
}
/* Add internal object to object list */
- efi_add_handle(obj);
- /* efi_exit() assumes that the handle points to the info */
- obj->handle = info;
+ efi_add_handle(&obj->parent);
- if (handle_ptr)
- *handle_ptr = obj->handle;
if (info_ptr)
*info_ptr = info;
+ if (handle_ptr)
+ *handle_ptr = obj;
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
info->file_path = file_path;
@@ -1516,8 +1514,8 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
* When asking for the device path interface, return
* bootefi_device_path
*/
- ret = efi_add_protocol(obj->handle, &efi_guid_device_path,
- device_path);
+ ret = efi_add_protocol(obj->parent.handle,
+ &efi_guid_device_path, device_path);
if (ret != EFI_SUCCESS)
goto failure;
}
@@ -1526,7 +1524,8 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
* When asking for the loaded_image interface, just
* return handle which points to loaded_image_info
*/
- ret = efi_add_protocol(obj->handle, &efi_guid_loaded_image, info);
+ ret = efi_add_protocol(obj->parent.handle,
+ &efi_guid_loaded_image, info);
if (ret != EFI_SUCCESS)
goto failure;
@@ -1609,6 +1608,8 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
efi_handle_t *image_handle)
{
struct efi_loaded_image *info;
+ struct efi_loaded_image_obj **image_obj =
+ (struct efi_loaded_image_obj **)image_handle;
efi_status_t ret;
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
@@ -1635,20 +1636,19 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
* file parts:
*/
efi_dp_split_file_path(file_path, &dp, &fp);
- ret = efi_setup_loaded_image(dp, fp, image_handle, &info);
+ ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
if (ret != EFI_SUCCESS)
goto failure;
} else {
/* In this case, file_path is the "device" path, i.e.
* something like a HARDWARE_DEVICE:MEMORY_MAPPED
*/
- ret = efi_setup_loaded_image(file_path, NULL, image_handle,
- &info);
+ ret = efi_setup_loaded_image(file_path, NULL, image_obj, &info);
if (ret != EFI_SUCCESS)
goto error;
}
- info->reserved = efi_load_pe(source_buffer, info);
- if (!info->reserved) {
+ (*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info);
+ if (!(*image_obj)->entry) {
ret = EFI_UNSUPPORTED;
goto failure;
}
@@ -1680,18 +1680,16 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
unsigned long *exit_data_size,
s16 **exit_data)
{
- EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
- struct efi_system_table *st);
- struct efi_loaded_image *info = image_handle;
+ struct efi_loaded_image_obj *image_obj =
+ (struct efi_loaded_image_obj *)image_handle;
efi_status_t ret;
EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
- entry = info->reserved;
efi_is_direct_boot = false;
/* call the image! */
- if (setjmp(&info->exit_jmp)) {
+ if (setjmp(&image_obj->exit_jmp)) {
/*
* We called the entry point of the child image with EFI_CALL
* in the lines below. The child image called the Exit() boot
@@ -1714,12 +1712,12 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
assert(__efi_entry_check());
debug("%sEFI: %lu returned by started image\n",
__efi_nesting_dec(),
- (unsigned long)((uintptr_t)info->exit_status &
+ (unsigned long)((uintptr_t)image_obj->exit_status &
~EFI_ERROR_MASK));
- return EFI_EXIT(info->exit_status);
+ return EFI_EXIT(image_obj->exit_status);
}
- ret = EFI_CALL(entry(image_handle, &systab));
+ ret = EFI_CALL(image_obj->entry(image_handle, &systab));
/*
* Usually UEFI applications call Exit() instead of returning.
@@ -1750,17 +1748,11 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
int16_t *exit_data)
{
/*
- * We require that the handle points to the original loaded
- * image protocol interface.
- *
- * For getting the longjmp address this is safer than locating
- * the protocol because the protocol may have been reinstalled
- * pointing to another memory location.
- *
* TODO: We should call the unload procedure of the loaded
* image protocol.
*/
- struct efi_loaded_image *loaded_image_info = (void *)image_handle;
+ struct efi_loaded_image_obj *image_obj =
+ (struct efi_loaded_image_obj *)image_handle;
EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status,
exit_data_size, exit_data);
@@ -1774,8 +1766,8 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
*/
efi_restore_gd();
- loaded_image_info->exit_status = exit_status;
- longjmp(&loaded_image_info->exit_jmp, 1);
+ image_obj->exit_status = exit_status;
+ longjmp(&image_obj->exit_jmp, 1);
panic("EFI application exited");
}
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index fdf40a62c8..a18ce0a570 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -48,20 +48,21 @@ static int machines[] = {
* If the program counter is located within the image the offset to the base
* address is shown.
*
+ * @obj: EFI object
* @image: loaded image
* @pc: program counter (use NULL to suppress offset output)
* @return: status code
*/
-efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc)
+static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj,
+ struct efi_loaded_image *image,
+ void *pc)
{
- if (!image)
- return EFI_INVALID_PARAMETER;
printf("UEFI image");
printf(" [0x%p:0x%p]",
- image->reloc_base, image->reloc_base + image->reloc_size - 1);
- if (pc && pc >= image->reloc_base &&
- pc < image->reloc_base + image->reloc_size)
- printf(" pc=0x%zx", pc - image->reloc_base);
+ obj->reloc_base, obj->reloc_base + obj->reloc_size - 1);
+ if (pc && pc >= obj->reloc_base &&
+ pc < obj->reloc_base + obj->reloc_size)
+ printf(" pc=0x%zx", pc - obj->reloc_base);
if (image->file_path)
printf(" '%pD'", image->file_path);
printf("\n");
@@ -82,6 +83,7 @@ void efi_print_image_infos(void *pc)
list_for_each_entry(handler, &efiobj->protocols, link) {
if (!guidcmp(handler->guid, &efi_guid_loaded_image)) {
efi_print_image_info(
+ (struct efi_loaded_image_obj *)efiobj,
handler->protocol_interface, pc);
}
}
@@ -196,7 +198,8 @@ static void efi_set_code_and_data_type(
* piece of memory. On successful load it then returns the entry point for
* the binary. Otherwise NULL.
*/
-void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
+void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
+ struct efi_loaded_image *loaded_image_info)
{
IMAGE_NT_HEADERS32 *nt;
IMAGE_DOS_HEADER *dos;
@@ -314,8 +317,8 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
/* Populate the loaded image interface bits */
loaded_image_info->image_base = efi;
loaded_image_info->image_size = image_size;
- loaded_image_info->reloc_base = efi_reloc;
- loaded_image_info->reloc_size = virt_size;
+ handle->reloc_base = efi_reloc;
+ handle->reloc_size = virt_size;
return entry;
}
--
2.19.0
2
1