Uboot如何向内核传递参数
UBOOT命令详解
常用U-boot命令详解(z)2010-09-30 15:05:52| 分类:学习心得体会|字号订阅U-boot发展到现在,他的命令行模式已经非常接近Linux下的shell了,在我编译的U-boot-2009.11中的命令行模式模式下支持“Tab”键的命令补全和命令的历史记录功能。
而且如果你输入的命令的前几个字符和别的命令不重复,那么你就只需要打这几个字符即可,比如我想看这个U-boot的版本号,命令就是“ version”,但是在所有的命令中没有其他任何一个的命令是由“v”开头的,所以只需要输入“v”即可。
[u-boot@MINI2440]# versionU-Boot 2009.11 ( 4月04 2010 - 12:09:25)[u-boot@MINI2440]# vU-Boot 2009.11 ( 4月04 2010 - 12:09:25)[u-boot@MINI2440]# baseBase Address: 0x00000000[u-boot@MINI2440]# baBase Address: 0x00000000由于U-boot支持的命令实在太多,一个一个细讲不现实,也没有必要。
所以下面我挑一些烧写和引导常用命令介绍一下,其他的命令大家就举一反三,或者“help”吧!(1)获取帮助命令:help 或?功能:查看当前U-boot版本中支持的所有命令。
[u-boot@MINI2440]#help?- alias for'help'askenv - get environment variables from stdinbase - print or set address offsetbdinfo - print Board Info structurebmp - manipulate BMP image databoot - boot default, i.e., run 'bootcmd'bootd - boot default, i.e., run 'bootcmd'bootelf - Boot from an ELF image in memorybootm - boot application image from memorybootp - boot image via network using BOOTP/TFTP protocolbootvx - Boot vxWorks from an ELF imagecmp - memory compareconinfo - print console devices and informationcp - memory copycrc32 - checksum calculationdate - get/set/reset date &timedcache - enable or disable data cachedhcp - boot image via network using DHCP/TFTP protocol echo - echo args to consoleeditenv - edit environment variableeeprom - EEPROM sub-systemerase - erase FLASH memoryexit-exit scriptfatinfo - print information about filesystemfatload - load binary file from a dos filesystemfatls -list files in a directory (default/)flinfo - print FLASH memory informationfsinfo - print information about filesystemsfsload - load binary file from a filesystem imagego - start application at address 'addr'help - print online helpi2c - I2C sub-systemicache - enable or disable instruction cacheiminfo - print header information for application image imls -list all images found in flashimxtract- extract a part of a multi-imageitest -return true/false on integer compareloadb - load binary file over serial line(kermit mode) loads - load S-Record file over serial lineloadx - load binary file over serial line(xmodem mode) loady - load binary file over serial line(ymodem mode) loop - infinite loop on address rangels -list files in a directory (default/)md - memory displaymm - memory modify (auto-incrementing address)mmc - MMC sub-systemmtest - simple RAM read/write testmw - memory write(fill)nand - NAND sub-systemnboot - boot from NAND devicenfs - boot image via network using NFS protocolnm - memory modify (constant address)ping -send ICMP ECHO_REQUEST to network hostprintenv- print environment variablesprotect - enable or disable FLASH write protection rarpboot- boot image via network using RARP/TFTP protocol reginfo - print register informationreset- Perform RESET of the CPUrun - run commands in an environment variablesaveenv - save environment variables to persistent storage setenv -set environment variablesshowvar - print local hushshell variablessleep- delay execution for some timesource - run script from memorytest- minimal test like /bin/shtftpboot- boot image via network using TFTP protocolunzip - unzip a memory regionusb - USB sub-systemusbboot - boot from USB deviceversion - print monitor version以bmp指令为例:Usage:bmp info <imageAddr>- display image infobmp display <imageAddr>[x y]- display image at x,y[u-boot@MINI2440]# h bmbmp - manipulate BMP image dataUsage:bmp info <imageAddr>- display image infobmp display <imageAddr>[x y]- display image at x,y(2)环境变量(environment variables,简称ENV)与相关指令和shell类似,U-Boot也有环境变量。
《uboot环境变量:详谈bootcmd和bootargs》
《uboot环境变量:详谈bootcmd和bootargs》1.uboot中的环境变量bootdelay:执⾏⾃动启动的等候秒数baudrate:串⼝控制台的波特率netmask:以太⽹接⼝的掩码ethaddr:以太⽹卡的⽹卡物理地址bootfile:缺省的下载⽂件bootargs:传递给内核的启动参数bootcmd:⾃动启动时执⾏的命令serverip:服务器端的ip地址ipaddr:本地ip 地址stdin:标准输⼊设备stdout:标准输出设备stderr:标准出错设备 以上是⼀些基本的环境变量。
uboot中⼀般会有⼀些缺省的环境变量。
在启动uboot后会将参数放在特定的FLASH区域,之后由kernel去获取解析。
还有另⼀种⽅法设置环境变量就是在uboot启动后进⼊命令⾏模式,设置环境变量,然后执⾏saveenv后,会将设置的环境变量保存到特定区域的FLASH中,由kernel去获取解析。
其中bootargs和bootcmd相对⽐较重要。
2.bootargs解析root: ⽬前很多新的开发板都是使⽤FLASH作为存储。
因为很多都直接使⽤MTD驱动程序。
MTD 驱动程序的主要优点在于 MTD 驱动程序是专门为基于闪存的设备所设计的,所以它们通常有更好的⽀持、更好的管理和基于扇区的擦除和读写操作的更好的接⼝。
Linux 下的 MTD驱动程序接⼝被划分为两类模块:⽤户模块和硬件模块。
有两个流⾏的⽤户模块可启⽤对闪存的访问: MTD_CHAR 和 MTD_BLOCK 。
MTD_CHAR 提供对闪存的原始字符访问,⽽ MTD_BLOCK 将闪存设计为可以在上⾯创建⽂件系统的常规块设备(象 IDE 磁盘)。
与MTD_CHAR 关联的设备是 /dev/mtd0、mtd1、mtd2(等等),⽽与 MTD_BLOCK 关联的设备是 /dev/mtdblock0、mtdblock1(等等)。
由于 MTD_BLOCK 设备提供象块设备那样的模拟,通常更可取的是在这个模拟基础上创建象 FTL 和 JFFS2 那样的⽂件系统。
UBoot操作和常用命令
UBoot常用命令
• usb start: 起动usb 功能 • usb info: 列出设备 • usb scan: 扫描usb storage(u 盘)设备 • f的at文ls:件列出DOS FAT文件系统, 如:fatls usb 0列出第一块U盘中 • fatload: 读入FAT中的一个文件,如:fatload usb 0 0x30000000
• 通常,Boot Loader 是严重地依赖于硬件而实现的, 特别是在嵌入式世界。因此,在嵌入式世界里建 立一个通用的Boot Loader 几乎是不可能的。尽管 如此,我们仍然可以对Boot Loader 归纳出一些通 用的概念来,以指导用户特定的Boot Loader 设计 与实现。
UBoot来源
• nand write [内存地址] [NAND地址] [大小]
– 将SDRAM中地址0x31000000中大小为0x00200000的内容写入NAND Flash的0x100000地址。
– nand write 0x31000000 0x00100000 0x00200000 – NAND write: device 0 offset 1048576, size 2097152 ... 2097152 bytes
Creating 5 MTD partitions on "NAND 256MiB 3,3V 8-bit": 0x000000000000-0x000000040000 : "supervivi" ftl_cs: FTL header not found. 0x000000040000-0x000000060000 : "param" uncorrectable error : 0x000000060000-0x000000560000 : "Kernel" ftl_cs: FTL header not found. 0x000000560000-0x000040560000 : "root" mtd: partition "root" extends beyond the end of device "NAND 256MiB 3,3V 8-bit" -- size truncated to 0xfaa0000 ftl_cs: FTL header not found. 0x000000000000-0x000040000000 : "nand" mtd: partition "nand" extends beyond the end of device "NAND 256MiB 3,3V 8-bit" -- size truncated to 0x10000000
uboot启动参数设置
nand erase 40000 1c0000 nand erase offset size
nand write 30800000 40000 1c0000 存放内存30800000位置上的uImge,烧写到nandflash的40000位置上
=========================================================================================
例如如下:
FS2410# setenv serverip 192.168.7.x (其中X是虚拟机中IP的最后的数字[用ifconfig可以获取])
farsight_N中的N用座位号来表示,比如座位4即为farsight_4 //设置uboot传给内核的参数
saveenv
自定义参数版本:
4.设置UBOOT参数
确保一下FS2410的核心班上的JP1跳线帽短接了,给板子上电,
查看板子启动信息,如果板子启动信息中,有U-Boot 1.3.1(Oct 25 2008 - 15:45:21)或者更新的版本,则直接设置下面的参数,否则根据文档烧录 u-boot131-for-farsight-shenzhen-advanced-drivers.bin(请参考文档"farsight-实验前的准备步骤-v2.3.doc")
setenv bootargs console=ttySAC0,115200 init=/linuxrc root=/dev/nfs nfsroot=192.168.7.113:/opt/filesystem ip=192.168.7.173:192.168.7.113:192.168.7.1:255.255.255.0:farsight_13:eth0:off //或者console=ttySAC0,115200 root=1f02 rootfstype=jffs2 rw init=/linuxrc mem=64M
Uboot传递参数与kernel解析参数
Uboot传递参数与kernel解析参数U-boot 会给linux Kernel 传递很多参数,例如:串口、RAM、commandline (bootargs)等。
而linux kernel 也会读取和处理这些参数。
它们两者之间通过ATAG方式来传递参数。
U-boot 把要传递给kernel 的数据保存在struct tag 数据结构中,启动内核时,把这个结构体的物理地址传给内核,然后内核通过这个地址,用parse_tags 分析出传递过来的参数。
这里以U-boot 传递RAM 参数和Linux kernel 读取RAM 参数为例进行介绍。
1、u-boot 向kernel 传递RAM 参数./common/cmd_bootm.c 文件调用./uboot/arch/arm/lib/bootm.c 文件中的do_nand_boot 函数来启动Linux kernel。
在do_nand_boot 函数中:int do_nand_boot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])DECLARE_GLOBAL_DATA_PTRint retd_t *bd = gd->bdulong addr, data, len, initrd_start, initrd_endvoid (*theKernel)(int zero, int arch, uint params)int strlechar *commandline = getenv ("bootargs")setup_start_tag (bd); // 初始化第一个kernel tag结构体setup_serial_tag (¶ms)setup_revision_tag (¶ms)setup_memory_tags (bd)theKernel (0, bd->bi_arch_number, bd->bi_boot_params);其中:thekernel其实不是个函数,而是指向内核入口地址的指针,把它强行转化为带三个参数的函数指针,会把三个参数保存到通用寄存器中,实现了向kernel传递信息的功能参数保存到通用寄存器中,实现了向kernel传递信息的功能bd->bi_boot_params :传给Kernel 的参数=(struct tag *) 型的setup_start_tag 和setup_memory_tags 函数说明如下:static void setup_start_tag (bd_t *bd)params = (struct tag *) bd->bi_boot_param/* 初始化(struct tag *) 型的全局变量params 为bd->bi_boot_params 的地址,* 之后的setup tags 相关函数如下面的setup_memory_tag* 就把其它tag 的数据放在此地址的偏移地址上。
uboot启动流程分析
uboot启动流程分析Uboot启动流程分析。
Uboot是一种常用的嵌入式系统启动加载程序,它的启动流程对于嵌入式系统的正常运行至关重要。
本文将对Uboot启动流程进行分析,以便更好地理解其工作原理。
首先,Uboot的启动流程可以分为以下几个步骤,Reset、初始化、设备初始化、加载内核。
接下来我们将逐一进行详细的分析。
Reset阶段是整个启动流程的起点,当系统上电或者复位时,CPU会跳转到Uboot的入口地址开始执行。
在这个阶段,Uboot会进行一些基本的硬件初始化工作,包括设置栈指针、初始化CPU寄存器等。
接着是初始化阶段,Uboot会进行一系列的初始化工作,包括初始化串口、初始化内存控制器、初始化时钟等。
这些初始化工作是为了确保系统能够正常地运行,并为后续的工作做好准备。
设备初始化阶段是Uboot启动流程中的一个重要环节,它包括对外设的初始化和检测。
在这个阶段,Uboot会初始化各种外设,如网卡、存储设备等,并对其进行检测,以确保它们能够正常工作。
最后一个阶段是加载内核,Uboot会从存储设备中加载操作系统的内核镜像到内存中,并跳转到内核的入口地址开始执行。
在这个过程中,Uboot会进行一些必要的设置,如传递启动参数给内核,并最终将控制权交给内核。
总的来说,Uboot的启动流程是一个非常重要的过程,它涉及到系统的硬件初始化、外设的初始化和内核的加载等工作。
只有当这些工作都顺利完成时,系统才能够正常地启动运行。
因此,对Uboot启动流程的深入理解对于嵌入式系统的开发和调试具有重要意义。
通过本文对Uboot启动流程的分析,相信读者对Uboot的工作原理有了更清晰的认识。
希望本文能够对大家有所帮助,谢谢阅读!。
uboot向内核模块传递参数的方法
uboot向内核模块传递参数的⽅法1 模块参数定义模块参数1、module_param(name, type, perm); 定义⼀个模块参数,name 变量名type 数据类型bool:布尔型invbool:⼀个布尔型( true 或者 false)值(相关的变量应当是 int 类型).invbool 类型颠倒了值,所以真值变成 false,反之亦然.charp :⼀个字符指针值. 内存为⽤户提供的字串分配, 指针因此设置.int:整形long:长整形short:短整形uint:⽆符号整形ulong:⽆符号长整形ushort:⽆符号短整形perm 访问权限#define S_IRWXU 00700#define S_IRUSR 00400#define S_IWUSR 00200#define S_IXUSR 00100#define S_IRWXG 00070#define S_IRGRP 00040#define S_IWGRP 00020#define S_IXGRP 00010#define S_IRWXO 00007#define S_IROTH 00004#define S_IWOTH 00002#define S_IXOTH 00001#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) //可以被所有⽤户访问不能改写2、module_param_array(name, type, nump, perm); 定义模块参数数组nump 数组元素的个数⽰例:static int test=0;module_param(test, int, S_IRUGO);在uboot 的启动参数中传递参数例如:setenv bootargs console=ttyS0,115200n8 root=${mmcroot} rootfstype=ext4 rootflags=data=writeback quiet testmodule.test=1testmodule模块名称(也就是.o⽂件或者.ko⽂件的名称) test 模块参数名称如果设置了上⾯的启动参数,在驱动中就可以看到test的值为1 2 直接⽤启动参数传递驱动中定义static int test=0;static int __init Get_test(char *str){test = simple_strtoul(str, NULL, 0);return1;}__setup("mode_test=", Get_test);static char *test_name;static int __init Get_testname(char *str){test_name = str;return1;}__setup("mode_testname=", Get_testname);在启动参数中setenv bootargs console=ttyS0,115200n8 root=${mmcroot} rootfstype=ext4 rootflags=data=writeback quiet test=1 test_name=name 按上⾯的设置,在驱动可以得到test的值为1,test_name为“name”。
U-Boot启动过程--详细版的完全分析
(一)U-Boot启动过程--详细版的完全分析我们知道,bootloader是系统上电后最初加载运行的代码。
它提供了处理器上电复位后最开始需要执行的初始化代码。
在PC机上引导程序一般由BIOS开始执行,然后读取硬盘中位于MBR(Main Boot Record,主引导记录)中的Bootloader(例如LILO或GRUB),并进一步引导操作系统的启动。
然而在嵌入式系统中通常没有像BIOS那样的固件程序,因此整个系统的加载启动就完全由bootloader来完成。
它主要的功能是加载与引导内核映像一个嵌入式的存储设备通过通常包括四个分区:第一分区:存放的当然是u-boot第二个分区:存放着u-boot要传给系统内核的参数第三个分区:是系统内核(kernel)第四个分区:则是根文件系统如下图所示:u-boot是一种普遍用于嵌入式系统中的Bootloader。
Bootloader介绍Bootloader是进行嵌入式开发必然会接触的一个概念,它是嵌入式学院<嵌入式工程师职业培训班>二期课程中嵌入式linux系统开发方面的重要内容。
本篇文章主要讲解Bootloader 的基本概念以及内部原理,这部分内容的掌握将对嵌入式linux系统开发的学习非常有帮助!Bootloader的定义:Bootloader是在操作系统运行之前执行的一小段程序,通过这一小段程序,我们可以初始化硬件设备、建立内存空间的映射表,从而建立适当的系统软硬件环境,为最终调用操作系统内核做好准备。
意思就是说如果我们要想让一个操作系统在我们的板子上运转起来,我们就必须首先对我们的板子进行一些基本配置和初始化,然后才可以将操作系统引导进来运行。
具体在Bootloader中完成了哪些操作我们会在后面分析到,这里我们先来回忆一下PC的体系结构:PC机中的引导加载程序是由BIOS和位于硬盘MBR中的OS Boot Loader(比如LILO和GRUB等)一起组成的,BIOS在完成硬件检测和资源分配后,将硬盘MBR中的Boot Loader读到系统的RAM中,然后将控制权交给OS Boot Loader。
mdio uboot 参数
mdio uboot 参数摘要:1.mdio uboot参数简介2.mdio uboot参数的作用3.如何配置mdio uboot参数4.配置mdio uboot参数的实例5.总结正文:U-Boot是一款常用的嵌入式系统启动代码,负责从存储器中读取内核并启动。
在U-Boot中,有一个名为mdio的参数,它用于配置MII(Media Independent Interface,媒体独立接口)或RMII(Reduced Media Independent Interface,简化媒体独立接口)模式。
mdio参数对于网络芯片的初始化和配置非常重要。
1.mdio uboot参数简介Mdio uboot参数主要用于配置网络芯片的接口模式,包括MII和RMII。
它涉及到PHY(Physical Layer,物理层)和MDIO(Media Dependent Interface,媒体相关接口)的初始化和配置。
在嵌入式系统中,网络芯片的配置对于网络通信至关重要。
2.mdio uboot参数的作用mdio uboot参数的主要作用是配置网络芯片的接口模式,从而实现正确的网络通信。
它可以设置PHY和MDIO的地址、数据和控制信号,以及接口的工作模式。
通过配置mdio uboot参数,可以使网络芯片在MII或RMII模式下工作,满足不同的网络应用需求。
3.如何配置mdio uboot参数配置mdio uboot参数通常需要修改U-Boot的源代码,通过烧写新的U-Boot镜像到嵌入式系统来实现。
具体步骤如下:- 获取U-Boot源代码,并在源代码中找到与mdio参数相关的内容。
- 根据需求修改mdio参数的配置,例如设置PHY地址、MDIO地址、数据和控制信号等。
- 编译并烧写新的U-Boot镜像到目标系统。
- 重启动目标系统,验证mdio参数配置是否正确。
4.配置mdio uboot参数的实例以下是一个配置mdio uboot参数的实例:```# 定义PHY地址CONFIG_PHY_ADDR=0x10# 定义MDIO地址CONFIG_MDIO_ADDR=0x10# 定义PHY寄存器地址CONFIG_PHY_REG_ADDR=0x10# 定义PHY数据线引脚CONFIG_PHY_DATA_PIN=12# 定义PHY控制线引脚CONFIG_PHY_CTRL_PIN=13# 定义MDIO数据线引脚CONFIG_MDIO_DATA_PIN=14# 定义MDIO控制线引脚CONFIG_MDIO_CTRL_PIN=15```5.总结Mdio uboot参数是嵌入式系统中非常重要的一个参数,用于配置网络芯片的接口模式。
经典=Uboot-2-命令详解(bootm)
bootm命令中地址参数,内核加载地址以及内核入口地址分类:u-boot2010-11-04 10:472962人阅读评论(0)收藏举报downloadlinuxbytecmdheaderimagebootm命令只能用来引导经过mkimage构建了镜像头的内核镜像文件以及根文件镜像,对于没有用mkimage对内核进行处理的话,那直接把内核下载到连接脚本中指定的加载地址0x30008000再运行就行,内核会自解压运行(不过内核运行需要一个tag来传递参数,而这个tag是由bootloader提供的,在u-boot下默认是由bootm命令建立的)。
通过mkimage可以给内核镜像或根文件系统镜像加入一个用来记录镜像的各种信息的头。
同样通过mkimage也可以将内核镜像进行一次压缩(指定-C none/gzip/bzip2),所以这里也就引申出了两个阶段的解压缩过程:第一个阶段是u-boot里面的解压缩,也就是将由mkimage压缩的镜像解压缩得到原始的没加镜像头的内核镜像。
第二个阶段是内核镜像的自解压,u-boot 里面的解压实际上是bootm 实现的,把mkimage -C bzip2或者gzip 生成的uImage进行解压;而kernel的自解压是对zImage进行解压,发生在bootm解压之后。
下面通过cmd_bootm.c文件中对bootm命令进行解析以及执行的过程来分析,这三种不同地址的区别:ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){......if (argc < 2) {addr = load_addr;//当bootm命令后面不带地址参数时,将默认的加载地址赋值给addr} else {addr = simple_strtoul(argv[1], NULL, 16); //如果bootm命令后面带了加载地址,则将该地址赋值给addr,所以最终有用的地址还是bootm命令后附带的地址}......//switch (hdr->ih_comp) { //开始判断利用mkimage命令后是否对内核镜像进行了压缩case IH_COMP_NONE: //如果没有被压缩,只是在原有的内核镜像前加了一个头if(ntohl(hdr->ih_load) == addr) { //这步很重要,涉及到我们要讨论的两个地址,我们知道在利用mkimage时指定-a选项后面就是指定的内核加载的地址,这个地址会被存放到镜像头结构的ih_load成员变量中如在smdk2410中ih_load为0x30008000,在这里开始作地址的判断,如果指定的加载地址和之前的addr也就是bootm后面附带的地址相同,则不用将内核镜像搬到其他地方,就在这个地址上执行,这样内核的入口地址就要在加载地址之后的64个字节(因为镜像头占了64个字节),所以入口地址为0x30008040printf (" XIP %s ... ", name);} else {//如果指定的加载地址和bootm命令后的附加地址不相同,我们看看下面data此时表示的是什么地址:data = addr + sizeof(image_header_t);可以看到如果指定加载地址与bootm命令后地址不相同,则从bootm命令后面地址所在地取出内核镜像的头进行检验,检验完后data指向真正的内核,然后将内核拷贝到指定的加载地址处来进行自解压运行,这个时候内核的入口地址就和加载地址一样,不需要加上40个字节,因为内核镜像前面的40个字节的头已经被取出来了。
uboot中bootfmh调用流程
bootm命令在U-Boot 中是用来启动Linux 内核或者Flat Device Tree (FDT) 格式的设备树以及可能包含的根文件系统镜像的命令。
bootm命令执行的流程通常涉及以下步骤:1.加载内核与设备树:在bootm执行前,通常需要使用fatload、ext2load或其他加载命令将Linux 内核映像(例如zImage 或uImage)、设备树blob(dtb 文件)加载到内存中预定义的位置。
2.验证与解析镜像头:bootm命令首先会检查指定内存区域的内容是否符合Multi-Component Boot (MCB) 格式,该格式允许在一个单一的二进制块中包含多个可启动组件的信息。
如果找到合法的MCB 头,它会进一步解析内核镜像和其他组件的相关信息。
3.设置环境变量:U-Boot 会根据加载的内核类型设置必要的环境变量,如bootargs(传递给内核的启动参数),fdtcontroladdr(设备树的加载地址)等。
4.初始化板级硬件:在启动内核前,确保所有必要的外设和SOC 功能已经被正确初始化,以便内核能够顺利接管控制权。
5.调用启动例程:最后,bootm命令会调用相关的启动例程来启动内核。
这个过程通常涉及到跳转到特定的启动函数,该函数会配置CPU 进入特定模式以运行ARM Linux 内核,然后调用内核的入口点开始执行内核代码。
具体来说,bootm命令在U-Boot 源代码中对应的实现部分主要包括:•cmd_bootm.c文件中包含了do_bootm()函数,它是bootm命令的主要执行体。
•在do_bootm()函数内部,会按照不同类型的镜像(单内核、多组件)分别处理。
•如果内核支持flattened device tree,会加载并验证设备树数据,并将其地址写入适当的寄存器或内存位置供内核启动时获取。
•设置栈指针、CPU模式、以及重定位向量表等,为内核启动做准备。
•最终,bootm调用类似boot_jump_linux()函数来跳转到内核的入口点开始执行。
uboot的常用命令及用法
uboot的常⽤命令及⽤法uboot是bootloader的⼀种,主要是⽤于引导内核启动.uboot除此功能外, 还带有很多其它功能. 功能是通过命令来调⽤.uboot的命令:help //列出当前uboot所有⽀持的命令help 命令 //查看指定命令的帮助reset //重启ubootbootm //⽤于启动内核⽤法: bootm 0x42000000 //从内存地址0x42000000启动内核, 启动前需把内核镜像uImage存放到指定的内存地址printenv //打印所有环境变量的值printenv 环境变量名 //查看指定的环境变量值常⽤环境变量:bootdelay // uboot启动后, 倒计时多少秒后⾃动执⾏环境变量bootcmd的语句bootcmd // 倒计时到0后,⾃动执⾏⾥⾯的语句bootargs // 是⽤于提供给内核的启动参数语句setenv //设置/修改/删除环境变量的值⽤法:setenv 环境变量名 //删除指定的环境变量setenv myargs "hello" //设置环境变量myargs=hello, 如果环境变量没有会创建出来,如果已存则会修改它的值saveenv //保存环境变量,环境变量修改过后必须执⾏此命令才可以保存起来,否则重启后环境变量就恢复了.loady //⽤于从uart线下载⽂件到板上内存⾥(loadb, loads, loadx基本⼀样) ⽤法:loady 0x40008000 //把下载的⽂件从内存地址0x40008000开始存放执⾏"loady 0x40008000"后, uboot就会进⼊等待状态,等着接收数据minicom具有通过uart传输⽂件的功能.按"ctrl+a", 松⼿后再按"s", 选择"ymodem", 在弹出的界⾯⾥按空格键选中要传的⽂件.md 内存地址 //⽤于查看内存地址上的值⽤法:md.b 0x40008000 100 //从内存地址0x40008000开始,查看0x100个字节并输出值md.w 0x40008000 100 //从内存地址0x40008000开始,查看0x100个16位值并输出值md.l 0x40008000 100 //从内存地址0x40008000开始,查看0x100个32位值并输出值mw //⽤于修改内存地址上的值⽤法:mw.b 0x40008000 0xab 100 //从内存地址0x40008000开始的0x100字节空间,设值为0xabmw.w 0x40008000 0xabcd 100 //从内存地址0x40008000开始的0x200字节空间,每16位值设为0xabcdmw.l 0x40008000 0xabcdef88 100 //从内存地址0x40008000开始的0x400字节空间,每32位值设为0xabcdef88 go //执⾏指定内存地址上的指令⽤法:go 0x40008000mmc // sd/mmc接⼝设备(sd卡, emmc)操作命令, 按扇区操作(每扇区512字节)⽤法:mmc read addr blk cnt //从mmc设备上的第blk个扇区开始,共读出cnt个扇区到内存地址addr上mmc write addr blk cnt //把内存地址addr上的数据写⼊mmc设备的第blk个扇区,共cnt个扇区⼤⼩mmc dev //⽤于当看当前的mmc设备是第⼏个mmc erase blk cnt //把mmc设备的第blk个扇区开始清零,共清除cnt个扇区⼤⼩ mmc part //列出当前mmc设备的分区信息mmc list //列出所有的mmc设备信息ext4ls //查看存储设备的ext2/3/4分区⾥的内容⽤法:ext4ls mmc 0:2 //查看第0个存储设备的第⼆个分区ext4load //从ext2/3/4分区⾥读出⽂件到指定的内存地址⽤法:ext4load mmc 0:2 0x40008000 /uImage //从第0个存储设备的第2个分区的根⽬录读出uImage⽂件到内存地址0x40008000 fatls //查看存储设备的fat分区⾥的内容⽤法:fatls mmc 0:1 //查看第0个存储设备的第1个分区(fat分区)fatload //从fat分区⾥读出⽂件到指定的内存地址⽤法:fatload mmc 0:1 0x40008000 /uImage //从第0个存储设备的第1个分区的根⽬录读出uImage⽂件到内存地址0x40008000fatwrite //把内存上的数据存储到fat分区的⼀个⽂件⾥⽤法:fatwrite mmc 0:1 0x40008000 /my.txt 0x35 //把内存地址0x40008000开始的0x35个字节数据写⼊到第0个设备的第1个分区⾥,⽂件名为my.txtrun //执⾏指定的环境变量⾥的语句⽤法:run bootcmd //执⾏环境变量bootcmd⾥的语句//如uboot上已驱动好⽹络设备并环境变设好IP及PC端IP,还可以使⽤以下命令:tftpboot 0x40008000 ⽂件名 // 通过⽹络下载⽂件到内存地址0x40008000, PC端需配置好tftp服务器nfs 0x40008000 pc端IP:/带路径的⽂件名 //pc端需配置好nfs服务器ping ip //检测⽹络是否通指令: bootmbootm ⽤于将内核镜像加载到内存的指定地址处例:bootm 0x82000000查看和修改环境变量指令常⽤环境变量列表bootdelay 执⾏⾃动启动(bootcmd中的命令)的等候秒数baudrate 串⼝控制台的波特率bootfile 默认的下载⽂件名bootargs 传递给Linux内核的启动参数bootcmd ⾃动启动时执⾏命令stdin 标准输⼊设备,⼀般是串⼝stdout 标准输出,⼀般是串⼝,也可是LCD(VGA)stderr 标准出错,⼀般是串⼝,也可是LCD(VGA)serverip TFTP服务器端的IP地址ipaddr 本地的IP地址ethaddr 以太⽹的MAC地址netmask 以太⽹的⽹络掩码gatewayip 以太⽹的⽹关指令: setenvname value第1个参数是环境变量的名称。
UBoot中MAC地址设置及往内核中传递修订版
U B o o t中M A C地址设置及往内核中传递集团标准化小组:[VVOPPT-JOPP28-JPPTL98-LOPPNN]一、内核参数的传递U-Boot向Linux驱动传递参数的方式有两种,一为在系统启动的时候由bootloader传入,还有一种是将驱动编译成模块,将参数作为模块加载的参数传入。
内核通过setup接口接受Bootloader传入的参数。
方式如下:staticint__initparam_mac_setup(char*str){……}__setup(“mac=”,param_mac_setup);这样,当在Bootloader中指定“mac=00:2E:79:38:6D:4E”,系统在加载这个模块的时候,就会执行相应的param_mac_setup()函数,而传入给它的参数就是等号后面的物理地址“00:2E:79:38:6D:4E”。
这样,该函数就可以对它进行相应的处理。
在U-Boot中,默认设置mac地址的参数为ethaddr,我们可以用过setenvethaddrMac地址来设置开发板的mac地址。
二、bootm传递参数的方式在bootm执行的流程图中,可以看到会调用do_bootm_linux()在执行Linux内核,内核的起始地址如下:void(*theKernel)(intzero,intarch,uintparams);image_header_t*hdr=&header;theKernel=(void(*)(int,int,uint))ntohl(hdr->ih_ep);header是uImage的头部,通过头部,得到内核映像起始的执行地址,标识为theKernel。
从中也可以看到,内核接受三个参数,第一个为0,第二个为系统的ID号,第三个是传入内核的参数。
在do_bootm_linux()的最后,会跳到内核去执行:theKernel(0,bd->bi_arch_number,bd->bi_boot_params);最后两个参数在board/smdk2410/smdk2410.c的board_init()中被初始化:/*archnumberofSMDK2410-Board*/gd->bd->bi_arch_number=MACH_TYPE_SMDK2410;/*193*//*adressofbootparameters*/可以看到,U-Boot传给内核的参数表存放在内存中起始偏移0×100的位置,这里只是指定了“指针”的位置,但还没初始化其中的值,这是在do_bootm_linux()中跳到内核前去完成的。
经典=Uboot-11-如何向内核传递启动参数(具体实现)
u-boot向linux内核传递启动参数(详细)U-BOOT 在启动内核时,会向内核传递一些参数.BootLoader 可以通过两种方法传递参数给内核,一种是旧的参数结构方式(parameter_struct),主要是2.6 之前的内核使用的方式。
另外一种就是现在的2.6内核在用的参数链表(tagged list) 方式。
这些参数主要包括,系统的根设备标志,页面大小,内存的起始地址和大小,RAMDISK的起始地址和大小,压缩的RAMDISK根文件系统的起始地址和大小,当前内核命令参数等而这些参数是通过struct tag来传递的。
U-boot 把要传递给kernel 的东西保存在struct tag 数据结构中,启动kernel 时,把这个结构体的物理地址传给kernel;Linux kernel 通过这个地址分析出u-boot传递的参数。
大家都知道U-Boot启动的时候会将启动参数的地址放入R2中,然后再启动内核。
首先看两个重要的数据结构:第一个是global_data,定义在include/asm-arm/global_data.h文件中:typedef struct global_data {bd_t *bd;unsigned long flags;unsigned long baudrate;unsigned long have_console; /* serial_init() was called */unsigned long reloc_off; /* Relocation Offset */unsigned long env_addr; /* Address of Environment struct */unsigned long env_valid; /* Checksum of Environment valid? */unsigned long fb_base; /* base address of frame buffer */#ifdef CONFIG_VFDunsigned char vfd_type; /* display type */#endif#if 0unsigned long cpu_clk; /* CPU clock in Hz! */unsigned long bus_clk;unsigned long ram_size; /* RAM size */unsigned long reset_status; /* reset status register at boot */#endifvoid **jt; /* jump table */} gd_t;在同一个文件中有如下定义:#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")在需要使用gd指针的时候,只需要加入DECLARE_GLOBAL_DATA_PTR这句话就可以了。
uboot下的fdt reserved-memory的定义-概述说明以及解释
uboot下的fdt reserved-memory的定义-概述说明以及解释1.引言1.1 概述概述部分的内容可以如下所示:概述U-Boot是一种广泛应用于嵌入式系统的开源引导加载程序。
它提供了一个灵活且可扩展的平台,用于引导和管理各种嵌入式设备。
在U-Boot 中,FDT(Flattened Device Tree)是一种用于描述硬件设备的数据结构。
通过使用FDT,我们可以在引导过程中动态配置硬件资源,如内存、设备节点等。
本文旨在探讨在U-Boot中的FDT reserved-memory的定义。
FDT reserved-memory是一种用于保留特定内存区域的机制。
在启动过程中,U-Boot可以通过配置FDT reserved-memory来指定需要被保留的内存区域,以供系统中其他组件使用。
这种机制在嵌入式系统中非常实用,特别是当我们需要在运行时划分内存空间时。
通过合理配置FDT reserved-memory,可以避免内存冲突和资源浪费,提高系统性能与稳定性。
接下来的章节将依次介绍U-Boot的简介、FDT的简介以及U-Boot 中的FDT reserved-memory。
在最后,我们将详细阐述FDT reserved-memory的定义,以帮助读者更好地理解和应用这一重要的概念。
通过对U-Boot下的FDT reserved-memory的定义的深入探讨,我们可以更好地了解如何在嵌入式系统中合理地管理和配置内存资源,优化系统性能与稳定性。
同时,本文也为进一步研究和应用U-Boot和FDT提供了有益的参考。
1.2文章结构文章结构部分的内容可以按照以下方式编写:1.2 文章结构本文将按照以下结构进行讲解:1. 引言1.1 概述1.2 文章结构1.3 目的2. 正文2.1 U-Boot简介2.2 FDT(Flattened Device Tree)简介2.3 U-Boot中的FDT reserved-memory2.4 FDT reserved-memory的定义3. 结论3.1 总结3.2 展望在引言部分,我们将对本文的主题进行概述,并介绍文章的结构和目的。
uboot开发流程
uboot开发流程U-Boot 开发流程U-Boot 是一个用于启动嵌入式系统的大约 40KB 的嵌入式固件。
它在系统启动过程中通常作为第一个软件组件被加载和执行,负责初始化硬件、加载内核并将其传递给内核。
开发 U-Boot 的步骤:1. 获取 U-Boot 源代码从 U-Boot 官方网站下载最新版本的 U-Boot 源代码。
2. 设置开发环境安装必要的工具链和依赖项,例如交叉编译器、Make 和 Perl。
还要创建一个用于开发和构建 U-Boot 的工作区。
3. 配置 U-Boot打开 U-Boot 配置文件(通常为 'config.h'),并根据您的特定板配置选项,例如板类型、内存大小和外围设备。
4. 编译 U-Boot使用 'make' 命令编译 U-Boot。
5. 调试 U-Boot使用 'gdb' 等调试器调试 U-Boot 代码,并修复任何编译错误或运行时问题。
6. 设置和测试 NAND/NOR 闪存配置 U-Boot 以使用 NAND 或 NOR 闪存,并通过写入和验证图像来测试该配置。
7. 集成 U-Boot 到板级支持包 (BSP)将编译后的 U-Boot 图像集成到您的 BSP 中,这是一个用于支持特定硬件板的软件包。
8. 在目标板上测试 U-Boot将 BSP 部署到目标板,并测试 U-Boot 是否可以正确启动系统。
9. 个性化 U-Boot根据您的特定需求定制 U-Boot 的命令行和功能,例如添加自定义命令或修改环境变量。
10. 维护 U-Boot随着时间的推移,跟踪和应用 U-Boot 社区的更新和补丁,以确保您的开发保持最新且安全。
提示:遵循 U-Boot 文档并充分利用社区支持。
使用版本控制系统来跟踪您的更改。
彻底测试您的代码以确保其稳定性。
保持 U-Boot 与您的目标板紧密集成。
定期更新 U-Boot 以利用最新功能和安全改进。
UBoot中MAC地址设置及往内核中传递
一、内核参数的传递U-Boot向Linux驱动传递参数的方式有两种;一为在系统启动的时候由bootloader传入;还有一种是将驱动编译成模块;将参数作为模块加载的参数传入..内核通过setup接口接受Bootloader传入的参数..方式如下:staticint__initparam_mac_setupcharstr{……}__setup“mac=”;param_mac_setup;这样;当在Bootloader中指定“mac=00:2E:79:38:6D:4E”;系统在加载这个模块的时候;就会执行相应的param_mac_setup函数;而传入给它的参数就是等号后面的物理地址“00:2E:79:38:6D:4E”..这样;该函数就可以对它进行相应的处理..在U-Boot中;默认设置mac地址的参数为ethaddr;我们可以用过setenvethaddrMac地址来设置开发板的mac地址..二、bootm传递参数的方式在bootm执行的流程图中;可以看到会调用do_bootm_linux在执行Linux内核;内核的起始地址如下:voidtheKernelintzero;intarch;uintparams;image_header_thdr=&header;theKernel=voidint;int;uintntohlhdr->ih_ep;header是uImage的头部;通过头部;得到内核映像起始的执行地址;标识为theKernel..从中也可以看到;内核接受三个参数;第一个为0;第二个为系统的ID号;第三个是传入内核的参数..在do_bootm_linux的最后;会跳到内核去执行:theKernel0;bd->bi_arch_number;bd->bi_boot_params;最后两个参数在board/smdk2410/smdk2410.c的board_init中被初始化:/archnumberofSMDK2410-Board/gd->bd->bi_arch_number=MACH_TYPE_SMDK2410;/193//adressofbootparameters/可以看到;U-Boot传给内核的参数表存放在内存中起始偏移0×100的位置;这里只是指定了“指针”的位置;但还没初始化其中的值;这是在do_bootm_linux中跳到内核前去完成的..三、参数列表的构建ifdefinedCONFIG_SETUP_MEMORY_TAGS||\definedCONFIG_CMDLINE_TAG||\definedCONFIG_INITRD_TAG||\ definedCONFIG_SERIAL_TAGsetup_start_tagbd;ifdefCONFIG_SERIAL_TAGsetup_serial_tag¶ms;endififdefCONFIG_REVISION_TAGsetup_revision_tag¶ms;endififdefCONFIG_SETUP_MEMORY_TAGSsetup_memory_tagsbd;endififdefCONFIG_CMDLINE_TAGsetup_commandline_tagbd;commandline; endififdefCONFIG_INITRD_TAGifinitrd_start&&initrd_endsetup_initrd_tagbd;initrd_start;initrd_end; endififdefinedCONFIG_VFD||definedCONFIG_LCDsetup_videolfb_taggd_tgd;endifsetup_end_tagbd;endif四、解决U-Boot命令行中不能重新设置ethaddr的问题;经常会提示Can’toverwrite“ethaddr”common/cmd_nvedit.c中函数_do_setenv中找到ifndefCONFIG_ENV_OVERWRITE/EthernetAddressandserialcanbesetonlyonce;verisreadonly./ifdefCONFIG_HAS_UID/Allowserialforcedoverwritewith0xdeaf4addflag/ifstrcmpname;“serial”==0&&flag=0xdeaf4add||elseifstrcmpname;“serial”==0||endifstrcmpname;“ethaddr”==0ifdefinedCONFIG_OVERWRITE_ETHADDR_ONCE&&definedCONFIG_ETHADDR&&strcmpcharenv_g et_addroldval;MK_STRCONFIG_ETHADDR=0endif/CONFIG_OVERWRITE_ETHADDR_ONCE&&CONFIG_ETHADDR/{printf“Can’toverwrite\”%s\”\n”;name;return1;}endif把strcmpname;“ethaddr”==0替换成0即可;五.为了让U-Boot命令行中设置的参数ethaddr传递到内核;必须修改U-Boot和linux内核两个地方:1U-Boot修改:lib_arm/armlinux.c在 ifdefCONFIG_CMDLINE_TAGsetup_commandline_tagbd;commandline;下面添加如下语句:charbuf1=malloc1024;sprintfbuf1;“%smac=%s”;getenv“bootargs”;getenv“ethaddr”;setup_commandline_tagbd;buf1;2linux内核修改:drivers/net/davinci_emac.cstaticintemac_eth_setupvoid{前面添加:staticchardavinci_mac_addr_uboot20=“”;staticint__initparam_mac_setupcharstr{strncpydavinci_mac_addr_uboot;str;sizeofdavinci_mac_addr_uboot; }__setup“mac=”;param_mac_setup;并在函数emac_eth_setup内部语句printk“TIDaVinciEMAC:MACaddressis%s\n”;emac_eth_string;前面添加:strncpyemac_eth_string;davinci_mac_addr_uboot;sizeofemac_eth_string; 添加完毕;重新编译uboot和内核..参考文献:。
UBOOT引导Linux内核及向内核传递参数的方式
UBOOT引导Linux内核及向内核传递参数的⽅式 ⼀直以来没有想过有什么好的办法通过寄存器向内核传递参数,直到今天读UBOOT的实现⽅式。
在UBOOT中,引导内核最常⽤的⽅法是bootm命令,bootm命令可以引导“UBOOT格式”的内核。
先花点时间了解⼀下什么是“UBOOT格式”的内核吧:⽤UBOOT⾃带的mkimage命令⽣成的内核称为"UBOOT"格式的内核。
以下⾯这条命令为例: mkimage -n "Kernel 2.4.18" -A arm -O linux -T kernel -C none -a30007fc0 -e 30008000 -d 4020.bin vmlinux-2.4.18.img 其中与内核引导最密切的是-e 30008000,也就是内核的⼊⼝地址。
其它参数可以参考帮助信息。
其它UBOOT格式的内核与原来相⽐,只是进⾏(可选)了压缩,并在前⾯加了⼀个0x40⼤⼩的头。
这个头⾥放了内核的位置(0x30007fc0)和⼊⼝地址(0x30008000)和其它信息。
bootm命令执⾏时,先对头部信息等进⾏校验,然后把头信息放到⼀个结构⾥⾯。
最后根据内核类型调⽤相应的启动函数。
对于Linux⽽⾔就是do_bootm_linux,在启动函数⾥⾯,有这么⼀个操作:theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);,这是最关键的⼀个操作,将内核的⼊⼝地址0x30008000赋给了theKernel,在启动函数的最后,使⽤theKernel (0, bd->bi_arch_number, bd->bi_boot_params);启动内核。
根据传参规范,三个变量分别⽤r0,r1,r2传给内核,这样就巧妙地利⽤了函数指针进⾏了参数传递,实在是精妙!上⾯讲完了内核的引导及传参,需要引起注意的就是在使⽤mkimage命令⽣成内核时,-e后⾯的地址要⽐-a后⾯的地址偏移0x40,原因很简单,就不在细说了。
uboot内核移植和裁剪详细步骤
uboot内核移植和裁剪详细步骤-U-boot内核移植步骤:Linux 3.3.5系统移植1. 将arch/arm/mach-s3c6410/下的,mach-smdk6410.c cp为mach-my6410.c;2. 打开arch/arm/mach-s3c6410/下的Kconfig,仿照MACH_SMDK6410做一个菜单项:config MACH_MY6410bool "MY6410"select CPU_S3C6410select SAMSUNG_DEV_ADCselect S3C_DEV_HSMMCselect S3C_DEV_HSMMC1select S3C_DEV_I2C1select SAMSUNG_DEV_IDEselect S3C_DEV_FBselect S3C_DEV_RTCselect SAMSUNG_DEV_TSselect S3C_DEV_USB_HOSTselect S3C_DEV_USB_HSOTGselect S3C_DEV_WDTselect SAMSUNG_DEV_BACKLIGHTselect SAMSUNG_DEV_KEYPADselect SAMSUNG_DEV_PWMselect HAVE_S3C2410_WATCHDOG if WATCHDOGselect S3C64XX_SETUP_SDHCIselect S3C64XX_SETUP_I2C1select S3C64XX_SETUP_IDEselect S3C64XX_SETUP_FB_24BPPselect S3C64XX_SETUP_KEYPADhelpMachine support for the Pillar MY64103. 打开arch/arm/tools/mach-types文件,这里面存的是机器ID必须要和uboot里面的ID保持一致,将其283行复制添加在后面并修改为: smdk6410MACH_SMDK6410 SMDK6410 1626 xx6410 MACH_XX6410 XX6410 1626 这个机器ID和UBOOT里的机器ID相同时才能启动内核;1. 修改BSP文件mach-my6410.c,内容如下:将mach-mach-my6410.c文件中的所有smdk6410改成my6410(不要改大写SMDK6410的)MACHINE_START(MY6410, "MY6410")//这个要和Kconfig里的MACH-MY6410匹配 2. 在当前目录的Makefile最后一行加上 obj-$(CONFIG_MACH_MY6410) += mach-my6410.o3. 修改顶层的Makefile:ARCH ?= armCROSS_COMPILE ?= /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux- 4. 复制arch/arm/configs/下的s3c6400-defconfig文件,然后将其保存为.config,配置内核支持EABI,再选中XX6410 board这一项,保存退出;5. 执行make menuconfig对内核进行配置:执行make编译执行make zImage生成zImage将uboot根目录下的mkimage拷贝到/user/bin目录下执行make uImage生成uImage通过以上几步linux内核移植完了,剩下就移植驱动了。
u-boot中分区和内核MTD分区关系
u-boot中分区和内核MTD分区关系⼀、u-boot中环境变量与uImage中MTD的分区关系分区只是内核的概念,就是说A~B地址放内核,C~D地址放⽂件系统,(也就是规定哪个地址区间放内核或者⽂件系统)等等。
⼀般我们只需要分3-4个区,第⼀个为boot区,⼀个为boot参数区(传递给内核的参数),⼀个为内核区,⼀个为⽂件系统区。
(但是有的内核就会有很多分区,⽐如内核参数会有两个,还有会Logo的地址)⽽对于bootloader中只要能将内核下载到A~B区的A地址开始处就可以,C~D区的C起始地址下载⽂件系统…….这些起始地址在MTD的分区信息中能找到。
所以bootloader对分区的概念不重要,只要它能把内核烧到A位置,把⽂件系统烧到C位置即可。
所以,在bootloader对Flash进⾏操作时,哪块区域放什么是以内核为主(内核中MTD的分区信息可以从内核的代码中看到)。
传递给u-boot 的参数只要和内核中MTD分区信息⼀致即可。
⽽为了⽅便操作,bootloader类似也引⼊分区的概念。
例如,可以使⽤“nandwrite 0x3000000 kernel 200000”命令将uImage烧到kernel分区,⽽不必写那么长:nand write 3000000 A 200000,也就是⽤分区名来代替具体的地址。
这要对bootloader对内核重新分区:这需要重新设置⼀下bootloader环境参数,就可以同步更新内核分区信息如:setenv bootargs 'noinitrd console=ttySAC0root=/dev/mtdblock3 rootfstype=jffs2 mtdparts=nand_flash:128k(u-boot)ro,64k(u-bootenvs),3m(kernel),30m(root.jffs2),30m(root.yaffs)'解析:在这⾥的挂载⽂件系统的地⽅mtdblock3,可以从mtdparts中看出来,第⼀个⽂件系统(jffs2格式)在第四个分区,所以使⽤mtdblock3,关于分区和⽂件系统的挂载在下⾯有解释。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Uboot如何向内核传递参数一:启动参数的传递过程启动参数是包装在数据结构里的,在linux kernel启动的时候,bootloader把这个数据结构拷贝到某个地址,在改动PC跳向内核接口的同时,通过通用寄存器R2来传递这个地址的值,下面这句话就是uboot跳向linuxkernel的代码(bootm命令)theKernel (0, bd->bi_arch_number, bd->bi_boot_params);thekernel其实不是个函数,而是指向内核入口地址的指针,把它强行转化为带三个参数的函数指针,会把三个参数保存到通用寄存器中,实现了向kernel传递信息的功能,在这个例子里,会把R0赋值为0,R1赋值为机器号R2赋值为启动参数数据结构的首地址因此,要向内核传递参数很简单,只要把启动参数封装在linux预定好的数据结构里,拷贝到某个地址(一般约定俗成是内存首地址+100dex)二:启动参数的数据结构启动参数可保存在两种数据结构中,param_struct和tag,前者是2.4内核用的,后者是2.6以后的内核更期望用的但是,到目前为止,2.6的内核也可以兼容前一种结构,两种数据结构具体定义如下(arm cpu):struct param_struct {union {struct {unsigned long page_size; /* 0 */unsigned long nr_pages; /* 4 */unsigned long ramdisk_size; /* 8 */unsigned long flags; /* 12 */#define FLAG_READONLY 1#define FLAG_RDLOAD 4#define FLAG_RDPROMPT 8unsigned long rootdev; /* 16 */unsigned long video_num_cols; /* 20 */unsigned long video_num_rows; /* 24 */unsigned long video_x; /* 28 */unsigned long video_y; /* 32 */unsigned long memc_control_reg; /* 36 */unsigned char sounddefault; /* 40 */unsigned char adfsdrives; /* 41 */unsigned char bytes_per_char_h; /* 42 */unsigned char bytes_per_char_v; /* 43 */unsigned long pages_in_bank[4]; /* 44 */unsigned long pages_in_vram; /* 60 */unsigned long initrd_start; /* 64 */unsigned long initrd_size; /* 68 */unsigned long rd_start; /* 72 */unsigned long system_rev; /* 76 */unsigned long system_serial_low; /* 80 */unsigned long system_serial_high; /* 84 */unsigned long mem_fclk_21285; /* 88 */} s;char unused[256];} u1;union {char paths[8][128];struct {unsigned long magic;char n[1024 - sizeof(unsigned long)];} s;} u2;char commandline[COMMAND_LINE_SIZE];};param_struct只需要设置cmmandline,u1.s.page_size,u1.s.nr_pages三个域,具体使用可参见下面的例子对于tag来说,在实际使用中是一个struct tag组成的列表,在tag->tag_header中,一项是u32 tag(重名,注意类型)其值用宏ATAG_CORE,ATAG_MEM,ATAG_CMDLINE,ATAG_NONE等等来表示,此时下面union就会使用与之相关的数据结构同时,规定tag列表中第一项必须是ATAG_CORE,最后一项必须是ATAG_NONE,比如在linux代码中,找到启动参数之后首先看tag列表中的第一项的tag->hdr.tag是否为ATAG_CORE,如果不是,就会认为启动参数不是tag 结构而是param_struct结构,然后调用函数来转换.在tag->tag_header中,另一项是u32 size,表示tag的大小,tag组成列表的方式就是指针+size,实际使用中用tag_next (params).tag的具体使用见三中的例子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;struct tag_acorn acorn; //Acorn specificstruct tag_omap omap; //OMAP specificstruct tag_memclk memclk; //DC21285 specific} u;};需要注意的是,这两个数据结构在uboot中和linux中分别有定义,这个定义必须一直才能正常传递参数如果实际使用中不一致的话就不能正常传递,可以自行修改三:通过两种数据结构传递参数的具体例子1:例子一:通过param_struct让uboot中的go命令可以传递参数分析:go的代码在common/cmd_boot.c中,里面并没有拷贝启动参数的代码,转向内核的时候也没有传送启动参数所在的地址,因此添加如下代码用于拷贝参数,可以看到,对于param_struct只需要设置cmmandlineu1.s.page_size,u1.s.nr_pages三个域char *commandline = getenv("bootargs");struct param_struct *lxy_params=(struct param_struct *)0x80000100;printf("setup linux parameters at 0x80000100\n");memset(lxy_params,0,sizeof(struct param_struct));lxy_params->u1.s.page_size=(0x1<<12); //4K 这个是必须有的,否则无法启动lxy_params->u1.s.nr_pages=(0x4000000)>>12; //64M 这个是必须有的,否则无法启动memcpy(lxy_params->commandline,commandline,strlen(commandline)+1);printf("linux command line is: \"%s\"\n",lxy_params->commandline);然后还要向内核传递参数地址,将下面一行代码修改:rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]); //需要被修改的代码rc = ((ulong(*)(int,int,uint))addr) (0, gd->bd->bi_arch_number,gd->bd->bi_boot_params);//修改之后的代码2:例子二:bootm命令中通过拷贝tag传递参数为方便阅读,进行了少许修改,但功能不变,该函数参数为存放启动参数的地址static void setup_linux_tag(ulong param_base){struct tag *params = (struct tag *)param_base;char *linux_cmd;char *p;memset(params, 0, sizeof(struct tag));/* step1: setup start tag */params->hdr.tag = ATAG_CORE;params->hdr.size = tag_size(tag_core);params->u.core.flags = 0;params->u.core.pagesize = LINUX_PAGE_SIZE;params->u.core.rootdev = 0;params = tag_next(params);/* step2: setup cmdline tag */params->hdr.tag = ATAG_CMDLINE;linux_cmd = getenv("bootargs");/* eat leading white space */for (p=linux_cmd; *p==' '; p++) {/* do nothing */;}params->hdr.size = (sizeof(struct tag_header)+strlen(linux_cmd)+1+4) >> 2;memcpy(params->u.cmdline.cmdline, linux_cmd, strlen(linux_cmd)+1);params = tag_next(params);/* step3: setup end tag */params->hdr.tag = ATAG_NONE;params->hdr.size = 0;}四:其他在uboot中,进行设置tag的函数都在lib_arm/armlinux.c中,在这些函数前面是有ifdef的#if defined (CONFIG_SETUP_MEMORY_TAGS) || \defined (CONFIG_CMDLINE_TAG) || \defined (CONFIG_INITRD_TAG) || \defined (CONFIG_SERIAL_TAG) || \defined (CONFIG_REVISION_TAG) || \defined (CONFIG_LCD) || \defined (CONFIG_VFD)因此,如果你的bootm命令不能传递内核参数,就应该是在你的board的config文件里没有对上述的宏进行设置,定义一下即可。