[efi] Honor ABR one-shot bootloader flag on EFI reset When GBL handles 'fastboot reboot-bootloader', it sets the ABR one-shot bootloader flag in durable_boot and calls UEFI ResetSystem(), which invokes efi_reset_system_boottime(). Unconditionally running 'reboot' sets the Amlogic reboot mode register (AO_SEC_SD_CFG15) to normal boot, causing legacy U-Boot to boot Zircon instead of entering fastboot after a bootloader rollback. Add GetAndClearOneShotBootloaderFlag() in zircon_boot.c (preserving one-shot recovery if set) and call it in efi_reset_system_boottime() to run 'reboot fastboot' when requested, logging a warning if the reboot command returns before falling back to do_reset(). TAG=agy CONV=d6901459-7b8c-4e0a-8447-092869375046 Bug: 571205565 Test: Built VIM3 U-Boot with ./fuchsia_build.py Change-Id: I020bcd960f94135f3266512cb170c9204eec2107 Reviewed-on: https://turquoise-internal-review.googlesource.com/c/third_party/u-boot/+/1683274 Reviewed-by: David Pursell <dpursell@google.com> Commit-Queue: Sergii Parubochyi <sergiip@google.com> GitOrigin-RevId: 8e7ac1835c7d1d9a54fca2fa5b4a3a139b887fd6
diff --git a/board/khadas/kvim3/zircon_boot.c b/board/khadas/kvim3/zircon_boot.c index 7f01c04..fcd9020 100644 --- a/board/khadas/kvim3/zircon_boot.c +++ b/board/khadas/kvim3/zircon_boot.c
@@ -279,6 +279,18 @@ return zircon_preboot(buffer, capacity, true) == 0 ? 0 : -1; } +bool GetAndClearOneShotBootloaderFlag(void) +{ + AbrOps abr_ops = GetAbrOpsFromZirconBootOps(&zb_ops); + AbrDataOneShotFlags one_shot_flags = kAbrDataOneShotFlagNone; + if (AbrGetAndClearOneShotFlags(&abr_ops, &one_shot_flags) == + kAbrResultOk && + AbrIsOneShotRecoveryBootSet(one_shot_flags)) { + AbrSetOneShotRecovery(&abr_ops, true); + } + return AbrIsOneShotBootloaderBootSet(one_shot_flags); +} + int do_zbi_boot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { long unsigned int loadaddr;
diff --git a/include/efi_loader.h b/include/efi_loader.h index f296d01..6b86e8e 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h
@@ -586,6 +586,7 @@ efi_status_t efi_gbl_debug_register(void); efi_status_t efi_gbl_boot_control_register(void); efi_status_t efi_gbl_avb_register(void); +bool GetAndClearOneShotBootloaderFlag(void); /* Called by efi_init_obj_list() to do initial measurement */ efi_status_t efi_tcg2_do_initial_measurement(void); /* measure the pe-coff image, extend PCR and add Event Log */
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 7fa507a..0a9305e 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c
@@ -210,8 +210,17 @@ case EFI_RESET_COLD: case EFI_RESET_WARM: case EFI_RESET_PLATFORM_SPECIFIC: - run_command("reboot", 0); + // TODO(https://fxbug.dev/573411501): Remove once GBL U-Boot rollout is + // complete. GBL already checks the ABR one-shot flag on boot, so this + // is only needed when flashing back to legacy U-Boot, which only checks + // the hardware reboot register (set by "reboot fastboot"). + if (GetAndClearOneShotBootloaderFlag()) { + run_command("reboot fastboot", 0); + } else { + run_command("reboot", 0); + } // Fallback if 'reboot' is unavailable or returns + printf("Warning: 'reboot' command failed, falling back to do_reset()\n"); do_reset(NULL, 0, 0, NULL); break; case EFI_RESET_SHUTDOWN: