Ubooti启动文件解析
start.S
#include <config.h>
#include <version.h>
#if defined(CONFIG_OMAP1610)
#include <./configs/omap1510.h>
#elif defined(CONFIG_OMAP730)
#include <./configs/omap730.h>
#elif defined(CONFIG_HISILICON)
#include <asm/arch/platform.h>
#endif
/*
*************************************************************************
*
*Jump vector table as in table 3.1 in [1]
*
*************************************************************************
*/
/*******.globl声明一个符号可以被外部使用,相当于声明一个全局变量******/
.globl _start
_start:
/*******该部分为处理器的异常向量表,地址0x0000 0000 ~ 0x0000 0020******/
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
/*******.word伪操作是分配第一段子内存单元,并用expr初始化,此处即为存放中断函数地址******/
_undefined_instruction:
.wordundefined_instruction
_software_interrupt:
.wordsoftware_interrupt
_prefetch_abort:
.wordprefetch_abort
_data_abort:
.worddata_abort
_not_used:
.wordnot_used
_irq:
.wordirq
_fiq:
.wordfiq
/*******.align等同于balign******/
.balignl16,0xdeadbeef
/*
*************************************************************************
*
*Startup Code (reset vector)
*
* doimportant init only if we don't start from memory!
*setup Memory and board specific bits prior to relocation.
*relocate armboot to ram
*setup stack
*
*************************************************************************
*/
/******定义在/board/hi3515v100/config.mk中*******/
_TEXT_BASE:
.word TEXT_BASE
.globl _armboot_start
_armboot_start:
.word_start
.globl _img_end
_img_end:
.word__img_end
/*
*These are defined in the board-specific linker script.
*/
.globl _bss_start
_bss_start:
.word__bss_start
.globl _bss_end
_bss_end:
.word_end
#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated atrun-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de
/* IRQ stack memory (calculated atrun-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word0x0badc0de
#endif
#ifdef CONFIG_HISILICON
_clr_remap_rom_entry:
.word ROM_TEXT_ADRS + do_clr_remap - TEXT_BASE
_clr_remap_nand_entry:
.word NAND_TEXT_ADRS + do_clr_remap - TEXT_BASE
#endif
/*
*the actual reset code
*/
/*******实际的处理代码从这里开始******/
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr /******将CPRS寄存器中的值传送给R0*******/
bic r0,r0,#0x1f /******清楚指定位r0 = r0&(!0x1f)*******/
orr r0,r0,#0xd3 /******或操作r0 = r0|0xd3*******/
msr cpsr,r0 /******将R0的值送回CPRS寄存器中*******/
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/*
* flush v4 I/D caches
*/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB <input type="text" >*/
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
mcr p15, 0, r0, c1, c0, 0
ldr r0, =REG_BASE_SCTL
ldr r1, [r0, #0x8c]
and r1, r1, #0x60
lsr r4, r1, #5
@Checkif I need jump to rom
@movs r0, pc, lsr#24 /* Z flag if r0 == 0 then 1 else 0 */
@bne do_clr_remap
mov r0, pc, lsr#24
cmp r0, #0x0
bne do_clr_remap
cmp r4, #2 /*boot from nand flash*/
ldreq pc, _clr_remap_nand_entry
cmp r4, #0 /* boot from nor flash */
ldreq pc, _clr_remap_rom_entry
do_clr_remap:
ldr r4, =REG_BASE_SCTL
@ldr r0, =REG_VALUE_SC_NOLOCK
@str r0, [r4, #REG_VALUE_SC_LOCKED]
ldr r0, [r4, #REG_SC_CTRL]
@Setclear remap bit.
orr r0, #(1<<8)
str r0, [r4, #REG_SC_CTRL]
@SetupITCM (ENABLED, 2KB)
ldr r0, =( 1 | (MEM_CONF_ITCM_SIZE<<2) |MEM_BASE_ITCM)
mcr p15, 0, r0, c9, c1, 1
@enableI-Cache now
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
mcr p15, 0, r0, c1, c0, 0
@Setuplowlevel sp
ldr sp, =(MEM_BASE_ITCM + MEM_SIZE_ITCM)
@Checkif I'm running in static mem bank
mov r0, pc, lsr#28
cmp r0, #(TEXT_BASE>>28)
/*
* Go setup Memory and board specific bitsprior to relocation.
*/
beq relocate
/******跳转到lowlevel_init,该函数在board/hi3515v100/lowlevel_init.c*******/
bl lowlevel_init /* go setup pll,mux,memory */
#endif
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
/******重定向代码,也就是uboot将自己从flash复制到RAM中*******/
relocate: /*relocate U-Boot to RAM */
ldr r0, =REG_BASE_SCTL
ldr r6, [r0, #0x8c]
and r6, #0x60
lsr r4, r6, #5
adr r0, _start /*r0 <- current position of code */
/******获取_TEXT_BASE地址,定义在/board/hi3515v100/config.mk中*******/
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc duringdebug */
beq stack_setup
ldr r2, _armboot_start
/******_img_end定义在/board/hi3515v100/u-boot.lds中*******/
ldr r3, _img_end
sub r2, r3, r2 /*r2 <- size of armboot */
cmp r4, #2
ldreq r2, =(CFG_NAND_U_BOOT_ONE_PART)
add r2, r0, r2 /*r2 <- source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /*until source end addreee [r2] */
ble copy_loop
#endif /*CONFIG_SKIP_RELOCATE_UBOOT */
/*Set up the stack */
//初始化堆栈
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /*leave 3 words for abort-stack */
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /*stop here */
mov r2, #0x00000000 /*clear */
clbss_l:str r2,[r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l
/******跳转到start_armboot函数,该函数在/lib_arm/board.c*******/
ldr pc, _start_armboot
_start_armboot:
.wordstart_armboot
/*
*************************************************************************
*
*Interrupt handling
*
*************************************************************************
*/
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE 72
#define S_OLD_R0 68
#define S_PSR 64
#define S_PC 60
#define S_LR 56
#define S_SP 52
#define S_IP 48
#define S_FP 44
#define S_R10 40
#define S_R9 36
#define S_R8 32
#define S_R7 28
#define S_R6 24
#define S_R5 20
#define S_R4 16
#define S_R3 12
#define S_R2 8
#define S_R1 4
#define S_R0 0
#define MODE_SVC 0x13
#define I_BIT 0x80
/*
*use bad_save_user_regs for abort/prefetch/undef/swi ...
*use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
*/
.macro bad_save_user_regs
@carve out a frame on current user stack
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
ldr r2, _armboot_start
sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
@get values for "aborted" pc and cpsr (into parm regs)
ldmia r2, {r2 - r3}
add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
add r5, sp, #S_SP
mov r1, lr
stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
mov r0, sp @save current stack into r0 (param register)
.endm
.macro irq_save_user_regs
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Calling r0-r12
@!!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
add r8, sp, #S_PC
stmdb r8, {sp, lr}^ @ Calling SP, LR
str lr, [r8, #0] @Save calling PC
mrs r6, spsr
str r6, [r8, #4] @Save CPSR
str r0, [r8, #8] @Save OLD_R0
mov r0, sp
.endm
.macro irq_restore_user_regs
ldmia sp, {r0 - lr}^ @ Calling r0 - lr
mov r0, r0
ldr lr, [sp, #S_PC] @ Get PC
add sp, sp, #S_FRAME_SIZE
subs pc, lr, #4 @return & move spsr_svc into cpsr
.endm
.macroget_bad_stack
ldr r13, _armboot_start @ setup our mode stack
sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved acouple spots in abort stack
str lr, [r13] @save caller lr in position 0 of saved stack
mrs lr, spsr @get the spsr
str lr, [r13, #4] @ save spsr in position 1 of saved stack
mov r13, #MODE_SVC @prepare SVC-Mode
@msr spsr_c, r13
msr spsr, r13 @switch modes, make sure moves will execute
mov lr, pc @capture return pc
movs pc, lr @jump to next instruction & switch modes.
.endm
.macroget_irq_stack @setup IRQ stack
ldr sp, IRQ_STACK_START
.endm
.macroget_fiq_stack @setup FIQ stack
ldr sp, FIQ_STACK_START
.endm
/*
*exception handlers
*/
.align 5
undefined_instruction:
get_bad_stack
bad_save_user_regs
bl do_undefined_instruction
.align 5
software_interrupt:
get_bad_stack
bad_save_user_regs
bl do_software_interrupt
.align 5
prefetch_abort:
get_bad_stack
bad_save_user_regs
bl do_prefetch_abort
.align 5
data_abort:
get_bad_stack
bad_save_user_regs
bl do_data_abort
.align 5
not_used:
get_bad_stack
bad_save_user_regs
bl do_not_used
#ifdef CONFIG_USE_IRQ
.align 5
irq:
get_irq_stack
irq_save_user_regs
bl do_irq
irq_restore_user_regs
.align 5
fiq:
get_fiq_stack
/*someone ought to write a more effiction fiq_save_user_regs */
irq_save_user_regs
bl do_fiq
irq_restore_user_regs
#else
.align 5
irq:
get_bad_stack
bad_save_user_regs
bl do_irq
.align 5
fiq:
get_bad_stack
bad_save_user_regs
bl do_fiq
#endif
main.c
void mian_loop(void)
{
#ifndef CFG_HUSH_PARSER
staticchar lastcommand[CFG_CBSIZE] = { 0, };
intlen;
intrc = 1;
intflag;
#endif
#if defined(CONFIG_BOOTDELAY) &&(CONFIG_BOOTDELAY >= 0)
char*s;
intbootdelay;
#endif
#ifdef CONFIG_PREBOOT
char*p;
#endif
#ifdef CONFIG_BOOTCOUNT_LIMIT
unsignedlong bootcount = 0;
unsignedlong bootlimit = 0;
char*bcs;
charbcs_set[16];
#endif /* CONFIG_BOOTCOUNT_LIMIT */
#if defined(CONFIG_VFD) && defined(VFD_TEST_LOGO)
ulongbmp = 0; /* default bitmap */
externint trab_vfd (ulong bitmap);
#ifdef CONFIG_MODEM_SUPPORT
if(do_mdm_init)
bmp= 1; /* alternate bitmap */
#endif
trab_vfd(bmp);
#endif /*CONFIG_VFD && VFD_TEST_LOGO */
#ifdef CONFIG_BOOTCOUNT_LIMIT
bootcount= bootcount_load();
bootcount++;
bootcount_store(bootcount);
sprintf(bcs_set, "%lu", bootcount);
setenv("bootcount", bcs_set);
bcs= getenv ("bootlimit");
bootlimit= bcs ? simple_strtoul (bcs, NULL, 10) : 0;
#endif /* CONFIG_BOOTCOUNT_LIMIT */
#ifdef CONFIG_MODEM_SUPPORT
debug("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init);
if(do_mdm_init) {
char*str = strdup(getenv("mdm_cmd"));
setenv("preboot", str); /* set ordelete definition */
if(str != NULL)
free(str);
mdm_init();/* wait for modem connection */
}
#endif /* CONFIG_MODEM_SUPPORT */
#ifdef CONFIG_VERSION_VARIABLE
{
externchar version_string[];
setenv("ver", version_string); /*set version variable */
}
#endif /* CONFIG_VERSION_VARIABLE */
#ifdef CFG_HUSH_PARSER
u_boot_hush_start();
#endif
#ifdef CONFIG_AUTO_COMPLETE
install_auto_complete();
#endif
#ifdef CONFIG_PREBOOT
if((p = getenv ("preboot")) != NULL) {
# ifdef CONFIG_AUTOBOOT_KEYED
intprev = disable_ctrlc(1); /* disableControl C checking */
# endif
# ifndef CFG_HUSH_PARSER
run_command(p, 0);
# else
parse_string_outer(p,FLAG_PARSE_SEMICOLON |
FLAG_EXIT_FROM_LOOP);
# endif
# ifdef CONFIG_AUTOBOOT_KEYED
disable_ctrlc(prev); /* restore Control C checking */
# endif
}
#endif /* CONFIG_PREBOOT */
#if defined(CONFIG_BOOTDELAY) &&(CONFIG_BOOTDELAY >= 0)
s= getenv ("bootdelay");
bootdelay= s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);
# ifdef CONFIG_BOOT_RETRY_TIME
init_cmd_timeout();
# endif /*CONFIG_BOOT_RETRY_TIME */
#ifdef CONFIG_POST
if(gd->flags & GD_FLG_POSTFAIL) {
s= getenv("failbootcmd");
}
else
#endif /* CONFIG_POST */
#ifdef CONFIG_BOOTCOUNT_LIMIT
if(bootlimit && (bootcount > bootlimit)) {
printf("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
(unsigned)bootlimit);
s= getenv ("altbootcmd");
}
else
#endif /* CONFIG_BOOTCOUNT_LIMIT */
s= getenv ("bootcmd");
debug("### main_loop: bootcmd=\"%s\"\n", s ? s :"<UNDEFINED>");
/* abortboot (bootdelay)返回1则不启动boot,否则启动boot */
if(bootdelay >= 0 && s && !abortboot (bootdelay)) {
/*llz added to pass mac address from uboot to kernel by merge the valueof ethaddr to bootargs.*/
// extern void merge_mac_to_bootargs(void);
// merge_mac_to_bootargs();
# ifdef CONFIG_AUTOBOOT_KEYED
intprev = disable_ctrlc(1); /* disableControl C checking */
# endif
# ifndef CFG_HUSH_PARSER
run_command(s, 0);
# else
parse_string_outer(s,FLAG_PARSE_SEMICOLON |
FLAG_EXIT_FROM_LOOP);
# endif
# ifdef CONFIG_AUTOBOOT_KEYED
disable_ctrlc(prev); /* restore Control C checking */
# endif
}
/* # ifdef CONFIG_MENUKEY该部分代码不会调用 */
# ifdef CONFIG_MENUKEY
if(menukey == CONFIG_MENUKEY) {
/*add by heliangbin 2012-7-21 */
printf("main_loop#################trace2!\n");
s = getenv("menucmd");
if (s) {
# ifndef CFG_HUSH_PARSER
run_command(s, 0);
/*add by heliangbin 2012-7-21 */
printf("main_loop#################trace3!\n");
# else
parse_string_outer(s,FLAG_PARSE_SEMICOLON |
FLAG_EXIT_FROM_LOOP);
# endif
}
}
#endif /* CONFIG_MENUKEY*/
#endif /*CONFIG_BOOTDELAY */
#ifdef CONFIG_AMIGAONEG3SE
{
extern void video_banner(void);
video_banner();
}
#endif
/*
* Main Loop for Monitor Command Processing
*/
#ifdef CFG_HUSH_PARSER
parse_file_outer();
/*This point is never reached */
for(;;);
#else
for(;;) {
#ifdef CONFIG_BOOT_RETRY_TIME
if(rc >= 0) {
/*Saw enough of a valid command to
* restart the timeout.
*/
reset_cmd_timeout();
}
#endif
len = readline (CFG_PROMPT);
flag= 0; /* assume no special flags for now*/
if(len > 0)
strcpy (lastcommand, console_buffer);
elseif (len == 0)
flag|= CMD_FLAG_REPEAT;
#ifdef CONFIG_BOOT_RETRY_TIME
elseif (len == -2) {
/*-2 means timed out, retry autoboot
*/
puts("\nTimed out waiting for command\n");
# ifdef CONFIG_RESET_TO_RETRY
/*Reinit board to run initialization code again */
do_reset(NULL, 0, 0, NULL);
# else
return; /* retry autoboot */
# endif
}
#endif
if(len == -1)
puts("<INTERRUPT>\n");
else
rc = run_command (lastcommand, flag);
/*add by heliangbin 2012-7-21 */
printf("main_looplastcommand = %s!\n", lastcommand);
//if(rc <= 0) {
/*invalid command or not repeatable, forget it */
lastcommand[0]= 0;
//}
}
#endif /*CFG_HUSH_PARSER*/
}