337 lines
12 KiB
Diff
337 lines
12 KiB
Diff
From 52ece15559cdb67ed3da2d6e1ce06bad0dc722f8 Mon Sep 17 00:00:00 2001
|
|
From: Dzmitry Sankouski <dsankouski@gmail.com>
|
|
Date: Tue, 25 Jan 2022 22:15:50 +0300
|
|
Subject: [PATCH 1/3 v3] arm: init: save previous bootloader data
|
|
|
|
When u-boot is used as a chain-loaded bootloader (replacing OS kernel),
|
|
previous bootloader leaves data in RAM, that can be reused.
|
|
|
|
For example, on recent arm linux system, when chainloading u-boot,
|
|
there are initramfs and fdt in RAM prepared for OS booting. Initramfs
|
|
may be modified to store u-boot's payload, thus providing the ability to
|
|
use chainloaded u-boot to boot OS without any storage support.
|
|
|
|
Two config options added:
|
|
- SAVE_PREV_BL_INITRAMFS_START_ADDR
|
|
saves initramfs start address to 'prevbl_initrd_start_addr' environment
|
|
variable
|
|
- SAVE_PREV_BL_FDT_ADDR
|
|
saves fdt address to 'prevbl_fdt_addr' environment variable
|
|
|
|
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
|
|
Cc: Tom Rini <trini@konsulko.com>
|
|
---
|
|
Changes for v2:
|
|
- change signed off line
|
|
Changes for v3:
|
|
- use if (CONFIG_IS_ENABLED... instead of #if defined
|
|
- fix save_prev_bl_data.o in Makefile
|
|
- add save_prev_bl_data call to env initialization
|
|
|
|
arch/arm/lib/Makefile | 5 ++
|
|
arch/arm/lib/save_prev_bl_data.c | 91 ++++++++++++++++++++++++++++++++
|
|
boot/Kconfig | 79 +++++++++++++++++----------
|
|
common/board_r.c | 5 ++
|
|
include/init.h | 13 +++++
|
|
5 files changed, 166 insertions(+), 27 deletions(-)
|
|
create mode 100644 arch/arm/lib/save_prev_bl_data.c
|
|
|
|
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
|
|
index c48e1f622d..f3c31c05e5 100644
|
|
--- a/arch/arm/lib/Makefile
|
|
+++ b/arch/arm/lib/Makefile
|
|
@@ -48,6 +48,11 @@ obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMCPY) += memcpy.o
|
|
endif
|
|
obj-$(CONFIG_SEMIHOSTING) += semihosting.o
|
|
|
|
+ifneq ($(filter y,$(CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR) $(CONFIG_SAVE_PREV_BL_FDT_ADDR)),)
|
|
+obj-y += save_prev_bl_data.o
|
|
+endif
|
|
+
|
|
+# obj-$(CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR) += save_prev_bl_data.o
|
|
obj-y += bdinfo.o
|
|
obj-y += sections.o
|
|
CFLAGS_REMOVE_sections.o := $(LTO_CFLAGS)
|
|
diff --git a/arch/arm/lib/save_prev_bl_data.c b/arch/arm/lib/save_prev_bl_data.c
|
|
new file mode 100644
|
|
index 0000000000..f4ee86a89c
|
|
--- /dev/null
|
|
+++ b/arch/arm/lib/save_prev_bl_data.c
|
|
@@ -0,0 +1,91 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * save_prev_bl_data - saving previous bootloader data
|
|
+ * to environment variables.
|
|
+ *
|
|
+ * Copyright (c) 2022 Dzmitry Sankouski (dsankouski@gmail.com)
|
|
+ */
|
|
+#include <init.h>
|
|
+#include <env.h>
|
|
+#include <fdtdec.h>
|
|
+#include <fdt_support.h>
|
|
+#include <fdt.h>
|
|
+#include <common.h>
|
|
+#include <linux/errno.h>
|
|
+#include <asm/system.h>
|
|
+#include <asm/armv8/mmu.h>
|
|
+
|
|
+static ulong reg0 __section(".data");
|
|
+
|
|
+/**
|
|
+ * Save x0 register value, assuming previous bootloader set it to
|
|
+ * point on loaded fdt or (for older linux kernels)atags.
|
|
+ */
|
|
+void save_boot_params(ulong r0)
|
|
+{
|
|
+ reg0 = r0;
|
|
+ save_boot_params_ret();
|
|
+}
|
|
+
|
|
+bool is_addr_accessible(phys_addr_t addr)
|
|
+{
|
|
+ struct mm_region *mem = mem_map;
|
|
+ phys_addr_t bank_start;
|
|
+ phys_addr_t bank_end;
|
|
+
|
|
+ while (mem->size) {
|
|
+ bank_start = mem->phys;
|
|
+ bank_end = bank_start + mem->size;
|
|
+ debug("check if block %pap - %pap includes %pap\n", &bank_start, &bank_end, &addr);
|
|
+ if (addr > bank_start && addr < bank_end)
|
|
+ return true;
|
|
+ mem++;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+int save_prev_bl_data(void)
|
|
+{
|
|
+ struct fdt_header *fdt_blob;
|
|
+ int node;
|
|
+ u64 initrd_start_prop;
|
|
+
|
|
+ if (!is_addr_accessible((phys_addr_t)reg0))
|
|
+ return -ENODATA;
|
|
+
|
|
+ fdt_blob = (struct fdt_header *)reg0;
|
|
+ if (!fdt_valid(&fdt_blob)) {
|
|
+ pr_warn("%s: address 0x%lx is not a valid fdt\n", __func__, reg0);
|
|
+ return -ENODATA;
|
|
+ }
|
|
+
|
|
+ if (CONFIG_IS_ENABLED(SAVE_PREV_BL_FDT_ADDR))
|
|
+ env_set_addr("prevbl_fdt_addr", (void *)reg0);
|
|
+ if (!CONFIG_IS_ENABLED(SAVE_PREV_BL_INITRAMFS_START_ADDR))
|
|
+ return 0;
|
|
+
|
|
+ node = fdt_path_offset(fdt_blob, "/chosen");
|
|
+ if (!node) {
|
|
+ pr_warn("%s: chosen node not found in device tree at addr: 0x%lx\n",
|
|
+ __func__, reg0);
|
|
+ return -ENODATA;
|
|
+ }
|
|
+ /*
|
|
+ * linux,initrd-start property might be either 64 or 32 bit,
|
|
+ * depending on primary bootloader implementation.
|
|
+ */
|
|
+ initrd_start_prop = fdtdec_get_uint64(fdt_blob, node, "linux,initrd-start", 0);
|
|
+ if (!initrd_start_prop) {
|
|
+ debug("%s: attempt to get uint64 linux,initrd-start property failed, trying uint\n",
|
|
+ __func__);
|
|
+ initrd_start_prop = fdtdec_get_uint(fdt_blob, node, "linux,initrd-start", 0);
|
|
+ if (!initrd_start_prop) {
|
|
+ debug("%s: attempt to get uint failed, too\n", __func__);
|
|
+ return -ENODATA;
|
|
+ }
|
|
+ }
|
|
+ env_set_addr("prevbl_initrd_start_addr", (void *)initrd_start_prop);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/boot/Kconfig b/boot/Kconfig
|
|
index c8d5906cd3..da2f0797e0 100644
|
|
--- a/boot/Kconfig
|
|
+++ b/boot/Kconfig
|
|
@@ -135,10 +135,10 @@ config FIT_IMAGE_POST_PROCESS
|
|
processed before being added to the FIT image).
|
|
|
|
config FIT_PRINT
|
|
- bool "Support FIT printing"
|
|
- default y
|
|
- help
|
|
- Support printing the content of the fitImage in a verbose manner.
|
|
+ bool "Support FIT printing"
|
|
+ default y
|
|
+ help
|
|
+ Support printing the content of the fitImage in a verbose manner.
|
|
|
|
if SPL
|
|
|
|
@@ -207,12 +207,12 @@ config SPL_LOAD_FIT
|
|
This path has the following limitations:
|
|
|
|
1. "loadables" images, other than FDTs, which do not have a "load"
|
|
- property will not be loaded. This limitation also applies to FPGA
|
|
- images with the correct "compatible" string.
|
|
+ property will not be loaded. This limitation also applies to FPGA
|
|
+ images with the correct "compatible" string.
|
|
2. For FPGA images, only the "compatible" = "u-boot,fpga-legacy"
|
|
- loading method is supported.
|
|
+ loading method is supported.
|
|
3. FDTs are only loaded for images with an "os" property of "u-boot".
|
|
- "linux" images are also supported with Falcon boot mode.
|
|
+ "linux" images are also supported with Falcon boot mode.
|
|
|
|
config SPL_LOAD_FIT_ADDRESS
|
|
hex "load address of fit image"
|
|
@@ -345,8 +345,8 @@ config SYS_EXTRA_OPTIONS
|
|
The old configuration infrastructure (= mkconfig + boards.cfg)
|
|
provided the extra options field. If you have something like
|
|
"HAS_BAR,BAZ=64", the optional options
|
|
- #define CONFIG_HAS
|
|
- #define CONFIG_BAZ 64
|
|
+ #define CONFIG_HAS
|
|
+ #define CONFIG_BAZ 64
|
|
will be defined in include/config.h.
|
|
This option was prepared for the smooth migration from the old
|
|
configuration to Kconfig. Since this option will be removed sometime,
|
|
@@ -380,7 +380,7 @@ config SYS_CLK_FREQ
|
|
int "CPU clock frequency"
|
|
default 125000000 if ARCH_LS1012A
|
|
default 100000000 if ARCH_P2020 || ARCH_T1024 || ARCH_T1042 || \
|
|
- ARCH_LS1021A || FSL_LSCH2 || FSL_LSCH3
|
|
+ ARCH_LS1021A || FSL_LSCH2 || FSL_LSCH3
|
|
default 66666666 if ARCH_P1010 || ARCH_P1020 || ARCH_T4240
|
|
default 66660000 if ARCH_T2080
|
|
default 33333333 if RCAR_GEN3
|
|
@@ -485,15 +485,15 @@ config BOOTSTAGE_REPORT
|
|
boot process. The report looks something like this:
|
|
|
|
Timer summary in microseconds:
|
|
- Mark Elapsed Stage
|
|
- 0 0 reset
|
|
+ Mark Elapsed Stage
|
|
+ 0 0 reset
|
|
3,575,678 3,575,678 board_init_f start
|
|
- 3,575,695 17 arch_cpu_init A9
|
|
- 3,575,777 82 arch_cpu_init done
|
|
- 3,659,598 83,821 board_init_r start
|
|
- 3,910,375 250,777 main_loop
|
|
+ 3,575,695 17 arch_cpu_init A9
|
|
+ 3,575,777 82 arch_cpu_init done
|
|
+ 3,659,598 83,821 board_init_r start
|
|
+ 3,910,375 250,777 main_loop
|
|
29,916,167 26,005,792 bootm_start
|
|
- 30,361,327 445,160 start_kernel
|
|
+ 30,361,327 445,160 start_kernel
|
|
|
|
config BOOTSTAGE_RECORD_COUNT
|
|
int "Number of boot stage records to store"
|
|
@@ -580,24 +580,24 @@ config SHOW_BOOT_PROGRESS
|
|
Legacy uImage format:
|
|
|
|
Arg Where When
|
|
- 1 common/cmd_bootm.c before attempting to boot an image
|
|
+ 1 common/cmd_bootm.c before attempting to boot an image
|
|
-1 common/cmd_bootm.c Image header has bad magic number
|
|
- 2 common/cmd_bootm.c Image header has correct magic number
|
|
+ 2 common/cmd_bootm.c Image header has correct magic number
|
|
-2 common/cmd_bootm.c Image header has bad checksum
|
|
- 3 common/cmd_bootm.c Image header has correct checksum
|
|
+ 3 common/cmd_bootm.c Image header has correct checksum
|
|
-3 common/cmd_bootm.c Image data has bad checksum
|
|
- 4 common/cmd_bootm.c Image data has correct checksum
|
|
+ 4 common/cmd_bootm.c Image data has correct checksum
|
|
-4 common/cmd_bootm.c Image is for unsupported architecture
|
|
- 5 common/cmd_bootm.c Architecture check OK
|
|
+ 5 common/cmd_bootm.c Architecture check OK
|
|
-5 common/cmd_bootm.c Wrong Image Type (not kernel, multi)
|
|
- 6 common/cmd_bootm.c Image Type check OK
|
|
+ 6 common/cmd_bootm.c Image Type check OK
|
|
-6 common/cmd_bootm.c gunzip uncompression error
|
|
-7 common/cmd_bootm.c Unimplemented compression type
|
|
- 7 common/cmd_bootm.c Uncompression OK
|
|
- 8 common/cmd_bootm.c No uncompress/copy overwrite error
|
|
+ 7 common/cmd_bootm.c Uncompression OK
|
|
+ 8 common/cmd_bootm.c No uncompress/copy overwrite error
|
|
-9 common/cmd_bootm.c Unsupported OS (not Linux, BSD, VxWorks, QNX)
|
|
|
|
- 9 common/image.c Start initial ramdisk verification
|
|
+ 9 common/image.c Start initial ramdisk verification
|
|
-10 common/image.c Ramdisk header has bad magic number
|
|
-11 common/image.c Ramdisk header has bad checksum
|
|
10 common/image.c Ramdisk header is OK
|
|
@@ -1067,4 +1067,29 @@ config DEFAULT_FDT_FILE
|
|
help
|
|
This option is used to set the default fdt file to boot OS.
|
|
|
|
+config SAVE_PREV_BL_FDT_ADDR
|
|
+ depends on ARM
|
|
+ bool "Saves fdt address, passed by the previous bootloader, to env var"
|
|
+ default n
|
|
+ help
|
|
+ When u-boot is used as a chain-loaded bootloader (replacing OS kernel),
|
|
+ enable this option to save fdt address, passed by the
|
|
+ previous bootloader for future use.
|
|
+ Address is saved to `prevbl_fdt_addr` environment variable.
|
|
+
|
|
+ If no fdt was provided by previous bootloader, no env variables
|
|
+ will be created.
|
|
+
|
|
+config SAVE_PREV_BL_INITRAMFS_START_ADDR
|
|
+ depends on ARM
|
|
+ bool "Saves initramfs address, passed by the previous bootloader, to env var"
|
|
+ default n
|
|
+ help
|
|
+ When u-boot is used as a chain-loaded bootloader(replacing OS kernel),
|
|
+ enable this option to save initramfs address, passed by the
|
|
+ previous bootloader for future use.
|
|
+ Address is saved to `prevbl_initrd_start_addr` environment variable.
|
|
+
|
|
+ If no initramfs was provided by previous bootloader, no env variables
|
|
+ will be created.
|
|
endmenu # Booting
|
|
diff --git a/common/board_r.c b/common/board_r.c
|
|
index c24d9b4e22..5b717e2162 100644
|
|
--- a/common/board_r.c
|
|
+++ b/common/board_r.c
|
|
@@ -445,6 +445,11 @@ static int initr_env(void)
|
|
env_set_hex("fdtcontroladdr",
|
|
(unsigned long)map_to_sysmem(gd->fdt_blob));
|
|
|
|
+ #if (CONFIG_IS_ENABLED(SAVE_PREV_BL_INITRAMFS_START_ADDR) || \
|
|
+ CONFIG_IS_ENABLED(SAVE_PREV_BL_FDT_ADDR))
|
|
+ save_prev_bl_data();
|
|
+ #endif
|
|
+
|
|
/* Initialize from environment */
|
|
image_load_addr = env_get_ulong("loadaddr", 16, image_load_addr);
|
|
|
|
diff --git a/include/init.h b/include/init.h
|
|
index 20c3976af0..1a55a0e2e4 100644
|
|
--- a/include/init.h
|
|
+++ b/include/init.h
|
|
@@ -166,6 +166,19 @@ int arch_setup_bdinfo(void);
|
|
*/
|
|
int setup_bdinfo(void);
|
|
|
|
+#if defined(CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR) || \
|
|
+defined(CONFIG_SAVE_PREV_BL_FDT_ADDR)
|
|
+/**
|
|
+ * save_prev_bl_data - Save prev bl data in env vars.
|
|
+ *
|
|
+ * When u-boot is chain-loaded, save previous bootloader data,
|
|
+ * like initramfs address to environment variables.
|
|
+ *
|
|
+ * Return: 0 if ok; -ENODATA on error
|
|
+ */
|
|
+int save_prev_bl_data(void);
|
|
+#endif
|
|
+
|
|
/**
|
|
* cpu_secondary_init_r() - CPU-specific secondary initialization
|
|
*
|
|
--
|
|
2.20.1
|
|
|