Apart from just using grep and starting at a sensible starting place, a couple of clues are very helpful. One is doing a build for the system of interest and using the object files as "breadcrumbs" to discern which files were actually used for the build. The other is to have on hand a log from the build, like this one:
On the S5P6818, several executables run before U-Boot itself, and I will ignore those. There is apparently no SPL. Also on some systems U-Boot gets loaded to one address then relocates itself to another. This does not seem to be the case on the S5P6818. In other words things are fairly simple once we get to the stage I intend to study.
Execution starts in arch/arm/cpu/armv8/start.S at _start. This branches to _reset (but don't be fooled) and after a fair bit of initialization this branches to _main. The symbol _main is in arch/arm/lib/crt0_64.S
There is a nice comment at the start of crt0_64.S describing what happens next. Two routines are involved in the next stage. They are board_init_f() and board_init_r(). Remember, F first, then R.
The routine board_init_f() is called first and does what it can. (This calls arch_cpu_init() -- just for the record). Then relocate_code() is called and ultimately board_init_r() is called. Reading doc/README.arm-relocation may provide more details. See common/board_f.c for board_init_f(). The routine relocate_code() would seem to be in arch/arm/lib/relocate_64.S. See common/board_r.c for board_init_r().
An interesting aspect of board_init_f() as well as board_init_r() is the use of a table driven list of initialization routines. In the case of board_init_f(), the table is static init_fnc_t init_sequence_f[]. This table is processed by the following call:
if (initcall_run_list(init_sequence_f)) hang();See lib/initcall.c (only 40 lines of code). board_init_r also uses this scheme, with the last entry in the list being run_main_loop(), which is where U-Boot executes when initialization is finished and it finally gets to work. The code is in common_board_r.c as well and looks like this:
for (;;) main_loop();Wrapping it in a loop allows it to retry if autoboot fails. The file common/main.c contains main_loop() and is pretty short. The critical parts look more or less like this:
cli_init(); run_preboot_environment_command(); s = bootdelay_process(); if (cli_process_fdt(&s)) cli_secure_boot_cmd(s); autoboot_command(s); cli_loop();Note that "fdt" is the "flat device tree", which is a whole 'nuther bundle of snakes I am not getting into here.
The file common/cli.c contains cli_init() and cli_loop(). The file common/autoboot.c contains autoboot_command(). The meat of autoboot.c is calles to run_command_list() which is also in common/cli.c.
#ifdef CONFIG_CMD_NET initr_ethaddr, #endif .... #ifdef CONFIG_CMD_NET INIT_FUNC_WATCHDOG_RESET initr_net, #endifThe initr_ethaddr() routine, does this:
eth_getenv_enetaddr("ethaddr", bd->bi_enetaddr);The initr_net() routine, does this:
puts("Net: "); eth_initialize();The routine eth_initialize() is in net/eth.c
Tom's electronics pages / tom@mmto.org