一、从本质上将,引导转载程序至少应提供以下功能

  (1)设置和初始化RAM

  (2)初始化一个串口

  (3)检测机器类型(machine type)

  (4)设置内核标签列表(tag list)

  (5)调用内核映像

二、.Uboot引导Linux内核时的启动状态

  zImage可以放在RAM的任意位置被调用,但是通常放在32KB处,因为前16KB用于存放Linux页表,不能占用。

  (1)停止所有的DMA

  (2)CPU寄存器配置:

    r0 = 0;

    r1 = 机器类型码

    r2 = 标签列表在系统RAM中的物理地址,或者设备树块(dtb)在系统RAM中的物理地址

  (3)CPU模式:必须在SVC模式,而且必须禁止所有类型的中断(irq和fiq)

  (4)缓存和MMU:MMU必须关闭,数据缓存必须关闭,指令缓存可关可不关

  引导加载程序应通过直接跳转到LInux镜像的第一条代码处来调用内核镜像

三、相关的bootm命令讲解

    在常用的 uboot 中完成一系列的初始化后最后通过 bootm 命令加载 linux 内核。bootm 将内核镜像从各种媒介中读出,存放在指定的位置;然后设置标记列表给   内核,传递参数;最后跳到内核的入口点去执行。

u-boot中每个命令都是通过 U_BOOT_CMD 宏来定义的,格式如下:

  U_BOOT_CMD(name,maxargs,repeatable,command,"usage","help")

各项参数的意义如下:

  (1) -- name:命令的名字,注意,它不是一个字符串(不要用双引号括起来);

  (2)-- maxargs:最大的参数个数;

  (3)-- repeatable:命令是否可以重复,可重复是指运行一个命令后,下次敲回车即可再次运行;

  (4)-- command:对应的函数指针,类型为(*cmd)(struct cmd_tbl_s *, int, int, char *[]);

  (5) -- usage:简单的使用说明,这是个字符串;

  (6)-- help:较详细的使用说明,这是个字符串。

bootm命令的源码路径为:u-boot源码路径/common/cmd_bootm.c,入口函数为d_bootm,(参考1中有对它的稍具体分析),该函数主要的工作流程是,通过bootm_start来获取内核镜像文件的信息,然后通过bootm_load_os函数来加载内核,

最后通过boot_fn来启动内核(这三个函数参考1中有对它的稍具体分析)。

四、kernel_entry函数

真正将控制权交给内核, 启动内核;满足arm架构linux内核启动时的寄存器设置条件:第一个参数为0 ;第二个参数为板子id需与内核中的id匹配,第三个参数为启动参数地址bi_boot_params 。主要操作:

(1)首先取出环境变量bootargs,这就是要传递给内核的参数。( u-boot 是通过标记列表向内核传递参数,标记在定义为tag,是一个结构体,在 arch/arm/include/asm/setup.h 中定义)

(2)调用setup_XXX_tag

参考1中有自己实现的6410的启动内核的例子

五、与启动系统相关的环境变量

  有bootcmd和bootargs,可保证在Uboot不重新编译的情况下可以以不同的方式启动

    ①bootcmd命令可以是好几个命令的集合,主要负责内核的引导工作,例如:bootcmd=movi read kernel 30008000;bootm 30008000,将内核拷贝到0x30008000的地方,然后从内存的0x30008000的地方启动内核;

    Uboot在完成一系列的初始化后,就开始加载内核到DRAM中,加载到的地址可由bootcmd命令指定,这个30008000是由内核的链接地址所确定的。

    ②bootargs命令主要是负责向内核传递参数,例如:bootargs=console=ttySAC2,115200 root=dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3,表示引导后控制台使用串口2,波特率115200,根文件系统在SD卡(0号

    设备)的第2分区,并且可读可写;进程1(init进程)的地址为/linuxrc,使用的根文件系统是ext3类型。

