S5P4418 uboot 分析

瘋耔新浪微博:   http://weibo.com/cpjphone

一:

1◑ 从链接脚本文件u-boot.lds('/opt/4418-source/android/u-boot' )中可以找到代码的起始:

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_stext)
SECTIONS
{
 . = 0x00000000;
 . = ALIGN(4);
 .text :
 {
  *(.__image_copy_start)
  arch/arm/cpu/slsiap/s5p4418/start.o (.text*)
  *(.text*)
 }

 

从中知道程序的入口点是_start,定位于arch/arm/cpu/slsiap/s5p4418/start.o (即u-boot启动的第一阶段)。

▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒

2◑ 下面我们来仔细分析一下 start.S。(请对照数据手册阅读源码):

 

/*
 * armboot - Startup Code for NXPxxxx/ARM Cortex CPU-core
 */

#include 
#include 
#include 
#include 
#include 

/*
 *************************************************************************
 *
 * Exception vectors as described in ARM reference manuals
 *
 * replace arm/lib/vectors.S
 *
 *************************************************************************
 */
    .globl    _stext
_stext:
    b     reset                //u-boot的主入口,跳入了后面的reset                
    ldr    pc, _undefined_instruction
    ldr    pc, _software_interrupt        //这些是跳转向量表,和芯片的体系结构有关
    ldr    pc, _prefetch_abort
    ldr    pc, _data_abort
    ldr    pc, _not_used            // ldr语句的意思是将第二个操作数(如:_undefined_instruction)指向的地址数据传给PC
    ldr    pc, _irq
    ldr    pc, _fiq

/* ldr语句的意思是将第二个操作数(如:_undefined_instruction)指向的地址数据传给PC,undefined_instruction 为地址, 即后面标号所对的偏移地址数据  */
_undefined_instruction:    .word undefined_instruction    
_software_interrupt:    .word software_interrupt
_prefetch_abort:    .word prefetch_abort
_data_abort:        .word data_abort
_not_used:        .word not_used
_irq:            .word irq
_fiq:            .word fiq

    .balignl 16,0xdeadbeef        //16字节对齐,并以0xdeadbeef填充,它是个Magic number。

/*
 *************************************************************************
 *
 * Text and section base
 *
 *************************************************************************
 */

.globl TEXT_BASE
TEXT_BASE:
    .word    CONFIG_SYS_TEXT_BASE        //这些和上面的一样,定义一个4字节的空间存放地址

/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start_ofs
_bss_start_ofs:
    .word __bss_start - _stext

.globl _bss_end_ofs
_bss_end_ofs:
    .word __bss_end - _stext

.globl _end_ofs
_end_ofs:
    .word _end - _stext

/*
 *************************************************************************
 *
 * Reset handling    代码从这里开始执行
 *
 *************************************************************************
 */

    .globl reset

reset:
    bl    save_boot_params
    /*
     * set the cpu to SVC32 mode        让系统进入SVC(管理)员
     */
    mrs    r0, cpsr
    bic    r0, r0, #0x1f
    orr    r0, r0, #0xd3
    msr    cpsr,r0

    /* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl    cpu_init_cp15
    bl    cpu_init_crit
#endif

#ifdef CONFIG_RELOC_TO_TEXT_BASE
relocate_to_text:
    /*
     * relocate u-boot code on memory to text base
     * for nexell arm core (add by jhkim)
     */
    adr    r0, _stext                /* 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 clear_bss

    ldr    r2, _bss_start_ofs
    add    r2, r0, r2                /* r2 <- source end address         */

copy_loop_text:
    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_text

    ldr    r1, TEXT_BASE            /* restart at text base */
    mov pc, r1

clear_bss:
    ldr    r0, _bss_start_ofs
    ldr    r1, _bss_end_ofs
    ldr    r4, TEXT_BASE            /* text addr */
    add    r0, r0, r4
    add    r1, r1, r4
    mov    r2, #0x00000000            /* clear */

clbss_l:str    r2, [r0]            /* clear loop... */
    add    r0, r0, #4
    cmp    r0, r1
    bne    clbss_l

#ifdef CONFIG_MMU_ENABLE
    bl    mmu_turn_on
#endif

    ldr    sp, =(CONFIG_SYS_INIT_SP_ADDR)
    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

    mov    sp, r9                        /* SP is GD's base address */
    bic    sp, sp, #7                    /* 8-byte alignment for ABI compliance */
    sub    sp, #GENERATED_BD_INFO_SIZE    /* allocate one BD above SP */
    bic    sp, sp, #7                    /* 8-byte alignment for ABI compliance */

    mov    r0, r9                        /* gd_t *gd */
    ldr r1, TEXT_BASE                /* ulong text */
    mov r2, sp                        /* ulong sp */
    bl    gdt_reset

    /* call board_init_r(gd_t *id, ulong dest_addr) */
    mov    r0, r9                            /* gd_t */
    ldr    r1,  =(CONFIG_SYS_MALLOC_END)    /* dest_addr for malloc heap end */
    /* call board_init_r */
    ldr    pc, =board_init_r                /* this is auto-relocated! */

#else    /* CONFIG_RELOC_TO_TEXT_BASE */

    bl    _main
#endif

/*------------------------------------------------------------------------------*/

ENTRY(c_runtime_cpu_setup)
/*
 * If I-cache is enabled invalidate it
 */
#ifndef CONFIG_SYS_ICACHE_OFF
    mcr    p15, 0, r0, c7, c5, 0    @ invalidate icache
    mcr     p15, 0, r0, c7, c10, 4    @ DSB
    mcr     p15, 0, r0, c7, c5, 4    @ ISB
#endif
/*
 * Move vector table
 */
    /* Set vector address in CP15 VBAR register */
    ldr     r0, =_stext
    mcr     p15, 0, r0, c12, c0, 0  @Set VBAR

    bx    lr

ENDPROC(c_runtime_cpu_setup)

/*************************************************************************
 *
 * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3)
 *    __attribute__((weak));
 *
 * Stack pointer is not yet initialized at this moment
 * Don't save anything to stack even if compiled with -O0
 *
 *************************************************************************/
ENTRY(save_boot_params)
    bx    lr            @ back to my caller
ENDPROC(save_boot_params)
    .weak    save_boot_params

/*************************************************************************
 *
 * cpu_init_cp15
 *
 * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
 * CONFIG_SYS_ICACHE_OFF is defined.
 * 操作CP15协处理器
 *
 *************************************************************************/
ENTRY(cpu_init_cp15)
    /*
     * Invalidate L1 I/D
     */
    mov    r0, #0            @ set up for MCR
    mcr    p15, 0, r0, c8, c7, 0    @ invalidate TLBs
    mcr    p15, 0, r0, c7, c5, 0    @ invalidate icache
    mcr    p15, 0, r0, c7, c5, 6    @ invalidate BP array

    dsb
    isb

    /*
     * disable MMU stuff and caches
     *下面主要是中断相关代码,但是U-boot基本不使用中断所以暂且略过。
     */
    mrc    p15, 0, r0, c1, c0, 0
    bic    r0, r0, #0x00002000    @ clear bits 13 (--V-)
    bic    r0, r0, #0x00000007    @ clear bits 2:0 (-CAM)
    orr    r0, r0, #0x00000002    @ set bit 1 (--A-) Align
    orr    r0, r0, #0x00000800    @ set bit 11 (Z---) BTB
#ifdef CONFIG_SYS_ICACHE_OFF
    bic    r0, r0, #0x00001000    @ clear bit 12 (I) I-cache
#else
    orr    r0, r0, #0x00001000    @ set bit 12 (I) I-cache
#endif
    mcr    p15, 0, r0, c1, c0, 0
    mov    pc, lr            @ back to my caller
ENDPROC(cpu_init_cp15)

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/*************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************/
ENTRY(cpu_init_crit)
    /*
     * Jump to board specific initialization...
     * The Mask ROM will have already initialized
     * basic memory. Go here to bump up clock rate and handle
     * wake up conditions.
     */
/* 

调用board/lowlevel_init.S中的lowlevel_init函数,对系统总线的初始化,初始化了连接存储器的位宽、速度、刷新率等重要参数。经过这个函数的正确初始化,Nor Flash、SDRAM才可以被系统使用。
 */
    b    lowlevel_init        @ go setup pll,mux,memory
ENDPROC(cpu_init_crit)
#endif

 

 

▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒

3◑现在我们再来看看lib/arm/board.c中的第二阶段入口函数board_init_r:

/*
 * (C) Copyright 2002-2006
 * Wolfgang Denk, DENX Software Engineering, [email protected].
 *
 * (C) Copyright 2002
 * Sysgo Real-Time Solutions, GmbH 
 * Marius Groeger 
 *
 * SPDX-License-Identifier:    GPL-2.0+
 */

/*
 * To match the U-Boot user interface on ARM platforms to the U-Boot
 * standard (as on PPC platforms), some messages with debug character
 * are removed from the default U-Boot build.
 *
 * Define DEBUG here if you want additional info as shown below
 * printed upon startup:
 *
 * U-Boot code: 00F00000 -> 00F3C774  BSS: -> 00FC3274
 * IRQ Stack: 00ebff7c
 * FIQ Stack: 00ebef7c
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#ifdef CONFIG_BITBANGMII
#include 
#endif

DECLARE_GLOBAL_DATA_PTR;

ulong monitor_flash_len;

#ifdef CONFIG_HAS_DATAFLASH
extern int  AT91F_DataflashInit(void);
extern void dataflash_print_info(void);
#endif

#if defined(CONFIG_HARD_I2C) || \
    defined(CONFIG_SYS_I2C)
#include 
#endif

/************************************************************************
 * Coloured LED functionality
 ************************************************************************
 * May be supplied by boards if desired
 */
inline void __coloured_LED_init(void) {}
void coloured_LED_init(void)
    __attribute__((weak, alias("__coloured_LED_init")));
inline void __red_led_on(void) {}
void red_led_on(void) __attribute__((weak, alias("__red_led_on")));
inline void __red_led_off(void) {}
void red_led_off(void) __attribute__((weak, alias("__red_led_off")));
inline void __green_led_on(void) {}
void green_led_on(void) __attribute__((weak, alias("__green_led_on")));
inline void __green_led_off(void) {}
void green_led_off(void) __attribute__((weak, alias("__green_led_off")));
inline void __yellow_led_on(void) {}
void yellow_led_on(void) __attribute__((weak, alias("__yellow_led_on")));
inline void __yellow_led_off(void) {}
void yellow_led_off(void) __attribute__((weak, alias("__yellow_led_off")));
inline void __blue_led_on(void) {}
void blue_led_on(void) __attribute__((weak, alias("__blue_led_on")));
inline void __blue_led_off(void) {}
void blue_led_off(void) __attribute__((weak, alias("__blue_led_off")));

/*
 ************************************************************************
 * Init Utilities                            *
 ************************************************************************
 * Some of this code should be moved into the core functions,
 * or dropped completely,
 * but let's get it working (again) first...
 */

#if defined(CONFIG_ARM_DCC) && !defined(CONFIG_BAUDRATE)
#define CONFIG_BAUDRATE 115200
#endif

static int init_baudrate(void)
{
    gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
    return 0;
}

static int display_banner(void)
{
    printf("\n\n%s\n\n", version_string);
    debug("U-Boot code: %08lX -> %08lX  BSS: -> %08lX\n",
           (ulong)&_start,
           (ulong)&__bss_start, (ulong)&__bss_end);
#ifdef CONFIG_MODEM_SUPPORT
    debug("Modem Support enabled\n");
#endif
#ifdef CONFIG_USE_IRQ
    debug("IRQ Stack: %08lx\n", IRQ_STACK_START);
    debug("FIQ Stack: %08lx\n", FIQ_STACK_START);
#endif

    return (0);
}

/*
 * WARNING: this code looks "cleaner" than the PowerPC version, but
 * has the disadvantage that you either get nothing, or everything.
 * On PowerPC, you might see "DRAM: " before the system hangs - which
 * gives a simple yet clear indication which part of the
 * initialization if failing.
 */
static int display_dram_config(void)
{
    int i;

#ifdef DEBUG
    puts("RAM Configuration:\n");

    for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
        printf("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
        print_size(gd->bd->bi_dram[i].size, "\n");
    }
#else
    ulong size = 0;

    for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
        size += gd->bd->bi_dram[i].size;

    puts("DRAM:  ");
    print_size(size, "\n");
#endif

    return (0);
}

#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
static int init_func_i2c(void)
{
    puts("I2C:   ");
#ifdef CONFIG_SYS_I2C
    i2c_init_all();
#else
    i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
#endif
    puts("ready\n");
    return (0);
}
#endif

#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
#include 
static int arm_pci_init(void)
{
    pci_init();
    return 0;
}
#endif /* CONFIG_CMD_PCI || CONFIG_PCI */

/*
 * Breathe some life into the board...
 *
 * Initialize a serial port as console, and carry out some hardware
 * tests.
 *
 * The first part of initialization is running from Flash memory;
 * its main purpose is to initialize the RAM so that we
 * can relocate the monitor code to RAM.
 */

/*
 * All attempts to come up with a "common" initialization sequence
 * that works for all boards and architectures failed: some of the
 * requirements are just _too_ different. To get rid of the resulting
 * mess of board dependent #ifdef'ed code we now make the whole
 * initialization sequence configurable to the user.
 *
 * The requirements for any new initalization function is simple: it
 * receives a pointer to the "global data" structure as it's only
 * argument, and returns an integer return code, where 0 means
 * "continue" and != 0 means "fatal error, hang the system".
 */
typedef int (init_fnc_t) (void);

void __dram_init_banksize(void)
{
    gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
    gd->bd->bi_dram[0].size =  gd->ram_size;
}
void dram_init_banksize(void)
    __attribute__((weak, alias("__dram_init_banksize")));

int __arch_cpu_init(void)
{
    return 0;
}
int arch_cpu_init(void)
    __attribute__((weak, alias("__arch_cpu_init")));

int __power_init_board(void)
{
    return 0;
}
int power_init_board(void)
    __attribute__((weak, alias("__power_init_board")));

    /* Record the board_init_f() bootstage (after arch_cpu_init()) */
static int mark_bootstage(void)
{
    bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");

    return 0;
}

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 */
    print_cpuinfo,        /* display cpu info (and speed) */
#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,
};

