Chinaunix首页 | 论坛 | 博客
  • 博客访问: 439490
  • 博文数量: 123
  • 博客积分: 2686
  • 博客等级: 少校
  • 技术积分: 1349
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-23 22:11
文章分类
文章存档

2012年(3)

2011年(10)

2010年(100)

2009年(10)

我的朋友

分类: LINUX

2010-01-05 23:46:13

在第二阶段执行,u-boot的所有代码都被搬运到内存中,在内存中执行入口点是/lib_arm/borad.c 中的函数:start_armboot.
1.start_armboot代码分析如下:
 

typedef int (init_fnc_t) (void);

int print_cpuinfo (void);

init_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
    arch_cpu_init,        /* basic arch cpu dependent setup */
#endif
    board_init,        /* basic board dependent setup */
#if defined(CONFIG_USE_IRQ)
    interrupt_init,        /* set up exceptions */
#endif
    timer_init,        /* initialize timer */
    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_SOFT_I2C)
    init_func_i2c,
#endif
    dram_init,        /* configure available RAM banks */
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
    arm_pci_init,
#endif
    display_dram_config,
    NULL,
};
//第二阶段函数的入口点
void start_armboot (void)
{
    init_fnc_t **init_fnc_ptr;//指针数组
    char *s;
#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
    unsigned long addr;
#endif
//分配一个存储全局数据的区域,位置在0x33f880000-MALLOC_LEN-sizeof(gd_t)

    /* Pointer is writable since we allocated a register for it */
    gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
    /* compiler optimization barrier needed for GCC >= 3.4 */
    __asm__ __volatile__("": : :"memory");


//初始化全局数据区域为0
    memset ((void*)gd, 0, sizeof (gd_t));

//为指向bd_t的数据结构的指针赋值,gd-sizeof(bd_t);
    gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
    memset (gd->bd, 0, sizeof (bd_t));
//为全局数据结构里面的标志flags 赋值为:GD_FLG_RELOC表示已经重定位到ram
    gd->flags |= GD_FLG_RELOC;
//monitor_flash_len就是u-boot代码长度
    monitor_flash_len = _bss_start - _armboot_start;

 

 


//调用一系列的初始化函数,这些函数的指针放在init_sequence数组中
    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
        if ((*init_fnc_ptr)() != 0) {
            hang ();
        }
    }

 

 

//mem_malloc_init函数做2个事情:一是为全局变量赋值,二是初始化malloc room

//mem_malloc_start = start;
//mem_malloc_end = start + size;
//mem_malloc_brk = start;

//memset((void *)mem_malloc_start, 0, size);
/* armboot_start is defined in the board-specific linker script */
    mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
            CONFIG_SYS_MALLOC_LEN);

 


#ifndef CONFIG_SYS_NO_FLASH
    /* configure available FLASH banks */

//因为我要移植的是s3c2440,flash_init这个函数在/board/samsung/

//smdk2440/flash.c中,而函数display_flash_config 仅仅是显示flash大小
    display_flash_config (flash_init ());
#endif /* CONFIG_SYS_NO_FLASH */


//LCD并不是移植的重点

/***************************LCD***********************************/
#ifdef CONFIG_VFD
#    ifndef PAGE_SIZE
#     define PAGE_SIZE 4096
#    endif
    /*
     * reserve memory for VFD display (always full pages)
     */

    /* bss_end is defined in the board-specific linker script */
    addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
    vfd_setmem (addr);
    gd->fb_base = addr;
#endif /* CONFIG_VFD */

#ifdef CONFIG_LCD
    /* board init may have inited fb_base */
    if (!gd->fb_base) {
#        ifndef PAGE_SIZE
#         define PAGE_SIZE 4096
#        endif
        /*
         * reserve memory for LCD display (always full pages)
         */

        /* bss_end is defined in the board-specific linker script */
        addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
        lcd_setmem (addr);
        gd->fb_base = addr;
    }
#endif /* CONFIG_LCD */
/***************************LCD***********************************/

 

//要在smdk2440.h中添加对CONFIG_CMD_NAND宏的定义。初始化Nand
#if defined(CONFIG_CMD_NAND)
    puts ("NAND: ");
    nand_init();        /* go init the NAND */
#endif

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

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

    /* initialize environment */
    env_relocate ();

#ifdef CONFIG_VFD
    /* must do this after the framebuffer is allocated */
    drv_vfd_init();
#endif /* CONFIG_VFD */

#ifdef CONFIG_SERIAL_MULTI
    serial_initialize();
#endif

    /* IP Address */
    gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

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

#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

    /* enable exceptions */
    enable_interrupts ();

    /* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_TI_EMAC
    /* XXX: this needs to be moved to board init */
extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
    if (getenv ("ethaddr")) {
        uchar enetaddr[6];
        eth_getenv_enetaddr("ethaddr", enetaddr);
        davinci_eth_set_mac_addr(enetaddr);
    }
#endif

#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
    /* XXX: this needs to be moved to board init */
    if (getenv ("ethaddr")) {
        uchar enetaddr[6];
        eth_getenv_enetaddr("ethaddr", enetaddr);
        smc_set_mac_addr(enetaddr);
    }
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */

    /* Initialize from environment */
    if ((s = getenv ("loadaddr")) != NULL) {
        load_addr = simple_strtoul (s, NULL, 16);
    }
