一、uboot最终目的:

1.读出内核 do_nand read kernel
{
  flash上存的内核:uImage = 头部 + 真正的内核;
}
2.启动内核。 do_bootm_linux
{
  (1)设置启动参数; uboot到kernel的启动参数的传递, 靠的就是告诉kernel参数存放的绝对地址,并按照约定好的格式存放。具体的格式约定比较复杂,见uboot
  (2)跳到入口地址.
}

二、在uboot里,打印一下环境变量,下面两句是启动kernel的关键字:

bootcmd=nand read 0x30000000 0x60000 0x200000;bootm 0x30000000
bootargs=noinitrd root=/dev/nfs nfsroot=192.168.2.109:/home/fs/work/nfs_root/fs_mini_mdev ip=192.168.2.111:192.168.2.109:192.168.2.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0

三、分析uboot代码,看它是如何实现上述功能的:

  写的比较抽象,仅供个人理解。

//uImage头部
typedef struct image_header {
uint32_t ih_magic; /* Image Header Magic Number */
uint32_t ih_hcrc; /* Image Header CRC Checksum */
uint32_t ih_time; /* Image Creation Timestamp */
uint32_t ih_size; /* Image Data Size */
uint32_t ih_load; /* Data Load Address 加载地址, 要运行内核时, 先把内核放在哪里*/
uint32_t ih_ep; /* Entry Point Address 要运行内核时,直接跳到这个地址就可以了*/
uint32_t ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t; //uboot和kernel传递参数所依赖的结构体,详细内容见 include/asm-arm/setup.h
struct tag {
struct tag_header hdr;
union {
struct tag_core core;
struct tag_mem32 mem;
struct tag_videotext videotext;
struct tag_ramdisk ramdisk;
struct tag_initrd initrd;
struct tag_serialnr serialnr;
struct tag_revision revision;
struct tag_videolfb videolfb;
struct tag_cmdline cmdline; /*
* Acorn specific
*/
struct tag_acorn acorn; /*
* DC21285 specific
*/
struct tag_memclk memclk;
} u;
};
//cmd_nand.c
//bootcmd-- nand read 0x30000000 0x60000 0x200000
int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
nand_read_opts(nand, &opts); // nand_read_opts : drivers/nand/nand_util.c
} //cmd_bootm.c
//bootcmd-- bootm 0x30000000
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
addr = simple_strtoul(argv[], NULL, );
//printf ("## Booting image at %08lx ...\n", addr);
memmove (&header, (char *)addr, sizeof(image_header_t));
//puts (" Verifying Checksum ... "); //unsigned long int data = start addr of kernel int the sdram after the cmd of nand read;
if(ntohl(hdr->ih_load) == data) //如果期望的kernel运行地址 = 实际从nand 读入内存的kernel起始地址。(都不含头)
{// 不需要移动
printf (" XIP %s ... ", name);
}
else
{// 需要移动
//printf (" Loading %s ... ", name);
len = ntohl(hdr->ih_size);
memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
} do_bootm_linux (cmdtp, flag, argc, argv,
addr, len_ptr, verify)
{
void (*theKernel)(int zero, int arch, uint params);
theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep); setup_start_tag (bd)/设置内核启动参数的其实存放地址bi_boot_params
{
bd_t *bd = gd->bd; //gd->bd->bi_boot_params = 0x30000100;
}
//这之后从bi_boot_params开始,依次存入各启动参数
setup_memory_tags (bd);
setup_commandline_tag (bd, commandline);// char *commandline = getenv ("bootargs");
setup_end_tag (bd);//表示完成启动参数的传递。 theKernel (, bd->bi_arch_number, bd->bi_boot_params);//跳到入口地址
}
} //uboot的核心:通过run_command实现各种功能
void main_loop (void)
{
getenv ("bootdelay"); //uboot如何启动内核:
s = getenv ("bootcmd");
printf("Booting Linux ...\n");
run_command (s, )
{
(cmdtp->cmd) (cmdtp, flag, argc, argv);
} //uboot如何接受用户命令:
for (;;)
{
readline (CFG_PROMPT); //read input into console_buffer
strcpy (lastcommand, console_buffer);
run_command (lastcommand, flag);
} }

uboot代码2:stage2代码,启动内核的更多相关文章

  1. 嵌入式Linux驱动学习之路(六)u-boot启动内核

    内核启动是需要必要的启动参数.不能开机自动完全从0开始启动,需要uboot帮助内核实现重定位并提供参数. 首先,uboo会从Kernel分区中读取bootcmd环境变量,根据环境变量可自动启动. 分区 ...

  2. 第2阶段——编写uboot之启动内核和制作Makefile(2)

    目标: 1   添加头文件setup.h和serial.h 2   写main函数   2.1 帮内核设置串口0, (内核启动会打印出启动信息) 2.2把内核读入到SDRAM 2.3设置参数(参考u- ...

  3. MPC8313ERDB在Linux从NAND FLASH读取UBoot环境变量的代码分析

    MPC8313ERDB在Linux从NAND FLASH读取UBoot环境变量的代码分析 Yao.GUET@2014-05-19 一.故事起因 由于文件系统的增大,已经大大的超出了8MB的NOR FL ...

  4. uboot启动内核的实现

    前面我们分析了uboot 的整个流程,我们知道uboot启动以后所有功能都是通过命令来实现的,启动kernel就是执行了bootcmd里面的命令.命令执行过程在uboot中是非常重要的现在我们就来看u ...

  5. UBOOT启动内核过程

    1.摘要 (1).启动4步骤第一步:将内核搬移到DDR中第二步:校验内核格式.CRC等第三步:准备传参第四步:跳转执行内核(2).涉及到的主要函数是:do_bootm和do_bootm_linux(3 ...

  6. u-boot学习(五):u-boot启动内核

    u-boot的目的是启动内核.内核位于Flash中,那么u-boot就要将内核转移到内存中.然后执行命令执行之.这些操作是由bootcmd命令完毕的. bootcmd=nand read.jffs2 ...

  7. U-boot 启动内核

    1:什么是UBOOT,为什么要有UBOOT? UBOOT的主要作用是用来启动linux内核,因为CPU不能直接从块设备中执行代码,需要把块设备中的程序复制到内存中,而复制之前还需要进行很多初始化工作, ...

  8. linux的几个内核镜像格式Image 和 u-boot启动内核和文件系统时的一些环境变量的设置

    关于编译powerpc linux的几个Image参考原文 http://blog.sina.com.cn/s/blog_86a30b0c0100wfzt.html 转载▼   PowerPC架构 L ...

  9. 嵌入式linux开发uboot启动内核的机制(二)

    一.嵌入式系统的分区 嵌入式系统部署在Flash设备上时,对于不同SoC和Flash设备,bootloader.kernel.rootfs的分区是不同的.三星S5PV210规定启动设备的分区方案如下: ...

随机推荐

  1. codeforces 623A. Graph and String 构造

    题目链接 给出一个图, 每个节点只有三种情况, a,b, c. a能和a, b连边, b能和a, b, c,连边, c能和b, c连边, 且无重边以及自环.给出初始的连边情况, 判断这个图是否满足条件 ...

  2. 基于PCA的人脸识别步骤

    代码下载:基于PCA(主成分分析)的人脸识别 人脸识别是一个有监督学习过程,首先利用训练集构造一个人脸模型,然后将测试集与训练集进行匹配,找到与之对应的训练集头像.最容易的方式是直接利用欧式距离计算测 ...

  3. Mongodb 设置密码

    Mongodb 配置用户密码: 首先创建admin数据库的用户密码 再创建pics的用户名密码 > show databases; admin 0.203125GB local 0.078125 ...

  4. cocos2dx进阶学习之CCSpriteBatchNode

    继承关系 CCSpriteBatchNode -> CCNode, CCTextureProtocol 成员变量 inline CCTextureAtlas* getTextureAtlas(v ...

  5. frame和bounds的区别

    frame:根据父视图坐标系来确定自己的位置 bounds:该视图在自己坐标系的位置和大小 修改bounds并不会引起视图位置的变化,会影响自身子视图的位置:修改frame会引起视图位置的变化 UIV ...

  6. POJ 1410 Intersection(线段相交&&推断点在矩形内&&坑爹)

    Intersection 大意:给你一条线段,给你一个矩形,问是否相交. 相交:线段全然在矩形内部算相交:线段与矩形随意一条边不规范相交算相交. 思路:知道详细的相交规则之后题事实上是不难的,可是还有 ...

  7. 《Android第一行代码》笔记

    学习Android开发差点儿相同有两年时间了.期间也做了大大小小的一些项目.近来抽出闲暇想把Android基础强化一下,之前在网上看到了郭霖郭大神的几篇博客.从中受益不少.于是花了近一周时间看完了郭神 ...

  8. 64位CentOS上编译 Hadoop 2.2.0

    下载了Hadoop预编译好的二进制包,hadoop-2.2.0.tar.gz,启动起来后.总是出现这样的警告: WARN util.NativeCodeLoader: Unable to load n ...

  9. MYSQL - 创建数据库时设置编码

    CREATE DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; CREATE DATABASE 的语法: CRE ...

  10. 关于int.TryParse的使用

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...