Mini440之uboot移植之源码分析(四)
board_init_r和board_init_f差不多,都是执行一个循环。这里是循环执行init_sequence_r[]里的函数指针。
一、board_init_r(common/board_r.c)
void board_init_r(gd_t *new_gd, ulong dest_addr) { #ifdef CONFIG_NEEDS_MANUAL_RELOC int i; #endif #ifdef CONFIG_AVR32 mmu_init_r(dest_addr); #endif #if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) gd = new_gd; #endif #ifdef CONFIG_NEEDS_MANUAL_RELOC for (i = 0; i < ARRAY_SIZE(init_sequence_r); i++) init_sequence_r[i] += gd->reloc_off; #endif if (initcall_run_list(init_sequence_r)) hang(); /* NOTREACHED - run_main_loop() does not return */ hang(); }
在上一篇博客中我们已经介绍了该函数调用表时会传入两个参数:
- new_gd:为u-boot重定位后的新地址的gd结构;
- dest_addr:u-boot重定位后的地址;
然后循环遍历init_sequence_r中的每一个函数,并执行。
二、init_sequence_r
/* * Over time we hope to remove these functions with code fragments and * stub funtcions, and instead call the relevant function directly. * * We also hope to remove most of the driver-related init and do it if/when * the driver is later used. * * TODO: perhaps reset the watchdog in the initcall function after each call? */ init_fnc_t init_sequence_r[] = { initr_trace, initr_reloc, /* TODO: could x86/PPC have this also perhaps? */ #ifdef CONFIG_ARM initr_caches, /* Note: For Freescale LS2 SoCs, new MMU table is created in DDR. * A temporary mapping of IFC high region is since removed, * so environmental variables in NOR flash is not availble * until board_init() is called below to remap IFC to high * region. */ #endif initr_reloc_global_data, #if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500) initr_unlock_ram_in_cache, #endif initr_barrier, initr_malloc, initr_console_record, #ifdef CONFIG_SYS_NONCACHED_MEMORY initr_noncached, #endif bootstage_relocate, #ifdef CONFIG_DM initr_dm, #endif initr_bootstage, #if defined(CONFIG_ARM) || defined(CONFIG_NDS32) board_init, /* Setup chipselects */ #endif /* * TODO: printing of the clock inforamtion of the board is now * implemented as part of bdinfo command. Currently only support for * davinci SOC's is added. Remove this check once all the board * implement this. */ #ifdef CONFIG_CLOCKS set_cpu_clk_info, /* Setup clock information */ #endif #ifdef CONFIG_EFI_LOADER efi_memory_init, #endif stdio_init_tables, initr_serial, initr_announce, INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_NEEDS_MANUAL_RELOC initr_manual_reloc_cmdtable, #endif #if defined(CONFIG_PPC) || defined(CONFIG_M68K) initr_trap, #endif #ifdef CONFIG_ADDR_MAP initr_addr_map, #endif #if defined(CONFIG_BOARD_EARLY_INIT_R) board_early_init_r, #endif INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_LOGBUFFER initr_logbuffer, #endif #ifdef CONFIG_POST initr_post_backlog, #endif INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_SYS_DELAYED_ICACHE initr_icache_enable, #endif #if defined(CONFIG_PCI) && defined(CONFIG_SYS_EARLY_PCI_INIT) /* * Do early PCI configuration _before_ the flash gets initialised, * because PCU ressources are crucial for flash access on some boards. */ initr_pci, #endif #ifdef CONFIG_WINBOND_83C553 initr_w83c553f, #endif #ifdef CONFIG_ARCH_EARLY_INIT_R arch_early_init_r, #endif power_init_board, #ifndef CONFIG_SYS_NO_FLASH initr_flash, #endif INIT_FUNC_WATCHDOG_RESET #if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_X86) || \ defined(CONFIG_SPARC) /* initialize higher level parts of CPU like time base and timers */ cpu_init_r, #endif #ifdef CONFIG_PPC initr_spi, #endif #ifdef CONFIG_CMD_NAND initr_nand, #endif #ifdef CONFIG_CMD_ONENAND initr_onenand, #endif #ifdef CONFIG_GENERIC_MMC initr_mmc, #endif #ifdef CONFIG_HAS_DATAFLASH initr_dataflash, #endif initr_env, #ifdef CONFIG_SYS_BOOTPARAMS_LEN initr_malloc_bootparams, #endif INIT_FUNC_WATCHDOG_RESET initr_secondary_cpu, #if defined(CONFIG_ID_EEPROM) || defined(CONFIG_SYS_I2C_MAC_OFFSET) mac_read_from_eeprom, #endif INIT_FUNC_WATCHDOG_RESET #if defined(CONFIG_PCI) && !defined(CONFIG_SYS_EARLY_PCI_INIT) /* * Do pci configuration */ initr_pci, #endif stdio_add_devices, initr_jumptable, #ifdef CONFIG_API initr_api, #endif console_init_r, /* fully init console as a device */ #ifdef CONFIG_DISPLAY_BOARDINFO_LATE show_board_info, #endif #ifdef CONFIG_ARCH_MISC_INIT arch_misc_init, /* miscellaneous arch-dependent init */ #endif #ifdef CONFIG_MISC_INIT_R misc_init_r, /* miscellaneous platform-dependent init */ #endif INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_CMD_KGDB initr_kgdb, #endif interrupt_init, #if defined(CONFIG_ARM) || defined(CONFIG_AVR32) initr_enable_interrupts, #endif #if defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) || defined(CONFIG_M68K) timer_init, /* initialize timer */ #endif #if defined(CONFIG_STATUS_LED) initr_status_led, #endif /* PPC has a udelay(20) here dating from 2002. Why? */ #ifdef CONFIG_CMD_NET initr_ethaddr, #endif #ifdef CONFIG_BOARD_LATE_INIT board_late_init, #endif #if defined(CONFIG_CMD_AMBAPP) ambapp_init_reloc, #if defined(CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP) initr_ambapp_print, #endif #endif #ifdef CONFIG_CMD_SCSI INIT_FUNC_WATCHDOG_RESET initr_scsi, #endif #ifdef CONFIG_CMD_DOC INIT_FUNC_WATCHDOG_RESET initr_doc, #endif #ifdef CONFIG_BITBANGMII initr_bbmii, #endif #ifdef CONFIG_CMD_NET INIT_FUNC_WATCHDOG_RESET initr_net, #endif #ifdef CONFIG_POST initr_post, #endif #if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_CMD_IDE) initr_pcmcia, #endif #if defined(CONFIG_CMD_IDE) initr_ide, #endif #ifdef CONFIG_LAST_STAGE_INIT INIT_FUNC_WATCHDOG_RESET /* * Some parts can be only initialized if all others (like * Interrupts) are up and running (i.e. the PC-style ISA * keyboard). */ last_stage_init, #endif #ifdef CONFIG_CMD_BEDBUG INIT_FUNC_WATCHDOG_RESET initr_bedbug, #endif #if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER) initr_mem, #endif #ifdef CONFIG_PS2KBD initr_kbd, #endif #if defined(CONFIG_SPARC) prom_init, #endif run_main_loop, };
通过反汇编代码我们可以确定实际定义了哪些函数:
0007220c: 722 0c: 0000eab0 .word 0x0000eab0 initr_trace 72210: 0000eab8 .word 0x0000eab8 initr_reloc 72214: 0000ec88 .word 0x0000ec88 initr_caches 72218: 0000ead0 .word 0x0000ead0 initr_reloc_global_data 7221c: 0000eaf8 .word 0x0000eaf8 initr_barrier 72220: 0000ec6c .word 0x0000ec6c initr_malloc 72224: 0000eb00 .word 0x0000eb00 initr_console_record 72228: 0000ea8c .word 0x0000ea8c bootstage_relocate 7222c: 0000ec58 .word 0x0000ec58 initr_bootstage 72230: 0000111c .word 0x0000111c board_init 72234: 000163c8 .word 0x000163c8 stdio_init_tables 72238: 0000ec48 .word 0x0000ec48 initr_serial 7223c: 0000eb10 .word 0x0000eb10 initr_announce 72240: 0000eb08 .word 0x0000eb08 power_init_board 72244: 0000ebcc .word 0x0000ebcc initr_flash 72248: 0000ebb0 .word 0x0000ebb0 initr_nand 7224c: 0000eb80 .word 0x0000eb80 initr_env 72250: 0000eaa0 .word 0x0000eaa0 initr_secondary_cpu 72254: 00016488 .word 0x00016488 stdio_add_devices 72258: 0000eb70 .word 0x0000eb70 initr_jumptable 7225c: 000146e0 .word 0x000146e0 console_init_r 72260: 00000ae0 .word 0x00000ae0 interrupt_init 72264: 0000eb60 .word 0x0000eb60 initr_enable_interrupts 72268: 0000eb40 .word 0x0000eb40 initr_ethaddr 7226c: 0000eb24 .word 0x0000eb24 initr_net 72270: 0000eb18 .word 0x0000eb18 run_main_loop
三、各个函数指针
3.1 initr_trace(common/board_r.c)
static int initr_trace(void) { #ifdef CONFIG_TRACE trace_init(gd->trace_buff, CONFIG_TRACE_BUFFER_SIZE); #endif return 0; }
3.2 initr_reloc(common/board_r.c)
static int initr_reloc(void) { /* tell others: relocation done */ gd->flags |= GD_FLG_RELOC | GD_FLG_FULL_MALLOC_INIT; return 0; }
常量GD_FLG_RELOC 和GD_FLG_FULL_MALLOC_INIT定义如下:
/* * Global Data Flags - the top 16 bits are reserved for arch-specific flags */ #define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */ #define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */ #define GD_FLG_SILENT 0x00004 /* Silent mode */ #define GD_FLG_POSTFAIL 0x00008 /* Critical POST test failed */ #define GD_FLG_POSTSTOP 0x00010 /* POST seqeunce aborted */ #define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */ #define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ #define GD_FLG_ENV_READY 0x00080 /* Env. imported into hash table */ #define GD_FLG_SERIAL_READY 0x00100 /* Pre-reloc serial console ready */ #define GD_FLG_FULL_MALLOC_INIT 0x00200 /* Full malloc() is ready */ #define GD_FLG_SPL_INIT 0x00400 /* spl_init() has been called */ #define GD_FLG_SKIP_RELOC 0x00800 /* Don't relocate */ #define GD_FLG_RECORD 0x01000 /* Record console */
设置gd->flags标志位第1位、第10位为1。
3.3 initr_caches(common/board_r.c)
static int initr_caches(void) { /* Enable caches */ enable_caches(); return 0; }
enable_caches()使能缓存,定义在arch/arm/lib/cache.c:
/* * Default implementation of enable_caches() * Real implementation should be in platform code */ __weak void enable_caches(void) { puts("WARNING: Caches not enabled\n"); }
3.4 initr_reloc_global_data(common/board_r.c)
static int initr_reloc_global_data(void) { #ifdef __ARM__ monitor_flash_len = _end - __image_copy_start; #elif defined(CONFIG_NDS32) monitor_flash_len = (ulong)&_end - (ulong)&_start; #elif !defined(CONFIG_SANDBOX) && !defined(CONFIG_NIOS2) monitor_flash_len = (ulong)&__init_end - gd->relocaddr; #endif #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) /* * The gd->cpu pointer is set to an address in flash before relocation. * We need to update it to point to the same CPU entry in RAM. * TODO: why not just add gd->reloc_ofs? */ gd->arch.cpu += gd->relocaddr - CONFIG_SYS_MONITOR_BASE; /* * If we didn't know the cpu mask & # cores, we can save them of * now rather than 'computing' them constantly */ fixup_cpu(); #endif #ifdef CONFIG_SYS_EXTRA_ENV_RELOC /* * Some systems need to relocate the env_addr pointer early because the * location it points to will get invalidated before env_relocate is * called. One example is on systems that might use a L2 or L3 cache * in SRAM mode and initialize that cache from SRAM mode back to being * a cache in cpu_init_r. */ gd->env_addr += gd->relocaddr - CONFIG_SYS_MONITOR_BASE; #endif #ifdef CONFIG_OF_EMBED /* * The fdt_blob needs to be moved to new relocation address * incase of FDT blob is embedded with in image */ gd->fdt_blob += gd->reloc_off; #endif #ifdef CONFIG_EFI_LOADER efi_runtime_relocate(gd->relocaddr, NULL); #endif return 0; }
全局变量monitor_flash_len定义:
ulong monitor_flash_len;
3.5 initr_barrier(common/board_r.c)
static int initr_barrier(void) { #ifdef CONFIG_PPC /* TODO: Can we not use dmb() macros for this? */ asm("sync ; isync"); #endif return 0; }
3.6 initr_malloc(common/board_r.c)
static int initr_malloc(void) { ulong malloc_start; #ifdef CONFIG_SYS_MALLOC_F_LEN debug("Pre-reloc malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr, gd->malloc_ptr / 1024); #endif /* The malloc area is immediately below the monitor copy in DRAM */ malloc_start = gd->relocaddr - TOTAL_MALLOC_LEN; mem_malloc_init((ulong)map_sysmem(malloc_start, TOTAL_MALLOC_LEN), TOTAL_MALLOC_LEN); return 0; }
从board_init_f画出的内存图可知,u-boot重定位地址的下面就是预留的堆区。
设置malloc的起始地址,malloc_start设置为u-boot重定位后的地址-TOTAL_MALLOC_LEN,TOTAL_MALLOC_LEN之前有介绍4MB。
然后填充了三个全局变量并将堆区全部清零。
3.7 initr_console_record(common/board_r.c)
static int initr_console_record(void) { #if defined(CONFIG_CONSOLE_RECORD) return console_record_init(); #else return 0; #endif }
3.8 bootstage_relocate(common/bootstage.c)
int bootstage_relocate(void) { int i; /* * Duplicate all strings. They may point to an old location in the * program .text section that can eventually get trashed. */ for (i = 0; i < BOOTSTAGE_ID_COUNT; i++) if (record[i].name) record[i].name = strdup(record[i].name); return 0; }
3.9 initr_bootstage(common/board_r.c)
static int initr_bootstage(void) { /* We cannot do this before initr_dm() */ bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r"); return 0; }
3.10 board_init(board/samaung/smdk2410.c)
int board_init(void) { /* arch number of SMDK2410-Board */ gd->bd->bi_arch_number = MACH_TYPE_SMDK2410; /* adress of boot parameters */ gd->bd->bi_boot_params = 0x30000100; icache_enable(); dcache_enable(); return 0; }
gd->bd->bi_arch_number修改成SMDK2410的机器码,启动linux需要的,但实际测试,这个就算不设置也能够启动,但我们还是将其添加上(可在arch/arm/include/asm/mach-types.h中找到。
#define MACH_TYPE_SMDK2410 193
然后设置gd->bd->bi_boot_params,从0x30000100地址开始存放启动参数,内核启动时会从这里取出参数。
3.11 stdio_init_tables(common/sdtio.c)
int stdio_init_tables(void) { #if defined(CONFIG_NEEDS_MANUAL_RELOC) /* already relocated for current ARM implementation */ ulong relocation_offset = gd->reloc_off; int i; /* relocate device name pointers */ for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) { stdio_names[i] = (char *) (((ulong) stdio_names[i]) + relocation_offset); } #endif /* CONFIG_NEEDS_MANUAL_RELOC */ /* Initialize the list */ INIT_LIST_HEAD(&(devs.list)); return 0; }
初始化了一个双向循环链表:
static inline void INIT_LIST_HEAD(struct list_head *list) { list->next = list; list->prev = list; }
3.12 initr_serial(common/board_r.c)
static int initr_serial(void) { serial_initialize(); return 0; }
串口初始化,serial_initialize定义在drivers/serial/serial.c文件:
/** * serial_initialize() - Register all compiled-in serial port drivers * * This function registers all serial port drivers that are compiled * into the U-Boot binary with the serial core, thus making them * available to U-Boot to use. Lastly, this function assigns a default * serial port to the serial core. That serial port is then used as a * default output. */ void serial_initialize(void) { amirix_serial_initialize(); arc_serial_initialize(); arm_dcc_initialize(); asc_serial_initialize(); atmel_serial_initialize(); au1x00_serial_initialize(); bfin_jtag_initialize(); bfin_serial_initialize(); bmw_serial_initialize(); clps7111_serial_initialize(); cogent_serial_initialize(); cpci750_serial_initialize(); evb64260_serial_initialize(); imx_serial_initialize(); iop480_serial_initialize(); jz_serial_initialize(); leon2_serial_initialize(); leon3_serial_initialize(); lh7a40x_serial_initialize(); lpc32xx_serial_initialize(); marvell_serial_initialize(); max3100_serial_initialize(); mcf_serial_initialize(); ml2_serial_initialize(); mpc512x_serial_initialize(); mpc5xx_serial_initialize(); mpc8260_scc_serial_initialize(); mpc8260_smc_serial_initialize(); mpc85xx_serial_initialize(); mpc8xx_serial_initialize(); mxc_serial_initialize(); mxs_auart_initialize(); ns16550_serial_initialize(); oc_serial_initialize(); p3mx_serial_initialize(); pl01x_serial_initialize(); pxa_serial_initialize(); s3c24xx_serial_initialize(); s5p_serial_initialize(); sa1100_serial_initialize(); sandbox_serial_initialize(); sconsole_serial_initialize(); sh_serial_initialize(); stm32_serial_initialize(); uartlite_serial_initialize(); zynq_serial_initialize(); serial_assign(default_serial_console()->name); }
3.13 initr_announce(common/board_r.c)
static int initr_announce(void) { debug("Now running in RAM - U-Boot at: %08lx\n", gd->relocaddr); return 0; }
3.14 power_init_board(common/board_r.c)
__weak int power_init_board(void) { return 0; }
3.15 initr_flash(common/board_r.c)
static int initr_flash(void) { ulong flash_size = 0; bd_t *bd = gd->bd; puts("Flash: "); if (board_flash_wp_on()) printf("Uninitialized - Write Protect On\n"); else flash_size = flash_init(); print_size(flash_size, ""); #ifdef CONFIG_SYS_FLASH_CHECKSUM /* * Compute and print flash CRC if flashchecksum is set to 'y' * * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX */ if (getenv_yesno("flashchecksum") == 1) { printf(" CRC: %08X", crc32(0, (const unsigned char *) CONFIG_SYS_FLASH_BASE, flash_size)); } #endif /* CONFIG_SYS_FLASH_CHECKSUM */ putc('\n'); /* update start of FLASH memory */ #ifdef CONFIG_SYS_FLASH_BASE bd->bi_flashstart = CONFIG_SYS_FLASH_BASE; #endif /* size of FLASH memory (final value) */ bd->bi_flashsize = flash_size; #if defined(CONFIG_SYS_UPDATE_FLASH_SIZE) /* Make a update of the Memctrl. */ update_flash_size(flash_size); #endif #if defined(CONFIG_OXC) || defined(CONFIG_RMU) /* flash mapped at end of memory map */ bd->bi_flashoffset = CONFIG_SYS_TEXT_BASE + flash_size; #elif CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE bd->bi_flashoffset = monitor_flash_len; /* reserved area for monitor */ #endif return 0; }
3.16 initr_nand(common/board_r.c)
static int initr_nand(void) { puts("NAND: "); nand_init(); return 0; }
初始化nand flash。
3.17 initr_env(common/board_r.c)
static int initr_env(void) { /* initialize environment */ if (should_load_env()) env_relocate(); else set_default_env(NULL); #ifdef CONFIG_OF_CONTROL setenv_addr("fdtcontroladdr", gd->fdt_blob); #endif /* Initialize from environment */ load_addr = getenv_ulong("loadaddr", 16, load_addr); #if defined(CONFIG_SYS_EXTBDINFO) #if defined(CONFIG_405GP) || defined(CONFIG_405EP) #if defined(CONFIG_I2CFAST) /* * set bi_iic_fast for linux taking environment variable * "i2cfast" into account */ { char *s = getenv("i2cfast"); if (s && ((*s == 'y') || (*s == 'Y'))) { gd->bd->bi_iic_fast[0] = 1; gd->bd->bi_iic_fast[1] = 1; } } #endif /* CONFIG_I2CFAST */ #endif /* CONFIG_405GP, CONFIG_405EP */ #endif /* CONFIG_SYS_EXTBDINFO */ return 0; }
3.18 initr_secondary_cpu(common/board_r.c)
static int initr_secondary_cpu(void) { /* * after non-volatile devices & environment is setup and cpu code have * another round to deal with any initialization that might require * full access to the environment or loading of some image (firmware) * from a non-volatile device */ /* TODO: maybe define this for all archs? */ cpu_secondary_init_r(); return 0; }
3.19 stdio_add_devices(common/sdtio.c)
int stdio_add_devices(void) { #ifdef CONFIG_DM_KEYBOARD struct udevice *dev; struct uclass *uc; int ret; /* * For now we probe all the devices here. At some point this should be * done only when the devices are required - e.g. we have a list of * input devices to start up in the stdin environment variable. That * work probably makes more sense when stdio itself is converted to * driver model. * * TODO(sjg@chromium.org): Convert changing uclass_first_device() etc. * to return the device even on error. Then we could use that here. */ ret = uclass_get(UCLASS_KEYBOARD, &uc); if (ret) return ret; /* Don't report errors to the caller - assume that they are non-fatal */ uclass_foreach_dev(dev, uc) { ret = device_probe(dev); if (ret) printf("Failed to probe keyboard '%s'\n", dev->name); } #endif #ifdef CONFIG_SYS_I2C i2c_init_all(); #else #if defined(CONFIG_HARD_I2C) i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); #endif #endif #ifdef CONFIG_DM_VIDEO struct udevice *vdev; # ifndef CONFIG_DM_KEYBOARD int ret; # endif for (ret = uclass_first_device(UCLASS_VIDEO, &vdev); vdev; ret = uclass_next_device(&vdev)) ; if (ret) printf("%s: Video device failed (ret=%d)\n", __func__, ret); #else # if defined(CONFIG_LCD) drv_lcd_init (); # endif # if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) drv_video_init (); # endif #endif /* CONFIG_DM_VIDEO */ #if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD) drv_keyboard_init (); #endif #ifdef CONFIG_LOGBUFFER drv_logbuff_init (); #endif drv_system_init (); serial_stdio_init (); #ifdef CONFIG_USB_TTY drv_usbtty_init (); #endif #ifdef CONFIG_NETCONSOLE drv_nc_init (); #endif #ifdef CONFIG_JTAG_CONSOLE drv_jtag_console_init (); #endif #ifdef CONFIG_CBMEM_CONSOLE cbmemc_init(); #endif return 0; }
3.20 initr_jumptable(common/board_r.c)
static int initr_jumptable(void) { jumptable_init(); return 0; }
3.21 console_init_r(common/sonsole.c)
int console_init_r(void) { struct stdio_dev *inputdev = NULL, *outputdev = NULL; int i; struct list_head *list = stdio_get_list(); struct list_head *pos; struct stdio_dev *dev; #ifdef CONFIG_SPLASH_SCREEN /* * suppress all output if splash screen is enabled and we have * a bmp to display. We redirect the output from frame buffer * console to serial console in this case or suppress it if * "silent" mode was requested. */ if (getenv("splashimage") != NULL) { if (!(gd->flags & GD_FLG_SILENT)) outputdev = search_device (DEV_FLAGS_OUTPUT, "serial"); } #endif /* Scan devices looking for input and output devices */ list_for_each(pos, list) { dev = list_entry(pos, struct stdio_dev, list); if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) { inputdev = dev; } if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) { outputdev = dev; } if(inputdev && outputdev) break; } /* Initializes output console first */ if (outputdev != NULL) { console_setfile(stdout, outputdev); console_setfile(stderr, outputdev); #ifdef CONFIG_CONSOLE_MUX console_devices[stdout][0] = outputdev; console_devices[stderr][0] = outputdev; #endif } /* Initializes input console */ if (inputdev != NULL) { console_setfile(stdin, inputdev); #ifdef CONFIG_CONSOLE_MUX console_devices[stdin][0] = inputdev; #endif } #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET stdio_print_current_devices(); #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ /* Setting environment variables */ for (i = 0; i < 3; i++) { setenv(stdio_names[i], stdio_devices[i]->name); } gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ #if 0 /* If nothing usable installed, use only the initial console */ if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) return 0; #endif print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL); return 0; }
3.22 interrupt_init(arch/arm/lib/interrupts.c)
int interrupt_init(void) { return 0; }
3.23 initr_enable_interrupts(common/board_r.c)
static int initr_enable_interrupts(void) { enable_interrupts(); return 0; }
3.24 initr_ethaddr(common/board_r.c)
static int initr_ethaddr(void) { bd_t *bd = gd->bd; /* kept around for legacy kernels only ... ignore the next section */ eth_getenv_enetaddr("ethaddr", bd->bi_enetaddr); #ifdef CONFIG_HAS_ETH1 eth_getenv_enetaddr("eth1addr", bd->bi_enet1addr); #endif #ifdef CONFIG_HAS_ETH2 eth_getenv_enetaddr("eth2addr", bd->bi_enet2addr); #endif #ifdef CONFIG_HAS_ETH3 eth_getenv_enetaddr("eth3addr", bd->bi_enet3addr); #endif #ifdef CONFIG_HAS_ETH4 eth_getenv_enetaddr("eth4addr", bd->bi_enet4addr); #endif #ifdef CONFIG_HAS_ETH5 eth_getenv_enetaddr("eth5addr", bd->bi_enet5addr); #endif return 0; }
3.25 initr_net(common/board_r.c)
static int initr_net(void) { puts("Net: "); eth_initialize(); #if defined(CONFIG_RESET_PHY_R) debug("Reset Ethernet PHY\n"); reset_phy(); #endif return 0; }
3.26 run_main_loop
到此,board_init_r也就分析完了,最后就是进入u-boot的大循环run_main_loop了,这个里面就是启动内核或者处理用户输入的命令,这部分后面再详细分析一下。
参考文章:
[1]u-boot2020.04移植(6、board_init_r)
[2]