Implementing Custom Boot Menus in U-Boot for Allwinner T527

Experimental Environment

  • Hardware: Forlinx OK-T527 Development Board
  • Software: Allwinner Longan SDK (U-Boot version 2018)

U-Boot Initialization Flow

To understand how to inject a custom menu, we must first examine the entry point for U-Boot's main logic. The core execution loop is defined in /common/main.c, specifically within the main_loop() function. This function is called after hardware initialization is complete and the system is ready to process commands.

/* <u-boot>/common/main.c */

void main_loop(void)
{
    const char *boot_cmd;

    bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");

#ifdef CONFIG_VERSION_VARIABLE
    env_set("ver", version_string);
#endif

    cli_init();

    /* Execute commands defined in the preboot environment variable */
    run_preboot_environment_command();

#if defined(CONFIG_UPDATE_TFTP)
    update_tftp(0UL, NULL, NULL);
#endif

    /* 
     * Retrieve 'bootdelay' and 'bootcmd' environment variables.
     * This determines how long to wait and what to boot.
     */
    boot_cmd = bootdelay_process();

    if (cli_process_fdt(&boot_cmd))
        cli_secure_boot_cmd(boot_cmd);

    /* 
     * Start the countdown timer.
     * This function monitors serial input for user interruption.
     */
    autoboot_command(boot_cmd);

    /* 
     * If the boot is interrupted or fails, enter the CLI loop.
     * This is the standard U-Boot command line.
     */
    cli_loop();

    panic("No CLI available");
}

The Auto-Boot Mechanism

The transition from countdown to either booting the OS or entering the shell is controlled by autoboot_command(). This function is implemented in /common/autoboot.c. It checks whether the countdown has expired or if a key press was detected.

/* <u-boot>/common/autoboot.c */

void autoboot_command(const char *cmd_str)
{
    debug("### main_loop: bootcmd=\"%s\"\n", cmd_str ? cmd_str : "<undefined>");

    /* 
     * Check if the boot delay is valid and if the boot process was
     * not aborted by the user (abortboot checks for key presses).
     */
    if (stored_bootdelay != -1 && cmd_str && !abortboot(stored_bootdelay)) {
        /* Run the boot command if no key was pressed */
        run_command_list(cmd_str, -1, 0);
    }
    
    /* 
     * If a key was pressed (abortboot returns non-zero), 
     * this function returns, allowing main_loop to proceed to cli_loop().
     * This is where a custom menu hook can be inserted.
     */
}
</undefined>

By default, if abortboot() detects a key press, autoboot_command() returns without executing the boot command. Consequently, main_loop() proceeds to call cli_loop(), launching the stanadrd shell. To implement a custom menu, developers can modify the code path following the key press detection to call a custom menu function instead of the standard CLI loop.

Tags: U-Boot Allwinner T527 Embedded Systems c programming Forlinx OK-T527

Posted on Sat, 22 Aug 2026 16:21:37 +0000 by ottoman_