1/* SPDX-License-Identifier: GPL-2.0+ */ 2/* 3 * This file implements recording of each stage of the boot process. It is 4 * intended to implement timing of each stage, reporting this information 5 * to the user and passing it to the OS for logging / further analysis. 6 * Note that it requires timer_get_boot_us() to be defined by the board 7 * 8 * Copyright (c) 2011 The Chromium OS Authors. 9 */ 10 11#ifndef _BOOTSTAGE_H 12#define _BOOTSTAGE_H 13 14#include <linux/types.h> 15#ifdef USE_HOSTCC 16#include <linux/kconfig.h> 17#endif 18 19/* Flags for each bootstage record */ 20enum bootstage_flags { 21 BOOTSTAGEF_ERROR = 1 << 0, /* Error record */ 22 BOOTSTAGEF_ALLOC = 1 << 1, /* Allocate an id */ 23}; 24 25/* bootstate sub-IDs used for kernel and ramdisk ranges */ 26enum { 27 BOOTSTAGE_SUB_FORMAT, 28 BOOTSTAGE_SUB_FORMAT_OK, 29 BOOTSTAGE_SUB_NO_UNIT_NAME, 30 BOOTSTAGE_SUB_UNIT_NAME, 31 BOOTSTAGE_SUB_SUBNODE, 32 33 BOOTSTAGE_SUB_CHECK, 34 BOOTSTAGE_SUB_HASH = 5, 35 BOOTSTAGE_SUB_CHECK_ARCH = 5, 36 BOOTSTAGE_SUB_CHECK_ALL, 37 BOOTSTAGE_SUB_GET_DATA, 38 BOOTSTAGE_SUB_CHECK_ALL_OK = 7, 39 BOOTSTAGE_SUB_GET_DATA_OK, 40 BOOTSTAGE_SUB_LOAD, 41}; 42 43/* 44 * A list of boot stages that we know about. Each of these indicates the 45 * state that we are at, and the action that we are about to perform. For 46 * errors, we issue an error for an item when it fails. Therefore the 47 * normal sequence is: 48 * 49 * progress action1 50 * progress action2 51 * progress action3 52 * 53 * and an error condition where action 3 failed would be: 54 * 55 * progress action1 56 * progress action2 57 * progress action3 58 * error on action3 59 */ 60enum bootstage_id { 61 BOOTSTAGE_ID_START = 0, 62 BOOTSTAGE_ID_CHECK_MAGIC, /* Checking image magic */ 63 BOOTSTAGE_ID_CHECK_HEADER, /* Checking image header */ 64 BOOTSTAGE_ID_CHECK_CHECKSUM, /* Checking image checksum */ 65 BOOTSTAGE_ID_CHECK_ARCH, /* Checking architecture */ 66 67 BOOTSTAGE_ID_CHECK_IMAGETYPE = 5,/* Checking image type */ 68 BOOTSTAGE_ID_DECOMP_IMAGE, /* Decompressing image */ 69 BOOTSTAGE_ID_KERNEL_LOADED, /* Kernel has been loaded */ 70 BOOTSTAGE_ID_DECOMP_UNIMPL = 7, /* Odd decompression algorithm */ 71 BOOTSTAGE_ID_CHECK_BOOT_OS, /* Calling OS-specific boot function */ 72 BOOTSTAGE_ID_BOOT_OS_RETURNED, /* Tried to boot OS, but it returned */ 73 BOOTSTAGE_ID_CHECK_RAMDISK = 9, /* Checking ram disk */ 74 75 BOOTSTAGE_ID_RD_MAGIC, /* Checking ram disk magic */ 76 BOOTSTAGE_ID_RD_HDR_CHECKSUM, /* Checking ram disk heder checksum */ 77 BOOTSTAGE_ID_RD_CHECKSUM, /* Checking ram disk checksum */ 78 BOOTSTAGE_ID_COPY_RAMDISK = 12, /* Copying ram disk into place */ 79 BOOTSTAGE_ID_RAMDISK, /* Checking for valid ramdisk */ 80 BOOTSTAGE_ID_NO_RAMDISK, /* No ram disk found (not an error) */ 81 82 BOOTSTAGE_ID_RUN_OS = 15, /* Exiting U-Boot, entering OS */ 83 84 BOOTSTAGE_ID_NEED_RESET = 30, 85 BOOTSTAGE_ID_POST_FAIL, /* Post failure */ 86 BOOTSTAGE_ID_POST_FAIL_R, /* Post failure reported after reloc */ 87 88 /* 89 * This set is reported only by x86, and the meaning is different. In 90 * this case we are reporting completion of a particular stage. 91 * This should probably change in the x86 code (which doesn't report 92 * errors in any case), but discussion this can perhaps wait until we 93 * have a generic board implementation. 94 */ 95 BOOTSTAGE_ID_BOARD_INIT_R, /* We have relocated */ 96 BOOTSTAGE_ID_BOARD_GLOBAL_DATA, /* Global data is set up */ 97 98 BOOTSTAGE_ID_BOARD_INIT_SEQ, /* We completed the init sequence */ 99 BOOTSTAGE_ID_BOARD_FLASH, /* We have configured flash banks */ 100 BOOTSTAGE_ID_BOARD_FLASH_37, /* In case you didn't hear... */ 101 BOOTSTAGE_ID_BOARD_ENV, /* Environment is relocated & ready */ 102 BOOTSTAGE_ID_BOARD_PCI, /* PCI is up */ 103 104 BOOTSTAGE_ID_BOARD_INTERRUPTS, /* Exceptions / interrupts ready */ 105 BOOTSTAGE_ID_BOARD_DONE, /* Board init done, off to main loop */ 106 /* ^^^ here ends the x86 sequence */ 107 108 /* Boot stages related to loading a kernel from an IDE device */ 109 BOOTSTAGE_ID_IDE_START = 41, 110 BOOTSTAGE_ID_IDE_ADDR, 111 BOOTSTAGE_ID_IDE_BOOT_DEVICE, 112 BOOTSTAGE_ID_IDE_TYPE, 113 114 BOOTSTAGE_ID_IDE_PART, 115 BOOTSTAGE_ID_IDE_PART_INFO, 116 BOOTSTAGE_ID_IDE_PART_TYPE, 117 BOOTSTAGE_ID_IDE_PART_READ, 118 BOOTSTAGE_ID_IDE_FORMAT, 119 120 BOOTSTAGE_ID_IDE_CHECKSUM, /* 50 */ 121 BOOTSTAGE_ID_IDE_READ, 122 123 /* Boot stages related to loading a kernel from an NAND device */ 124 BOOTSTAGE_ID_NAND_PART, 125 BOOTSTAGE_ID_NAND_SUFFIX, 126 BOOTSTAGE_ID_NAND_BOOT_DEVICE, 127 BOOTSTAGE_ID_NAND_HDR_READ = 55, 128 BOOTSTAGE_ID_NAND_AVAILABLE = 55, 129 BOOTSTAGE_ID_NAND_TYPE = 57, 130 BOOTSTAGE_ID_NAND_READ, 131 132 /* Boot stages related to loading a kernel from an network device */ 133 BOOTSTAGE_ID_NET_CHECKSUM = 60, 134 BOOTSTAGE_ID_NET_ETH_START = 64, 135 BOOTSTAGE_ID_NET_ETH_INIT, 136 137 BOOTSTAGE_ID_NET_START = 80, 138 BOOTSTAGE_ID_NET_NETLOOP_OK, 139 BOOTSTAGE_ID_NET_LOADED, 140 BOOTSTAGE_ID_NET_DONE_ERR, 141 BOOTSTAGE_ID_NET_DONE, 142 143 BOOTSTAGE_ID_FIT_FDT_START = 90, 144 /* 145 * Boot stages related to loading a FIT image. Some of these are a 146 * bit wonky. 147 */ 148 BOOTSTAGE_ID_FIT_KERNEL_START = 100, 149 150 BOOTSTAGE_ID_FIT_CONFIG = 110, 151 BOOTSTAGE_ID_FIT_TYPE, 152 153 BOOTSTAGE_ID_FIT_COMPRESSION, 154 BOOTSTAGE_ID_FIT_OS, 155 BOOTSTAGE_ID_FIT_LOADADDR, 156 BOOTSTAGE_ID_OVERWRITTEN, 157 158 /* Next 10 IDs used by BOOTSTAGE_SUB_... */ 159 BOOTSTAGE_ID_FIT_RD_START = 120, /* Ramdisk stages */ 160 161 /* Next 10 IDs used by BOOTSTAGE_SUB_... */ 162 BOOTSTAGE_ID_FIT_SETUP_START = 130, /* x86 setup stages */ 163 164 BOOTSTAGE_ID_IDE_FIT_READ = 140, 165 BOOTSTAGE_ID_IDE_FIT_READ_OK, 166 167 BOOTSTAGE_ID_NAND_FIT_READ = 150, 168 BOOTSTAGE_ID_NAND_FIT_READ_OK, 169 170 BOOTSTAGE_ID_FIT_LOADABLE_START = 160, /* for Loadable Images */ 171 172 BOOTSTAGE_ID_FIT_SPL_START = 170, /* for SPL Images */ 173 /* 174 * These boot stages are new, higher level, and not directly related 175 * to the old boot progress numbers. They are useful for recording 176 * rough boot timing information. 177 */ 178 BOOTSTAGE_ID_AWAKE, 179 BOOTSTAGE_ID_START_TPL, 180 BOOTSTAGE_ID_END_TPL, 181 BOOTSTAGE_ID_START_SPL, 182 BOOTSTAGE_ID_END_SPL, 183 BOOTSTAGE_ID_START_VPL, 184 BOOTSTAGE_ID_END_VPL, 185 BOOTSTAGE_ID_START_UBOOT_F, 186 BOOTSTAGE_ID_START_UBOOT_R, 187 BOOTSTAGE_ID_USB_START, 188 BOOTSTAGE_ID_ETH_START, 189 BOOTSTAGE_ID_BOOTP_START, 190 BOOTSTAGE_ID_BOOTP_STOP, 191 BOOTSTAGE_ID_BOOTM_START, 192 BOOTSTAGE_ID_BOOTM_HANDOFF, 193 BOOTSTAGE_ID_MAIN_LOOP, 194 BOOTSTAGE_ID_ENTER_CLI_LOOP, 195 BOOTSTAGE_KERNELREAD_START, 196 BOOTSTAGE_KERNELREAD_STOP, 197 BOOTSTAGE_ID_BOARD_INIT, 198 BOOTSTAGE_ID_BOARD_INIT_DONE, 199 200 BOOTSTAGE_ID_CPU_AWAKE, 201 BOOTSTAGE_ID_MAIN_CPU_AWAKE, 202 BOOTSTAGE_ID_MAIN_CPU_READY, 203 204 BOOTSTAGE_ID_ACCUM_LCD, 205 BOOTSTAGE_ID_ACCUM_SCSI, 206 BOOTSTAGE_ID_ACCUM_SPI, 207 BOOTSTAGE_ID_ACCUM_DECOMP, 208 BOOTSTAGE_ID_ACCUM_OF_LIVE, 209 BOOTSTAGE_ID_FPGA_INIT, 210 BOOTSTAGE_ID_ACCUM_DM_SPL, 211 BOOTSTAGE_ID_ACCUM_DM_F, 212 BOOTSTAGE_ID_ACCUM_DM_R, 213 BOOTSTAGE_ID_ACCUM_FSP_M, 214 BOOTSTAGE_ID_ACCUM_FSP_S, 215 BOOTSTAGE_ID_ACCUM_MMAP_SPI, 216 217 /* a few spare for the user, from here */ 218 BOOTSTAGE_ID_USER, 219 BOOTSTAGE_ID_ALLOC, 220}; 221 222/* 223 * Return the time since boot in microseconds, This is needed for bootstage 224 * and should be defined in CPU- or board-specific code. If undefined then 225 * you will get a link error. 226 */ 227ulong timer_get_boot_us(void); 228 229#if defined(USE_HOSTCC) || !CONFIG_IS_ENABLED(SHOW_BOOT_PROGRESS) 230#define show_boot_progress(val) do {} while (0) 231#else 232/** 233 * Board code can implement show_boot_progress() if needed. 234 * 235 * @param val Progress state (enum bootstage_id), or -id if an error 236 * has occurred. 237 */ 238void show_boot_progress(int val); 239#endif 240 241#if !defined(USE_HOSTCC) 242#if CONFIG_IS_ENABLED(BOOTSTAGE) 243#define ENABLE_BOOTSTAGE 244#endif 245#endif 246 247#ifdef ENABLE_BOOTSTAGE 248 249#include <mapmem.h> 250 251/* This is the full bootstage implementation */ 252 253/** 254 * Relocate existing bootstage records 255 * 256 * Call this after relocation has happened and after malloc has been initted. 257 * We need to copy any pointers in bootstage records that were added pre- 258 * relocation, since memory can be overwritten later. 259 * Return: Always returns 0, to indicate success 260 */ 261int bootstage_relocate(void); 262 263/** 264 * Add a new bootstage record 265 * 266 * @param id Bootstage ID to use (ignored if flags & BOOTSTAGEF_ALLOC) 267 * @param name Name of record, or NULL for none 268 * @param flags Flags (BOOTSTAGEF_...) 269 * @param mark Time to record in this record, in microseconds 270 */ 271ulong bootstage_add_record(enum bootstage_id id, const char *name, 272 int flags, ulong mark); 273 274/** 275 * Mark a time stamp for the current boot stage. 276 */ 277#define bootstage_mark(id) bootstage_mark_name(id, __func__) 278#define bootstage_error(id) bootstage_error_name(id, __func__) 279 280/** 281 * bootstage_mark_name - record bootstage with passing id and name 282 * @id: Bootstage id to record this timestamp against 283 * @name: Textual name to display for this id in the report 284 * 285 * Return: recorded time stamp 286 */ 287ulong bootstage_mark_name(enum bootstage_id id, const char *name); 288 289/** 290 * bootstage_error_name - record bootstage error with passing id and name 291 * @id: Bootstage id to record this timestamp against 292 * @name: Textual name to display for this id in the report 293 * 294 * Return: recorded time stamp 295 */ 296ulong bootstage_error_name(enum bootstage_id id, const char *name); 297 298/** 299 * Mark a time stamp in the given function and line number 300 * 301 * See BOOTSTAGE_MARKER() for a convenient macro. 302 * 303 * @param file Filename to record (NULL if none) 304 * @param func Function name to record 305 * @param linenum Line number to record 306 * Return: recorded time stamp 307 */ 308ulong bootstage_mark_code(const char *file, const char *func, 309 int linenum); 310 311/** 312 * Mark the start of a bootstage activity. The end will be marked later with 313 * bootstage_accum() and at that point we accumulate the time taken. Calling 314 * this function turns the given id into a accumulator rather than and 315 * absolute mark in time. Accumulators record the total amount of time spent 316 * in an activty during boot. 317 * 318 * @param id Bootstage id to record this timestamp against 319 * @param name Textual name to display for this id in the report (maybe NULL) 320 * Return: start timestamp in microseconds 321 */ 322uint32_t bootstage_start(enum bootstage_id id, const char *name); 323 324/** 325 * Mark the end of a bootstage activity 326 * 327 * After previously marking the start of an activity with bootstage_start(), 328 * call this function to mark the end. You can call these functions in pairs 329 * as many times as you like. 330 * 331 * @param id Bootstage id to record this timestamp against 332 * Return: time spent in this iteration of the activity (i.e. the time now 333 * less the start time recorded in the last bootstage_start() call 334 * with this id. 335 */ 336uint32_t bootstage_accum(enum bootstage_id id); 337 338/* Print a report about boot time */ 339void bootstage_report(void); 340 341/** 342 * Add bootstage information to the device tree 343 * 344 * Return: 0 if ok, -ve on error 345 */ 346int bootstage_fdt_add_report(void); 347 348/** 349 * Stash bootstage data into memory 350 * 351 * @param base Base address of memory buffer 352 * @param size Size of memory buffer 353 * Return: 0 if stashed ok, -1 if out of space 354 */ 355int bootstage_stash(void *base, int size); 356 357/** 358 * Read bootstage data from memory 359 * 360 * Bootstage data is read from memory and placed in the bootstage table 361 * in the user records. 362 * 363 * @param base Base address of memory buffer 364 * @param size Size of memory buffer (-1 if unknown) 365 * Return: 0 if unstashed ok, -ENOENT if bootstage info not found, -ENOSPC if 366 * there is not space for read the stashed data, or other error if 367 * something else went wrong 368 */ 369int bootstage_unstash(const void *base, int size); 370 371/** 372 * bootstage_get_size() - Get the size of the bootstage data 373 * 374 * Return: size of boostage data in bytes 375 */ 376int bootstage_get_size(void); 377 378/** 379 * bootstage_init() - Prepare bootstage for use 380 * 381 * @first: true if this is the first time bootstage is set up. This causes it 382 * to add a 'reset' record with a time of 0. 383 */ 384int bootstage_init(bool first); 385 386#else 387static inline ulong bootstage_add_record(enum bootstage_id id, 388 const char *name, int flags, ulong mark) 389{ 390 return 0; 391} 392 393/* 394 * This is a dummy implementation which just calls show_boot_progress(), 395 * and won't even do that unless CONFIG_SHOW_BOOT_PROGRESS is defined 396 */ 397 398static inline int bootstage_relocate(void) 399{ 400 return 0; 401} 402 403static inline ulong bootstage_mark(enum bootstage_id id) 404{ 405 show_boot_progress(id); 406 return 0; 407} 408 409static inline ulong bootstage_error(enum bootstage_id id) 410{ 411 show_boot_progress(-id); 412 return 0; 413} 414 415static inline ulong bootstage_mark_name(enum bootstage_id id, const char *name) 416{ 417 show_boot_progress(id); 418 return 0; 419} 420 421static inline ulong bootstage_mark_code(const char *file, const char *func, 422 int linenum) 423{ 424 return 0; 425} 426 427static inline uint32_t bootstage_start(enum bootstage_id id, const char *name) 428{ 429 return 0; 430} 431 432static inline uint32_t bootstage_accum(enum bootstage_id id) 433{ 434 return 0; 435} 436 437static inline int bootstage_stash(void *base, int size) 438{ 439 return 0; /* Pretend to succeed */ 440} 441 442static inline int bootstage_unstash(const void *base, int size) 443{ 444 return 0; /* Pretend to succeed */ 445} 446 447static inline int bootstage_get_size(void) 448{ 449 return 0; 450} 451 452static inline int bootstage_init(bool first) 453{ 454 return 0; 455} 456 457#endif /* ENABLE_BOOTSTAGE */ 458 459/* helpers for SPL */ 460int _bootstage_stash_default(void); 461int _bootstage_unstash_default(void); 462 463static inline int bootstage_stash_default(void) 464{ 465 if (CONFIG_IS_ENABLED(BOOTSTAGE) && IS_ENABLED(CONFIG_BOOTSTAGE_STASH)) 466 return _bootstage_stash_default(); 467 468 return 0; 469} 470 471static inline int bootstage_unstash_default(void) 472{ 473 if (CONFIG_IS_ENABLED(BOOTSTAGE) && IS_ENABLED(CONFIG_BOOTSTAGE_STASH)) 474 return _bootstage_unstash_default(); 475 476 return 0; 477} 478 479/* Helper macro for adding a bootstage to a line of code */ 480#define BOOTSTAGE_MARKER() \ 481 bootstage_mark_code(__FILE__, __func__, __LINE__) 482 483#endif 484