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 <dsankou...@gmail.com> Cc: Ramon Fried <rfried....@gmail.com> Cc: Tom Rini <tr...@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@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