接下来我们来看一下uboot中的核心功能,也就是说我们uboot最终目的是干什么的,就是启动加载内核。那么怎么加载内核,其实我们的uboot给我们提供的两种方案。第一种方案就是uboot本身自带的叫做bootm的命令。这个叫做bootm的命令主要目的就是为了启动,当然,等一下我们会简单说一下bootm他启动内核稍微要在内核里做一些手脚。然后还有一个命令叫做go命令,go命令顾名思义就是说把这个程序的PC指针指到一个地方,他就能运行起来,比如说我们之前假设有一款内核,然后把内核放到一个地方,然后我找到那个地方就让PC直接从内核中开始运行,相当于吧uboot的主动权交到了内核空间,因为把PC已经指过去了。
那么这样是不是就可以启动内核了?这些疑问我们一起来验证一下。首先要想启动内核还是要有一个内核的原文件。
如图,这个原文件我们在这个地方已经给大家编译好了叫“uImage”说到这,我们先简单的提一下,因为我们会在后面单独提内核是如何编译的。内核中的名字,一般来说,主要分这么几个一个叫做uimage就是我们现在看到的,还有一个叫做zimge,还可能听过image也还可能听过bzimage。就说这些,不管是什么样的image最终来说就是内核给我们运行到开发板上的可执行文件。
这个文件主要的问题就是格式不一样。内部来说,大量的代码都是相同的,只是前面有些头格式不太一致,其中在我们后面三个,zimge、image、bzimage这三个都可以称之为内核的最原始的数据包,而这个uimage最特殊。是我们专门针对uboot在我们内核原始数据前提之下加了一个关于uboot的头。
如何理解看下图:
如图,我们后面会看到一个具体脚本怎么去制作这些东西,但是我们现在要有一个认识就是说image、bzimage其实都可以认为是一块东西(如图中内部的四边形)只是说它可能数据压缩的格式不太一致,最终反应就是内核,这些内核按理说直接跳过去就可以执行,但是在uboot中有一个新的用法也就是他们自己的规范,就是说一定要再这样的数据中再加一个头(如图中的椭圆)而这个头按照我们特殊的格式其实就是uboot中特定的格式(椭圆中的长方形)然后组合成的这样一个大文件(图中最大的四边形)我们就把它称之为叫uimage,所以说uimage是一个比较特殊的数据包,这个数据包既包含内核中真正数据包,同时又包含跟uboot之间衔接的一些小数据。
下面我们就来尝试一下把这个uimage给下载下来。就下载我们的开发板上,然后去用go命令指过去运行看看行不行。
如图,我们先输入命令“tftp 2000080000 uImage”有些同学会说为什么不先是8000而是20000,这个在我们之后看内核就会知道要有一个偏移,这个偏移其主要目的就是为了我们在内存管理中建立一定的内存单元管理的表。这个表一般来说都会预留这样一段空间。所以这个空间我们在实际的物理内存中也应该预留出来,这样在启动的时候才不会出现一些特殊或者奇怪的问题。然后点击回车键,这个时候已经下载完成。
我们输入命令“go 2000080000”这个时候你就会发现,其实这个程序是死掉了,原因就是这个go命令只是把指针指到20008000,而真正的,一旦指下去就有几个毛病,第一个uimage本身来说最开始并不是代码,而是uboot中的一些数据信息,所以它不具备可执行能力,一旦执行肯定跑飞。第二个就是我们必须要用bootm命令去把前面的头信息给解析出来然后再去启动,所以这是我们要注意的go命令天生是启动不了内核的。
原因就在于等一下我会重点给大家讲的内核启动条件,内核启动,并不是大家所想象的直接启动的可执行的东西。并不是你直接把PC指针一指过去它就开始运行的,内核启动是需要一定的前提条件,要不然他要uboot干什么。
如图,所以说这是我们需要关心的一个问题,那么下面我们再来测试一下,在测试之前,我还要做一件事情就是我之前做实验的时候因为懒得每次都敲所以已经把bootargs和bootcmd这两个命令写死了。那么下面我们输入命令“setenv bootargs”把这个环境变量删掉,然后在把它保存一下。
如图,我们就会发现其实已经没有那个选项了。然后我们在输入命令“tftp 20008000 uImage”下载下来。
如图,因为刚才说了go命令不行那么我们输入命令“bootm 20008000”然后点击回车键,我们会发现这个时候有一个新的问题,出来的代码变得很奇怪,如果以后你用代码去调然后你会发现还是在uboot中,内核还没有真正起来。
所以总的来说,bootm和go命令只是启动内核的一个条件而已,也就是说它只能把PC指过去让他开始运行,真正想启动内核我们还需要一个非常重要的条件就是刚才我们删掉的环境变量叫bootargs,也就是说内核启动条件中有一个非常重要的环境叫bootargs,这个环境变量来充当了uboot跟内核数据衔接的一个过程,怎么理解这句话呢?让我们来思考一下。
我们可以这样想uboot是一个人内核也是一个人,这样的话uboot最终要启动内核的时候要告诉内核应该以什么样的方式启动,我们这个开发板中我们什么是输出,这样我们才能把相应的一些内核的启动或者环境交给内核去处理。
所以说我们现在看不到任何打印信息的主要原因就是uboot并没有告诉内核你该如何去工作。
因为之前uboot会有这样一些信息,我们需要把这些信息通过bootargs这样环境变量的参数告知给内核,这样内核就可以根据这个参数知道它要做些什么事情了。
原文链接:http://www.maiziedu.com/wiki/embed/core/