Uboot启动代码解析

合集下载

uboot代码完全解析

uboot代码完全解析
1.相关文件 ....................................................................................................................................28 2.数据结构 ....................................................................................................................................28 3.ENV 的初始化...........................................................................................................................30
目录
u-boot-1.1.6 之 cpu/arm920t........................................................................2 u-boot 中.lds 连接脚本文件的分析 ...................................................................................................12 分享一篇我总结的 uboot 学习笔记(转) .....................................................................................15 U-BOOT 内存布局及启动过程浅析 ...................................................................................................22 u-boot 中的命令实现 ..........................................................................................................................25 U-BOOT 环境变量实现 ........................................................................................................................28

u-boot启动分析

u-boot启动分析

背景:Board →ar7240(ap93)Cpu →mips1、首先弄清楚什么是u-bootUboot是德国DENX小组的开发,它用于多种嵌入式CPU的bootloader程序, uboot不仅支持嵌入式linux系统的引导,当前,它还支持其他的很多嵌入式操作系统。

除了PowerPC系列,还支持MIPS,x86,ARM,NIOS,XScale。

2、下载完uboot后解压,在根目录下,有如下重要的信息(目录或者文件):以下为为每个目录的说明:Board:和一些已有开发板有关的文件。

每一个开发板都以一个子目录出现在当前目录中,子目录存放和开发板相关的配置文件。

它的每个子文件夹里都有如下文件(以ar7240/ap93为例):MakefileConfig.mkAp93.c 和板子相关的代码Flash.c Flash操作代码u-boot.lds 对应的链接文件common:实现uboot命令行下支持的命令,每一条命令都对应一个文件。

例如bootm命令对应就是cmd_bootm.ccpu:与特定CPU架构相关目录,每一款Uboot下支持的CPU在该目录下对应一个子目录,比如有子目录mips等。

它的每个子文件夹里都有入下文件:MakefileConfig.mkCpu.c 和处理器相关的代码sInterrupts.c 中断处理代码Serial.c 串口初始化代码Start.s 全局开始启动代码Disk:对磁盘的支持Doc:文档目录。

Uboot有非常完善的文档。

Drivers:Uboot支持的设备驱动程序都放在该目录,比如网卡,支持CFI的Flash,串口和USB等。

Fs:支持的文件系统,Uboot现在支持cramfs、fat、fdos、jffs2和registerfs。

Include:Uboot使用的头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件。

该目下configs目录有与开发板相关的配置文件,如ar7240_soc.h。

U-boot解析

U-boot解析

u-boot源码解析u-boot介绍Uboot是德国DENX小组的开发用于多种嵌入式CPU的bootloader程序, UBoot不仅仅支持嵌入式Linux系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS 嵌入式操作系统。

UBoot除了支持PowerPC系列的处理器外,还能支持MIPS、 x86、ARM、NIOS、XScale等诸多常用系列的处理器。

board:和一些已有开发板有关的文件。

每一个开发板都以一个子目录出现在当前目录中,子目录中存放与开发板相关的配置文件。

它的每个子文件夹里都有如下文件:makefileconfig.mksmdk2410.c 和板子相关的代码(以smdk2410为例)flash.c Flash操作代码memsetup.s 初始化SDRAM代码u-boot.lds 对应的连接文件common:实现uboot命令行下支持的命令,每一条命令都对应一个文件。

例如bootm命令对应就是cmd_bootm.c。

cpu:与特定CPU架构相关目录,每一款Uboot下支持的CPU在该目录下对应一个子目录,比如有子目录arm920t等。

cpu/ 它的每个子文件夹里都有如下文件:makefileconfig.mkcpu.c 和处理器相关的代码interrupts.c 中断处理代码serial.c 串口初始化代码start.s 全局开始启动代码disk:对磁盘的支持。

doc:文档目录。

Uboot有非常完善的文档,推荐大家参考阅读。

drivers:Uboot支持的设备驱动程序都放在该目录,比如各种网卡、支持CFI的Flash、串口和USB等。

fs: 支持的文件系统,Uboot现在支持cramfs、fat、fdos、jffs2和registerfs。

include:Uboot使用的头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件。

UBOOT源码分析

UBOOT源码分析

UBOOT源码分析UBOOT是一种开放源码的引导加载程序。

作为嵌入式系统启动的第一阶段,它负责初始化硬件设备、设置系统环境变量、加载内核镜像以及跳转到内核开始执行。

Uboot的源码是开放的,让我们可以深入了解其内部工作机制和自定义一些功能。

