[PATCH 1/2] soc: sdm845: implement ABL info collecting, add bootcommand and usage doc

Dzmitry Sankouski dsankouski at gmail.com
Tue Jan 11 17:01:58 CET 2022


U-boot is intended to replace linux kernel in android boot image, and
it's FIT payload to replace initramfs file. The boot process is similar to
boot image with linux:
- android bootloader (ABL) unpacks android boot image
- ABL sets `linux,initrd-start property` in chosen node in unpacked FDT
- ABL sets x0 register to FDT address, and passes control to u-boot
- u-boot reads x0 register, and stores it in `abl_fdt_addr` env variable
- u-boot reads `linux,initrd-start` property,
and stores it in `abl_initrd_start_addr`

In this way, u-boot bootcmd relies on `abl_initrd_start_addr` env variable,
and boils down to `bootm $abl_initrd_start_addr`. If more control on
boot process is desired, pack a boot script in FIT image, and put it to
default configuration

Signed-off-by: Dzmitry Sankouski <dsankouski at gmail.com>
Cc: Ramon Fried <rfried.dev at gmail.com>
Cc: Tom Rini <trini at konsulko.com>
---
 arch/arm/mach-snapdragon/init_sdm845.c | 60 ++++++++++++++++++++----
 doc/board/qualcomm/sdm845.rst          | 63 +++++++++++++++++++++++++-
 include/configs/sdm845.h               |  5 ++
 3 files changed, 116 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-snapdragon/init_sdm845.c b/arch/arm/mach-snapdragon/init_sdm845.c
index 5f53c21947..6aeaeeb53a 100644
--- a/arch/arm/mach-snapdragon/init_sdm845.c
+++ b/arch/arm/mach-snapdragon/init_sdm845.c
@@ -7,6 +7,7 @@
 
 #include <init.h>
 #include <env.h>
+#include <fdtdec.h>
 #include <common.h>
 #include <asm/system.h>
 #include <asm/gpio.h>
@@ -14,6 +15,14 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static ulong fdt_addr __section(".data");
+
+void save_boot_params(ulong r0)
+{
+	fdt_addr = r0;
+	save_boot_params_ret();
+}
+
 int dram_init(void)
 {
 	return fdtdec_setup_mem_size_base();
@@ -29,8 +38,33 @@ __weak int board_init(void)
 	return 0;
 }
 
-/* Check for vol- and power buttons */
-__weak int misc_init_r(void)
+void set_abl_env(void)
+{
+	const void *fdt_blob;
+	int node, ret;
+	ulong initrd_start_prop;
+
+	ret = env_set_addr("abl_fdt_addr", fdt_addr);
+	if (ret < 0) {
+		printf("Failed to set abl device tree address\n");
+		return;
+	}
+
+	fdt_blob = (void *)fdt_addr;
+	node = fdt_path_offset(fdt_blob, "/chosen");
+	if (!node) {
+		printf("Chosen node not found in device tree at addr: 0x%ll\n", fdt_addr);
+		return;
+	}
+	initrd_start_prop = fdtdec_get_addr(fdt_blob, node, "linux,initrd-start");
+	if (!initrd_start_prop) {
+		printf("linux,initrd-start property is not set\n");
+		return;
+	}
+	env_set_addr("abl_initrd_start_addr", initrd_start_prop);
+}
+
+void read_pressed_keys(void)
 {
 	struct udevice *pon;
 	struct gpio_desc resin;
@@ -39,19 +73,19 @@ __weak int misc_init_r(void)
 	ret = uclass_get_device_by_name(UCLASS_GPIO, "pm8998_pon at 800", &pon);
 	if (ret < 0) {
 		printf("Failed to find PMIC pon node. Check device tree\n");
-		return 0;
+		return;
 	}
 
 	node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pon),
-				  "key_vol_down");
+					  "key_vol_down");
 	if (node < 0) {
 		printf("Failed to find key_vol_down node. Check device tree\n");
-		return 0;
+		return;
 	}
 	if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0,
-				       &resin, 0)) {
+					   &resin, 0)) {
 		printf("Failed to request key_vol_down button.\n");
-		return 0;
+		return;
 	}
 	if (dm_gpio_get_value(&resin)) {
 		env_set("key_vol_down", "1");
@@ -64,12 +98,12 @@ __weak int misc_init_r(void)
 				  "key_power");
 	if (node < 0) {
 		printf("Failed to find key_power node. Check device tree\n");
-		return 0;
+		return;
 	}
 	if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0,
