u-boot总结
来源:互联网 发布:openwrt mac地址过滤 编辑:程序博客网 时间:2024/06/05 14:55
这个周末复习下u-boot,看韦东山老师的从零开始写u-boot视频是个不错的学习教程,本次总结借鉴周立功,韦东山,上课笔记,csdn上其他博客的资料汇总来的,总结可能也不是特别全面。
上篇:
本次总结的内容有:
1. u-boot的SD卡启动细节
2. 分析u-boot是如何启动内核
3. 分析几个重点:u-boot链接文件,makefile
4. 韦东山精简u-boot编写
5. u-boot常用命令
下篇:
uboot可以学习的内容还有好多
1、u-boot环境变量实现
http://blog.csdn.net/gongyuan073/article/details/47150473
2、u-boot 编译过程
http://blog.csdn.net/kevin_mr/article/details/51428535
3、u-boot 的流程、主要的数据结构、内存分配
http://blog.csdn.net/xiaoaid01/article/details/39700375
4、基于 NOR FLASH 和 NAND FLASH 启动
http://www.cnblogs.com/aaronLinux/p/5540606.html
5、u-boot 内存布局及启动过程浅析
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29589379&id=5571499
6u-boot-1.1.6 之 cpu/arm920t/start.s 分析
http://blog.csdn.net/yu704645129/article/details/50441751
7、u-boot之重定位
http://blog.csdn.net/funkunho/article/details/52474373
8、u-boot代码修改支持nandflash,norflash
http://blog.csdn.net/fulinus/article/details/41286211
9、u-boot添加自定义命令
http://blog.csdn.net/itxiebo/article/details/50991049
10、如何移植u-boot
http://blog.csdn.net/zqixiao_09/article/details/50818428
上篇:
1、uboot的SD卡启动细节
(1)uboot编译好之后有200多KB,超出了16KB。uboot的组织方式就是前面16KB 为BL1,剩下的部分为BL2.
(2)uboot在烧录到SD卡的时候,先截取uboot.bin的前16KB(实际脚本截取的是8KB)烧录到SD卡的block1~bolck32;然后将整个uboot烧录到SD卡的某个扇区中(譬如49扇区)
(3)实际uboot从SD卡启动时是这样的:iROM先执行,根据OMpin判断出启动设备是SD卡,然后从S卡的block1开始读取16KB(8KB)到SRAM中执行BL1,BL1执行时负责初始化DDR,并且从SD卡的49扇区开始复制整个uboot到DDR中指定位置(0x23E00000)去备用;然后BL1继续执行直到ldr pc, =main时BL1跳转到DDR上的BL2中接着执行uboot的第二阶段。
启动卡的制作:
http://blog.csdn.net/morixinguan/article/details/70196668
SD卡详细分析:
http://blog.chinaunix.net/uid-28110044-id-4006225.html
2. 分析uboot是如何启动内核
U-Boot启动过程–详细版的完全分析
http://blog.csdn.net/u013256622/article/details/41951033Tiny4412 u-boot分析(2)u-boot启动流程
http://www.cnblogs.com/CoderTian/p/5995409.html
使用do_bootm_linux(),在/lib_arm/bootm.c定义,因为我们已经知道入口地址了,所以只需跳到入
口地址就可以启动linux内核了,但是在这之前需要做一件事————uboot传递参数给内核!!
现在来分析do_bootm_linux()这个函数:
theKernel = (void (*)(int, int, uint))images->ep;//先是将入口地址赋值给theKernel theKernel (0, machid, bd->bi_boot_params);//然后是调用thekernel
函数,以0,machid,bd->bi_boot_params作为参数
下面分析这三个参数:
1.machid就是uboot里设置好的板子的机器码,mini2440的是MACH_TYPE_MINI2440 (1999),内核所设置的机器码和uboot所设置的机器码必须一致才能启动内核
2.bd->bi_boot_parmas就是uboot需传递给内核的启动参数所位于的地址
3.0暂时还不知道什么作用
那么uboot传给内核的启动参数是在哪里设置的呢?
其实就是在调用 theKernel (0, machid, bd->bi_boot_params);前面的一小段代码里设置的,下面我截取了部分片段:
setup_start_tag (bd);setup_revision_tag (¶ms);setup_memory_tags (bd);setup_commandline_tag (bd, commandline);setup_initrd_tag (bd, images->rd_start, images->rd_end);setup_videolfb_tag ((gd_t *) gd);setup_end_tag (bd);
每一个启动参数对应一个tag结构体,所谓的设置传递参数其实就是初始化这些tag的值,想了解这个结构体以及这些tag的值是如何设置的请看韦东山的书关于uboot移植章节!
下面我们看一下setup_start_tag(bd)这个函数先:
static void setup_start_tag (bd_t *bd){ params = (struct tag *) bd->bi_boot_params; //在board.c中有一句gd->bd->bi_boot_params = 0x30000100,这里设置了参数存放的位置 params->hdr.tag = ATAG_CORE; params->hdr.size = tag_size (tag_core); params->u.core.flags = 0; params->u.core.pagesize = 0; params->u.core.rootdev = 0; params = tag_next (params);}
我们再来看下
setup_commandline_tag (bd, commandline);这个函数:static void setup_commandline_tag (bd_t *bd, char *commandline){// commandline就是我们的bootargs char *p; if (!commandline) return; for (p = commandline; *p == ' '; p++); if (*p == '\0') return; params->hdr.tag = ATAG_CMDLINE; params->hdr.size = (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2; strcpy (params->u.cmdline.cmdline, p); params = tag_next (params);}
Linux内核启动时就会去读取这些tag参数
3、分析几个重点:uboot链接文件,makefile
makdfile
http://www.cnblogs.com/amanlikethis/p/3419858.html
uboot链接文件
对于.lds 文件,它定义了整个程序编译之后的连接过程,决定了一个可执行程序的各个段的存储位置。虽然现在我还没怎么用它,但感觉还是挺重要的,有必要了解一下。
定义入口。由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。
/board/samsung/smdkc110/**u-boot.lds
链接文件:给链接器使用的一个文件,该文件告诉链接器我们编译好的目标文件如何链接:
1、链接的地址
2、程序的段(.text代码段、.data数据段、.bss未初始化段)如何链接
3、程序的入口
secname和 contents是必须的,其他的都是可选的。下面挑几个常用的看看:1、 secname:段名2、 contents:决定哪些内容放在本段,可以是整个目标文件,也可以是目标文件中的某段(代码段、数据段等)3、 start:本段连接(运行)的地址,如果没有使用 AT(ldadr),本段存储的地址也是 start。 GNU 网站上说 start 可以用任意一种描述地址的符号来描述。4、 AT(ldadr):定义本段存储(加载)的地址。
4. 韦东山精简uboot编写
最简单的bootloader的编写步骤:1. 初始化硬件:关看门狗、设置时钟、设置SDRAM、初始化NAND FLASH2. 如果bootloader比较大,要把它重定位到SDRAM3. 把内核从NAND FLASH读到SDRAM4. 设置"要传给内核的参数"5. 跳转执行内核int main(void){ void (*theKernel)(int zero, int arch, unsigned int params); volatile unsigned int *p = (volatile unsigned int *)0x30008000; /* 0. 帮内核设置串口: 内核启动的开始部分会从串口打印一些信息,但是内核一开始没有初始化串口 */ uart0_init(); /* 1. 从NAND FLASH里把内核读入内存 */ puts("Copy kernel from nand\n\r"); nand_read(0x60000+64, (unsigned char *)0x30008000, 0x200000); puthex(0x1234ABCD); puts("\n\r"); puthex(*p); puts("\n\r"); /* 2. 设置参数 */ puts("Set boot params\n\r"); setup_start_tag(); setup_memory_tags(); setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0"); setup_end_tag(); /* 3. 跳转执行 */ puts("Boot kernel\n\r"); theKernel = (void (*)(int, int, unsigned int))0x30008000; theKernel(0, 362, 0x30000100); /* * mov r0, #0 * ldr r1, =362 * ldr r2, =0x30000100 * mov pc, #0x30008000 */ puts("Error!\n\r"); /* 如果一切正常, 不会执行到这里 */ return -1;}
5. uboot常用命令
举例:
setenv ipaddr 192.168.1.3
setenv serverip 192.168.1.2
setenv gatewayip 192.168.1.1
saveenv
bdinfo
GEC210 # bdinfoarch_number = 0x00000998 //机器码boot_params = 0x30000100 //存放启动参数的地址DRAM bank = 0x00000000-> start = 0x30000000-> size = 0x10000000DRAM bank = 0x00000001-> start = 0x40000000-> size = 0x10000000ethaddr = 00:40:5C:26:0A:5Bip_addr = 192.168.1.3baudrate = 115200 bps //uart0的速率
1)arch_number = 0x00000998 uboot针对不同的硬件平台有唯一的一个机器码(软件设定,用户定义)。 kernel针对不同的硬件平台有唯一的一个机器码 uboot启动后,会将机器码传给kernel,kernel将uboot传过来的机器码与自身的机器码做对比,如果二者一致,kernel才可以正常启动。2)boot_params = 0x30000100 uboot在加载kernel之前,会将kernel的启动参数存放在该地址下;kernel在启动过程中,会从该地址下拿到启动参数。
printenv
GEC210 # printenvbootargs=root=/dev/mtdblock4 rootfstype=yaffs2 init=/init console=ttySAC0,115200bootcmd=nand read 0x30008000 0x600000 0x500000 ;bootm 0x30008000baudrate=115200ethaddr=00:40:5c:26:0a:5bnetmask=255.255.0.0ipaddr=192.168.1.3serverip=192.168.1.2gatewayip=192.168.1.1bootdelay=5stdin=serialstdout=serialstderr=serial
启动命令–bootcmd
bootcmd=nand read 0x30008000 0x600000 0x500000 ;bootm 0x30008000
(1)nand read 0x30008000 0x600000 0x500000 从nand
flash的0x600000地址开始,读取0x500000大小的内容(5MB,kernel),读到内存的0x30008000地址下
去哪里找到内核,并完成将内核拷贝到内存(2)bootm 0x30008000
在0x30008000地址上,启动kernel告诉uboot,去哪里找内核,并启动内核。
如何设置启动命令:
setenv bootcmd ‘nand read 0x30008000 0x600000 0x500000; bootm
0x30008000’
启动参数 –bootargs
(1)root=/dev/mtdblock4 rootfs是在nand flash的第4个分区中。我们要去该位置上挂载rootfs。 /dev/mtdblock4 --->nand flash第四个分区的设备文件,应用程序通过设备文件访问驱动。(2)rootfstype=yaffs2 rootfs文件系统的格式(3)init=/sbin/init init是linux启动的第一个进程,也是所有进程的父进程,PID=1,也是唯一的一个由linux内核发起的进程。 告诉内核,init进程做什么工作。 /sbin/init ---》处理busybox 什么是busybox --->shell命令(4)console=ttySAC0,115200 设置linux内核的控制台(stdin、stdout、stderr)为串口0(UART0),串口0的波特率是115200.
下篇:
待补充。
- U-BOOT移植总结
- u-boot 移植 总结
- U-Boot移植总结
- u-boot总结
- u-boot 在s3c44b0移植总结
- u-boot 在s3c44b0移植总结
- U-Boot学习笔记总结摘要
- u-boot 在s3c44b0移植总结
- u-boot移植总结(二)
- U-BOOT移植总结(三)
- U-Boot编译问题之总结
- u-boot 在s3c44b0移植总结
- u-boot 在s3c44b0移植总结
- U-Boot学习笔记总结摘要
- U-Boot start.s学习心得总结
- u-boot启动内核学习总结
- U-BOOT
- u-boot
- ZooKeeper快速上手(复制集群)
- 工作感悟
- [LeetCode] 145.Binary Tree Postorder Traversal
- Windows 钩子的使用
- Android环境下使用SocketClient
- u-boot总结
- Linux系统剪裁
- SSM框架整合技术
- SSH与SSM学习之hibernate08——hibernate中的实体规则
- 一首词——雨霖铃
- Dubbo : ZooKeeper安装配置(一)
- builder模式
- Android动画知识汇总
- Android动画Animator开发问题