六、判断镜像的种类

  Uboot将Linux内核加载到DRAM的链接地址处后,就开始读镜像的头信息,找到MAGIC_NUM,以此来判断镜像的类型,镜像有两种格式:在Image和uImage

    zImage:Linux内核编译出来后,最先生成的是.elf格式的可执行文件,类似Windows下的.exe文件,其中包含了在操作系统下运行的大量信息,但是Linux内核是个逻辑程序,不需要这些信息,删掉他们后大小变为Image(.bin,

  已经可以直接运行了)文件,大小为原来的1/10,然后再对其进行压缩,就形成了zImage文件。这个zImage是自解压的,解压操作由其头部的解压程序来完成,不需要Uboot的参与。

    uImage是Uboot发明的一种镜像类型。它是在zImage的前面加上一些信息和一些校验信息,64字节。将zImage加工为uImage的工具在U-boot根目录下/tools中的mkimage程序,只需将其复制到/usr/local/bin/,编译内核时输

  入make uImage,然后就能产生uImage了。

  判断完镜像种类后 ,Uboot将对镜像头进行校验,然后再次读取头信息,从头信息中读取这个镜像的各种信息(比如镜像长度,镜像种类,入口地址等)。

七、新版的Uboot与内核之间的传参引导

  近年来的内核在启动时还需要设备树的dts文件,于是比较新的uboot都实现了传递dtb的功能,为了使能设备树,需要在编译U-boot的时候在config文件中加入:#define CONFIG_OF_LIBFDT

  一般分为三种情况:

  (1)利用U-boot的命令,在引导kernel时将dts传入。这种方式需要将dtb的地址写到uboot中(一般是环境变量),比如:首先将kernel载入内存,然后用fdt addr ${fdtaddr}命令将dtb载入内存,

   最后使用bootz ${loadaddr} ${initrdaddr} ${fdtaddr}来引导内核,(其中initrd是临时文件系统,嵌入式中用得极少)实际使用时用“-”代替:bootz ${loadaddr} - ${fdtaddr}

  (2)将dts和kernel打包为pImage。这种方式无需将dtb的地址写到uboot中(但uboot中要实现读pImage头部的功能),uboot可以去pImage的头部信息处读取到dtb的地址,然后传给传递给kernel。

  (3)启用kernel中”ARM_APPENDED_DTB”选项,该选项的意思是将dtb和kernel打包在一起,如此一来kernel启动时会去紧挨着它的地方寻找dtb,这样就不需要uboot来传递dtb地址了。

八、引导内核时可能出现的问题

  如果U-boot确认无误可以启动起来,而kernel的启动却出现了问题,那么一般是以下几种情况:

  1. 对于老版本的U-boot,有大概率是U-boot传给kernel参数的时候出了问题,着重注意一下创建tag的宏有没有正常定义,如CONFIG_CMDLINE_TAG、CONFIG_MTDPARTITION等
  2. kernel的链接地址与加载地址不符,链接地址可以通过kernel的head.S获知,详见kernel启动汇编阶段分析
  3. kernel的自解压地址与链接地址不符,zImage这类kernel格式必须把自己解压到自己的链接地址,自解压地址在kernel源码目录arch/arm/mach-xxxx/Makefile.boot文件中
  4. 环境变量未被正常设置

参考1:http://www.cnblogs.com/CoderTian/p/6006400.html

参考2:http://blog.csdn.net/qq_28992301/article/details/51873201