-				       &resin, 0)) {
+					   &resin, 0)) {
 		printf("Failed to request key_power button.\n");
-		return 0;
+		return;
 	}
 	if (dm_gpio_get_value(&resin)) {
 		env_set("key_power", "1");
@@ -77,6 +111,12 @@ __weak int misc_init_r(void)
 	} else {
 		env_set("key_power", "0");
 	}
+}
+
+__weak int misc_init_r(void)
+{
+	set_abl_env();
+	read_pressed_keys();
 
 	return 0;
 }
diff --git a/doc/board/qualcomm/sdm845.rst b/doc/board/qualcomm/sdm845.rst
index cd46cbe9cf..e14fd05118 100644
--- a/doc/board/qualcomm/sdm845.rst
+++ b/doc/board/qualcomm/sdm845.rst
@@ -13,11 +13,27 @@ SDM845 - hi-end qualcomm chip, introduced in late 2017.
 Mostly used in flagship phones and tablets of 2018.
 
 U-Boot can be used as a replacement for Qualcomm's original ABL (UEFI) bootloader.
-It is loaded as an Android boot image through ABL
+It's replaces linux kernel in android boot image, and
+it's FIT payload replaces initramfs file. The boot process is similar to
+boot image with linux:
+
+- ABL unpacks android boot image
+- ABL sets `linux,initrd-start property` in chosen node in unpacked FDT
+- ABL sets x0 register to FDT address, and passes control to u-boot
+- u-boot reads x0 register, and stores it in `abl_fdt_addr` env variable
+- u-boot reads `linux,initrd-start` property,
+and stores it in `abl_initrd_start_addr`
+
+In this way, u-boot bootcmd relies on `abl_initrd_start_addr` env variable,
+and boils down to `bootm $abl_initrd_start_addr`. If more control on
+boot process is desired, pack a boot script in FIT image, and put it to
+default configuration
 
 Installation
 ------------
-First, setup ``CROSS_COMPILE`` for aarch64. Then, build U-Boot for your board::
+Build
+^^^^^^^^^^^^^^^^^^^^^^^^
+Setup ``CROSS_COMPILE`` for aarch64 and build U-Boot for your board::
 
 	$ export CROSS_COMPILE=<aarch64 toolchain prefix>
 	$ make <your board name here, see Boards section>_defconfig
@@ -25,6 +41,49 @@ First, setup ``CROSS_COMPILE`` for aarch64. Then, build U-Boot for your board::
 
 This will build ``u-boot.bin`` in the configured output directory.
 
+Generate FIT image
+^^^^^^^^^^^^^^^^^^^^^^^^
+See doc/uImage.FIT for more details
+
+Pack android boot image
+^^^^^^^^^^^^^^^^^^^^^^^^
+We'll assemble android boot image with ``u-boot.bin`` instead of linux kernel,
+and FIT image instead of ``initramfs``. Android bootloader expect gzipped kernel
+with appended dtb, so let's mimic linux to satisfy stock bootloader:
+
+- create dump dtb::
+
+	workdir=/tmp/prepare_payload
+	mkdir -p "$workdir"
+	cd "$workdir"
+	mock_dtb="$workdir"/payload_mock.dtb
+
+	dtc -I dts -O dtb -o "$mock_dtb" << EOF
+	/dts-v1/;
+	/ {
+		memory {
+			/* We expect the bootloader to fill in the size */
+			reg = <0 0 0 0>;
+		};
+
+		chosen { };
+	};
+	EOF
+
+- gzip u-boot ``gzip u-boot.bin``
+- append dtb to gzipped u-boot: ``cat u-boot.bin.gz "$mock_dtb" > u-boot.bin.gz-dtb``
+
+Now we've got everything to build android boot image:::
+
+	mkbootimg --base 0x0 --kernel_offset 0x00008000 \
+	--ramdisk_offset 0x02000000 --tags_offset 0x01e00000 \
+	--pagesize 4096 --second_offset 0x00f00000 \
+	--ramdisk "$fit_image" \
+	--kernel u-boot.bin.gz-dtb \
+	-o boot.img
+
+Flash image with your phone's flashing method.
+
 Boards
 ------------
 starqlte
diff --git a/include/configs/sdm845.h b/include/configs/sdm845.h
index af9ba197d4..cdf0f7e030 100644
--- a/include/configs/sdm845.h
+++ b/include/configs/sdm845.h
@@ -16,6 +16,11 @@
 /* Generic Timer Definitions */
 #define COUNTER_FREQUENCY	19000000
 
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"bootm_size=0x4000000\0"	\
+	"bootcmd=bootm $abl_initrd_start_addr\0"	\
+	"bootm_low=0x80000000\0"
+
 /* Size of malloc() pool */
 #define CONFIG_SYS_BOOTM_LEN	SZ_64M
 
-- 
2.20.1



More information about the U-Boot mailing list