xloader启动流程

Xloader是在rom code和uboot之间的一个小的BootLoader,其启动分析如下:
从下面lds文件中可以看到xloader的入口函数
x-loader/board/omap1710h3/x-load.lds

OUTPUT_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的分析如下:
入口函数首先执行reset
reset:
	/*
	 * 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, #0x20000000
next:
	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    */
#清bss
clear_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;
}

你可能感兴趣的:(xloader)