u-boot学习(两):u-boot简要分析
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
看到不错的文章。不要加入收藏夹,想着以后有时间再看。由于非常有可能你以后再也不会看它们了。
想写总结的文章。不要想着等到以后有时间了再总结,由于非常有可能你以后更没有时间总结它们了。
——送给自己
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
要想知道一个程序的作用。最好的办法是分析程序的源代码。这一方法对了解u-boot的功能也适用,因此。我们首先看u-boot的源代码结构,然后依据源代码结构总结出u-boot的主要特性。
最后,依据配置、编译的过程,简单分析u-boot。
(一)
以u-boot-1.1.6为例分析文件夹结构例如以下:
1、平台相关的或开发板相关的文件夹:board、cpu、lib_i386类似
2、通用函数的文件夹:include、lib_generic、common
3、通用的设备驱动程序:disk、drivers、dtt、fs、nand_spl、net、post、rtc
4、u-boot工具、演示样例程序、文档:doc、example、tools
u-boot顶层文件夹说明
文件夹 | 特性 | 解释说明 |
board | 开发板相关 | 相应不同配置的电路板(即使CPU同样),比方smdk2410等 |
cpu | 平台相关 | 相应不同的CPU,如arm920t、i386等。 |
lib_i386 | 平台相关 | 某一架构下通用的文件 |
include | 通用函数 | 头文件和开发板配置文件,开发板的配置文件都放在include/configs文件夹下 |
lib_generic | 通用函数 | 须要通用的库函数。比方printf等 |
common | 通用函数 | 通用函数,多是对下一层驱动程序的进一步封装 |
disk | 通用设备驱动程序 | 硬盘接口程序 |
drivers | 通用设备驱动程序 |
各类详细设备的驱动程序 |
dtt | 通用设备驱动程序 |
数字温度測量或者传感器的驱动 |
fs | 通用设备驱动程序 |
文件系统 |
nand_spl | 通用设备驱动程序 |
u-boot一般从ROM、NORFLASH等设备启动。如今開始支持NAND Flash启动 |
net | 通用设备驱动程序 |
各种网络协议 |
post | 通用设备驱动程序 |
上电自检程序 |
rtc | 通用设备驱动程序 |
实时时钟的驱动 |
doc | 文档 | 开发、使用文档 |
example | 演示样例程序 | 一些測试程序。能够使用u-boot下载后执行 |
tools | 工具 | 制作S-Record、u-boot格式映像的工具,如mkimage |
从上表中u-boot文件夹的分析能够看出u-boot的一些特性:支持多种嵌入式操作系统内核,如Linux、Vxworks等;支持多个处理器系列。如PowerPC、ARM、x86等;丰富的设备驱动源代码,如串口、SDRAM、Flash、以太网等;支持NFS挂载、RAMDISK形式的根文件系统、从Flash中引导压缩或非压缩系统内核;支持目标板环境变量多种存储方式。如Flash等。CRC32校验、上电自检功能等。
u-boot中各文件夹间也是层次结构的,这有助于在移植过程中为我们须要改动哪些文件提供信息。由下图能够知道。仅仅需改动board、cpu、lib_xxx文件夹下的文件。就可以完毕移植过程。假设想要加入其它的命令等,则须要改动其它文件。
lib_generic common |
post net fs disk |
dtt nand_spl rtc drivers |
board cpu lib_xxx |
(二)配置
上一篇的u-boot概述中配置u-boot时使用了命令:make 100ask24x0_config命令。
运行该命令时运行Makefile中的例如以下一行规则:
100ask24x0_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0
该规则解释为:
100ask24x0_config : unconfig
mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0
因此配置过程。我们能够分析根文件夹下的mkconfig文件。从而了解配置过程,做了哪些工作。逐行分析例如以下:
#!/bin/sh -e # Script to create header files and links to configure
# U-Boot for a specific board.
#
# Parameters: Target Architecture CPU Board [VENDOR] [SOC]
#
# (C) 2002-2006 DENX Software Engineering, Wolfgang Denk <wd@denx.de>
# APPEND=no # Default: Create new config file
BOARD_NAME="" # Name to print in make output mkconfig 100ask24x0 arm arm920t smdk2410 NULL s3c24x0
$0 $1 $2 $3 $4 $5 $6 while [ $# -gt 0 ] ; do <span style="color:#ff6666;">/*$ # :保存程序命令行參数的数目*/</span>
case "$1" in
--) shift ; break ;;
-a) shift ; APPEND=yes ;;
-n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
*) break ;;
esac
done [ "${BOARD_NAME}" ] || BOARD_NAME="$1" <span style="color:#ff6666;">/*由于上面定义了BOARD_NAME="",所以该句得到结果为BOARD_NAME=100ask24x0*/
</span>
[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1 <span style="color:#ff6666;">/*$#是參数的个数。此处$#=6。所以这两句都不会运行到exit 1语句*/</span> echo "Configuring for ${BOARD_NAME} board..."
<span style="color:#ff6666;">/*此句便是运行make 100ask24x0_config时显示的那条语句:Configuring for 100ask24x0 board...*/</span>
#
# Create link to architecture specific headers
#
<span style="color:#ff6666;">/*查看Makefile可知。
*OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
*SRCTREE := $(CURDIR)
*所以if语句不运行,而是运行以下的else语句
*/</span>
if [ "$SRCTREE" != "$OBJTREE" ] ; then
mkdir -p ${OBJTREE}/include
mkdir -p ${OBJTREE}/include2
cd ${OBJTREE}/include2
rm -f asm
ln -s ${SRCTREE}/include/asm-$2 asm
LNPREFIX="../../include2/asm/"
cd ../include
rm -rf asm-$2
rm -f asm
mkdir asm-$2
ln -s asm-$2 asm
else
cd ./include
rm -f asm
ln -s asm-$2 asm <span style="color:#ff6666;">/*删除asm文件。然后再次建立asm文件,并令它链接向asm-$2文件夹。即asm-arm文件夹*/</span>
fi rm -f asm-$2/arch <span style="color:#ff6666;">/*删除asm-$2/arch文件,即asm-arm/arch文件*/</span> if [ -z "$6" -o "$6" = "NULL" ] ; then <span style="color:#ff6666;">/* -z string表示string为null $6也不是NULL,因此运行else分支*/</span>
ln -s ${LNPREFIX}arch-$3 asm-$2/arch
else
ln -s ${LNPREFIX}arch-$6 asm-$2/arch <span style="color:#ff6666;">/*由于LNPREFIX为空,该句为ln -s arch-s3c24x0 asm-arm/arch*/</span>
fi if [ "$2" = "arm" ] ; then
rm -f asm-$2/proc
ln -s ${LNPREFIX}proc-armv asm-$2/proc <span style="color:#ff6666;">/*又一次建立asm-arm/proc文件。并让它链接向proc-armv文件夹*/</span>
fi #
# Create include file for Make
#
<span style="color:#ff6666;">/*
*创建config.mk文件
*ARCH = arm
*CPU = arm920t
*BOARD= smdk2410
*SOC = s3c24x0
*/</span>
echo "ARCH = $2" > config.mk
echo "CPU = $3" >> config.mk
echo "BOARD = $4" >> config.mk [ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk [ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk #
# Create board specific header file
#
<span style="color:#ff6666;">/*创建config.h文件*/</span>
if [ "$APPEND" = "yes" ] # Append to existing config file
then
echo >> config.h
else
> config.h # Create new config file
fi
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include <configs/$1.h>" >>config.h exit 0
总结配置的作用有以下4点:
1、开发板名称BOARD_NAME等于$1
2、创建到平台/开发板相关的头文件的链接。例如以下所看到的
ln -s asm-$2 asm
ln -s arch-$6 asm-$2/arch
ln -s proc-armv asm-$2/proc
3、创建顶层Makefile包括的文件include/config.mk
4、创建开发板相关的头文件include/config.h
(三)编译、链接
既然在编译之前必须经过上面的配置过程,那么配置过程一定为编译过程提供了某些东西。否则的话,我们直接编译就能够了。那么。上面配置过程生成的文件、改动的地方是怎样在编译过程中体现的呢。
事实上,这在Makefile文件里有所体现。
如:
include $(OBJTREE)/include/config.mk <span style="color:#ff6666;">//包括了配置过程中宏生成的include/config.mk文件</span>
export ARCH CPU BOARD VENDOR SOC
include $(TOPDIR)/config.mk <span style="color:#ff6666;">//包括了配置过程中生成的顶层的config.mk文件</span>
配置完毕后,运行make命令就可以链接。运行make。我们运行的是Makefile里的make all语句,它的命令例如以下:
ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) all: $(ALL) $(obj)u-boot.hex: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ $(obj)u-boot.srec: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ $(obj)u-boot.bin: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ $(obj)u-boot.img: $(obj)u-boot.bin
./tools/mkimage -A $(ARCH) -T firmware -C none \
-a $(TEXT_BASE) -e 0 \
-n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
-d $< $@ $(obj)u-boot.dis: $(obj)u-boot
$(OBJDUMP) -d $< > $@ $(obj)u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
<span style="color:#ff6666;">UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
-Map u-boot.map -o u-boot
从执行结果反看Makefile的执行:
UNDEF_SYM=</span>`arm-linux-objdump -x lib_generic/libgeneric.a board/100ask24x0/lib100ask24x0.a cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a drivers/nand_legacy/libnand_legacy.a drivers/usb/libusb.a drivers/sk98lin/libsk98lin.a common/libcommon.a |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
cd /work/system/u-boot-1.1.6</span> && arm-linux-ld -Bstatic -T /work/system/u-boot-1.1.6/board/100ask24x0/u-boot.lds -Ttext 0x33F80000 $UNDEF_SYM cpu/arm920t/start.o \
<span style="color:#ff6666;">--start-group</span> lib_generic/libgeneric.a board/100ask24x0/lib100ask24x0.a cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a drivers/nand_legacy/libnand_legacy.a drivers/usb/libusb.a drivers/sk98lin/libsk98lin.a common/libcommon.a --end-group -L /work/tools/gcc-3.4.5-glibc-2.3.6/lib/gcc/arm-linux/3.4.5 -lgcc \
<span style="color:#ff6666;">-Map u-boot.map -o u-boot
总结编译流程:
1、编译cpu/$(CPU)/start.S。
2、然后,对于平台/开发板相关的每一个文件夹、每一个通用文件夹都使用它们各自的Makefile生成对应的库。
3、将1、2步骤生成的.o、.a文件依照board/$(BOARDDIR)/config.mk文件里指定的代码段起始地址、board/$(BOARDDIR)/U-Boot.lds链接脚本进行链接。
4、第3步得到的ELF格式的U-Boot,后面Makefile还会将它转换为二进制格式S-Record格式。
(四)逐行分析链接文件
/*
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") <span style="color:#ff6666;">/*定义3种输出文件的格式(大小端)*/</span>
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm) <span style="color:#ff6666;">/*设置输出文件的machine architecture(体系结构)*/</span>
ENTRY(_start) <span style="color:#ff6666;">/*将符号_start的值设置成入口地址*/</span>
SECTIONS
{
. = 0x00000000; . = ALIGN(4);
.text :
{
cpu/arm920t/start.o (.text)
board/100ask24x0/boot_init.o (.text)
*(.text)
} <span style="color:#ff6666;">/*将start.o boot_init.o 以及除此之外的全部(*符号代表随意输入文件)
*输入文件的.text section 以4字节对齐的方式合并成一个.text section,
*该section的地址由定位器符号的值指定,即为0x00000000
*/</span> . = ALIGN(4);
.rodata : { *(.rodata) }
<span style="color:#ff6666;">/*将全部输入文件的仅仅读数据段.rodata section 以4字节对齐的方式
*合并成一个.rodata section,该section的地址为
*0x00000000+.text section的大小
*/</span>
. = ALIGN(4);
.data : { *(.data) }
<span style="color:#ff6666;">/*将全部输入文件的数据段.data section 以4字节对齐的方式
*合并成一个.data section,该section的地址为
*0x00000000+.text section的大小+.rodata section的大小
*/</span>
. = ALIGN(4);
.got : { *(.got) } . = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .; . = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}
參考:韦东山《嵌入式Linux应用开发全然手冊》
版权声明:本文博客原创文章,博客,未经同意,不得转载。
u-boot学习(两):u-boot简要分析的更多相关文章
- Spring Boot学习笔记---Spring Boot 基础及使用idea搭建项目
最近一段时间一直在学习Spring Boot,刚进的一家公司也正好有用到这个技术.虽然一直在学习,但是还没有好好的总结,今天周末先简单总结一下基础知识,等有时间再慢慢学习总结吧. Spring Boo ...
- spring boot 学习(二)spring boot 框架整合 thymeleaf
spring boot 框架整合 thymeleaf spring boot 的官方文档中建议开发者使用模板引擎,避免使用 JSP.因为若一定要使用 JSP 将无法使用. 注意:本文主要参考学习了大神 ...
- spring boot 学习(六)spring boot 各版本中使用 log4j2 记录日志
spring boot 各版本中使用 log4j2 记录日志 前言 Spring Boot中默认日志工具是 logback,只不过我不太喜欢 logback.为了更好支持 spring boot 框架 ...
- Spring Boot学习笔记——Spring Boot与ActiveMQ的集成
Spring Boot对JMS(Java Message Service,Java消息服务)也提供了自动配置的支持,其主要支持的JMS实现有ActiveMQ.Artemis等.这里以ActiveMQ为 ...
- Spring Boot学习笔记——Spring Boot与Redis的集成
一.添加Redis缓存 1.添加Redis起步依赖 在pom.xml中添加Spring Boot支持Redis的依赖配置,具体如下: <dependency> <groupId> ...
- Spring Boot学习笔记——Spring Boot与MyBatis的集成(项目示例)
1.准备数据库环境 # 创建数据库 CREATE DATABASE IF NOT EXISTS zifeiydb DEFAULT CHARSET utf8 COLLATE utf8_general_c ...
- Spring Boot学习 之 Spring Boot Actuator(一)
Spring Boot版本:2.1.4.RELEASE 启用: spring-boot-actuator模块提供了一系列的用于监控的端点.最简单的开启这个功能的方法就是,在pom文件中添加如下的依赖. ...
- spring boot 学习10 定义springboot的两种方法
使用spring boot的两种方法: A:继承spring-boot-starter-parent项目 这种方式很简单,只需要在POM里面添加parent父工程即可. B: 如果你不喜欢继承spri ...
- 转载:spring boot学习
Spring Boot学习 Spring Boot是为了简化Spring应用的创建.运行.调试.部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置. 简单来说,它提 ...
随机推荐
- 给定一个set字符和一个正数k,找出所有该做set它可以由长度构成k该字符串集合 print-all-combinations-of-given-length
// 给定一个set字符和一个正数k,找出所有该做set它可以由长度构成k该字符串集合 /* Input: set[] = {'a', 'b'}, k = 3 Output: aaa aab aba ...
- Linux环境Eclipse + Tomcat + MySQL 构造J2EE方法开发环境
1. 版本号信息 (1)CentOS 6.4释64位置.uname -a 下面的示例演示显著样本: Linux localhost.localdomain 3.11.6 #1 SMP Sat Nov ...
- Android APK反编译详解(非常有用)
如何学习最快呢?无疑是通过研究别人的源代码? 但是,获取别人的源代码,比较困难.本文,仅限于用于学习开发. 这段时间在学Android应用开发,在想既然是用Java开发的应该很好反编译从而得到源代码吧 ...
- PHP 闭包函数 function use 使用方法实例
/** * @param string $hisStart * @param string $hisEnd * @param int $range * @param string $format * ...
- IT薪酬
新加坡IT薪酬 2014-06-12 12:51 by 圣殿骑士, 8856 阅读, 37 评论, 收藏, 编辑 很多朋友发邮件或留言问我关于新加坡IT薪酬的问题,由于前段时间比较忙,所以没有及时一一 ...
- DDD Reference
版权声明:本文博客原创文章.博客,未经同意,不得转载.
- 编写WCF服务时右击配置文件无“Edit WCF Configuration”(编辑 WCF 配置)远程的解决办法
原文:编写WCF服务时右击配置文件无“Edit WCF Configuration”远程的解决办法 今天在看<WCF揭秘>书中看到作者提出可以在一个WCF Host应用程序的App.Con ...
- 如何让格斗游戏的横版过关(2) Cocos2d-x 2.0.4
在第一章<如何使横版格戏>基础上.添加角色运动.碰撞.敌人.AI和音乐音效,原文<How To Make A Side-Scrolling Beat 'Em Up Game Like ...
- UI測试内容
我们在实际工作其中,针对web应用程序,也就是常常所说的B/S系统,能够从例如以下方面来进行用户界面測试: 导航測试 导航描写叙述了用户在一个页面内操作的方式,在不同的用户接口控制之间,比如butto ...
- erlang R17新socket选项{active,N}
erlang R17带来了新的socket选项{active,N} .与{active,once}连同应用层提供的流量控制.为什么会这样选择,{active,once}不能够有效地抑制了很多socke ...