Uboot源码的文件组织结构非常清晰,主要分为三个大类:目录、文件和配置。

其中目录包含了一系列相关的文件,文件存放具体的源码实现代码,配置文件包含了针对特定硬件平台的配置选项。

Uboot源码的核心部分是启动代码,位于arch目录下的CPU架构相关目录中。

不同的CPU架构拥有不同的启动代码实现,如arm、x86等。

这些启动代码主要包括以下几个关键功能:1. 初始化硬件设备:Uboot首先需要初始化硬件设备,例如设置时钟、中断控制器、串口等设备。

这些初始化操作是在启动代码中完成的。

通过查看该部分代码,我们可以了解硬件的初始化过程,以及如何配置相关寄存器。

2. 设置启动参数:Uboot启动参数存储在一个称为"bd_info"的数据结构中,它包含了一些关键的设备和内存信息,例如DRAM大小、Flash 大小等。

这些参数是在启动代码中设置的,以便内核启动时能够正确识别硬件情况。

3. 加载内核镜像:Uboot负责加载内核镜像到内存中,以便内核可以正确执行。

在启动代码中,会通过读取Flash设备或者网络等方式,将内核镜像加载到指定的内存地址处。

加载过程中,可能会进行一些校验和修正操作,以确保内核数据的完整性。

4. 启动内核:在内核镜像加载完成后,Uboot会设置一些寄存器的值,并执行一个汇编指令,跳转到内核开始执行。

此时,Uboot的使命即结束,控制权交由内核处理。

除了启动代码,Uboot源码中还包含了许多其他功能模块,如命令行解析器、存储设备驱动、网络协议栈等。

这些功能模块可以根据需求进行配置和编译,以满足不同平台的需求。

例如,可以通过配置文件选择启用一些功能模块,或者自定义一些新的功能。

MIPS uboot代码注释

MIPS uboot代码注释

MIPS U-Boot——by M.CUboot启动流程关中断设置kseg0no cache初始化gp指针lowlevel_init mips_cache_reset 设置kseg0cache mips_cache_lockBoard_init_f relocate_code Board_init_r启动内核根据CPU rate初始化外部时钟、内存初始化cachecache未初始化前不能用cache已初始化设置临时cache栈把uboot程序从flash搬到ram执行start.Smtc0zero, CP0_WATCHLO mtc0zero, CP0_WATCHHI 清除硬件数据断点,防止产生调试断点,导致程序停止。

芯片在复位后,某些寄存器的内容也许是你想要的结果,但是谁知道呢,为了保证准确无误,最好还是重新进行手动初始化mfc0k0, CP0_STATUSli k1, ~ST0_IEand k0, k1mtc0k0, CP0_STATUS禁止全局中断mtc0zero, CP0_CAUSE初始化异常寄存器,清除异常原因指示mtc0zero, CP0_COUNTmtc0zero, CP0_COMPARE初始化时钟寄存器,防止产生计数器中断li t0, CONF_CM_UNCACHEDmtc0t0, CP0_CONFIG设置kseg0区不经过cache。

cache需要先初始化才能使用。

bal1fnop.word_gp1:lw gp, 0(ra)bal分支调用,ra返回地址指向下下一条指令,即.word _gp把.word_gp的存储位置载入gp寄存器,即设置GOT表的起始位置la t9, lowlevel_init jalr t9nop 根据CPU rate初始化外部时钟、内存。

lowlevel_init函数定义见lowlevel_init.Sla t9, mips_cache_reset jalr t9nop 初始化高速缓存cache。

uboot笔记uboot命令分析+实现

uboot笔记uboot命令分析+实现

