您的位置:首页 > 其它

uboot分析第二阶段学习笔记

2013-11-15 12:23 537 查看
=====================================================================

第二阶段工作

1 从FLASH读出内核

2 启动内核

======================================================================

第一种方法是从nand启动 先执行nand_spl\Nand_boot.c

后从arc/arm/lib下的boot.c作一些初始化的工作

以下的arc/arm/lib下的boot.c

/*

* (C) Copyright 2002-2006

* Wolfgang Denk, DENX Software Engineering,
wd@denx.de.

*

* (C) Copyright 2002

* Sysgo Real-Time Solutions, GmbH <www.elinos.com>

* Marius Groeger <mgroeger@sysgo.de>

*

* See file CREDITS for list of people who contributed to this

* project.

*

* This program is free software; you can redistribute it and/or

* modify it under the terms of the GNU General Public License as

* published by the Free Software Foundation; either version 2 of

* the License, or (at your option) any later version.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program; if not, write to the Free Software

* Foundation, Inc., 59 Temple Place, Suite 330, Boston,

* MA 02111-1307 USA

*/

/*

* 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 <common.h>

#include <command.h>

#include <malloc.h>

#include <stdio_dev.h>

#include <timestamp.h>

#include <version.h>

#include <net.h>

#include <serial.h>

#include <nand.h>

#include <onenand_uboot.h>

#include <mmc.h>

#ifdef CONFIG_BITBANGMII

#include <miiphy.h>

#endif

#ifdef CONFIG_DRIVER_SMC91111

#include "../drivers/net/smc91111.h"

#endif

#ifdef CONFIG_DRIVER_LAN91C96

#include "../drivers/net/lan91c96.h"

#endif

#if defined(CONFIG_MINI6410_LED)

#include <asm/arch/s3c6400.h>

#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

#ifndef CONFIG_IDENT_STRING

#define CONFIG_IDENT_STRING ""

#endif

const char version_string[] =

U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")"CONFIG_IDENT_STRING;

#ifdef CONFIG_DRIVER_RTL8019

extern void rtl8019_get_enetaddr (uchar * addr);

#endif

#if defined(CONFIG_HARD_I2C) || \

defined(CONFIG_SOFT_I2C)

#include <i2c.h>

#endif

/************************************************************************

* Coloured LED functionality

************************************************************************

* May be supplied by boards if desired

*/

void inline __coloured_LED_init (void) {}

void coloured_LED_init (void) __attribute__((weak, alias("__coloured_LED_init")));

void inline __red_LED_on (void) {}

void red_LED_on (void) __attribute__((weak, alias("__red_LED_on")));

void inline __red_LED_off(void) {}

void red_LED_off(void) __attribute__((weak, alias("__red_LED_off")));

void inline __green_LED_on(void) {}

void green_LED_on(void) __attribute__((weak, alias("__green_LED_on")));

void inline __green_LED_off(void) {}

void green_LED_off(void) __attribute__((weak, alias("__green_LED_off")));

void inline __yellow_LED_on(void) {}

void yellow_LED_on(void) __attribute__((weak, alias("__yellow_LED_on")));

void inline __yellow_LED_off(void) {}

void yellow_LED_off(void) __attribute__((weak, alias("__yellow_LED_off")));

void inline __blue_LED_on(void) {}

void blue_LED_on(void) __attribute__((weak, alias("__blue_LED_on")));

void inline __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)

{

char tmp[64]; /* long enough for environment variables */

int i = getenv_f("baudrate", tmp, sizeof (tmp));

gd->baudrate = (i > 0)

? (int) simple_strtoul (tmp, NULL, 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",

_TEXT_BASE,

_bss_start_ofs+_TEXT_BASE, _bss_end_ofs+_TEXT_BASE);

#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_SOFT_I2C)

static int init_func_i2c (void)

{

puts ("I2C: ");

i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);

puts ("ready\n");

return (0);

}

#endif

#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)

#include <pci.h>

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

int print_cpuinfo (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")));

init_fnc_t *init_sequence[] = {

#if defined(CONFIG_ARCH_CPU_INIT)

arch_cpu_init, /* basic arch cpu dependent setup */

#endif

#if defined(CONFIG_BOARD_EARLY_INIT_F)

board_early_init_f,

#endif

timer_init, /* initialize timer */

#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_SOFT_I2C)

init_func_i2c,

#endif

dram_init, /* configure available RAM banks */

#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)

arm_pci_init,

#endif

NULL,

};

void board_init_f (ulong bootflag)

{

bd_t *bd;

init_fnc_t **init_fnc_ptr;

gd_t *id;

ulong addr, addr_sp;

#if defined(CONFIG_MINI6410_LED)

s3c64xx_gpio * const gpio = s3c64xx_get_base_gpio();

#endif

/* Pointer is writable since we allocated a register for it */

gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);

/* compiler optimization barrier needed for GCC >= 3.4 */

__asm__ __volatile__("": : :"memory");

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

gd->mon_len = _bss_end_ofs;

for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {

if ((*init_fnc_ptr)() != 0) {

hang ();

}

}

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 + 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

*/

i = getenv_r ("pram", (char *)tmp, sizeof (tmp));

reg = (i > 0) ? simple_strtoul ((const char *)tmp, NULL, 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_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE))