#if defined(CONFIG_CMD_NET)
    if ((s = getenv ("bootfile")) != NULL) {
        copy_filename (BootFile, s, sizeof (BootFile));
    }
#endif

#ifdef BOARD_LATE_INIT
    board_late_init ();
#endif

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

#ifdef CONFIG_BITBANGMII
    bb_miiphy_init();
#endif
#if defined(CONFIG_CMD_NET)
#if defined(CONFIG_NET_MULTI)
    puts ("Net: ");
#endif
    eth_initialize(gd->bd);
#if defined(CONFIG_RESET_PHY_R)
    debug ("Reset Ethernet PHY\n");
    reset_phy();
#endif
#endif

/* main_loop() can return to retry autoboot, if so just run it again. */
    for (;;) {
        main_loop ();
    }

    /* NOTREACHED - no way out of command loop except booting */
}


2.全局数据结构分析

2.1. bd_t数据结构,这是u-boot对内核的一个接口,内核在执行时要读取bd_info里面的数据。

typedef struct bd_info {
    unsigned long bi_memstart; /* start of DRAM memory */
    phys_size_t    bi_memsize; /* size of DRAM memory in bytes */
    unsigned long bi_flashstart; /* start of FLASH memory */
    unsigned long bi_flashsize; /* size of FLASH memory */
    unsigned long bi_flashoffset; /* reserved area for startup monitor */
    unsigned long bi_sramstart; /* start of SRAM memory */
    unsigned long bi_sramsize; /* size of SRAM memory */
    unsigned long bi_ip_addr; /* IP Address */
    unsigned long bi_baudrate; /* Console Baudrate */
    unsigned long    bi_boot_params; /* where this board expects params */
} bd_t;

2.2 gd_t数据结构,是一个全局数据类型。

typedef struct global_data {
 bd_t *bd;//指向一个存放存储器信息,波特率,ip地址的一个数据结构
 unsigned long flags;
 unsigned long baudrate;//波特率
 unsigned long cpu_clk; /* CPU clock in Hz! */
 unsigned long have_console; /* serial_init() was called */
 phys_size_t ram_size; /* RAM size */
 unsigned long env_addr; /* Address of Environment struct */
 unsigned long env_valid; /* Checksum of Environment valid */
#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER)
 unsigned long post_log_word; /* Record POST activities */
 unsigned long post_init_f_time; /* When post_init_f started */
#endif
 void **jt; /* Standalone app jump table */
} gd_t;

3. main_loop()代码分析
 

void main_loop (void)
{
#ifndef CONFIG_SYS_HUSH_PARSER

#CONFIG_SYS_CBSIZE是输入命令字符的最大数,lastcommand保存输入命令
    static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
    int len;
    int rc = 1;
    int flag;
#endif

#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
    char *s;
    int bootdelay;
#endif
#ifdef CONFIG_PREBOOT
    char *p;
#endif
#ifdef CONFIG_BOOTCOUNT_LIMIT
    unsigned long bootcount = 0;
    unsigned long bootlimit = 0;
    char *bcs;
    char bcs_set[16];
#endif /* CONFIG_BOOTCOUNT_LIMIT */

#if defined(CONFIG_VFD) && defined(VFD_TEST_LOGO)
    ulong bmp = 0;        /* default bitmap */
    extern int 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 */

#if defined(CONFIG_UPDATE_TFTP)
    update_tftp ();
#endif /* CONFIG_UPDATE_TFTP */

#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 or delete definition */
        if (str != NULL)
            free (str);
        mdm_init(); /* wait for modem connection */
    }
#endif /* CONFIG_MODEM_SUPPORT */

#ifdef CONFIG_VERSION_VARIABLE
    {
        extern char version_string[];

        setenv ("ver", version_string); /* set version variable */
    }
#endif /* CONFIG_VERSION_VARIABLE */

#ifdef CONFIG_SYS_HUSH_PARSER
    u_boot_hush_start ();
#endif

#if defined(CONFIG_HUSH_INIT_VAR)
    hush_init_var ();
#endif

#ifdef CONFIG_AUTO_COMPLETE
    install_auto_complete();
#endif

#ifdef CONFIG_PREBOOT
    if ((p = getenv ("preboot")) != NULL) {
# ifdef CONFIG_AUTOBOOT_KEYED
        int prev = disable_ctrlc(1);    /* disable Control C checking */
# endif

# ifndef CONFIG_SYS_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 : "");

    if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
# ifdef CONFIG_AUTOBOOT_KEYED
        int prev = disable_ctrlc(1);    /* disable Control C checking */
# endif

# ifndef CONFIG_SYS_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
    if (menukey == CONFIG_MENUKEY) {
     s = getenv("menucmd");
     if (s) {
# ifndef CONFIG_SYS_HUSH_PARSER
        run_command (s, 0);
# 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 CONFIG_SYS_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 (CONFIG_SYS_PROMPT);

        flag = 0;    /* assume no special flags for now */
        if (len > 0)
            strcpy (lastcommand, console_buffer);
        else if (len == 0)
            flag |= CMD_FLAG_REPEAT;
#ifdef CONFIG_BOOT_RETRY_TIME
        else if (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 ("\n");
        else
            rc = run_command (lastcommand, flag);

        if (rc <= 0) {
            /* invalid command or not repeatable, forget it */
            lastcommand[0] = 0;
        }
    }
#endif /*CONFIG_SYS_HUSH_PARSER*/
}


阅读(2107) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~