uboot笔记uboot命令分析+实现uboot笔记:uboot命令分析+实现Ubootuboot命令分析+实现先贴⼀个重要结构,位于uboot/include/command.h,这个结构代表每个uboot命令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 CFG_LONGHELPchar *help; /* Help message (long) 长的帮助信息*/#endif#ifdef CONFIG_AUTO_COMPLETE/* do auto completion on the arguments */ int (*complete)(intargc, char *argv[], charlast_char, intmaxv, char *cmdv[]); #endif};typedefstruct cmd_tbl_s cmd_tbl_t;============================================================uboot的第⼀阶段:硬件相关初始化0.reset执⾏arm920t/start.s 过程如下1.设置cpu svc管理模式2.关看门狗中断,mmu等3.设置时钟,sdram,外部总线4.代码重定位,搬运代码,从flash到sdram5.设置栈,bss段清零, bss⽤于未初始化的全局变量和静态变量6.ldr pc, _start_armboot即进⼊uboot启动的第⼆阶段,调⽤c函数start_armboot()从start_armboot开始经过⼀系列外设初始化⽐如falsh_initnand_init...最后循环调⽤mian_loop()main_loop主要流程{1. ⽣成环境变量mtdparts, 调⽤mtdparts_init2. 在启动过程中若⽆空格键按下则boot_zImage,即run_command(getenv("bootcmd"),0)有空格键按下则run_command("menu",0)3. shell过程,读取⽤户的输⼊并执⾏相应的命令{从控制台获得命令,保存在全局变量comsole_buffer中解析命令⾏字符串,分割命令与参数,最后执⾏run_command(...); }}也就是说在mian_loop中,是处理环境变量和控制台⼈机交互,mian_loop调⽤readline ()读取命令⾏到console_buffer,再把console_buffer复制到lastcommand中去,还要设置flag,最后调⽤run_command (lastcommand, flag)函数,run_command (lastcommand, flag)函数中,⾸先定义cmd_tbl_t *cmdtp,再解析命令⾏。

uboot源码分析(2)uboot环境变量实现简析

uboot源码分析(2)uboot环境变量实现简析

uboot源码分析(2)uboot环境变量实现简析uboot 环境变量实现简析----------基于u-boot-2010.03u-boot的环境变量是使⽤u-boot的关键,它可以由你⾃⼰定义的,但是其中有⼀些也是⼤家经常使⽤,约定熟成的,有⼀些是u-boot⾃⼰定义的,更改这些名字会出现错误,下⾯的表中我们列出了⼀些常⽤的环境变量:bootdelay 执⾏⾃动启动的等候秒数baudrate 串⼝控制台的波特率netmask 以太⽹接⼝的掩码ethaddr 以太⽹卡的⽹卡物理地址bootfile 缺省的下载⽂件bootargs 传递给内核的启动参数bootcmd ⾃动启动时执⾏的命令serverip 服务器端的ip地址ipaddr 本地ip 地址stdin 标准输⼊设备stdout 标准输出设备stderr 标准出错设备上⾯只是⼀些最基本的环境变量,请注意,板⼦⾥原本是没有环境变量的,u-boot的缺省情况下会有⼀些基本的环境变量,在你执⾏了saveenv之后,环境变量会第⼀次保存到flash或者eeprom中,之后你对环境变量的修改,保存都是基于保存在flash中的环境变量的操作。

环境变量可以通过printenv命令查看环境变量的设置描述,通过setenv 命令进⾏重新设置,设置完成后可以通过saveenv将新的设置保存在⾮易失的存储设备中(nor flash 、nand flash 、eeprom)。

例如:setenv bootcmd "nand read 0x30008000 0x80000 0x500000;bootm 0x30008000"saveenv通过这两条命令就完成了环境变量bootcmd的重新设置,并讲其保存在固态存储器中。

下⾯简单分析下uboot中环境变量的实现流程。

uboot启动后,执⾏玩start.S中的汇编程序,将跳⼊board.c 中定义的start_arm_boot()函数中,在该函数中,uboot讲完成板⼦外设和相关系统环境的初始化,然后进⼊main_loop循环中进⾏系统启动或者等待与⽤户交互,这其中就包括环境变量的初始化和重定位。

Uboot代码分析

Uboot代码分析

UBOOT分析报告整理修改中2011-3-10目录Uboot介绍 (2)Uboot 启动流程 (2)I.Uboot启动过程 (2)II.Uboot启动汇编代码部分 (3)III.Uboot启动C代码部分 (4)IV.Uboot中初试环境变量位置及调整方法 (6)V.Uboot c代码中gd(全局数据)的保存位置 (6)Uboot的编译生成 (6)Uboot 汇编代码探究 (6)Uboot C代码探究 (6)一、Uboot下命令实现 (6)二、env_* 环境变量操作函数实现(如saveenv) (7)1、env_sf.c环境变量要保存在spi flash时调用 (7)Uboot 内部宏定义 (7)1.DECLARE_GLOBLE_DATA_PTR (7)2. CONFIG_ENV_ADDR (8)3. CONFIG_ENV_OFFSET (8)4. CONFIG_ENV_SECT_SIZE (8)5. CONFIG_ENV_IS_EMBEDDED (8)6. CONFIG_ENV_IS_IN_NAND (9)Uboot 目录结构功能 (10)Uboot介绍Uboot全写Universal Boot Loader,是芯片加电或复位后进入操作系统之前运行的一段代码,用于完成从硬件到操作系统的过度。

