本文共 4861 字,大约阅读时间需要 16 分钟。
Xloader是在rom code和uboot之间的一个小的BootLoader,其启动分析如下:从下面lds文件中可以看到xloader的入口函数x-loader/board/omap1710h3/x-load.ldsOUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{ . = 0x00000000; . = ALIGN(4); .text : { cpu/arm926ejs/start.o (.text) *(.text) } . = ALIGN(4); .rodata : { *(.rodata) } . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); .got : { *(.got) } . = ALIGN(4); __bss_start = .; .bss : { *(.bss) } _end = .;}其中start.s的分析如下:入口函数首先执行resetreset: /* * set the cpu to SVC32 mode */ mrs r0,cpsr bic r0,r0,#0x1f orr r0,r0,#0xd3 msr cpsr,r0 #关掉watchdog /* * turn off the watchdog, unlock/diable sequence */ mov r1, #0xF5 ldr r0, =WDTIM_MODE strh r1, [r0] mov r1, #0xA0 strh r1, [r0] /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =REG_IHL1_MIR str r1, [r0] ldr r0, =REG_IHL2_MIR str r1, [r0] /* * we do sys-critical inits at reboot, */ bl cpu_init_crit /* * relocate exception vectors to SRAM where ROM code expects */#ifdef CFG_BOOT_CS0 adr r0, _start /* r0 <- current position of code */ add r0, r0, #4 /* skip reset vector */ mov r2, #36 /* r2 <- size of data (8+1 words) */ add r2, r0, r2 /* r2 <- source end address */ mov r1, #0x20000000next: ldmia r0!, {r3-r10} /* copy from source address [r0] */ stmia r1!, {r3-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end address [r2] */ ble next#endif #执行重定位relocate: /* relocate X-Loader to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ /*beq stack_setup*/ ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ add r2, r0, r2 /* r2 <- source end address */ /* Set up the stack */stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated X-Loader */ sub sp, r0, #128 /* leave 32 words for abort-stack */#清bssclear_bss: ldr r0, _bss_start /* find start of bss segment */ add r0, r0, #4 /* start at first byte of bss */ ldr r1, _bss_end /* stop here */ mov r2, #0x00000000 /* clear */clbss_l:str r2, [r0] /* clear loop... */ add r0, r0, #4 cmp r0, r1 bne clbss_l#最终执行c的函数_start_armboot ldr pc, _start_armboot_start_armboot: .word start_armboot其中_start_armboot 函数实现如下:lib/board.c:105:void start_armboot (void)void start_armboot (void){ init_fnc_t **init_fnc_ptr; int i; uchar *buf; char boot_dev_name[8]; u32 boot_device = 0; #首先初始化一些信息 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { hang (); } }#ifdef START_LOADB_DOWNLOAD strcpy(boot_dev_name, "UART"); do_load_serial_bin (CFG_LOADADDR, 115200);#else#从寄存器中得到当前是从nand/emmc/sd 等device boot /* Read boot device from saved scratch pad */ boot_device = __raw_readl(0x480029c0) & 0xff; buf = (uchar*) CFG_LOADADDR; switch(boot_device) { case 0x03: strcpy(boot_dev_name, "ONENAND");#if defined(CFG_ONENAND) for (i = ONENAND_START_BLOCK; i < ONENAND_END_BLOCK; i++) { if (!onenand_read_block(buf, i)) buf += ONENAND_BLOCK_SIZE; else goto error; }#endif break; case 0x02: default: strcpy(boot_dev_name, "NAND");#if defined(CFG_NAND) for (i = NAND_UBOOT_START; i < NAND_UBOOT_END; i+= NAND_BLOCK_SIZE) { if (!nand_read_block(buf, i)) buf += NAND_BLOCK_SIZE; /* advance buf ptr */ }#endif break;#加入我们从mmc中boot的话,这里会将uboot 从emmc 中读取到dram中 case 0x05: strcpy(boot_dev_name, "EMMC");#if defined(CONFIG_MMC) if (mmc_read_bootloader(1, 0) != 0) goto error;#else goto error;#endif break; case 0x06: strcpy(boot_dev_name, "MMC/SD1");#if defined(CONFIG_MMC) && defined(CFG_CMD_FAT) if (mmc_read_bootloader(0, 1) != 0) goto error;#else goto error;#endif break; };#endif#开始跳入到uboot中执行,正常情况下后面的code 都不会执行 /* go run U-Boot and never return */ printf("Starting OS Bootloader from %s ...\n", boot_dev_name); ((init_fnc_t *)CFG_LOADADDR)(); /* should never come here */#if defined(CFG_ONENAND) || defined(CONFIG_MMC)error:#endif#如果失败的话,则挂载这里 printf("Could not read bootloader!\n"); hang();}其中从emmc中读取uboot的code如下:int mmc_read_bootloader(int dev, int part){ long size; unsigned long offset = CFG_LOADADDR; block_dev_desc_t *dev_desc = NULL; unsigned char ret = 0;#首先初始化emmc 控制器 ret = mmc_init(dev); if (ret != 0){ printf("\n MMC init failed \n"); return -1; }#然后从emmc中读取uboot if (part) { /* FAT Read for extenal SD card */ dev_desc = mmc_get_dev(dev); size = file_fat_read("u-boot.bin", (unsigned char *)offset, 0); if (size == -1) return -1; } else { /* RAW read for EMMC */ ret = mmc_read(dev, 0x400, (unsigned char *)offset, 0x60000); if (ret != 1) return -1; } return 0;}
转载地址:http://tcnmi.baihongyu.com/