Files
uboot-rtwo/board/qualcomm/qcom-phone.env
T
snlavaise 7e0a580700 rtwo: switch chainload boot from bootm+FIT to bootefi (EFI stub)
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.
2026-09-18 00:09:27 -03:00

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