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.
This commit is contained in:
@@ -41,7 +41,64 @@ serial_gadget=setenv stdin serial,button-kbd,usbacm; \
|
||||
# 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
|
||||
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; pause; scsi dev 3; if scsi read $ramdisk_addr_r $fit_lba $fit_blk_cnt; then echo pmOS: FIT read OK, about to bootm at $ramdisk_addr_r; pause; bootm $ramdisk_addr_r; echo pmOS: bootm on FIT returned control, this should not happen; pause; else echo pmOS: scsi read of FIT failed; pause; fi; else echo pmOS: could not resolve boot_a partition; fi; echo pmOS: raw boot_a read failed, trying prevbl_initrd_start_addr=$prevbl_initrd_start_addr; bootm $prevbl_initrd_start_addr; echo pmOS: bootm failed; bootefi bootmgr; pause; run menucmd
|
||||
# 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
|
||||
|
||||
Reference in New Issue
Block a user