- 了解Uboot Bootstage
1.Kconfig Introduction
- CONFIG_BOOTSTAGE
common/Kconfig:
config BOOTSTAGE
bool "Boot timing and reporting"
help
Enable recording of boot time while booting. To use it, insert
calls to bootstage_mark() with a suitable BOOTSTAGE_ID from
bootstage.h. Only a single entry is recorded for each ID. You can
give the entry a name with bootstage_mark_name(). You can also
record elapsed time in a particular stage using bootstage_start()
before starting and bootstage_accum() when finished. Bootstage will
add up all the accumulated time and report it.
Normally, IDs are defined in bootstage.h but a small number of
additional 'user' IDs can be used by passing BOOTSTAGE_ID_ALLOC
as the ID.
Calls to show_boot_progress() will also result in log entries but
these will not have names.
- CONFIG_BOOTSTAGE_REPORT
config BOOTSTAGE_REPORT
bool "Display a detailed boot timing report before booting the OS"
depends on BOOTSTAGE
help
Enable output of a boot time report just before the OS is booted.
This shows how long it took U-Boot to go through each stage of the
boot process. The report looks something like this:
Timer summary in microseconds:
Mark Elapsed Stage
0 0 reset
3,575,678 3,575,678 board_init_f start
3,575,695 17 arch_cpu_init A9
3,575,777 82 arch_cpu_init done
3,659,598 83,821 board_init_r start
3,910,375 250,777 main_loop
29,916,167 26,005,792 bootm_start
30,361,327 445,160 start_kernel
- CONFIG_BOOTSTAGE_STASH_ADDR
config BOOTSTAGE_STASH_ADDR
hex "Address to stash boot timing information"
default 0
help
Provide an address which will not be overwritten by the OS when it
starts, so that it can read this information when ready.
- CONFIG_BOOTSTAGE_STASH_SIZE
config BOOTSTAGE_STASH_SIZE
hex "Size of boot timing stash region"
default 0x1000
help
This should be large enough to hold the bootstage stash. A value of
4096 (4KiB) is normally plenty.
2.BOOTSTAGE_ID_*
enum bootstage_id {
BOOTSTAGE_ID_START = 0,
BOOTSTAGE_ID_CHECK_MAGIC, /* Checking image magic */
BOOTSTAGE_ID_CHECK_HEADER, /* Checking image header */
BOOTSTAGE_ID_CHECK_CHECKSUM, /* Checking image checksum */
BOOTSTAGE_ID_CHECK_ARCH, /* Checking architecture */
BOOTSTAGE_ID_CHECK_IMAGETYPE = 5,/* Checking image type */
BOOTSTAGE_ID_DECOMP_IMAGE, /* Decompressing image */
BOOTSTAGE_ID_KERNEL_LOADED, /* Kernel has been loaded */
BOOTSTAGE_ID_DECOMP_UNIMPL = 7, /* Odd decompression algorithm */
BOOTSTAGE_ID_CHECK_BOOT_OS, /* Calling OS-specific boot function */
BOOTSTAGE_ID_BOOT_OS_RETURNED, /* Tried to boot OS, but it returned */
BOOTSTAGE_ID_CHECK_RAMDISK = 9, /* Checking ram disk */
BOOTSTAGE_ID_RD_MAGIC, /* Checking ram disk magic */
BOOTSTAGE_ID_RD_HDR_CHECKSUM, /* Checking ram disk heder checksum */
BOOTSTAGE_ID_RD_CHECKSUM, /* Checking ram disk checksum */
BOOTSTAGE_ID_COPY_RAMDISK = 12, /* Copying ram disk into place */
BOOTSTAGE_ID_RAMDISK, /* Checking for valid ramdisk */
BOOTSTAGE_ID_NO_RAMDISK, /* No ram disk found (not an error) */
BOOTSTAGE_ID_RUN_OS = 15, /* Exiting U-Boot, entering OS */
BOOTSTAGE_ID_NEED_RESET = 30,
BOOTSTAGE_ID_POST_FAIL, /* Post failure */
BOOTSTAGE_ID_POST_FAIL_R, /* Post failure reported after reloc */
...
3.代码分析
3.1. 常用函数
common/bootstage.c:
int bootstage_init(bool first);
ulong bootstage_add_record(enum bootstage_id id, const char *name,
int flags, ulong mark);
ulong bootstage_mark(enum bootstage_id id);
ulong bootstage_mark_name(enum bootstage_id id, const char *name);
ulong bootstage_mark_code(const char *file, const char *func,
int linenum);
uint32_t bootstage_start(enum bootstage_id id, const char *name);
uint32_t bootstage_accum(enum bootstage_id id);
int bootstage_stash(void *base, int size);
int bootstage_unstash(const void *base, int size);
3.2.bootstage初始化
498 int bootstage_init(bool first)
499 {
500 struct bootstage_data *data;
501 int size = sizeof(struct bootstage_data);
502
503 gd->bootstage = (struct bootstage_data *)malloc(size);
504 if (!gd->bootstage)
505 return -ENOMEM;
506 data = gd->bootstage;
507 memset(data, '\0', size);
508 if (first) {
509 data->next_id = BOOTSTAGE_ID_USER;
510 bootstage_add_record(BOOTSTAGE_ID_AWAKE, "reset", 0, 0);
511 }
512
513 return 0;
514 }
初始化全局变量gd->bootstage,然后调用bootstage_add_record添加record到结构体数组struct bootstage_record record[RECORD_COUNT]; 数组大小由RECORD_COUNT决定。
19 enum {
20 RECORD_COUNT = CONFIG_VAL(BOOTSTAGE_RECORD_COUNT),
21 };
3.3.添加自定义
- bootstage_mark(BOOTSTAGE_ID_RUN_OS);
- bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, “board_init_f”);
3.4. config配置
CONFIG_ BOOTSTAGE=y
CONFIG_ SPL_BOOTSTAGE=y
CONFIG_ CMD_BOOTSTAGE=y
CONFIG_ BOOTSTAGE_STASH=y
CONFIG_ BOOTSTAGE_STASH_SIZE=0x4096
CONFIG_ BOOTSTAGE_REPORT=y
CONFIG_ BOOTSTAGE_RECORD_COUNT=40
CONFIG_ SPL_BOOTSTAGE_RECORD_COUNT=40
3.5.Debug
=> bootstage report
Timer summary in microseconds (6 records):
Mark Elapsed Stage
13,284,026 0 board_init_f
16,594,567 3,310,541 board_init_r
17,887,992 1,293,425 id=64
17,898,594 10,602 main_loop
17,961,225 62,631 id=173
Accumulated time:
102,461 dm_r
849,307 dm_f
=> bootstage stash 0 0x4096
Stashed 7 records
=> bootstage unstash 0 0x4096
Unstashed 7 records