Uboot 启动流程I.Uboot启动过程Uboot启动过程主要分为7块:1.CPU初始化:设置CPU工作模式与工作频率2.时钟、串口、内存初始化3.划分内存:分配堆、栈,设置环境变量位置、Uboot自身代码位置、指定程序代码入口4.根据Uboot启动选项将自身加载至内存5.加载环境变量6.初始化flash pci以及网口等7.进入命令行或者根据环境变量启动Linux的kernelUboot的启动过程中会有两大步骤,一部分是汇编代码部分,一部分是C代码部分,由于运行C代码部分需要配置堆栈所以前一部分初始化主要由汇编语言完成。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

U-Boot启动过程开发板上电后,执行U-Boot的第一条指令,然后顺序执行U-Boot 启动函数。

看一下board/smdk2410/u-boot.lds这个链接脚本,可以知道目标程序的各部分链接顺序。

第一个要链接的是cpu/arm920t/start.o,那么U-Boot的入口指令一定位于这个程序中。

下面分两阶段介绍启动流程:第一阶段1.cpu/arm920t/start.S这个汇编程序是U-Boot的入口程序,开头就是复位向量的代码。

_start: b reset //复位向量ldr pc, _undefined_instructionldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _not_usedldr pc, _irq //中断向量ldr pc, _fiq //中断向量…/* the actual reset code */reset: //复位启动子程序/* 设置CPU为SVC32模式 */mrs r0,cpsrbic r0,r0,#0x1forr r0,r0,#0xd3msr cpsr,r0/* 关闭看门狗 */…………relocate: /* 把U-Boot重新定位到RAM */ adr r0, _start /* r0是代码的当前位置 */ldr r1, _TEXT_BASE /*_TEXT_BASE是RAM中的地址 */ cmp r0, r1 /* 比较r0和r1,判断当前是从Flash启动,还是RAM */beq stack_setup /* 如果r0等于r1,跳过重定位代码 *//* 准备重新定位代码 */ldr r2, _armboot_startldr r3, _bss_startsub r2, r3, r2 /* r2 得到armboot的大小 */ add r2, r0, r2 /* r2 得到要复制代码的末尾地址 */ copy_loop: /* 重新定位代码 */ldmia r0!, {r3-r10} /*从源地址[r0]复制 */stmia r1!, {r3-r10} /* 复制到目的地址[r1] */cmp r0, r2 /* 复制数据块直到源数据末尾地址[r2] */ ble copy_loop/* 初始化堆栈等 */stack_setup:ldr r0, _TEXT_BASE /* 上面是128 KiB重定位的u-boot */ sub r0, r0, #CFG_MALLOC_LEN /* 向下是内存分配空间 */ sub r0, r0, #CFG_GBL_DATA_SIZE /* 然后是bdinfo结构体地址空间 */#ifdef CONFIG_USE_IRQsub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endifsub sp, r0, #12 /* 为abort-stack预留3个字 */ clear_bss:ldr r0, _bss_start /* 找到bss段起始地址 */ldr r1, _bss_end /* bss段末尾地址 */mov r2, #0x00000000 /* 清零 */clbss_l:str r2, [r0]/* bss段地址空间清零循环... */add r0, r0, #4cmp r0, r1bne clbss_l/* 跳转到start_armboot函数入口,_start_armboot字保存函数入口指针 */ldr pc, _start_armboot_start_armboot: .word start_armboot //start_armboot 函数在lib_arm/board.c中实现第二阶段2.lib_arm/board.cstart_armboot是U-Boot执行的第一个C语言函数,完成系统初始化工作,进入主循环,处理用户输入的命令。

3.init_sequence[]init_sequence[]数组保存着基本的初始化函数指针。