/* reserve TLB table */

addr -= (4096 * 4);

/* round down to next 64 kB limit */

addr &= ~(0x10000 - 1);

gd->tlb_addr = addr;

debug ("TLB table at: %08lx\n", addr);

#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_VFD

# ifndef PAGE_SIZE

# define PAGE_SIZE 4096

# endif

/*

* reserve memory for VFD display (always full pages)

*/

addr -= vfd_setmem (addr);

gd->fb_base = addr;

#endif /* CONFIG_VFD */

#ifdef CONFIG_LCD

/* reserve memory for LCD display (always full pages) */

addr = lcd_setmem (addr);

gd->fb_base = 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);

#if defined(CONFIG_SKIP_RELOCATE_UBOOT)

addr = CONFIG_SYS_PHY_UBOOT_BASE; //FIXME

#endif

debug ("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);

#ifndef CONFIG_PRELOADER

/*

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

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

/* 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 -= 3;

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

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

memcpy (id, (void *)gd, sizeof (gd_t));

#if defined(CONFIG_MINI6410_LED)

debug ("relocate_code : text --> 0X%p gd --> 0X%p sp --> 0X%p \n",

(void *)addr, (void *)id, (void *)addr_sp);

gpio->GPKDAT &= ~0x20;

#endif

relocate_code (addr_sp, id, addr);

}

#if !defined(CONFIG_SYS_NO_FLASH)

static char *failed = "*** failed ***\n";

#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)

{

char *s;

bd_t *bd;

ulong malloc_start;

#if !defined(CONFIG_SYS_NO_FLASH)

ulong flash_size;

#endif

#if defined(CONFIG_MINI6410_LED)

s3c64xx_gpio * const gpio = s3c64xx_get_base_gpio();

#endif

gd = id;

bd = gd->bd;

gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */

monitor_flash_len = _bss_start_ofs;

debug ("monitor flash len: %08lX\n", monitor_flash_len);

board_init(); /* Setup chipselects */

#ifdef CONFIG_SERIAL_MULTI

serial_initialize();

#endif

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

/*对flash的初始化*/

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

#if !defined(CONFIG_SYS_NO_FLASH)

puts ("FLASH: ");

if ((flash_size = flash_init ()) > 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

*/

s = getenv ("flashchecksum");

if (s && (*s == 'y')) {

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

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

puts("MMC: ");

mmc_initialize(bd);

#endif

#ifdef CONFIG_HAS_DATAFLASH

AT91F_DataflashInit();

dataflash_print_info();

#endif

/*设置环境变量 默认的和在flash上保存的*/

/* initialize environment */

env_relocate ();

#ifdef CONFIG_VFD

/* must do this after the framebuffer is allocated */

drv_vfd_init();

#endif /* CONFIG_VFD */

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

/* set up exceptions */

interrupt_init ();

/* enable exceptions */

enable_interrupts ();

/* Perform network card initialisation if necessary */

#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_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

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

uchar memsz[32];

#ifdef CONFIG_PRAM

char *s;

if ((s = getenv ("pram")) != NULL) {

pram = simple_strtoul (s, NULL, 10);

} else {

pram = CONFIG_PRAM;

}

#else

pram=0;

#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", (bd->bi_memsize / 1024) - pram);

setenv ("mem", (char *)memsz);

}

#endif

#if defined(CONFIG_MINI6410_LED)

debug ("init finish! goto command loop!\n");

gpio->GPKDAT &= ~0x10;

#endif

{

uchar ramsize[10];

sprintf(ramsize, "%dM", (gd->ram_size/1024/1024));

if (setenv("ramsize", ramsize) != 0) {

printf("set ramsize error!!\n");

}

}

/**/

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

for (;;) {

/*跳转到common下的main.c*/

/*s = getenv ("bootdelay");取环境变量*/

/*s = getenv ("bootcmd");启动内核命令*/

/*run_command (s, 0);如果倒数计时时没有按空格,就执行此命令*/

/* This point is never reached 等待串口输入 */

/* for (;;);*/

/*cmd_tbl_s 命令的结构体*/

main_loop ();

}

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

}

void hang (void)

{

puts ("### ERROR ### Please RESET the board ###\n");

for (;;);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: