本着学习交流的原则, 将个人移植u-boot的过程做一个记录. 文章参考了csdn blog里面的很多内容, 有的已经记不得出处了, 只好把当时的摘要直接贴出来. 如果冒犯, 还请见谅. 如有侵权, 请与我邮件联系. 谢谢!
all: $(ALL-y) $(SUBDIR_EXAMPLES)
# Always append ALL so that arch config.mk's can add custom ones
ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map
ALL-$(CONFIG_NAND_U_BOOT) += $(obj)u-boot-nand.bin
ALL-$(CONFIG_ONENAND_U_BOOT) += $(obj)u-boot-onenand.bin
ALL-$(CONFIG_SPL) += $(obj)spl/u-boot-spl.bin
ALL-$(CONFIG_SPL_FRAMEWORK) += $(obj)u-boot.img
ALL-$(CONFIG_TPL) += $(obj)tpl/u-boot-tpl.bin
ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb $(obj)u-boot-dtb.bin
ifneq ($(CONFIG_SPL_TARGET),)
ALL-$(CONFIG_SPL) += $(obj)$(subst ",,$(CONFIG_SPL_TARGET))
endif
# enable combined SPL/u-boot/dtb rules for tegra
ifneq ($(CONFIG_TEGRA),)
ifeq ($(CONFIG_OF_SEPARATE),y)
ALL-y += $(obj)u-boot-dtb-tegra.bin
else
ALL-y += $(obj)u-boot-nodtb-tegra.bin
endif
endif
$(obj)u-boot.srec: $(obj)u-boot $(OBJCOPY) -O srec $< $@ $(obj)u-boot.bin: $(obj)u-boot $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ $(BOARD_SIZE_CHECK)它们都依赖于u-boot
ifeq ($(CONFIG_SANDBOX),y) GEN_UBOOT = \ cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds \ -Wl,--start-group $(__LIBS) -Wl,--end-group \ $(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map -o u-boot else GEN_UBOOT = \ cd $(LNDIR) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \ $(__OBJS) \ --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \ -Map u-boot.map -o u-boot endif $(obj)u-boot: depend \ $(SUBDIR_TOOLS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds $(GEN_UBOOT)
# If board code explicitly specified LDSCRIPT or CONFIG_SYS_LDSCRIPT, use # that (or fail if absent). Otherwise, search for a linker script in a # standard location. LDSCRIPT_MAKEFILE_DIR = $(dir $(LDSCRIPT)) ifndef LDSCRIPT #LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug ifdef CONFIG_SYS_LDSCRIPT # need to strip off double quotes LDSCRIPT := $(subst ",,$(CONFIG_SYS_LDSCRIPT)) endif endif # If there is no specified link script, we look in a number of places for it ifndef LDSCRIPT ifeq ($(CONFIG_NAND_U_BOOT),y) LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds ifeq ($(wildcard $(LDSCRIPT)),) LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot-nand.lds endif endif ifeq ($(wildcard $(LDSCRIPT)),) LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds endif ifeq ($(wildcard $(LDSCRIPT)),) LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot.lds endif ifeq ($(wildcard $(LDSCRIPT)),) LDSCRIPT := $(TOPDIR)/arch/$(ARCH)/cpu/u-boot.lds # We don't expect a Makefile here LDSCRIPT_MAKEFILE_DIR = endif ifeq ($(wildcard $(LDSCRIPT)),) $(error could not find linker script) endif endif
ENTRY(_main) /* * Set up initial C runtime environment and call board_init_f(0). */ #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) ldr sp, =(CONFIG_SPL_STACK) #else ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) #endif bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ sub sp, #GD_SIZE /* allocate one GD above SP */ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ mov r9, sp /* GD is above SP */ mov r0, #0 bl board_init_f
#if ! defined(CONFIG_SPL_BUILD) /* * Set up intermediate environment (new sp and gd) and call * relocate_code(addr_moni). Trick here is that we'll return * 'here' but relocated. */ ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ ldr r9, [r9, #GD_BD] /* r9 = gd->bd */ sub r9, r9, #GD_SIZE /* new GD is below bd */ adr lr, here ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */ add lr, lr, r0 ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ b relocate_code here: /* Set up final (full) environment */ bl c_runtime_cpu_setup /* we still call old routine here */ ldr r0, =__bss_start /* this is auto-relocated! */ ldr r1, =__bss_end /* this is auto-relocated! */ mov r2, #0x00000000 /* prepare zero to clear BSS */ clbss_l:cmp r0, r1 /* while not at end of BSS */ strlo r2, [r0] /* clear 32-bit BSS word */ addlo r0, r0, #4 /* move to next */ blo clbss_l bl coloured_LED_init bl red_led_on /* call board_init_r(gd_t *id, ulong dest_addr) */ mov r0, r9 /* gd_t */ ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */ /* call board_init_r */ ldr pc, =board_init_r /* this is auto-relocated! */ /* we should not return here. */ #endif
memset((void *)gd, 0, sizeof(gd_t));
#ifdef CONFIG_OF_EMBED /* Get a pointer to the FDT */ gd->fdt_blob = _binary_dt_dtb_start; #elif defined CONFIG_OF_SEPARATE /* FDT is at end of image */ gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE); #endif /* Allow the early environment to override the fdt address */ gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, (uintptr_t)gd->fdt_blob);
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { hang (); } }
#ifdef CONFIG_OF_CONTROL /* For now, put this check after the console is ready */ if (fdtdec_prepare_fdt()) { panic("** CONFIG_OF_CONTROL defined but no FDT - please see " "doc/README.fdt-control"); } #endif
#if defined(CONFIG_SYS_MEM_TOP_HIDE) /* * Subtract specified amount of memory to hide so that it won't * get "touched" at all by U-Boot. By fixing up gd->ram_size * the Linux kernel should now get passed the now "corrected" * memory size and won't touch it either. This should work * for arch/ppc and arch/powerpc. Only Linux board ports in * arch/powerpc with bootwrapper support, that recalculate the * memory size from the SDRAM controller setup will have to * get fixed. */ gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE; #endif
addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size; #ifdef CONFIG_LOGBUFFER #ifndef CONFIG_ALT_LB_ADDR /* reserve kernel log buffer */ addr -= (LOGBUFF_RESERVE); debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr); #endif #endif #ifdef CONFIG_PRAM /* * reserve protected RAM */ reg = getenv_ulong("pram", 10, CONFIG_PRAM); addr -= (reg << 10); /* size is in kB */ debug("Reserving %ldk for protected RAM at %08lx\n", reg, addr); #endif /* CONFIG_PRAM */ #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) /* reserve TLB table */ gd->arch.tlb_size = 4096 * 4; addr -= gd->arch.tlb_size; /* round down to next 64 kB limit */ addr &= ~(0x10000 - 1); gd->arch.tlb_addr = addr; debug("TLB table from %08lx to %08lx\n", addr, addr + gd->arch.tlb_size); #endif /* round down to next 4 kB limit */ addr &= ~(4096 - 1); debug("Top of RAM usable for U-Boot at: %08lx\n", addr); #ifdef CONFIG_LCD #ifdef CONFIG_FB_ADDR gd->fb_base = CONFIG_FB_ADDR; #else /* reserve memory for LCD display (always full pages) */ addr = lcd_setmem(addr); gd->fb_base = addr; #endif /* CONFIG_FB_ADDR */ #endif /* CONFIG_LCD */ /* * reserve memory for U-Boot code, data & bss * round down to next 4 kB limit */ addr -= gd->mon_len; addr &= ~(4096 - 1); debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr); #ifndef CONFIG_SPL_BUILD /* * reserve memory for malloc() arena */ addr_sp = addr - TOTAL_MALLOC_LEN; debug("Reserving %dk for malloc() at: %08lx\n", TOTAL_MALLOC_LEN >> 10, addr_sp); /* * (permanently) allocate a Board Info struct * and a permanent copy of the "global" data */ addr_sp -= sizeof (bd_t); bd = (bd_t *) addr_sp; gd->bd = bd; debug("Reserving %zu Bytes for Board Info at: %08lx\n", sizeof (bd_t), addr_sp); #ifdef CONFIG_MACH_TYPE gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */ #endif addr_sp -= sizeof (gd_t); id = (gd_t *) addr_sp; debug("Reserving %zu Bytes for Global Data at: %08lx\n", sizeof (gd_t), addr_sp); #if defined(CONFIG_OF_SEPARATE) && defined(CONFIG_OF_CONTROL) /* * If the device tree is sitting immediate above our image then we * must relocate it. If it is embedded in the data section, then it * will be relocated with other data. */ if (gd->fdt_blob) { fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32); addr_sp -= fdt_size; new_fdt = (void *)addr_sp; debug("Reserving %zu Bytes for FDT at: %08lx\n", fdt_size, addr_sp); } #endif /* setup stackpointer for exeptions */ gd->irq_sp = addr_sp; #ifdef CONFIG_USE_IRQ addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ); debug("Reserving %zu Bytes for IRQ stack at: %08lx\n", CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp); #endif /* leave 3 words for abort-stack */ addr_sp -= 12; /* 8-byte alignment for ABI compliance */ addr_sp &= ~0x07; #else addr_sp += 128; /* leave 32 words for abort-stack */ gd->irq_sp = addr_sp; #endif interrupt_init(); debug("New Stack Pointer is: %08lx\n", addr_sp); #ifdef CONFIG_POST post_bootmode_init(); post_run(NULL, POST_ROM | post_bootmode_get(0)); #endif gd->bd->bi_baudrate = gd->baudrate; /* Ram ist board specific, so move it to board code ... */ dram_init_banksize(); display_dram_config(); /* and display it */ gd->relocaddr = addr; gd->start_addr_sp = addr_sp; gd->reloc_off = addr - _TEXT_BASE; debug("relocation Offset is: %08lx\n", gd->reloc_off); if (new_fdt) { memcpy(new_fdt, gd->fdt_blob, fdt_size); gd->fdt_blob = new_fdt; } memcpy(id, (void *)gd, sizeof(gd_t));
init_fnc_t *init_sequence[] = { arch_cpu_init, /* basic arch cpu dependent setup */ mark_bootstage, #ifdef CONFIG_OF_CONTROL fdtdec_check_fdt, #endif #if defined(CONFIG_BOARD_EARLY_INIT_F) board_early_init_f, #endif timer_init, /* initialize timer */ #ifdef CONFIG_BOARD_POSTCLK_INIT board_postclk_init, #endif #ifdef CONFIG_FSL_ESDHC get_clocks, #endif env_init, /* initialize environment */ init_baudrate, /* initialze baudrate settings */ serial_init, /* serial communications setup */ console_init_f, /* stage 1 init of console */ display_banner, /* say that we are here */ #if defined(CONFIG_DISPLAY_CPUINFO) print_cpuinfo, /* display cpu info (and speed) */ #endif #if defined(CONFIG_DISPLAY_BOARDINFO) checkboard, /* display board info */ #endif #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C) init_func_i2c, #endif dram_init, /* configure available RAM banks */ NULL, };
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
board_init(); /* Setup chipselects */
serial_initialize();
/* The Malloc area is immediately below the monitor copy in DRAM */ malloc_start = dest_addr - TOTAL_MALLOC_LEN; mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
power_init_board();
nand_init();
mmc_initialize
env_relocate
stdio_init
jumptable_init
console_init_r(); /* fully init console as a device */
#ifdef CONFIG_BOARD_LATE_INIT board_late_init(); #endif
#if defined(CONFIG_CMD_NET) puts("Net: "); eth_initialize(gd->bd); #if defined(CONFIG_RESET_PHY_R) debug("Reset Ethernet PHY\n"); reset_phy(); #endif #endif
for (;;) { main_loop(); }