u-boot分析

4.Bootloader:u-boot.2009.08分析与移植

4.1:分析u-boot根目录下的Makefile,可以看到uboot编译的顺序如下,由此可知编译执行的第一个文件是cpu/$(CPU)/start.o,又由于是基于

arm920t架构的,所以去分析cpu/arm920t/start.S源文件。

# U-Boot objects....order is important (i.e. start must be first)

OBJS  = cpu/$(CPU)/start.o

OBJS := $(addprefix $(obj),$(OBJS))

LIBS  = lib_generic/libgeneric.a

LIBS += lib_generic/lzma/liblzma.a

LIBS += lib_generic/lzo/liblzo.a

LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \

"board/$(VENDOR)/common/lib$(VENDOR).a"; fi)

LIBS += cpu/$(CPU)/lib$(CPU).a

LIBS += lib_$(ARCH)/lib$(ARCH).a

LIBS += fs/...(.a)

LIBS += net/libnet.a

LIBS += disk/libdisk.a

LIBS += drivers/...(.a)

LIBS += common/libcommon.a

LIBS += libfdt/libfdt.a

LIBS += api/libapi.a

LIBS += post/libpost.a

LIBS := $(addprefix $(obj),$(LIBS))

4.2:分析cpu/arm920t/start.S源文件:由ARM架构可知程序的执行顺序是开发板一上电即从零地址开始执行,在零地址存放的是一条复位异常中断处

理,依次分析可知程序从上电开始的执行依次如下:设置处理器模式、关闭看门狗、关闭中断、设置分频系数比、系统初始化(flush I/D cache、disable MMU

、内存sdram相关初始化)、重定位代码(从flash复制uboot代码到SDRAM中)、初始化堆栈、清除bss段、跳转到第二阶段的C语言代码入口函数start_armboot处

执行。

(1).globl _start

_start:
b       start_code

(2)start_code:

/* set the cpu to SVC32 mode*/

/* turn off the watchdog */

/* mask all IRQs by setting all bits in the INTMR - default */

/* setup FCLK:HCLK:PCLK */

bl cpu_init_crit  /*do sys-critical inits only at reboot*/

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

/* relocate U-Boot from nor flash to RAM */

/* Set up the stack */

/* Clear bss */

/*  jump to second stage */

ldr pc, _start_armboot

_start_armboot:
.word start_armboot

4.3:分析/lib_arm/board.c里的start_armboot函数:

gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

memset ((void*)gd, 0, sizeof (gd_t));等,初始化gd_t结构体指针gd,并初始化。

typedef int (init_fnc_t) (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,

};

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

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

hang ();

}

},通过一个for循环来依次访问函数指针数组init_sequence中的成员函数,进一步完成相关初始化和相关设置。

nand_init();
/* go init the NAND */,初始化nand flash。

serial_initialize();   ,初始化串口。

/* 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 */,在无限for循环内,执行main_loop函数。

4.4:分析/common/main.c里的main_loop函数:处理uboot命令。

/*

* Main Loop for Monitor Command Processing

*/

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 ("<INTERRUPT>\n");

else

rc = run_command (lastcommand, flag);

if (rc <= 0) {

/* invalid command or not repeatable, forget it */

lastcommand[0] = 0;

}

}

根据输入的命令格式,解析命令参数,执行命令(执行run_command函数),/commmon/main.c里的run_command函数,根据命令表结构体cmd_tbl_s来找

到输入命令所对应的实现函数。

/*

* Monitor Command Table

*/

struct cmd_tbl_s {

char *name;
/* Command Name */

int maxargs;
/* maximum number of arguments */

int repeatable;
/* autorepeat allowed? */

/* Implementation function
*/

int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);

char *usage;
/* Usage message (short)
*/

#ifdef
CONFIG_SYS_LONGHELP

char *help;
/* Help  message (long)
*/

#endif

#ifdef CONFIG_AUTO_COMPLETE

/* do auto completion on the arguments */

int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);

#endif

};

typedef struct cmd_tbl_s
cmd_tbl_t;

cmd_tbl_t *cmdtp;

/* OK - call function to do the command */

if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {

rc = -1;

}//至此,根据不同的uboot命令,去执行不同的实现函数。

4.5:uboot启动linux操作系统的命令是bootm,uboot的bootm命令的实现文件是cmd_bootm.c,所以接着来分析/common/cmd_bootm.c文件:命令实

现的格式如下:其中命令是bootm,实现函数是do_bootm函数。

#define Struct_Section  __attribute__ ((unused,section (".u_boot_cmd")))

#ifdef  CONFIG_SYS_LONGHELP

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \

cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}

#else /* no long help info */

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \

cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage}

#endif
/* CONFIG_SYS_LONGHELP */

U_BOOT_CMD(

bootm,
CONFIG_SYS_MAXARGS, 1,
do_bootm,

"boot application image from memory",

"[addr [arg ...]]\n    - boot application image stored in memory\n"

"\tpassing arguments ‘arg ...‘; when booting a Linux kernel,\n"

"\t‘arg‘ can be the address of an initrd image\n"

"\tbdt     - OS specific bd_t processing\n"

"\tcmdline - OS specific command line processing/setup\n"

"\tprep    - OS specific prep before relocation or go\n"

"\tgo      - start OS"

);

4.6:分析/common/cmd_bootm.c中的do_bootm函数:

static bootm_headers_t images;
/* pointers to os/initrd/fdt images */

int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);

disable_interrupts();

usb_stop();

icache_disable();

dcache_disable();

ret = bootm_load_os(images.os, &load_end, 1); //加载具体的操作系统

images.os.os == IH_OS_LINUX  //如果具体加载的是linux,则有以下

boot_os_fn
*boot_fn;

boot_fn = boot_os[images.os.os];//boot_fn指针指向boot_os数组中的特定类型函数

boot_fn(0, argc, argv, &images);//调用do_bootm_linux函数

boot_os_fn * boot_os[] = {

#ifdef CONFIG_BOOTM_LINUX

[IH_OS_LINUX] = do_bootm_linux,

#endif

... ...

}; //由此可知,若加载的是linux系统,则调用do_bootm_linux函数,do_bootm_linuxm在/lib_arm/bootm.c文件里

4.7:分析/lib_arm/bootm.c中的do_bootm_linux函数:

void (*theKernel)(int zero, int arch, uint params);

theKernel = (void (*)(int, int, uint))images->ep;//images->ep(entry point)

setup_start_tag (bd);

... ...

setup_end_tag (bd);

theKernel (0, machid, bd->bi_boot_params); //至此,跳转到linux内核开始执行,系统启动起来

/* does not return */

return 1;

u-boot分析

时间: 2024-08-29 12:19:39

u-boot分析的相关文章

android uboot中的mmc命令

一:mmc的命令如下: 1:对mmc读操作 mmc read addr blk# cnt 2:对mmc写操作 mmc write addr blk# cnt 3:对mmc擦除操作 mmc erase blk# cnt 4:重新搜索mmc设备 mmc rescan 5:列出mmc的分区 mmc part - lists available partition oncurrent mmc device 6:查看当前的设备号,或者设置设备号及分区 mmc dev [dev] [part] - show

uboot中的mmc命令

一:mmc的命令例如以下: 1:对mmc读操作 mmc read addr blk# cnt 2:对mmc写操作 mmc write addr blk# cnt 3:对mmc擦除操作 mmc erase blk# cnt 4:又一次搜索mmc设备 mmc rescan 5:列出mmc的分区 mmc part - lists available partition oncurrent mmc device 6:查看当前的设备号,或者设置设备号及分区 mmc dev [dev] [part] - s

spring boot应用启动原理分析

spring boot quick start 在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个Web Server. 如果之前没有使用过spring boot可以通过下面的demo来感受下. 下面以这个工程为例,演示如何启动Spring boot项目: git clone [email protected]:hengyunabc/spring-boot-demo.git mvn spring-b

Spring Boot实战与原理分析

1:Spring Boot概述与课程概要介绍 2:Spring4 快速入门 3:Spring4 扩展分析(一) 4:Spring4 扩展分析(二) 5:Spring Boot 快速入门 6:Spring Boot 配置分析(一) 7:Spring Boot 配置分析(二) 8:Spring Boot 自动配置 9:Spring Boot @Enable*注解的工作原理 10:Spring Boot @EnableAutoConfiguration深入分析 11:Spring Boot 事件监听

Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机

文章目录 1. 开箱即用,内藏玄机 2. 总结 3. 源代码 Spring Boot提供了很多"开箱即用"的依赖模块,那么,Spring Boot 如何巧妙的做到开箱即用,自动配置的呢? 开箱即用,内藏玄机 Spring Boot提供了很多"开箱即用"的依赖模块,都是以spring-boot-starter-xx作为命名的.例如,之前提到的 spring-boot-starter-redis.spring-boot-starter-data-mongodb.spri

Spring Boot实战与原理分析视频课程

1.Spring Boot概述与课程概要介绍 2.Spring4 快速入门 3.Spring4 扩展分析(一) 4.Spring4 扩展分析(二) 5.Spring Boot 快速入门 6.Spring Boot 配置分析(一) 7.Spring Boot 配置分析(二) 8.Spring Boot 自动配置 9.Spring Boot @Enable*注解的工作原理 10.Spring Boot @EnableAutoConfiguration深入分析 11.Spring Boot 事件监听

spring boot实战(第十五篇)嵌入tomcat源码分析

嵌入tomcat源码分析 在启动spring boot工程时利用@SpringBootApplication注解,该注解启动@EnableAutoConfiguration自动配置,加载META-INF/spring.factories文件 # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.admin.Spri

Spring Boot 揭秘与实战 源码分析 - 工作原理剖析

文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoConfiguration4. 扩展阅读 3.1. 核心注解 3.2. 注入 Bean 结合<Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机>一文,我们再来深入的理解 Spring Boot 的工作原理. 在<Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏

理解boot.img与逆向分析Android/linux内核

一些尝试和理解. 1>提取boot.img: 其中,msm代表是高通的芯片,msm_sdcc.1是外接的SD卡挂载的目录,by-name指的是这个sd卡分区的名称.下面几行代表每个分区存储的东西. 记得提前su,dd if=/dev/block/mmcblk0p8 of=/data/local/tmp/boot.img.将boot.img dump出来 adb root获得root权限,将boot.img 移到pc上. 2>boot.img格式分析 如system/core/mkbootimg

nova boot代码流程分析(三):nova与neutron的交互(2)

继续<nova boot代码流程分析(三):nova与neutron的交互(1)>的分析. #/nova/virt/libvirt/driver.py:LibvirtDriver # NOTE(ilyaalekseyev): Implementation like in multinics # for xenapi(tr3buchet) def spawn(self, context, instance, image_meta, injected_files, admin_password,