void board_init_f(ulong bootflag)
{
    bd_t *bd;
    init_fnc_t **init_fnc_ptr;
    gd_t *id;
    ulong addr, addr_sp;
#ifdef CONFIG_PRAM
    ulong reg;
#endif
    void *new_fdt = NULL;
    size_t fdt_size = 0;

    memset((void *)gd, 0, sizeof(gd_t));

    gd->mon_len = (ulong)&__bss_end - (ulong)_start;
#ifdef CONFIG_OF_EMBED
    /* Get a pointer to the FDT */
    gd->fdt_blob = __dtb_dt_begin;
#elif defined CONFIG_OF_SEPARATE
    /* FDT is at end of image */
    gd->fdt_blob = &_end;
#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

    debug("monitor len: %08lX\n", gd->mon_len);
    /*
     * Ram is setup, size stored in gd !!
     */
    debug("ramsize: %08lX\n", gd->ram_size);
#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 + get_effective_memsize();

#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 = PGTABLE_SIZE;
    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

#ifndef CONFIG_ARM64
    /* 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    /* CONFIG_ARM64 */
    /* 16-byte alignment for ABI compliance */
    addr_sp &= ~0x0f;
#endif    /* CONFIG_ARM64 */
#else
    addr_sp += 128;    /* leave 32 words for abort-stack   */
    gd->irq_sp = addr_sp;
#endif

    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

    /* 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 - (ulong)&_start;
    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));
}

#if !defined(CONFIG_SYS_NO_FLASH)
static char *failed = "*** failed ***\n";
#endif

/*
 * Tell if it's OK to load the environment early in boot.
 *
 * If CONFIG_OF_CONFIG is defined, we'll check with the FDT to see
 * if this is OK (defaulting to saying it's not OK).
 *
 * NOTE: Loading the environment early can be a bad idea if security is
 *       important, since no verification is done on the environment.
 *
 * @return 0 if environment should not be loaded, !=0 if it is ok to load
 */
static int should_load_env(void)
{
#ifdef CONFIG_OF_CONTROL
    return fdtdec_get_config_int(gd->fdt_blob, "load-environment", 1);
#elif defined CONFIG_DELAY_ENVIRONMENT
    return 0;
#else
    return 1;
#endif
}

#if defined(CONFIG_DISPLAY_BOARDINFO_LATE) && defined(CONFIG_OF_CONTROL)
static void display_fdt_model(const void *blob)
{
    const char *model;

    model = (char *)fdt_getprop(blob, 0, "model", NULL);
    printf("Model: %s\n", model ? model : "");
}
#endif

/************************************************************************
 *
 * This is the next part if the initialization sequence: we are now
 * running from RAM and have a "normal" C environment, i. e. global
 * data can be written, BSS has been cleared, the stack size in not
 * that critical any more, etc.
 *
 ************************************************************************
 */

void board_init_r(gd_t *id, ulong dest_addr)
{
    ulong malloc_start;
#if !defined(CONFIG_SYS_NO_FLASH)
    ulong flash_size;
#endif

    gd->flags |= GD_FLG_RELOC;    /* tell others: relocation done */
    bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");

    monitor_flash_len = (ulong)&__rel_dyn_end - (ulong)_start;

    /* Enable caches */
    enable_caches();

    debug("monitor flash len: %08lX\n", monitor_flash_len);
    board_init();    /* Setup chipselects */
    /*
     * TODO: printing of the clock inforamtion of the board is now
     * implemented as part of bdinfo command. Currently only support for
     * davinci SOC's is added. Remove this check once all the board
     * implement this.
     */
#ifdef CONFIG_CLOCKS
    set_cpu_clk_info(); /* Setup clock information */
#endif
    serial_initialize();

    debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);

#ifdef CONFIG_LOGBUFFER
    logbuff_init_ptrs();
#endif
#ifdef CONFIG_POST
    post_output_backlog();
#endif

    /* 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);

#ifdef CONFIG_ARCH_EARLY_INIT_R
    arch_early_init_r();
#endif

#ifndef CONFIG_PMIC_REG_DUMP
    power_init_board();
#endif

#if !defined(CONFIG_SYS_NO_FLASH)
    puts("Flash: ");

    flash_size = flash_init();
    if (flash_size > 0) {
# ifdef CONFIG_SYS_FLASH_CHECKSUM
        print_size(flash_size, "");
        /*
         * Compute and print flash CRC if flashchecksum is set to 'y'
         *
         * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
         */
        if (getenv_yesno("flashchecksum") == 1) {
            printf("  CRC: %08X", crc32(0,
                (const unsigned char *) CONFIG_SYS_FLASH_BASE,
                flash_size));
        }
        putc('\n');
# else    /* !CONFIG_SYS_FLASH_CHECKSUM */
        print_size(flash_size, "\n");
# endif /* CONFIG_SYS_FLASH_CHECKSUM */
    } else {
        puts(failed);
        hang();
    }
#endif

#if defined(CONFIG_CMD_NAND)
#if defined(CONFIG_NAND_MTD)
    puts("NAND:  ");
    nand_init();        /* go init the NAND */
#elif defined(CONFIG_NAND_FTL)
#include 
    puts("NAND FTL:  ");
    nand_ftl_init();        /* go init the NAND */
#endif
#endif /* CONFIG_CMD_NAND */

#if defined(CONFIG_CMD_ONENAND)
    onenand_init();
#endif

#ifdef CONFIG_GENERIC_MMC
    puts("MMC:   ");
    mmc_initialize(gd->bd);
#endif

#ifdef CONFIG_CMD_SCSI
    puts("SCSI:  ");
    scsi_init();
#endif

#ifdef CONFIG_HAS_DATAFLASH
    AT91F_DataflashInit();
    dataflash_print_info();
#endif

    /* initialize environment */
    if (should_load_env())
        env_relocate();
    else
        set_default_env(NULL);

#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI)
    arm_pci_init();
#endif

    stdio_init();    /* get the devices list going. */

    jumptable_init();

#if defined(CONFIG_API)
    /* Initialize API */
    api_init();
#endif

    console_init_r();    /* fully init console as a device */

#ifdef CONFIG_PMIC_REG_DUMP
    power_init_board();
