bootm_find_os() leaves images.os.arch at IH_ARCH_INVALID for Android boot images: unlike the legacy and FIT headers, the Android boot image header carries no architecture field. The arm64 Image relocation in bootm_load_os() (booti_setup()) is therefore skipped, and a kernel that is executed in place, which android_image_get_kernel_addr() arranges for any uncompressed kernel whose header holds the default kernel address (or with ANDROID_BOOT_IMAGE_IGNORE_BLOB_ADDR), whatever the header version, runs from boot.img + page size, which is not 2 MiB aligned. The kernel reports "Kernel image misaligned at boot, please fix your bootloader!" and dies early (observed as a stack overflow in start_kernel() with a GKI 6.12 kernel on QEMU virt).
Set IH_ARCH_DEFAULT, the one architecture this U-Boot can boot and the only value available for this image format, so that booti_setup() moves the kernel to a properly aligned address. The other readers of os.arch are not affected: - arch/arm/lib/bootm.c switches to AArch32 only for IH_ARCH_ARM, so an Android image keeps taking the AArch64 path exactly as it does with IH_ARCH_INVALID. Its update_os_arch_secondary_cores() hook, implemented by Layerscape, marks the spin table entries OS_ARCH_SAME only when os_arch equals IH_ARCH_DEFAULT, so with IH_ARCH_INVALID an Android boot currently releases the secondary cores as if the kernel were a different architecture; this is fixed as well. - the x86 setup.bin lookup in bootm.c is only reached on an x86 U-Boot, where the Android format is not bootable through bootm anyway. - ARM32 and RISC-V do not read os.arch after bootm_find_os(). For a v0-v2 image whose ramdisk is used in place, booti_setup() can now move the kernel forward by up to 2 MiB, and the memmove() of image_size bytes (which includes BSS) overwrites the start of the ramdisk that follows the kernel in boot.img. Executing in place already had the same problem, since the kernel clears its BSS early, so this is not a regression; the ramdisk is relocated by the ramdisk_high logic when it is in use, and loading the kernel to kernel_addr_r instead of executing it in place, like the compressed case, is a separate change. The LMB reservation also still covers the original load range, as it does for FIT. Signed-off-by: Igor Opaniuk <[email protected]> Reviewed-by: Simon Glass <[email protected]> --- Changes in v2: - reword the commit message (Simon Glass): the Android header has no architecture field, the in-place execution is not specific to header v3/v4, why IH_ARCH_DEFAULT is safe for the other readers of os.arch (and fixes the Layerscape secondary core release), note on the ramdisk overlap for v0-v2 images booted in place and on the LMB reservation; code unchanged, kept unconditional - add Simon's Reviewed-by - Link to v1: https://patch.msgid.link/20261011-upstream-bootm_android_b4-v1-1-3e82462ac...@oss.qualcomm.com --- boot/bootm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/bootm.c b/boot/bootm.c index b6ae0163b27..75b34f39cca 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -432,6 +432,7 @@ static int bootm_find_os(const char *cmd_name, const char *addr_fit) images.os.type = IH_TYPE_KERNEL; images.os.comp = android_image_get_kcomp(boot_img, vendor_boot_img); images.os.os = IH_OS_LINUX; + images.os.arch = IH_ARCH_DEFAULT; images.os.end = android_image_get_end(boot_img, vendor_boot_img); images.os.load = android_image_get_kload(boot_img, vendor_boot_img); images.ep = images.os.load; --- base-commit: ed869863c7e2aca50d57a05d843830dd843138c4 change-id: 20261011-upstream-bootm_android_b4-4e94dca526b5 Best regards, -- Igor Opaniuk <[email protected]>
