bootm's ramdisk initrd delivery (boot_ramdisk_high()/LMB high-address placement plus the fixed start/loados/ramdisk/fdt/cmdline/bdt/prep/go ordering in bootm_run_states()) kept producing a kernel that booted cleanly but silently discarded its initramfs, ending in "VFS: Cannot open root device". Confirmed on hardware, multiple attempts, none panned out (in-place mode collided with the kernel relocation; reordering bootm substates is rejected by U-Boot itself as "out of order"; the reserved-memory collision theory was disproven against the compiled dtb). Switched to bootefi instead: same FIT (no repackaging), parsed with imxtract (kernel/fdt/ramdisk each extracted to a separate address), then booted via the kernel's own EFI stub + LoadFile2 initrd protocol -- a different code path in both U-Boot (efi_loader, not boot_ramdisk_high()) and the kernel (efi_load_initrd(), never touches reserve_initrd_mem()). Two real bugs found and fixed along the way, both confirmed on hardware: - ramdisk destination must not be a hand-computed offset from (that address is our own scratch buffer holding the whole FIT, not the board's dedicated ramdisk block) -- use $kernel_comp_addr_r instead, a separate 64 MiB LMB block the board reserves for kernel decompression, unused since our Image is uncompressed. - bootefi's first argument (the kernel) needs an explicit ":size" suffix. Without it, cmd/bootefi.c assumes the address was set by a prior load/tftp command tracked via efi_set_image_parameters() -- imxtract never touches that tracking, so the address never matches and bootefi fails with "No UEFI binary known" even though the bytes there are a perfectly valid kernel image. CONFIRMED ON HARDWARE 2026-09-18: reaches a live debug shell console.
130 lines
9.6 KiB
Bash
130 lines
9.6 KiB
Bash
bootdelay=0
|
|
bootretry=1
|
|
stdin=serial,button-kbd
|
|
stdout=serial,vidconsole
|
|
stderr=serial,vidconsole
|
|
|
|
# Fastboot is keen to use the address from kconfig, but we
|
|
# allocate its buffer at runtime.
|
|
fastboot=fastboot -l $fastboot_addr_r usb 0
|
|
|
|
# Always probe for UFS storage, though it should be done by board code.
|
|
preboot=scsi scan
|
|
|
|
# Shortcut to enable USB serial gadget and disable bootretry
|
|
serial_gadget=setenv stdin serial,button-kbd,usbacm; \
|
|
setenv stdout serial,vidconsole,usbacm; \
|
|
setenv stderr serial,vidconsole,usbacm; \
|
|
setenv bootretry -1; \
|
|
echo Enabled U-Boot console serial gadget
|
|
|
|
# bootretry will run this command over and over, if we fail once
|
|
# then bail out to the boot menu instead (with a pause to read
|
|
# the error message)
|
|
#
|
|
# rtwo (Motorola Edge 40 Pro, SM8550): the FIT image (mainline Image +
|
|
# dtb + initramfs) is packed by pack-fixedoff.py at a FIXED FILE OFFSET
|
|
# (0x18c000) inside boot_a -- same offset the ABL uses to load kernel/
|
|
# dtb, discovered via RE because this ABL does NOT follow the standard
|
|
# Android boot.img formula. Confirmed in hardware (2026-09-17): trusting
|
|
# $prevbl_initrd_start_addr (CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR,
|
|
# i.e. what the ABL claims via /chosen/linux,initrd-start) fails with
|
|
# "ERROR -91E: can't get kernel image!" (EPROTOTYPE, no FIT magic at
|
|
# that address) -- consistent with the ABL's fixed-offset loading not
|
|
# populating that property correctly either. So: read the FIT ourselves
|
|
# straight from boot_a at the known offset via the UFS/SCSI block layer
|
|
# (preboot already did `scsi scan`) into $ramdisk_addr_r (128 MiB
|
|
# scratch region board_late_init reserves, arch/arm/mach-snapdragon/
|
|
# board.c). Block size is derived at runtime (100663296 / blocks-in-
|
|
# partition) instead of assumed, since we don't know if this UFS LU
|
|
# reports 512B or 4096B logical blocks. Falls back to the old
|
|
# prevbl_initrd_start_addr attempt, then to the phone menu, if this
|
|
# fails -- see memoria rtwo-uboot-chainload-fit-raw-read.
|
|
pmos_bootargs=earlycon console=ttyMSM0,115200n8 console=tty0 ignore_loglevel panic=5 pmos.debug-shell clk_ignore_unused pd_ignore_unused regulator_ignore_unused allow_mismatched_32bit_el0 pmos_boot_uuid=d4373976-057c-4cf3-a43d-00734001b405 pmos_root_uuid=09804032-85bb-4d57-95a5-00d1965fb10f pmos_rootfsopts=defaults
|
|
# ESTADO 2026-09-17: vuelto a dejar tal cual quedo justo despues del PRIMER
|
|
# cambio de la implementacion EFI (antes de corregir el offset del ramdisk
|
|
# de imxtract y antes de sacar ignore_loglevel) -- checkpoint pedido para
|
|
# retomar la exploracion del camino EFI, esta vez via una particion real
|
|
# (userdata) en vez del RAM-only que se probo primero.
|
|
#
|
|
# DEBUG 2026-09-17 (quinta vuelta): probar el camino EFI en vez de bootm+FIT.
|
|
# bootefi usa boot/efi_loader (AllocatePages/LoadFile2) para el initrd, no
|
|
# boot_ramdisk_high()/LMB "high address" -- codigo completamente distinto,
|
|
# asi que el bug de orden fijo start/loados/ramdisk/fdt de bootm no aplica
|
|
# aca. Ademas, en el lado del kernel, el stub EFI arm64 (CONFIG_EFI_STUB=y,
|
|
# ya compilado) carga el initrd via efi_load_initrd()/LoadFile2, que NUNCA
|
|
# pasa por early_init_dt_check_for_initrd()/reserve_initrd_mem() -- el
|
|
# chequeo memblock_is_region_reserved() que sospechabamos ni siquiera se
|
|
# ejecuta para este camino. bootargs se sigue pasando igual (bootefi
|
|
# convierte $bootargs a UTF-16 como load options).
|
|
#
|
|
# Mismo FIT de siempre (sin repackaging), pero en vez de bootm lo parseamos
|
|
# con imxtract (CONFIG_CMD_XIMG=y, ya compilado) para sacar cada sub-imagen
|
|
# a una direccion de RAM aparte:
|
|
# - kernel -> $kernel_addr_r (misma que bootm usaba para relocar)
|
|
# - fdt -> $fdt_addr_r (la misma que bootmenu_10 ya usa con exito)
|
|
# - ramdisk -> $kernel_comp_addr_r (NO un offset inventado desde
|
|
# $ramdisk_addr_r -- eso fue el bug original: $ramdisk_addr_r + 0x8000000
|
|
# coincidia EXACTO con $kernel_addr_r y piso el kernel ya extraido
|
|
# ("No UEFI binary known at <addr>"). Investigado en la lista de U-Boot
|
|
# (parche "mach-snapdragon: dynamic load addresses", 2026): board.c
|
|
# arma estas variables como bloques LMB DEDICADOS y consecutivos --
|
|
# kernel_addr_r=128MiB, ramdisk_addr_r=128MiB (por eso el offset exacto
|
|
# de 0x8000000=128MiB), kernel_comp_addr_r=64MiB, fdt_addr_r=2MiB. El
|
|
# bug de fondo era usar $ramdisk_addr_r para algo que NO es su proposito
|
|
# (nuestro buffer crudo del FIT completo, ~55 MiB) y encima calcular un
|
|
# offset a mano dentro de ese mismo bloque de 128 MiB, invadiendo el
|
|
# vecino. $kernel_comp_addr_r es un bloque separado, dedicado a
|
|
# descomprimir un kernel comprimido -- el nuestro (Image sin comprimir,
|
|
# CONFIG_EFI_ZBOOT apagado) no lo usa, asi que esta libre y garantizado
|
|
# sin solaparse con ningun otro _addr_r por construccion.
|
|
# imxtract fija $filesize despues de cada extraccion (confirmado en
|
|
# cmd/ximg.c), por eso el tamano del ramdisk y del kernel se guardan aparte
|
|
# antes de que la siguiente llamada los pise.
|
|
#
|
|
# 2026-09-18: "No UEFI binary known at <addr>" seguia apareciendo incluso
|
|
# con las tres direcciones ya sin solaparse (kernel_comp_addr_r confirmado
|
|
# en hardware como un bloque separado y limpio). Causa real, en
|
|
# cmd/bootefi.c:204-226 (do_bootefi_image): si el PRIMER argumento de
|
|
# `bootefi` NO lleva ":tamano", el comando asume que la direccion ya viene
|
|
# de un `load`/`tftp` previo (que actualiza un registro interno de "ultima
|
|
# imagen cargada" via efi_set_image_parameters()) y compara contra ESE
|
|
# registro -- si no matchea (o nunca se seteo, como en nuestro caso porque
|
|
# usamos `imxtract`, que NO actualiza ese registro), falla con este mensaje
|
|
# sin importar que los bytes en esa direccion sean un kernel EFI valido.
|
|
# Fix: pasarle ":tamano" tambien al kernel (no solo al ramdisk, que ya lo
|
|
# llevaba) -- eso fuerza la rama que trata la direccion como explicita
|
|
# (efi_clear_bootdev()) sin depender de ningun registro previo.
|
|
#
|
|
# Si bootefi no funciona por algun motivo, cae al `bootm` de siempre como
|
|
# red de seguridad (mismo fallback que ya existia).
|
|
bootcmd=setenv bootargs $pmos_bootargs; if part start scsi 3 boot_a boot_a_start && part size scsi 3 boot_a boot_a_size; then setexpr blksz 0x6000000 / $boot_a_size; setexpr fit_blk_off 0x18c000 / $blksz; setexpr fit_lba $boot_a_start + $fit_blk_off; setexpr fit_blk_cnt $boot_a_size - $fit_blk_off; echo pmOS: boot_a start=$boot_a_start size=$boot_a_size blksz=$blksz fit_lba=$fit_lba fit_cnt=$fit_blk_cnt; scsi dev 3; if scsi read $ramdisk_addr_r $fit_lba $fit_blk_cnt; then echo pmOS: FIT read OK, addr=$ramdisk_addr_r; setenv verify no; setenv initrd_stage_addr $kernel_comp_addr_r; if imxtract $ramdisk_addr_r kernel $kernel_addr_r; then setenv kernel_stage_size $filesize; echo pmOS: kernel extracted addr=$kernel_addr_r size=$kernel_stage_size; if imxtract $ramdisk_addr_r fdt $fdt_addr_r; then echo pmOS: fdt extracted addr=$fdt_addr_r size=$filesize; if imxtract $ramdisk_addr_r ramdisk $initrd_stage_addr; then setenv initrd_stage_size $filesize; echo pmOS: ramdisk extracted addr=$initrd_stage_addr size=$initrd_stage_size; echo pmOS: trying bootefi; pause; bootefi $kernel_addr_r:$kernel_stage_size $initrd_stage_addr:$initrd_stage_size $fdt_addr_r; echo pmOS: bootefi returned, should not happen; pause; else echo pmOS: ramdisk imxtract FAILED; pause; fi; else echo pmOS: fdt imxtract FAILED; pause; fi; else echo pmOS: kernel imxtract FAILED; pause; fi; else echo pmOS: scsi read of FIT failed; pause; fi; else echo pmOS: could not resolve boot_a partition; fi; echo pmOS: bootefi path failed, trying old bootm path via prevbl_initrd_start_addr=$prevbl_initrd_start_addr; bootm $prevbl_initrd_start_addr; echo pmOS: bootm failed; bootefi bootmgr; pause; run menucmd
|
|
|
|
# When entering the menu (either from button press or failed boot)
|
|
# remap bootcmd so it will re-open the menu and we won't get stuck
|
|
# at the console with no way to type
|
|
menucmd=setenv bootcmd run menucmd; bootmenu -1
|
|
|
|
# Pause is used so the output can be read on the display
|
|
bootmenu_0=Boot pmOS mainline (FIT)=setenv bootargs $pmos_bootargs; bootm $prevbl_initrd_start_addr; pause
|
|
bootmenu_1=Boot=bootefi bootmgr; pause
|
|
bootmenu_2=Enable serial console gadget=run serial_gadget
|
|
bootmenu_3=Enable USB mass storage=echo "Press any key to exit UMS mode"; ums 0 scsi 0
|
|
bootmenu_4=Enable fastboot mode=echo "Press any key to exit fastboot mode"; run fastboot
|
|
# Disabling bootretry means we'll just drop the shell
|
|
bootmenu_5=Drop to shell=setenv bootretry -1
|
|
bootmenu_6=Reset device=reset
|
|
bootmenu_7=Dump clocks=clk dump; pause
|
|
bootmenu_8=Dump environment=printenv; pause
|
|
bootmenu_9=Board info=bdinfo; pause
|
|
bootmenu_10=Dump bootargs=fdt addr $fdt_addr_r; fdt print /chosen bootargs; pause
|
|
bootmenu_11=Power off=poweroff
|
|
bootmenu_12=Diag SCSI boot_a=scsi scan; scsi info; pause; if part number scsi 0 boot_a i; then echo scsi0:part=$i; else echo scsi0:no-boot_a; fi; if part number scsi 1 boot_a i; then echo scsi1:part=$i; else echo scsi1:no-boot_a; fi; if part number scsi 2 boot_a i; then echo scsi2:part=$i; else echo scsi2:no-boot_a; fi; if part number scsi 3 boot_a i; then echo scsi3:part=$i; else echo scsi3:no-boot_a; fi; pause; if part number scsi 4 boot_a i; then echo scsi4:part=$i; else echo scsi4:no-boot_a; fi; if part number scsi 5 boot_a i; then echo scsi5:part=$i; else echo scsi5:no-boot_a; fi; if part number scsi 6 boot_a i; then echo scsi6:part=$i; else echo scsi6:no-boot_a; fi; if part number scsi 7 boot_a i; then echo scsi7:part=$i; else echo scsi7:no-boot_a; fi; pause
|
|
bootmenu_13=Diag USB gadget=dm uclass usb_gadget; pause; dm uclass usb; pause; dm uclass phy; pause
|
|
bootmenu_14=Diag UFS=dm uclass ufs; pause; dm uclass phy; pause; ufs init 0; echo ufs_init_ret=$?; pause
|
|
|
|
# Allow holding the volume down button while U-Boot loads to enter
|
|
# the boot menu
|
|
button_cmd_0_name=Volume Down
|
|
button_cmd_0=run menucmd
|