标签:
uboot第二阶段应该做什么?
uboot的第二阶段就是要初始化剩下的还没被初始化的硬件,主要是SOC外部硬件(譬如inand、网卡芯片)、uboot本身的一些东西(uboot的命令、环境变量等),然后最终初始化完必要的东西后进入uboot的命令行准备接受命令。
uboot第二阶段完结于何处?
uboot启动后自动运行打印出很多信息,这些信息就是uboot第一和第二阶段不断进行初始化时,打印出来的信息,然后uboot进入了bootdelay然后执行bootcmd对应的启动命令,如果这时候用户不干涉,会执行bootcmd进入自动启动内核的流程了。(uboot的生命周期就结束了);所以uboot完结于命令行下,读取命令,解析命令,执行命令。命令行死循环是uboot的最终归宿
void start_armboot (void) { init_fnc_t **init_fnc_ptr; char *s; int mmc_exist = 0; #if !defined(CFG_NO_FLASH) || defined (CONFIG_VFD) || defined(CONFIG_LCD) ulong size; #endif #if defined(CONFIG_VFD) || defined(CONFIG_LCD) unsigned long addr; #endif #if defined(CONFIG_BOOT_MOVINAND) uint *magic = (uint *) (PHYS_SDRAM_1); #endif /* Pointer is writable since we allocated a register for it */ #ifdef CONFIG_MEMORY_UPPER_CODE /* by scsuh */ ulong gd_base; gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t); #ifdef CONFIG_USE_IRQ gd_base -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ); #endif gd = (gd_t*)gd_base; #else gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); #endif /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory"); memset ((void*)gd, 0, sizeof (gd_t)); gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); memset (gd->bd, 0, sizeof (bd_t)); monitor_flash_len = _bss_start - _armboot_start; for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { hang (); } } #ifndef CFG_NO_FLASH /* configure available FLASH banks */ size = flash_init (); display_flash_config (size); #endif /* CFG_NO_FLASH */ #ifdef CONFIG_VFD # ifndef PAGE_SIZE # define PAGE_SIZE 4096 # endif /* * reserve memory for VFD display (always full pages) */ /* bss_end is defined in the board-specific linker script */ addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); size = vfd_setmem (addr); gd->fb_base = addr; #endif /* CONFIG_VFD */ #ifdef CONFIG_LCD /* board init may have inited fb_base */ if (!gd->fb_base) { # ifndef PAGE_SIZE # define PAGE_SIZE 4096 # endif /* * reserve memory for LCD display (always full pages) */ /* bss_end is defined in the board-specific linker script */ addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); size = lcd_setmem (addr); gd->fb_base = addr; } #endif /* CONFIG_LCD */ /* armboot_start is defined in the board-specific linker script */ #ifdef CONFIG_MEMORY_UPPER_CODE /* by scsuh */ mem_malloc_init (CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE); #else mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); #endif //******************************// // Board Specific // #if defined(CONFIG_SMDKXXXX) //******************************// #if defined(CONFIG_SMDK6410) #if defined(CONFIG_GENERIC_MMC) puts ("SD/MMC: "); mmc_exist = mmc_initialize(gd->bd); if (mmc_exist != 0) { puts ("0 MB\n"); } #else #if defined(CONFIG_MMC) puts("SD/MMC: "); if (INF_REG3_REG == 0) movi_ch = 0; else movi_ch = 1; movi_set_capacity(); movi_init(); movi_set_ofs(MOVI_TOTAL_BLKCNT); #endif #endif if (INF_REG3_REG == BOOT_ONENAND) { #if defined(CONFIG_CMD_ONENAND) puts("OneNAND: "); onenand_init(); #endif /*setenv("bootcmd", "onenand read c0008000 80000 380000;bootm c0008000");*/ } else { puts("NAND: "); nand_init(); if (INF_REG3_REG == 0 || INF_REG3_REG == 7) setenv("bootcmd", "movi read kernel c0008000;movi read rootfs c0800000;bootm c0008000"); else setenv("bootcmd", "nand read c0008000 80000 380000;bootm c0008000"); } #endif /* CONFIG_SMDK6410 */ #if defined(CONFIG_SMDKC100) #if defined(CONFIG_GENERIC_MMC) puts ("SD/MMC: "); mmc_exist = mmc_initialize(gd->bd); if (mmc_exist != 0) { puts ("0 MB\n"); } #endif #if defined(CONFIG_CMD_ONENAND) puts("OneNAND: "); onenand_init(); #endif #if defined(CONFIG_CMD_NAND) puts("NAND: "); nand_init(); #endif #endif /* CONFIG_SMDKC100 */ #if defined(CONFIG_X210) #if defined(CONFIG_GENERIC_MMC) puts ("SD/MMC: "); mmc_exist = mmc_initialize(gd->bd); if (mmc_exist != 0) { puts ("0 MB\n"); #ifdef CONFIG_CHECK_X210CV3 check_flash_flag=0;//check inand error! #endif } #ifdef CONFIG_CHECK_X210CV3 else { check_flash_flag=1;//check inand ok! } #endif #endif #if defined(CONFIG_MTD_ONENAND) puts("OneNAND: "); onenand_init(); /*setenv("bootcmd", "onenand read c0008000 80000 380000;bootm c0008000");*/ #else //puts("OneNAND: (FSR layer enabled)\n"); #endif #if defined(CONFIG_CMD_NAND) puts("NAND: "); nand_init(); #endif #endif /* CONFIG_X210 */ #if defined(CONFIG_SMDK6440) #if defined(CONFIG_GENERIC_MMC) puts ("SD/MMC: "); mmc_exist = mmc_initialize(gd->bd); if (mmc_exist != 0) { puts ("0 MB\n"); } #else #if defined(CONFIG_MMC) if (INF_REG3_REG == 1) { /* eMMC_4.3 */ puts("eMMC: "); movi_ch = 1; movi_emmc = 1; movi_init(); movi_set_ofs(0); } else if (INF_REG3_REG == 7 || INF_REG3_REG == 0) { /* SD/MMC */ if (INF_REG3_REG & 0x1) movi_ch = 1; else movi_ch = 0; puts("SD/MMC: "); movi_set_capacity(); movi_init(); movi_set_ofs(MOVI_TOTAL_BLKCNT); } else { } #endif #endif if (INF_REG3_REG == 2) { /* N/A */ } else { puts("NAND: "); nand_init(); //setenv("bootcmd", "nand read c0008000 80000 380000;bootm c0008000"); } #endif /* CONFIG_SMDK6440 */ #if defined(CONFIG_SMDK6430) #if defined(CONFIG_GENERIC_MMC) puts ("SD/MMC: "); mmc_exist = mmc_initialize(gd->bd); if (mmc_exist != 0) { puts ("0 MB\n"); } #else #if defined(CONFIG_MMC) puts("SD/MMC: "); if (INF_REG3_REG == 0) movi_ch = 0; else movi_ch = 1; movi_set_capacity(); movi_init(); movi_set_ofs(MOVI_TOTAL_BLKCNT); #endif #endif if (INF_REG3_REG == BOOT_ONENAND) { #if defined(CONFIG_CMD_ONENAND) puts("OneNAND: "); onenand_init(); #endif /*setenv("bootcmd", "onenand read c0008000 80000 380000;bootm c0008000");*/ } else if (INF_REG3_REG == BOOT_NAND) { puts("NAND: "); nand_init(); } else { } if (INF_REG3_REG == 0 || INF_REG3_REG == 7) setenv("bootcmd", "movi read kernel c0008000;movi read rootfs c0800000;bootm c0008000"); else setenv("bootcmd", "nand read c0008000 80000 380000;bootm c0008000"); #endif /* CONFIG_SMDK6430 */ #if defined(CONFIG_SMDK6442) #if defined(CONFIG_GENERIC_MMC) puts ("SD/MMC: "); mmc_exist = mmc_initialize(gd->bd); if (mmc_exist != 0) { puts ("0 MB\n"); } #else #if defined(CONFIG_MMC) puts("SD/MMC: "); movi_set_capacity(); movi_init(); movi_set_ofs(MOVI_TOTAL_BLKCNT); #endif #endif #if defined(CONFIG_CMD_ONENAND) if (INF_REG3_REG == BOOT_ONENAND) { puts("OneNAND: "); onenand_init(); } #endif #endif /* CONFIG_SMDK6442 */ #if defined(CONFIG_SMDK2416) || defined(CONFIG_SMDK2450) #if defined(CONFIG_NAND) puts("NAND: "); nand_init(); #endif #if defined(CONFIG_ONENAND) puts("OneNAND: "); onenand_init(); #endif #if defined(CONFIG_BOOT_MOVINAND) puts("SD/MMC: "); if ((0x24564236 == magic[0]) && (0x20764316 == magic[1])) { printf("Boot up for burning\n"); } else { movi_init(); movi_set_ofs(MOVI_TOTAL_BLKCNT); } #endif #endif /* CONFIG_SMDK2416 CONFIG_SMDK2450 */ #ifdef CONFIG_HAS_DATAFLASH AT91F_DataflashInit(); dataflash_print_info(); #endif /* initialize environment */ env_relocate (); #ifdef CONFIG_VFD /* must do this after the framebuffer is allocated */ drv_vfd_init(); #endif /* CONFIG_VFD */ #ifdef CONFIG_SERIAL_MULTI serial_initialize(); #endif /* IP Address */ gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); /* MAC Address */ { int i; ulong reg; char *s, *e; char tmp[64]; i = getenv_r ("ethaddr", tmp, sizeof (tmp)); s = (i > 0) ? tmp : NULL; for (reg = 0; reg < 6; ++reg) { gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0; if (s) s = (*e) ? e + 1 : e; } #ifdef CONFIG_HAS_ETH1 i = getenv_r ("eth1addr", tmp, sizeof (tmp)); s = (i > 0) ? tmp : NULL; for (reg = 0; reg < 6; ++reg) { gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0; if (s) s = (*e) ? e + 1 : e; } #endif } devices_init (); /* get the devices list going. */ #ifdef CONFIG_CMC_PU2 load_sernum_ethaddr (); #endif /* CONFIG_CMC_PU2 */ jumptable_init (); #if !defined(CONFIG_SMDK6442) console_init_r (); /* fully init console as a device */ #endif #if defined(CONFIG_MISC_INIT_R) /* miscellaneous platform dependent initialisations */ misc_init_r (); #endif /* enable exceptions */ enable_interrupts (); /* Perform network card initialisation if necessary */ #ifdef CONFIG_DRIVER_TI_EMAC extern void dm644x_eth_set_mac_addr (const u_int8_t *addr); if (getenv ("ethaddr")) { dm644x_eth_set_mac_addr(gd->bd->bi_enetaddr); } #endif #ifdef CONFIG_DRIVER_CS8900 cs8900_get_enetaddr (gd->bd->bi_enetaddr); #endif #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96) if (getenv ("ethaddr")) { smc_set_mac_addr(gd->bd->bi_enetaddr); } #endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */ /* Initialize from environment */ if ((s = getenv ("loadaddr")) != NULL) { load_addr = simple_strtoul (s, NULL, 16); } #if defined(CONFIG_CMD_NET) if ((s = getenv ("bootfile")) != NULL) { copy_filename (BootFile, s, sizeof (BootFile)); } #endif #ifdef BOARD_LATE_INIT board_late_init (); #endif #if defined(CONFIG_CMD_NET) #if defined(CONFIG_NET_MULTI) puts ("Net: "); #endif eth_initialize(gd->bd); #if defined(CONFIG_RESET_PHY_R) debug ("Reset Ethernet PHY\n"); reset_phy(); #endif #endif #if defined(CONFIG_CMD_IDE) puts("IDE: "); ide_init(); #endif /****************lxg added**************/ #ifdef CONFIG_MPAD extern int x210_preboot_init(void); x210_preboot_init(); #endif /****************end**********************/ /* check menukey to update from sd */ extern void update_all(void); if(check_menu_update_from_sd()==0)//update mode { puts ("[LEFT DOWN] update mode\n"); run_command("fdisk -c 0",0); update_all(); } else puts ("[LEFT UP] boot mode\n"); /* main_loop() can return to retry autoboot, if so just run it again. */ for (;;) { main_loop (); } /* NOTREACHED - no way out of command loop except booting */ }
start_armboot分析(uboot\uboot_jiuding\uboot\lib_arm 444行):
① init_fnc_t **init_fnc_ptr;
解析:
typedef int (init_fnc_t) (void);
这是一个函数类型,init_fnc_ptr就是一个二重函数指针,这里是用来指向一个函数指针数组。
这个文件开头有一个宏: DECLARE_GLOBAL_DATA_PTR;
跳到定义处:
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
定义了一个全局变量gd,这个变量是一个指针类型,占四个字节,用volatile和register修饰,后面asm ("r8"),是gcc支持的;把gd放到r8中;
将这些全局变量定义成结构体gd,然后放到寄存器中,定义为register变量完全是为了访问效率的提高。
gd_t定义在include/asm-arm
typedef struct global_data { bd_t *bd; unsigned long flags; unsigned long baudrate; unsigned long have_console; /* serial_init() was called */ unsigned long reloc_off; /* Relocation Offset */ unsigned long env_addr; /* Address of Environment struct */ unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long fb_base; /* base address of frame buffer */ #ifdef CONFIG_VFD unsigned char vfd_type; /* display type */ #endif void **jt; /* jump table */ } gd_t; /* * Global Data 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 DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
#ifndef _U_BOOT_H_ #define _U_BOOT_H_ 1 typedef struct bd_info { int bi_baudrate; /* serial console baudrate */ unsigned long bi_ip_addr; /* IP Address */ unsigned char bi_enetaddr[6]; /* Ethernet adress */ struct environment_s *bi_env; ulong bi_arch_number; /* unique id for this board */ ulong bi_boot_params; /* where this board expects params */ struct /* RAM configuration */ { ulong start; ulong size; } bi_dram[CONFIG_NR_DRAM_BANKS]; #ifdef CONFIG_HAS_ETH1 /* second onboard ethernet port */ unsigned char bi_enet1addr[6]; #endif } bd_t; #define bi_env_data bi_env->data #define bi_env_crc bi_env->crc #endif /* _U_BOOT_H_ */
标签:
原文地址:http://www.cnblogs.com/yr-linux/p/5477103.html