#endif

#ifdef CONFIG_DISPLAY_BOARDINFO_LATE
# ifdef CONFIG_OF_CONTROL
    /* Put this here so it appears on the LCD, now it is ready */
    display_fdt_model(gd->fdt_blob);
# else
    checkboard();
# endif
#endif

#if defined(CONFIG_ARCH_MISC_INIT)
    /* miscellaneous arch dependent initialisations */
    arch_misc_init();
#endif
#if defined(CONFIG_MISC_INIT_R)
    /* miscellaneous platform dependent initialisations */
    misc_init_r();
#endif

     /* set up exceptions */
    interrupt_init();
    /* enable exceptions */
    enable_interrupts();

    /* Initialize from environment */
    load_addr = getenv_ulong("loadaddr", 16, load_addr);

#ifdef CONFIG_BOARD_LATE_INIT
    board_late_init();
#endif

#ifdef CONFIG_BITBANGMII
    bb_miiphy_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

#ifdef CONFIG_POST
    post_run(NULL, POST_RAM | post_bootmode_get(0));
#endif

#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
    /*
     * Export available size of memory for Linux,
     * taking into account the protected RAM at top of memory
     */
    {
        ulong pram = 0;
        uchar memsz[32];

#ifdef CONFIG_PRAM
        pram = getenv_ulong("pram", 10, CONFIG_PRAM);
#endif
#ifdef CONFIG_LOGBUFFER
#ifndef CONFIG_ALT_LB_ADDR
        /* Also take the logbuffer into account (pram is in kB) */
        pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / 1024;
#endif
#endif
        sprintf((char *)memsz, "%ldk", (gd->ram_size / 1024) - pram);
        setenv("mem", (char *)memsz);
    }
#endif

    /* main_loop() can return to retry autoboot, if so just run it again. */
    for (;;) {
        main_loop();
    }
    /*
    进入主循环,其中会读取bootdelay和bootcmd

    在bootdelay时间内按下键进入命令行,否则执行bootcmd的命令。
    */
    /* NOTREACHED - no way out of command loop except booting */
}

 

 

希望网友积极留言,共同完成4418资料集

 

 

-----------------------------

转载于:https://www.cnblogs.com/Ph-one/p/4810900.html

你可能感兴趣的:(S5P4418 uboot 分析)