u-boot剖析(一)----Makefile分析
由于u-boot比较庞大,所以我们分开来分析,对于一个大型的项目我们想快速的了解其代码架构和内容,最方便的方法就是分析Makefile,所以我们今天以三星的s3c2440来分析Makefile。我们今天通过对u-boot的分析要得到以下内容:
1. U-boot的入口
2. 链接地址
l U-boot配置过程分析
我们在编译u-boot之前首先要进行u-boot的配置,以三星的s3c2440为例我们的配置命令是make smdk2440_config,所以我们在u-boot顶层的Makefile中搜索smdk2440_config我们可以轻松的找到下面代码:
smdk2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm s3c24xx smdk2440 samsung s3c2440
从上面代码我们可以确定当我们执行make smdk2440_config的时候其执行了@$(MKCONFIG) $(@:_config=) arm s3c24xx smdk2440 samsung s3c2440在Makefile中我们又可以找到MKCONFIG := $(SRCTREE)/mkconfig所以上面的命令就可以替换为mkconfig smdk2440 arm s3c24xx smdk2440 samsung s3c2440 也就是说我们执行make smdk2440_config的时候其就是执行上面的命令。
接下来我们打开mkconfig
1. 分析传入的参数,确定开发板的名称,由于我们没有-- 、-a、-n参数所以下面代码可以忽略。
APPEND=no # Default: Create new config file
BOARD_NAME=""# Name to print in make output
SETMMU="no"# use mmu in nand uboot,but do not use in mmc.bin
while[ $# -gt ] ; do
case"$1" in
--) shift ;break;;
-a) shift ; APPEND=yes ;;
-n) shift ; BOARD_NAME="${1%%_config}"; shift ;;
*)break;;
esac
done
["${BOARD_NAME}"]|| BOARD_NAME="$1"//如果BOARD_NAME已定义后面的代码就不会执行,但是我们这里没有定义,所以执行BOARD_NAME="$1",然而$1 就是smdk2440所以执行完后BOARD_NAME= smdk2440
[ $# -lt ] && exit //参数的个数小于4退出
[ $# -gt ] && exit //参数的个数大于9退出
echo "Configuring for ${BOARD_NAME} board which boot from $7 $8 $9..."
#
# Create link to architecture specific headers
#
if["$SRCTREE"!="$OBJTREE"]; then
mkdir -p ${OBJTREE}/include
mkdir -p ${OBJTREE}/include2
cd ${OBJTREE}/include2
rm -f asm
ln -s ${SRCTREE}/include/asm-$ asm
LNPREFIX="../../include2/asm/"
cd ../include
rm -rf asm-$
rm -f asm
mkdir asm-$
ln -s asm-$ asm
else
cd ./include
rm -f asm
ln -s asm-$ asm
fi
上面的这个if [ "$SRCTREE" != "$OBJTREE" ] 然而我们在顶层的Makefile中可以找到
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))//如果定义BUILD_DIR则OBJTREE就为BUILD_DIR没定义就为$(CURDIR)
SRCTREE := $(CURDIR)
通过上面两行代码显然我们可以知道OBJTREE和SRCTREE是相等的,所以执行else分支
cd ./include
rm -f asm
ln -s asm-$ asm#就是ln –s asm-arm asm
rm -f asm-$/arch //rm –f asm-arm/arch
if[-z "$6"-o "$6"="NULL"]; then//第6个参数为空或者为NULL显然不成立执行else分支
ln -s ${LNPREFIX}arch-$ asm-$/arch
else
ln -s ${LNPREFIX}arch-$ asm-$/arch//因为LNPREFIX未定义所以该命令类似与ln –s arch- s3c2440 asm-arm/arch
fi
这里我们发现其建立的链接竟然不是连到arch- s3c2440的而是连到arch- s3c24xx的难道我们错了?这个问题下面会解释到。
# create link for s3c24xx SoC
if["$3"="s3c24xx"]; then
rm -f regs.h
ln -s $.h regs.h//建立链接文件ln –s s3c2440.h regs.h
rm -f asm-$/arch
ln -s arch-$ asm-$/arch//建立链接文件ln –s arch- s3c24xx asm-arm/arch
fi
上面的最后一个连接文件,也就是我们刚才为什么看到不正确的链接了,因为其在这里更改了指向。
# create link for s3c64xx SoC
if["$3"="s3c64xx"];then//我们的"$3"=”s3c24xx”的所以不执行
rm -f regs.h
ln -s $.h regs.h
rm -f asm-$/arch
ln -s arch-$ asm-$/arch
fi
if["$2"="arm"];then
rm -f asm-$/proc
ln -s ${LNPREFIX}proc-armv asm-$/proc//建立链接文件ln -s proc-armv asm-arm/proc
fi
# create link for s3c64xx-mp SoC
if["$3"="s3c64xx-mp"];then//不相等不执行
rm -f regs.h
ln -s $.h regs.h
rm -f asm-$/arch
ln -s arch-$ asm-$/arch
fi
#
# Create include file for Make
#
echo "ARCH = $2"> config.mk//输出ARCH = arm到config.mk
echo "CPU = $3">> config.mk//追加CPU = s3c24xx到 config.mk
echo "BOARD = $4">> config.mk//追加BOARD = smdk2440 到 config.mk
["$5"]&&["$5"!="NULL"]&& echo "VENDOR = $5">> config.mk//我们第5个参数为samsung追加VENDOR =samsung 到 config.mk
["$6"]&&["$6"!="NULL"]&& echo "SOC = $6">> config.mk//我们第6个参数为s3c2440追加SOC = s3c2440 到 config.mk
#
# Create board specific header file
#
if["$APPEND"="yes"]// Append to existing config file在开始时我们定义APPEND=no所以执行else分支
then
echo >> config.h
else
> config.h // Create new config file创建一个config.h文件
fi
echo "/* Automatically generated - do not edit */">>config.h//追加/*Automatically generated -do not edit */到config.h
case $ in//我们没有第7个参数所以不执行
SD)
echo "#define FORLINX_BOOT_SD">> config.h
SETMMU="no"
;;
NAND)
echo "#define FORLINX_BOOT_NAND">> config.h
SETMMU="yes"
;;
*)
;;
esac
case $ in//我们没有第8个参数所以不执行
ram128)
echo "#define FORLINX_BOOT_RAM128">> config.h
>../board/samsung/smdk6410/config.mk # clear file context
echo "ifndef TEXT_BASE">>../board/samsung/smdk6410/config.mk
if[ ${SETMMU}="yes"]
then
echo "TEXT_BASE = 0xC7E00000">>../board/samsung/smdk6410/config.mk
else
echo "TEXT_BASE = 0x57E00000">>../board/samsung/smdk6410/config.mk
fi
echo "endif">>../board/samsung/smdk6410/config.mk
;;
ram256)
echo "#define FORLINX_BOOT_RAM256">> config.h
>../board/samsung/smdk6410/config.mk # clear file context
echo "ifndef TEXT_BASE">>../board/samsung/smdk6410/config.mk
if[ ${SETMMU}="yes"]
then
echo "TEXT_BASE = 0xCFE00000">>../board/samsung/smdk6410/config.mk
else
echo "TEXT_BASE = 0x5FE00000">>../board/samsung/smdk6410/config.mk
fi
echo "endif">>../board/samsung/smdk6410/config.mk
;;
*)
;;
esac
if["$9"="hdmi"];then//我们没有第9个参数所以不执行
echo "#define FORLINX_LCDOUT_HDMI">> config.h
fi
echo "#include <configs/$1.h>">>config.h//追加#include <configs/ smdk2440.h>到 config.h exit
在我们的配置过程中我们主要有一下工作;
1. 创建于开发板相关的头文件的链接
2. 创建include/config.mk文件
3. 创建include/config.h头文件
l U-boot编译
在我们执行make的时候其将会生成第一个目标也就是all,以all为突破口我们找到all又依赖于$(ALL)而ALL又等于
ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)
而u-boot.srec u-boot.bin又依赖于u-boot
$(obj)u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
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
通过展开编译命令(当然有点麻烦)我们可以直接执行make然后找到和这条命令相似的命令,通过得到的命令我们可以顺利的找到其在编译过程中所用到的链接器脚本
OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm","elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)//入口地址_start
SECTIONS
{
.=0x00000000;
.= ALIGN();
.text ://代码段排布
{
cpu/s3c24xx/start.o (.text)//先是该代码,最先运行
cpu/s3c24xx/s3c2440/cpu_init.o (.text)
*(.text)
}
.= ALIGN();
.rodata :{*(.rodata)}
.= ALIGN();
.data :{*(.data)}
.= ALIGN();
.got :{*(.got)}
.=.;
__u_boot_cmd_start =.;
.u_boot_cmd :{*(.u_boot_cmd)}
__u_boot_cmd_end =.;
.= ALIGN();
.mmudata :{*(.mmudata)}
.= ALIGN();
__bss_start =.;
.bss :{*(.bss)}
_end =.;
}
在cpu/s3c24xx/start.o我们可以轻松找到其所有代码的入口
.globl _start
_start:
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
至此我们找到了正个程序的入口,但是其的链接地址又在什么地方呢?
我们在顶层的config.mk中找到
LDFLAGS +=-Bstatic-T $(LDSCRIPT)-Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)
其实整个程序的链接地址就在TEXT_BASE通过全局搜索我们在\board\samsung\smdk2440\config.mk 中找到TEXT_BASE = 0x30008000至此我们今天的任务完成。
u-boot剖析(一)----Makefile分析的更多相关文章
- makefile 分析 -- 内置变量及自动变量
makefile 分析1 -p 选项,可以打印出make过程中的数据库, 下面研究一下内置的变量和规则. -n 选项, 只运行,不执行, -d 选项,相当于--debug=a, b(basic), ...
- Arachnid包含一个简单的HTML剖析器能够分析包含HTML内容的输入流
Arachnid是一个基于Java的web spider框架.它包含一个简单的HTML剖析器能够分析包含HTML内容的输入流.通过实现Arachnid的子类就能够开发一个简单的Web spiders并 ...
- Android发展的一个重要方面Makefile分析
Android发展的一个重要方面Makefile分析 随着移动互联网的发展,移动开发也越来越吃香了.眼下最火的莫过于android.android是什么就不用说了,android自从开源以来,就受到非 ...
- Spring Boot 实战与原理分析视频课程
Spring Boot 实战与原理分析视频课程 链接:https://pan.baidu.com/share/init?surl=PeykcoeqZtd1d9lN9V_F-A 提取码: 关注公众号[G ...
- uboot主Makefile分析(t配置和编译过程详解)
1.编译uboot前需要三次make make distcleanmake x210_sd_configmake -j4 make distclean为清楚dist文件. make x210_sd_c ...
- uboot主Makefile分析
VERSION = 1 PATCHLEVEL = 3 SUBLEVEL = 4 EXTRAVERSION = U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(S ...
- spring boot启动原理步骤分析
spring boot最重要的三个文件:1.启动类 2.pom.xml 3.application.yml配置文件 一.启动类->main方法 spring boot启动原理步骤分析 1.spr ...
- uboot 主Makefile分析
一. Makefile 配置 1.1. make xxx_config 1.1.1. 笔者实验时是make x210_sd_config a. x210_sd_config是Makefile下的一个目 ...
- LibOpenCM3(二) 项目模板 Makefile分析
目录 LibOpenCM3(一) Linux下命令行开发环境配置 LibOpenCM3(二) 项目模板 Makefile分析 LibOpenCM3 项目模板 项目模板地址: https://githu ...
随机推荐
- AI-Info-Micron-Insight:通往完全自主之路
ylbtech-AI-Info-Micron-Insight:通往完全自主之路 1.返回顶部 1. 通往完全自主之路 自动驾驶汽车正在从未来梦想演变为当代现实,随着技术成熟,个人和公共交通将永远转变. ...
- win7 64位搭建Mantis 缺陷管理系统
什么是Mantis MantisBT is a free popular web-based bugtracking system (feature list). It is written in t ...
- JVM中的Hello World运行机制:
栗子: package zagoo; public class HelloWorld { public static String HELLOWORLD="Hello World" ...
- linux svn 客户端基本使用命令
1.从svn获取项目 svn co URL --username XX --password XX; 2.添加code file svn add codeFile; svn ci -m "c ...
- 反射-Class
package classes; public class ClassDemo1 { public static void main(String[] args){ Foo foo1 = new Fo ...
- 32bit / 64bit co-exist Linux, ld-linux.so, linux-gate.so.1 etc
before this, confirm that you don't have 32bit libs notably 32bit libc, e.g. you have /lib64/ld-linu ...
- 3. 关于sql注入的综合题
关于sql注入的综合题 ----------南京邮电大学ctf : http://cms.nuptzj.cn/ 页面上也给了好多信息: 根据这个sm. ...
- Python开发【第四篇】:运算符
1. 算术运算符 算术运算符包括+.-.*./.%.//.**,即加减乘除,取余,取商(地板除法)以及幂运算. >>> 5 + 2 7 >>> 5 - 2 ...
- 记微软OpenHack机器学习挑战赛
有幸参加了微软OpenHack挑战赛,虽然题目难度不大,但是很有意思,学到了很多东西,还有幸认识了微软梁健老师,谢谢您的帮助!同时还认识同行的很多朋友,非常高兴,把这段难忘的比赛记录一下~~也分享一下 ...
- 洛谷P2950 [USACO09OPEN]牛绣Bovine Embroidery
P2950 [USACO09OPEN]牛绣Bovine Embroidery 题目描述 Bessie has taken up the detailed art of bovine embroider ...