uboot解析;uboot对bootcmd、bootargs读取传递

 

1 uboot编译:

打补丁:patch -p1 < ../u-boot-1.1.6_jz2440.patch   //-p1忽略掉第1个斜杠之前的数据

配置:make 100ask24x0_config

编译:make

执行make 100ask24x0_config后发生了什么


uboot的目标:

1 从flash中读取内核放到ram中

2 启动内核

uboot应有的功能:

1 读flash

2 初始化ram、初始化时钟、初始化串口

3 启动内核


1.1 uboot配置:

make 100ask24x0_config  //执行Makefile中的内容如下:

SRCTREE := $(CURDIR)
MKCONFIG := $(SRCTREE)/mkconfig
100ask24x0_config:unconfig
//'$@’的值是目标100ask24x0_config,所以$(@:_config=) 为100ask24x0
@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0
=mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0  //所以是执行这个脚本命令,进入mkconfig脚本执行

#mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0   //执行的内容如下:

#mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0

APPEND=no	# Default: Create new config file
BOARD_NAME=""	# Name to print in make output

BOARD_NAME=smdk2410


echo "Configuring for ${BOARD_NAME} board..."

#
# Create link to architecture specific headers
#
# $1 传入的第一个参数  $x 传入的第x个参数 
# $# 传入的参数的个数
#./mkconfig  smdk2410 arm arm920t smdk2410 NULL s3c24x0
#$0 		     $1	      $2	 $3	    $4            $5     $6
//创建asm到 asm-$2的软连接
        cd ./include
	rm -f asm
	ln -s asm-$2 asm   //ln -s asm-arm asm  
	
//创建asm-$2/arch到 arch-$6的软连接
        rm -f asm-$2/arch   //rm -f asm-arm/arch
	ln -s ${LNPREFIX}arch-$6 asm-$2/arch  //ln -s arch-s3c24x0 asm-arm/arch


//创建asm-$2/proc到proc-armv
	rm -f asm-$2/proc      //rm -f asm- arm/proc
	ln -s ${LNPREFIX}proc-armv asm-$2/proc  // ln -s proc-armv asm-arm/proc