init_fnc_t *init_sequence[] = {cpu_init, /* 基本的处理器相关配置-- cpu/arm920t/cpu.c */board_init, /* 基本的板级相关配置-- board/smdk2410/smdk2410.c */interrupt_init, /* 初始化中断处理--cpu/arm920t/s3c24x0/interrupt.c */env_init, /* 初始化环境变量 -- common/cmd_flash.c */init_baudrate, /* 初始化波特率设置 -- lib_arm/board.c */serial_init, /* 串口通讯设置-- cpu/arm920t/s3c24x0/serial.c */console_init_f, /* 控制台初始化阶段 1 -- common/console.c */display_banner, /* 打印u-boot信息-- lib_arm/board.c */dram_init, /* 配置可用的RAM -- board/smdk2410/smdk2410.c */display_dram_config, /* 显示RAM的配置大小-- lib_arm/board.c */NULL,};void start_armboot (void){/* 顺序执行init_sequence数组中的初始化函数 */for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {if ((*init_fnc_ptr)() != 0) {hang ();}}/*配置可用的Flash */size = flash_init ();display_flash_config (size);/* _armboot_start 在u-boot.lds链接脚本中定义 */ mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);/* 配置环境变量*/env_relocate ();/* 从环境变量中获取IP地址 */gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");/* 以太网接口MAC 地址 */……devices_init (); /* 获取列表中的设备 */jumptable_init ();console_init_r (); /* 完整地初始化控制台设备*/enable_interrupts (); /* 使能中断处理 *//* 通过环境变量初始化 */if ((s = getenv ("loadaddr")) != NULL) {load_addr = simple_strtoul (s, NULL, 16); }/* main_loop()循环不断执行 */for (;;){main_loop (); /* 主循环函数处理执行用户命令-- common/main.c */}命令实现U-Boot作为Bootloader,具备多种引导内核启动的方式。

常用的go和bootm命令可以直接引导内核映像启动。

U-Boot与内核的关系主要是内核启动过程中参数的传递。

1.go命令的实现/* common/cmd_boot.c */int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ulong addr, rc;int rcode = 0;if (argc < 2) {printf ("Usage:\n%s\n", cmdtp->usage);return 1;}addr = simple_strtoul(argv[1], NULL, 16);printf ("## Starting application at 0x%08lX ...\n", addr);rc = ((ulong (*)(int, char []))addr) (--argc, &argv[1]); /* 运行程序 */if (rc != 0) rcode = 1;printf ("## Application terminated, rc = 0x%lX\n", rc); /*如果是运行linux,这条指令是否能运行?*/return rcode;}go命令调用do_go()函数,跳转到某个地址执行的。

如果在这个地址准备好了自引导的内核映像,就可以启动了。

尽管go命令可以带变参,实际使用时不用来传递参数。

2.bootm命令的实现/* common/cmd_bootm.c */int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){…………/* 检查头部 */if (crc32 (0, (uchar *)data, len) != checksum) { puts ("Bad Header Checksum\n");SHOW_BOOT_PROGRESS (-2);return 1;}…………/*解压缩*/switch (hdr->ih_comp) {case IH_COMP_NONE:if(ntohl(hdr->ih_load) == addr) {printf (" XIP %s ... ", name);} else {#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)size_t l = len;void *to = (void *)ntohl(hdr->ih_load);void *from = (void *)data;printf (" Loading %s ... ", name);while (l > 0) {size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;WATCHDOG_RESET();memmove (to, from, tail);to += tail;from += tail;l -= tail;}#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ }break;case IH_COMP_GZIP:printf (" Uncompressing %s ... ", name);if (gunzip ((void *)ntohl(hdr->ih_load), unc_len,(uchar *)data, &len) != 0) {puts ("GUNZIP ERROR - must RESET board to recover\n");SHOW_BOOT_PROGRESS (-6);do_reset (cmdtp, flag, argc, argv);}break;#ifdef CONFIG_BZIP2case IH_COMP_BZIP2:printf (" Uncompressing %s ... ", name);/** If we've got less than 4 MB of malloc() space,* use slower decompression algorithm which requires* at most 2300 KB of memory.*/i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load),&unc_len, (char *)data, len,CFG_MALLOC_LEN < (4096 * 1024), 0);if (i != BZ_OK) {printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i);SHOW_BOOT_PROGRESS (-6);udelay(100000);do_reset (cmdtp, flag, argc, argv);}break;#endif /* CONFIG_BZIP2 */default:if (iflag)enable_interrupts();printf ("Unimplemented compression type %d\n", hdr->ih_comp);SHOW_BOOT_PROGRESS (-7);return 1;}}………………switch (hdr->ih_os) {default: /* handled by (original) Linux case */ case IH_OS_LINUX:do_bootm_linux (cmdtp, flag, argc, argv,addr, len_ptr, verify);break;case IH_OS_NETBSD:do_bootm_netbsd (cmdtp, flag, argc, argv,addr, len_ptr, verify);break;case IH_OS_RTEMS:do_bootm_rtems (cmdtp, flag, argc, argv,addr, len_ptr, verify);break;case IH_OS_VXWORKS:do_bootm_vxworks (cmdtp, flag, argc, argv,addr, len_ptr, verify);break;case IH_OS_QNX:do_bootm_qnxelf (cmdtp, flag, argc, argv,addr, len_ptr, verify);break;}bootm命令调用do_bootm函数。

相关文档
最新文档