1_5.1.6_U-boot分析与使用_uboot启动内核_P

发布者:SereneWhisper最新更新时间:2021-08-20 来源: eefocus关键字:U-boot  启动内核 手机看文章 扫描二维码
随时随地手机看文章

现在来分析uboot是怎么启动内核的。


我们知道,u-boot启动内核是通过两条指令来实现的。


nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0


读出内核

nand read.jffs2 0x30007FC0 kernel


从kernel分区中读出内核,放到地址0x30007FC0去。


分区:对于windows系统来说,每个硬盘上都有分区表;对于嵌入式Linux来说,Flash没有分区表,但是我们可以人为的将这块Flash分为几个区,这些分区没有分区表,而是在源码中(100ask24x0.h)写死的。需要注意的是,对于这些分区,我们关心的不是分区的名字,而是分区的起始地址和大小。

在这里插入图片描述

可以使用mtd指令来查看分区,首先是256KB的BootLoader,然后是128KB的环境变量参数,然后是2M的kernel,起始地址是0x00060000,最后是root分区(根文件系统)。

在这里插入图片描述

所以nand read.jffs2 0x30007FC0 kernel就等于nand read.jffs2 0x30007FC0 0x00060000 0x00200000,这里再说明一下,分区名字不重要,重要的是起始地址和大小。


下面分析一下nand指令,在u-boot中使用? nand查看一下帮助信息,可以看到nand read的格式,后面的参数可以是地址+偏移,也可以直接是分区名字。

在这里插入图片描述

do_nand函数中对于read操作有单独的处理,如果是.jffs2,后面的size可以不需要页对齐,具体的实现暂时不管。

在这里插入图片描述

启动内核

bootm 0x30007FC0


Flash上存的内核是什么格式?


答:是UImage,UImage是由头部+真正的内核构成的。

在这里插入图片描述

使用指令bootm 地址,启动内核,会先读入头部,然后看内核是否已经加载完毕,如果加载完毕了就跳到 入口地址 去执行内核,否则先加载内核再跳转。


首先是读入头部。

在这里插入图片描述

然后判断内核是否已经加载完毕,如果没有就加载内核。

在这里插入图片描述

跳转地址是0x30008000,加载地址是0x30007FC0,中间相差64字节,这64字节就是头部的大小。


bootm的功能是:


根据头部,移动内核到合适的地方;

启动内核,这是通过do_bootm_linux函数完成的。

在这里插入图片描述

加载完毕之后,并不是直接跳到跳转地址就可以启动内核,正如PC机,在启动操作系统之前还需要检测内存等操作,Linux还需要告诉内核一些参数,也就是设置启动参数,然后才跳转到入口地址去启动内核。


所以启动内核之前,do_bootm_linux要做这些事情:


设置启动参数;

跳转入口地址。

我们先看一下是怎么跳转到入口地址的,在do_bootm_linux函数的末尾,有一个函数指针,u-boot就是通过这个函数指针来实现启动内核的。

在这里插入图片描述

可以看到,指向的是内核头部的跳转地址。

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210330192043307.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzMTQxMzUz,size_16,color_FFFFFF,t_70

那么,跳转到入口地址之前,这些参数要怎么设置呢?


猜测:在Flash的某个位置,按某种格式保存这些参数,在设置时读出来设置即可。


对于2440开发板,就是在某个地址(0x30000100)按某种格式(TAG)保存数据,在启动内核时把这些数据读出来解析。

在这里插入图片描述
在这里插入图片描述

下图是设置启动参数的一些函数调用,其中start和end都是必须的,其他则是设置不同参数的tag。

在这里插入图片描述

这里选出四个函数来分析,分别是:


setup_start_tag

setup_memory_tags

setup_commandline_tag

setup_end_tag

setup_start_tag

首先是setup_start_tag,其中的bd->bi_boot_params在前面设置过,为0x30000100,所以这个函数会从0x30000100地址开始设置参数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

函数执行完,结果如下,从0x30000100开始存放数据,结束后params指向下一个空闲地址。

在这里插入图片描述

setup_memory_tags

之前有说过,windows系统在启动会需要检测内存,检测出大小,然后告诉操作系统,Linux系统同样需要,并且是通过setup_memory_tags来实现的。