tiny4412-Uboot启动分析的更多相关文章

  1. 4412 uboot启动分析

    感谢sea1105, https://blog.csdn.net/sea1105/article/details/52142772 在学习过程中,由于tiny4412资料太过于少,因此参考210的视屏 ...

  2. tiny4412 u-boot 启动参数的设置

    参考 http://www.cnblogs.com/chenfulin5/p/5887552.html 制作SD卡 u-boot 编译完之后, 进入 u-boot 目录里面的 sd_fuse cd ~ ...

  3. Uboot启动分析之Start.S

    1.start.S引入 1.1.u-boot.lds中找到start.S入口 1)C语言中代码的分析第一步就是找到main.c,找到函数的入口 2)uboot中因为有汇编语言参与所以就不能像C一样.U ...

  4. u-boot简单学习笔记(三)——AR9331 uboot启动分析

    1.最开始系统上电后 ENTRY(_start)程序入口点是 _start  由board/ap121/u-boot.lds引导 2._start: cpu/mips/start.S 是第一个源程序文 ...

  5. tiny4412 串口驱动分析一 --- u-boot中的串口驱动

    作者:彭东林 邮箱:pengdonglin137@163.com 开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 ...

  6. Tiny4412 u-boot分析(2)u-boot启动流程

    从大方面来说,u-boot的启动分成两个阶段,第一个阶段主要的职责是准备初始化的环境,主要有以下几点 ①设置异常向量表 ②把CPU的工作模式设置为SVC32模式 ③关闭中断.MMU和cache ④关闭 ...

  7. 第二章、Tiny4412 U-BOOT移植二 启动分析【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37521481 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.启动过程说明 讲解启动过 ...

  8. tiny4412学习(一)之从零搭建linux系统(烧写uboot、内核进emmc+uboot启动内核)【转】

    本文转载自:http://blog.csdn.net/fengyuwuzu0519/article/details/74080109 版权声明:本文为博主原创文章,转载请注明http://blog.c ...

  9. 嵌入式Linux驱动学习之路(五)u-boot启动流程分析

    这里说的u-boot启动流程,值得是从上电开机执行u-boot,到u-boot,到u-boot加载操作系统的过程.这一过程可以分为两个过程,各个阶段的功能如下. 第一阶段的功能: 硬件设备初始化. 加 ...

  10. (转载)U-boot启动完全分析

    1.1 U-Boot工作过程 U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下: (1)第一阶段的功能 Ø 硬件设备初始化 Ø 加载U-Boot第二阶段代码到RAM空间 Ø 设置好栈 Ø ...

随机推荐

  1. English trip -- MC(情景课)3 C Do you have a sister?

    xu言:   学了困难的在去看以前的课程,发现真的容易多了.So 学习的最好方法和提速方式,那就是找困难的不断去挑战.尝试.尝试.在尝试! Grmmar ['græmə]  focus  ['fəʊk ...

  2. OAuth简介(包含简明使用教程)

    SSO:用户一次登陆后在多个系统免登录. 博客gem 'doorkeeper'  https://i.cnblogs.com/EditPosts.aspx?postid=9255973 OAuth:用 ...

  3. Confluence 6 使用 LDAP 授权连接一个内部目录概述

    你可以为你的 Confluence 连接 LDAP 服务器使用使用委托认证.这个意思是 Confluence 将会设置一个内部目录,这个目录仅被用来处理 LDAP 的授权. 这个设置将会为尝试登录系统 ...

  4. 怎么使用response.write来做一个javascript的alert弹出窗口

    Page.RegisterStartupScript("alert", "<script language=javascript>alert('添加成功'); ...

  5. EBS R12 MOAC原理探索 (转)

    转载地址 EBS R12 MOAC原理探索

  6. HttpServletResponse输出的中文乱码

    HttpServletResponse输出有两种格式,一种是字符流,一种是字节流. 1.字符流 // 这句话的意思,是让浏览器用utf8来解析返回的数据,即设置客户端解析的编码 response.se ...

  7. IOS-底层数据结构

      Objective-C底层数据结构 类的数据结构 Class(指针) typedef struct objc_class *Class; /* 这是由编译器为每个类产生的数据结构,这个结构定义了一 ...

  8. httpclient 使用代理

    httpclient_使用代理 当爬取网页的时候,有的目标站点有反爬虫机制,对于频繁访问站点以及规则性访问站点的行为,会采用屏蔽IP的措施. 这时候代理IP就派上用场了. 代理的分类 透明代理 匿名代 ...

  9. learning uboot switch to standby system using button

    pseudocode: If(reset_button was pressed ) { Change  uboot env bootslot^1 }

  10. 快速切题 sgu117. Counting 分解质因数

    117. Counting time limit per test: 0.25 sec. memory limit per test: 4096 KB Find amount of numbers f ...