u-boot分析与使用—Makefile结构分析
- 硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3)
- 软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统
- 参考资料:《嵌入式Linux应用开发手册》、《嵌入式Linux应用开发手册第2版》
- 开发环境:Linux 2.6.22.6 内核、arm-linux-gcc-3.4.5-glibc-2.3.6工具链、u-boot-1.1.6
一、前言
在【5.1 u-boot分析与使用—u-boot编译体验】中,分析了u-boot的主要目的是启动内核,至于其如何成功的使用内核,需要分析其的代码,对于代码的分析需要先分析Makefile
来了解整个工程的编译流程。
二、配置与编译过程:make 100ask24x0_config
在配置u-boot时,在/work/system/u-boot-1.1.6
目录下,直接执行make 100ask24x0_config
命令。
1、Makefile
调用mkconfig
通过搜索Makefile
文件中100ask24x0_config
可以找到如下代码:
最终拆开后代码如下:
mkconfig 100ask24x0_config arm arm920t 100ask24x0 NULL s3c24x0
可以看到此时会调用源文件所在目录下的mkconfig
2、分析mkconfig
可以看到在/work/system/u-boot-1.1.6
目录下有一个mkconfig
- 具体执行的源码如下(分析的完全源码在下一项):
# mkconfig 100ask24x0_config arm arm920t 100ask24x0 NULL s3c24x0
# $0 $1 $2 $3 $4 $5 $6
APPEND=no # Default: Create new config file
BOARD_NAME="" # Name to print in make output
# 判断BOARD_NAME是否有定义
# 若定义就执行[ "${BOARD_NAME}" ]
# 未定位就执行BOARD_NAME="$1" $1(命令的第一个参数或第一条命令)--->100ask24x0_config
[ "${BOARD_NAME}" ] || BOARD_NAME="$1"
# BOARD_NAME = 100ask24x0_config
# 打印Configuring for ${BOARD_NAME} board...
echo "Configuring for ${BOARD_NAME} board..."
# Create link to architecture specific headers
# OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
# 如果定义 OBJTREE=$BUILD_DIR 未定义OBJTREE=$CURDIR
# BUILD_DIR := $(O)未定义,
# SRCTREE := $(CURDIR)
# 如果 SRCTREE != OBJTREE 条件成立
cd ./include
rm -f asm
ln -s asm-$2 asm #ln -s asm-arm asm 建立链接文件asm->asm-arm
fi
rm -f asm-$2/arch # rm -f asm-arm/arch
# 如果$6(第六个参数)为空或者为NULL
else
ln -s ${LNPREFIX}arch-$6 asm-$2/arch #ln -s arch-s3c24x0 asm-arm/arch 建立链接文件asm-arm/arch->arch-s3c24x0
fi
# 如果$2(第二个参数) = "arm"
if [ "$2" = "arm" ] ; then
rm -f asm-$2/proc
ln -s ${LNPREFIX}proc-armv asm-$2/proc #ln -s proc-armv asm-arm/proc 建立链接文件asm-arm/proc->proc-armv
fi
# Create include file for Make
# > 表示新建一个文件config.mk,>> 表示追加,在config.mk中追加
echo "ARCH = $2" > config.mk # ARCH = arm
echo "CPU = $3" >> config.mk # CPU = arm920t
echo "BOARD = $4" >> config.mk # BOARD = 100ask24x0
# $6(第六个参数)存在 且 不等于"NULL"
[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk # SOC = s3c24x0
# config.mk内容如下:
# ARCH = arm
# CPU = arm920t
# BOARD = 100ask24x0
# SOC = s3c24x0
# Create board specific header file
# 创建一个单板相关的头文件
# APPEND = “no”
else
> config.h # Create new config file 新建一个config.h文件
fi
# config.h的内容:
# /* Automatically generated - do not edit */
# #include <configs/100ask24x0_config.h> 配置文件
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include <configs/$1.h>" >>config.h
# 退出
exit 0
通过查看 /work/system/u-boot-1.1.6/include
目录下的config.mk
、config.h
文件可以知道其执行的上述代码过程
- 带注释分析源码如下:
#!/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>
#
# mkconfig 100ask24x0_config arm arm920t 100ask24x0 NULL s3c24x0
# $0 $1 $2 $3 $4 $5 $6
APPEND=no # Default: Create new config file
BOARD_NAME="" # Name to print in make output
#分析命令传入的参数有没有--、-a、-n、*这些东西
while [ $# -gt 0 ] ; do
case "$1" in
--) shift ; break ;;
-a) shift ; APPEND=yes ;;
-n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
*) break ;;
esac
done
# 判断BOARD_NAME是否有定义
# 若定义就执行[ "${BOARD_NAME}" ]
# 未定位就执行BOARD_NAME="$1" $1(命令的第一个参数或第一条命令)--->100ask24x0_config
[ "${BOARD_NAME}" ] || BOARD_NAME="$1"
# BOARD_NAME = 100ask24x0_config
[ $# -lt 4 ] && exit 1 # 参数小于4个退出
[ $# -gt 6 ] && exit 1 # 参数大于6个退出
# 打印Configuring for ${BOARD_NAME} board...
echo "Configuring for ${BOARD_NAME} board..."
#
# Create link to architecture specific headers
# OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
# 如果定义 OBJTREE=$BUILD_DIR 未定义OBJTREE=$CURDIR
# BUILD_DIR := $(O)未定义,
# SRCTREE := $(CURDIR)
# 如果 SRCTREE != OBJTREE 条件成立
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 #ln -s asm-arm asm 建立链接文件asm->asm-arm
fi
rm -f asm-$2/arch # rm -f asm-arm/arch
# 如果$6(第六个参数)为空或者为NULL
if [ -z "$6" -o "$6" = "NULL" ] ; then
ln -s ${LNPREFIX}arch-$3 asm-$2/arch
else
ln -s ${LNPREFIX}arch-$6 asm-$2/arch #ln -s arch-s3c24x0 asm-arm/arch 建立链接文件asm-arm/arch->arch-s3c24x0
fi
# 如果$2(第二个参数) = "arm"
if [ "$2" = "arm" ] ; then
rm -f asm-$2/proc
ln -s ${LNPREFIX}proc-armv asm-$2/proc #ln -s proc-armv asm-arm/proc 建立链接文件asm-arm/proc->proc-armv
fi
#
# Create include file for Make
# > 表示新建一个文件config.mk,>> 表示追加,在config.mk中追加
echo "ARCH = $2" > config.mk # ARCH = arm
echo "CPU = $3" >> config.mk # CPU = arm920t
echo "BOARD = $4" >> config.mk # BOARD = 100ask24x0
# $5(第五个参数)存在 且 不等于"NULL"
[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk # VENDOR = NULL
# $6(第五个参数)存在 且 不等于"NULL"
[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk # SOC = s3c24x0
# config.mk内容如下:
# ARCH = arm
# CPU = arm920t
# BOARD = 100ask24x0
# SOC = s3c24x0
# Create board specific header file
# 创建一个单板相关的头文件
# APPEND = “yes”
if [ "$APPEND" = "yes" ] # Append to existing config file
then
echo >> config.h
else
> config.h # Create new config file 新建一个config.h文件
fi
# config.h的内容:
# /* Automatically generated - do not edit */
# #include <configs/100ask24x0_config.h> 配置文件
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include <configs/$1.h>" >>config.h
# 退出
exit 0
3、Makefile
生成u-boot.bin
对于执行make
命令输出的信息如下:可以看到它使用了目录下的u-boot.lds
脚本
4、u-boot.lds
脚本
其源码如下:
/*
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <[email protected]>
*
* 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")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000; //链接地址:0x33f80000 + 0x00000000 = 0x33f80000
. = ALIGN(4);
.text :
{
cpu/arm920t/start.o (.text) //这个文件的代码段 /cpu/arm920t/start.S
board/100ask24x0/boot_init.o (.text) //这个文件的代码段
*(.text) //其他所有文件的代码段
}
. = ALIGN(4);
.rodata : { *(.rodata) } //所有文件的只读数据段
. = ALIGN(4);
.data : { *(.data) } //所有文件的数据段
. = ALIGN(4);
.got : { *(.got) }
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) } //所有文件的u_boot_cmd段
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}
三、推荐
对于这篇文章,只是比较简单的大致流程分析,详细的推荐大家可以看看这篇https://blog.csdn.net/dhauwd/article/details/80149843