函数如下,可以看到是通过设置不同的块信息来实现内存设置的。

在这里插入图片描述

我们使用的是两块32MB的SDRAM拼在一起,也就是一块,共64MB。

在这里插入图片描述
在这里插入图片描述

setup_memory_tags执行完成后,params指向下一个空闲地址。

在这里插入图片描述

setup_commandline_tag

调用setup_commandline_tag时还传入了一个临时变量commandline。

在这里插入图片描述

该变量是来自于环境变量bootargs的。

在这里插入图片描述

可以看到,bootargs = noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200。


我们大概来分析一下这个指令,root就是根文件系统(相当于windows的C盘),它位于第3个Flash分区(从0开始),然后init=/linuxrc表示第一个应用程序是/linuxrc,最后console=ttySAC0,115200表示内核的调试信息从串口打印出来,波特率是115200。

在这里插入图片描述

下面是setup_commandline_tag的源码。

在这里插入图片描述

执行过后,数据的存放如下,可以看到这个就是把指令commandline存到内存中。

在这里插入图片描述

setup_end_tag

我们初始化变量,何时结束呢?就是setup_end_tag函数来结束的。


直接在tag位置设为结束标志0x00000000,就表示参数设置完成了。


在这里插入图片描述
在这里插入图片描述

这些数据都有特定的格式,内核启动时,就会来这些地方按tag格式来读取这些数据。


u-boot的最终目标是启动内核,为了实现这个目标,需要:


从Flash中读出内核;

启动:a.设置启动参数;b.跳转到入口地址。

跳转到入口地址时,我们传了三个参数,第一个参数是0,第三个参数是参数地址也就是0x30000100,那么第二个参数是什么呢?

在这里插入图片描述

答:是机器ID,u-boot可以支持很多种单板,这种单板也就是机器,那么具体现在使用的要支持哪种机器,就是通过这个机器ID来决定的。


在一开始board_init初始化的时候,我们就给bi_arch_number赋了一个值MACH_TYPE_S3C2440也就是362,这个值表示现在使用的机器是2440。

在这里插入图片描述
在这里插入图片描述

关键字:U-boot  启动内核 引用地址:1_5.1.6_U-boot分析与使用_uboot启动内核_P

上一篇:1_5.1.5_U-boot分析与使用_u-boot分析之u-boot命令实现_P
下一篇:1_5.3.1_内核配置裁剪及启动流程_内核启动流程分析之编译

推荐阅读最新更新时间:2024-11-02 01:31