#
# Create include file for Make
#
echo "ARCH   = $2" >  config.mk
echo "CPU    = $3" >> config.mk
echo "BOARD  = $4" >> config.mk
# ">"新建文件
#">>" 追加数据到文件
#内容为
#ARCH=arm 
#CPU=arm920t 
#BOART = 100ask24x0 
#SOC=s3c24x0
//第五个参数存在且第五个参数不等于null的话,执行
[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk

[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC    = $6" >> config.mk

#
# Create board specific header file
#

	> config.h		# Create new config file

echo "/* Automatically generated - do not edit */" >>config.h
echo "#include <configs/smdk2410.h>" >>config.h

exit 0



uboot配置结果:

创建到平台/开发板相关的头文件连接:

ln -s asm-$2 asm                        //ln -s asm-arm asm 

ln -s arch-$6 asm-$2/arch          //ln -s arch-s3c24x0 asm-arm/arch

ln -s proc-armv asm-$2/proc      // ln -s proc-armv asm-arm/proc

创建顶层Makefile包含的文件include/config.mk,内容如下:

ARCH =$2               #ARCH=arm 

CPU  = $3               #CPU=arm920t 

BOARD = $4           #BOART = 100ask24x0 

VENDOR = $5

SOC = $6                #SOC=s3c24x0

创建开发板相关的头文件include/config.h,内容如下:

#include <configs/smdk2410.h>

注:uboot通过include/config.h文件调用include/configs/smdk2410.h文件。smdk2410.h文件就是针对板子的配置文件,内核启动参数等都在其中

2 uboot源码分析

2.1 uboot第一阶段代码分析

           从cpu/arm920t/start.S开始
1 硬件设备初始化
2 为加载bootloader的第二阶段准备ram空间
3 复杂bootloader的第二阶段代码到ram空间中
4 设置好栈


5 转到第二阶段的代码入口点

2.2 uboot第二阶段代码分析

第二阶段从lib-arm/board.c中的start_armboot函数开始:



1 初始化本阶段要使用到的硬件设备
2 检测系统内存映射
3 uboot命令的格式
    也就是说我们在uboot的界面输入的命令都是传给U_BOOT_CMD(name,maxargs,repeatable,command,"usage","help")函数执行的
4 为内核设置启动参数
    uboot也是通过 标记列表向内核传递参数的。
    对应arm架构的cpu,都是通过lib_arm/armlinux.c中的do_bootm_linux函数来执行内核的。这个函数中,设置标记列表,最后通过
“theKernel(0,bd->bi_arch_number,bd->bi_boot_params)”调用内核。其中,theKernel指向内核存放的地址(对于arm架构的cpu,
通常是0x30008000),bd->bi_arch_number就是前面board_init函数设置的机器id,而bd->bi_boot_params就是标记列表的开始地址。

3 bootcmd参数、bootargs参数是如何传入内核执行的

2.2.1 main_loop函数详解

 uboot main_loop函数分析http://www.cnblogs.com/amanlikethis/p/3555516.html

main_loop函数承接uboot启动第二阶段的结尾;
摘要:
main_loop()
setenv ("bootcount", bcs_set);
bcs = getenv ("bootlimit");
if (!getenv("mtdparts"))
   
       {
        run_command("mtdparts default", 0);
    }
    else
    {
        mtdparts_init();
    }
s = getenv ("bootdelay");
s = getenv ("bootcmd"); // 获取启动命令参数
//在启动命令非0(有启动命令)的情况下,如果在启动延时时间到之前按下键终止了,abortboot返回1,
否则如果一 //直没有键按下,直到启动延时时间到,那么函数返回0。所以,如果按下键了,就可以跳过启动操作系统;
如果没   //按就直接启动操作系统了。
if (bootdelay >= 0 && s && !abortboot (bootdelay))
{
# ifdef CONFIG_AUTOBOOT_KEYED
int prev = disable_ctrlc(1); /* disable Control C checking */
# endif


# ifndef CFG_HUSH_PARSER
        {
            printf("Booting Linux ...\n");            
       run_command (s, 0);    //运行启动命令,启动操作系统   通过bootcmd参数启动内核,
        }
# else
parse_string_outer(s, FLAG_PARSE_SEMICOLON |
   FLAG_EXIT_FROM_LOOP);
# endif


# ifdef CONFIG_AUTOBOOT_KEYED
disable_ctrlc(prev); /* restore Control C checking */
# endif
}

注: do_boot_linux 函数中会会调用“ theKernel (0, bd->bi_arch_number, bd->bi_boot_params) ”启动内核,其 theKernel 指向内核存放内存地址,这个用来实现程序跳转到内核存在的内存地址处,开始内核的执行。 bd->bi_arch_number 就是前面 board_init 函数设置的机器类型 ID ,在内核引导阶段的 __lookup_processor_type 函数已经用到。而 bd->bi_boot_params 就是标记列表的开始地址,预先存在该地址的存放一个 tag 列表,  tag 列表将在 setup_arch 函数中进行初步的处理。

也就是说 bootargs参数也在表中,也是被传给setup_arch函数解析执行的。





4  修改默认参数以方便使用

        为了使用uboot时,减少一些设置,现在修改配置文件 include/configs/smdk2410.h,增加默认配置参数,果然发现默认配置参数都是写在include/config.h相关路径下的,uboot下修改内核参数后的saveenv就是将新的参数写入这个文件的对应位置中了。


uboot通过theKernel(0,bd->bi_arch_number,bd->bi_boot_params)函数调用启动内核,

0,bd->bi_arch_number,bd->bi_boot_params就是uboot传给内核的参数;

theKernel指向内核存放的地址(对于arm架构的cpu,通常是0x30008000),

bd->bi_arm_number 是board_init函数设置的机器id,

bd->bi_boot_params是标记列表的开始地址。

5 标记列表

Bootloader 将参数放在某个约定的地方之后,再启动内核,内核启动后从这个地方获得参数。
除了约定好参数存放的地址外,还要规定参数的结构。Linux 2.4.x 以后的内核都期望
标记列表(tagged list)的形式来传递启动参数
。标记,就是一种数据结构;标记列表,就是
挨着存放的多个标记。
标记列表以标记ATAG_CORE 开始,以标记ATAG_NONE 结束。
标记的数据结构为tag,它由一个tag_header 结构和一个联合(union)组成。
tag_header结构表示标记的类型及长度,比如是表示内存还是表示命令行参数等。
对于不同类型的标记使用不同的联合(union),比如表示内存时使用tag_mem32,表示命令行时使用tag_cmdline。
数据结构tag 和tag_header 定义在Linux 内核源码的uboot/include/asm-arm/setup.h头文件中


       标记列表中存放的就是启动参数,有默认的启动参数,如果在启动时进入uboot界面设置启动参数,后再继续启动就是把新参数代替旧参数

放入标记列表中用于启动。











  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值