May 5, 2026

Allwinner H5 -- the U-boot "go" command

The reason for investigating this is to study the transition from a running U-boot to my code running Kyu. As I investiage the strange configuration of the cache invalidate/flush handling, I begin to wonder what register settings U-boot may "clean up" before tranfering control to code it loads.

The directory "cmd" in the U-boot distribution holds code that implements each of the U-boot commands. This code is architecture and board agnostic. Individual commands (like "go") are implemented by a C function named "do_go()", and I find such a function in the file cmd/boot.c

The general case is very simple, and is handled by the routine do_go_exec() -- also in boot.c in the general case. It just casts the desired address into a function pointer and uses it:

	ulong (*entry) (int, ... );
    return entry (argc, argv);

The function do_go_exec() is declared "weak" so that it can be overridden by specific function for other architectures and/or boards. Having ctags configured is your friend in situations like this.

There are more interesting versions of do_go_exec(), such as this one in board/xilinx/versal/board.c

	if (current_el() > 1) {
        smp_kick_all_cpus();
        dcache_disable();
        armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry, ES_TO_AARCH64);
    } else {
        printf("FAIL: current EL is not above EL1\n");
        ret = EINVAL;
    }
This disables the D cache and switches to EL1, letting EL1 start up at the desired entry point.


Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org