移植u-boot-2010.12.tar.bz2版本到s3c2440过程
1,tar解压 2,修改根目录下的makefile文件中的交叉编译为 arm-linux- 3,make distclean 4,make trab_bigflash_congfig 5, 修改/uboot/include/config.h,添加CONFIG_SYS_SDRAM_BASE=0等两个宏,不添加make会报错,所以根据错误添加一下 6,make all 7,make all会出错,提示找不到lstubs这个库,修改/u-boot/examples/standalone/makefile,将libstubs.o修改为libstubs.a,如果提示找不到其他库的话,按照同样的方法修改makefile.
[单片机]
1_5.1.2_U-boot分析与使用_u-boot分析之Makefile结构分析_P
我们分析一个文件的时候,最好的方式就是看它的makefile。 之前体验编译uboot时,我们第一步是配置uboot,第二步是编译。 分析配置uboot指令 配置uboot使用的指令是make 100ask24x0_config。 首先找到Makefile,用vim打开,查找100ask24x0_config,定位如下: 那么make 100ask24x0_config其实就是执行@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0指令,下面分析这条指令。 最左边的@符号表示执行该命令时不在终端显示该命令,然后是一个变量MKCONFIG,查
[单片机]
1_5.1.2_U-boot分析与使用_<font color='red'>u-boot</font>分析之Makefile结构分析_P
利用U-Boot作为系统bootloader实现uClinux向S3C44B0的移植
1 引言 S3C44B0是Samsung公司推出的一款为手持设备或其他通用设备开发的32位处理器,它基于ARM7TDMI核,没有内存管理单元(MMU)。在采用无MMU的微处理器的嵌入式系统中广泛采用的就是uClinux系统,作为linux的衍生系统,其具有支持多任务、内核精简、高效稳定和源代码开放的优点。系统移植的基本过程包括:获取较新版本的linux-2.6.9内核源码,根据目标平台对源码中与硬件平台相关部分进行修改,添加必要的外设驱动程序,对系统进行针对目标平台的交叉编译,生成的内核映像文件的下载调试等。 2 硬件环境介绍 硬件平台以S3C44B0为核心,采用的外部晶振频率为6MHz,内核主频最高可达到66
[单片机]
利用<font color='red'>U-Boot</font>作为系统bootloader实现uClinux向S3C44B0的移植
u-boot-1.1.6移植之dm9000
网卡dm9000的执行过程(u-boot版本:u-boot-1.1.6): 在board.c里面有eth_initialize(gd- bd); eth_initialize的实现在eth.c里面,但是eth_initialize函数里面没有dm9000的初始化eth_init 常见有nfs,tftp,ping命令会用到网络设备,可以从这里入手。 U_BOOT_CMD( ping, 2, 1, do_ping, pingt- send ICMP ECHO_REQUEST to network hostn , pingAddressn ); 而其处
[单片机]
u-boot移植(六)---代码修改---串口
一、代码流程 1.1 串口代码   程序流程图如下;      default_serial_console 执行的代码如下:         在JZ2440.H中有如下定义:      则执行结构体s3c24xx_serial0_device,从而执行INIT_S3C_SERIAL_STRUCTURE(0, s3ser0 ):      _serial_setbrg 为串口时钟设置函数:      其中,调用get_PCLK()进行串口时钟的设置:      PCLK的计算涉及到 HCLK,在函数中调用了get_HCLK() 来获取HCLK的值。      get HCLK的代码就HCLK的计算,这里对应着寄存器
[单片机]
<font color='red'>u-boot</font>移植(六)---代码修改---串口
u-boot移植s3c2410
u-boot的向s3c2410板上的移植(只是编译而以)可谓是千辛万苦啊(对于菜鸟而言,(*^__^*) ,高手除外),下面就是我的痛苦经历。 过程如下: 下载u-boot-1.1.6版本,然后解压,进入解压完的目录之后,首先是修改对应文件,该部分是参见网上blogs。 http://blog.csdn.net/hhq0216/archive/2006/12/29/1466894.aspx,按照上面的做法来修改文件内容,然后回到u-boot目录, 执行如下命令: make distclean make smdk2410_config make 之后error出现:make: *** Error 1 然后google之得到下面的方
[单片机]
从Nand Flash启动U-BOOT的基本原理
前4K的问题 如果S3C2410被配置成从Nand Flash启动(配置由硬件工程师在电路板设置), S3C2410的Nand Flash控制器有一个特殊的功能,在S3C2410上电后,Nand Flash控制器会自动的把Nand Flash上的前4K数据搬移到4K内部RAM中,并把0x00000000设置内部RAM的起始地址,CPU从内部RAM的0x00000000位置开 始启动。这个过程不需要程序干涉。 程序员需要完成的工作,是把最核心的启动程序放在Nand Flash的前4K中。 启动程序的安排 由于Nand Flash控制器从Nand Flash中搬移到内部RAM的代码是有限的,所以在启动代码的前4K里,我们必须完成S3C
[单片机]
U-Boot-2009-03移植笔记(从Nandflash启动二)
在U-Boot-2009-03移植笔记(从Nandflash启动一)中,我们写好了nandflash的读驱动,并且试图将u-boot本身从nandflash中读到sdram中,最后同时点亮led1和led2,可惜结果并不是我们想要的结果,本文就使用openjtag的调试方法,来诊断问题(不熟悉调试方法的,请参考U-Boot-2009-03移植笔记(调试篇))。 问题的发现 我们反编译u-boot文件,发现我们的程序还是在33f800090调用了nand_init_ll函数,那么我们在0x00000090和0x00000094两个地址设置断点,如图: 发现程序在0x00000090之后就跑飞了,怎么办?我们看看u-boot的
[单片机]
U-Boot-2009-03移植笔记(从Nandflash<font color='red'>启动</font>二)
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved