由于所找到的资料均是英语的,故此文也直接用英语。
Chapter 2 Uboot make file
2.1How to make uboot for arm architecture
To build uboot for arm architecture in the host machine, we need cross compiler.The default cross compiler in uboot is arm-linux-gcc, and we can use our own cross compiler. There are 2 ways to set our own cross compiler:
a.export CROSS_COMPILE=arm-none-linux-gnueabi-
b.Change the top make file of uboot by adding:
ifeq ($(ARCH),arm)
CROSS_COMPILE=arm-none-linux-gnueabi-
endif
just behind:
ifeq ($(HOSTARCH), $(ARCH))
CROSS_COMPILE?=
endif
To build uboot for arm architecture in the source directory (local build), we type the following command (cross compiler was set properly in the above step):
make distclean
make <board_type>_config
make all
To build uboot out of the source directory, we do:
export BUILD_DIR=~/project/uboot
make distclean
make<board_type>_config
make all
or
make O=~/project/uboot
make distclean
make <board_type>_config
make all
Note: O command line setting overrides BUILD_DIR environment variable.
To make the analysis easier, we build uboot in the source directory in the following sections.
2.2 Uboot make file outline
a.make <board_type>_config
It will pass the Target, Architecture, CPU, Board, [Vendor], [Soc] arguments tothe ./mkconfig (under the same directory of top makefile) script.
The./mkconfig script will create link: ./include/asm to the real arch'sinclude/asm.
It also creates ./include/config.mk and ./include/config.h. ./include/config.mk will be included by top Makefile, and ./include/config.h is the auto-generated header file for given board_type.
b.make all
1.make all will first update the ./include/autoconf.mk and./include/autoconf.mk.dep based on the file ./include/config.h generated by command make <board_type>_config.
./include/autoconf.mk.dep contains a rule, whose target is ./include/autoconf.mk, and prerequisites are all files included by ./include/common.h.
./include/autoconf.mk is the collection of macros startting with “CONFIG_” defined in./include/common.h and files included by ./include/common.h.
2. make all then includes ./include/config.mk and ./config.mk to decide src, objdirectory, and cross compile tools’ flags based on included specific arch, cpu,board, and soc’s config.mk, and pattern rules for various object files.
3.make all finally updates the all prerequisites of the target $(obj)uboot: depend, $(SUBDIR), $(OBJS), $(LIBBOARD), $(LIBS), $(LDSCRIPT),$(ojb)u-boot.lds, $(GEN_UBOOT) to update the global target $(obj)uboot.
2.3make <board_type>_config
2.3.1make <board_type>_config outline
Let's take smdk2410_config as example to analyze the progress of make<board_type>_config.
MKCONFIG := $(SRCTREE)/mkconfig
exportMKCONFIG
smdk2410_config: unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 samsung s3c24x0
unconfig:
@rm -f $(obj)include/config.h \
$(obj)include/config.mk \
$(obj)board/*/config.tmp \
$(obj)board/*/*/config.tmp \
$(obj)include/autoconf.mk \
$(obj)include/autoconf.mk.dep
#Here unconfig doesn't have any prerequisites, and it isn't a real file, so it always will be updated (the target doesn't exist, and thus the recipe is always triggered), when we type makesmdk2410_config. It's better we declare unconfig as a phony target, but the uboot make file doesn't do this. Unconfig removes almost all files generated inthe process of building uboot.
In the recipe to update smdk2410_config target, $(MKCONFIG) will be expanded as the mkconfig under the top make file, which is a bash script file.
$(@:_config=)is equivalent to $(patsubst, %_config, %, $(@)), i.e. $(patsubst, %config, %,$@). It means replacing _config in the rule's target name by empty string, thus$(@:_config=) generates smdk2410.
So the recipe is invoked as following:
./mkconfigsmdk2410 arm arm920t smdk2410 samsung s3c24x0
2.3.2mkconfig script file
Now we analyze the bash script file line by line.
#!/bin/sh -e
# Script tocreate header files and links to configure
# U-Boot for aspecific 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
TARGETS=""
while [ $# -gt0 ] ; do
case "$1" in
--)shift ; break ;;
-a) shift ; APPEND=yes ;;
-n) shift ; BOARD_NAME="${1%%_config}" ;shift ;;
-t) shift ; TARGETS="`echo $1 | sed 's:_::g'` ${TARGETS}" ; shift ;;
*) break ;;
esac
done
#This checks the argument options passed into the script. However, when we invoke mkconfig by make <board_type>_config, we don't pass any argumentoption. So, this part is not executed.
["${BOARD_NAME}" ] || BOARD_NAME="$1"
#This set BOARD_NAME to the board name argument.
[ $# -lt 4 ]&& exit 1
[ $# -gt 6 ]&& exit 1
#It checks the argument count, if it's < 4 or > 6, then exit.
if ["${ARCH}" -a "${ARCH}" != "$2" ]; then
echo "Failed: \$ARCH=${ARCH}, should be '$2'for ${BOARD_NAME}" 1>&2
exit 1
fi
#It checks whether the arch environment variable ARCH is equal to arch argumentor not. If not, exit.
echo"Configuring for ${BOARD_NAME} board..."
#
# Create linkto architecture specific headers
#
if ["$SRCTREE" != "$OBJTREE" ] ; then
mkdir -p ${OBJTREE}/include
mkdir -p ${OBJTREE}/include2
cd ${OBJTREE}/include2
rm -f asm
ln -s ${SRCTREE}/arch/$2/include/asm asm
LNPREFIX=${SRCTREE}/arch/$2/include/asm/
cd ../include
rm -f asm
ln -s ${SRCTREE}/arch/$2/include/asm asm
else
cd ./include
rm -f asm
ln -s ../arch/$2/include/asm asm
fi
rm -f asm/arch
#For local build, it creates a link ./include/asm to ./arch/arm/include/asm. And remove the arch directory under ./include/asm. In fact, there is no arch under./arch/arm/include/asm.
if [ -z"$6" -o "$6" = "NULL" ] ; then
ln -s ${LNPREFIX}arch-$3 asm/arch
else
ln -s ${LNPREFIX}arch-$6 asm/arch
fi
#Here $6 is s3c24x0, so the else clause is executed. For local build, ${LNPREFIX} is empty, thus it creates a link ./include/asm/arch to ./include/asm/arch-s3c24x0.
if ["$2" = "arm" ] ; then
rm -f asm/proc
ln -s ${LNPREFIX}proc-armv asm/proc
fi
#If the architecture is arm, it creates a link ./include/asm/proc to ./include/asm/proc-armv.
#
# Createinclude file for Make
#
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
#Write the ARCH CPU BOARD VENDOR SOC variables into ./include/config.mk.
# Assign boarddirectory to BOARDIR variable
if [ -z"$5" -o "$5" = "NULL" ] ; then
BOARDDIR=$4
else
BOARDDIR=$5/$4
fi
#Set BOARDDIR to samsung/smdk2410.
#
# Create boardspecific header file
#
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
for i in${TARGETS} ; do
echo "#define CONFIG_MK_${i} 1">>config.h ;
done
#TARGETS is empty, thus nothing was written into config.h.
cat <<EOF >> config.h
#defineCONFIG_BOARDDIR board/$BOARDDIR
#include<config_defaults.h>
#include<configs/$1.h>
#include<asm/config.h>
EOF
#cat will write anything to config.h until EOF appeared.
exit 0
Inconclusion:
1.mkconfig creates 3 links based on the arch argument:
./include/asm--> ./arch/arm/include/asm
./include/asm/arch--> ./include/asm/arch-s3c24x0
./include/asm/proc--> ./include/asm/proc-armv.
2.Creates the include file: config.mk, which will be used by Make. Config.mk contains all the arguments passed to the mkconfig script.
3.Auto generates the config.h file for the specific board type.
2.4.make all
2.4.1How make all knows System was not configued
make<board_type>_config should be executed before make all. How Makefileknows about this?
Line 144: ifeq($(obj)include/config.mk,$(wildcard $(obj)include/config.mk))
# Includeautoconf.mk before config.mk so that the config options are available
# to all toplevel build files. We need the dummyall: target to prevent the
# dependencytarget in autoconf.mk.dep from being the default.
all:
......
Line 454: else # !config.mk
all $(obj)u-boot.hex $(obj)u-boot.srec$(obj)u-boot.bin \
$(obj)u-boot.img $(obj)u-boot.dis $(obj)u-boot \
$(filter-outtools,$(SUBDIRS)) $(TIMESTAMP_FILE) $(VERSION_FILE) gdbtools \
updater envdepend dep tags ctags etags cscope $(obj)System.map:
@echo "System not configured - seeREADME" >&2
@ exit 1
Aswe know, $(obj)include/config.mk was generated in the process of make<board_type>_config. $(wildcard $(obj)/include/config.mk) will return null if $(obj)include/config.mk doesn't exist. So, by checking$(obj)include/config.mk, Makefile knows whether system was configured or not.
2.4.2 How to automaticallygenerate makefile:
./include/autoconf.mk.dep./include/autoconf.mk
In GNU Make manual: How Makefiles are remade, it says after reading in all makefiles, make will consider each as a goal target and attempt to update it.If a makefile has a rule which says how to update it, or if an implicit rule applies to it, it will be updated if necessary. After all makefiles have been checked, if any have been actually been changed, make starts with a clean stateand reads all the makefiles over again. (It will also attempt to update each ofthem over again, but normally this will not change them again, since they arealready up to date.)
In uboot Makefile, there are 2 phases of remaking Makefile.
Phase1: After reading in all makefiles, make will try to create autoconf.mk.dep andautoconf.mk according to the below rules.
Phase2: make reads in all makefiles again,and find there are rules for autoconf.mk.dep and autoconf.mk, make will try toupdate them again. Note in this phase,the rule for updating autoconf.mk is different from that of phase 1, becausethe included autoconf.mk.dep also has a rule to update autoconf.mk. In thisphase, make will find nothing needs to be updated. Then make continues toupdate the goal.
The above process will be illuminated by –d option of make. i.e. make –d all.
In the top makefile, there are rules to update
./include/autoconf.mk.depand ./include/autoconf.mk:
#
# Auto-generatethe autoconf.mk file (which is included by all makefiles)
#
# This targetactually generates 2 files; autoconf.mk and autoconf.mk.dep.
# the dep fileis only include in this top level makefile to determine when
# toregenerate the autoconf.mk file.
$(obj)include/autoconf.mk.dep:$(obj)include/config.h include/common.h
@$(XECHO) Generating $@ ; \
set -e ; \
: Generate the dependancies ; \
$(CC) -x c -DDO_DEPS_ONLY -M $(HOSTCFLAGS)$(CPPFLAGS) \
-MQ $(obj)include/autoconf.mkinclude/common.h > $@
#$@: automatic variable, it is the target of the rule.
:bash builtin: it will ignore the followed arguments. It’s some kind of bash comment.
Set–e builtin: set shell to exit immediately if a pipeline returns a non-zerostatus.
-xc: GCC option, it specifies explicitly the c language for the following inputfiles.
-DDO_DEPS_ONLY:define DO_DEPS_ONLY as a macro with definition 1.
-M:It outputs a rule suitable for make describing the dependency of the main source file. Here, the preprocessor will output a rule containing the object file (include/common.o) for the source file (include/common.h) as target, andthe names of all included files (even files included by the included files),including those coming from –include or –imacro command line options, as theprerequisites.
-MQ target: Change the target of rule generated by –M. Here the original target:include/common.o will be replaced by $(obj)include/autoconf.mk.
Thus,the file $(obj)include/autoconf.mk.dep contains a rule, whose target is$(obj)include/autoconf.mk, and prerequisites are include/common.h and all filesincluded by include/common.h.
$(obj)include/autoconf.mk:$(obj)include/config.h
@$(XECHO) Generating $@ ; \
set -e ; \
: Extract the config macros ; \
$(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dMinclude/common.h | \
sed -n -f tools/scripts/define2mk.sed> $@.tmp && \
mv $@.tmp $@
#-dM: It generates a list of ‘#define’ directives for all the macros definedduring the execution of the preprocessor, including predefined macros (such asDO_DEPS_ONLY).
sed–n: When –n is used, the ‘p’ flag will cause the modified line to be printed.
-f:Read editing command from script file: tools/scripts/define2mk.sed. The commentin the script file is very clear. It processes any line beginning with #defineCONFIG_* by changing them to CONFIG_*=VALUE. The processed line then will beoutput to autoconf.mk.
>$@.tmp: redirect the output to $@.tmp, i.e.$(obj)include/autoconf.mk.tmp
&&mv $@.tmp $@: and move $@.tmp to$@(i.e $(obj)include/autoconf.mk).
Thus,autoconf.mk is a collection of all macros beginning with CONFIG_ defined in allprerequisites of the rule in autoconf.mk.dep (i.e. common.h and all filesincluded by common.h). In fact, only the following files contains macro beginswith CONFIG_:
include/common.h,
include/config.h,
include/config_defaults.h,
include/configs/smdk2410.h,
include/config_cmd_default.h,
arch/arm/include/asm/config.h
include/command.h
Note:CONFIG_ARM is a predefined macro, which is defined in arch/arm/config.mk.
2.4.3./config.mk analysis
./config.mkwill be included by the top make file. Let's take a look at it.
1.Setup src and obj directory
Line 26 ifneq($(OBJTREE),$(SRCTREE))
ifeq($(CURDIR),$(SRCTREE))
dir :=
else
dir := $(subst$(SRCTREE)/,,$(CURDIR))
endif
obj := $(if$(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/)
src := $(if$(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/)
$(shell mkdir-p $(obj))
else
obj :=
src :=
endif
#Since we only consider local build, so both obj and src are empty.
2.Set compiler tools’ flags
Line 42 #clean the slate ...
PLATFORM_RELFLAGS=
PLATFORM_CPPFLAGS=
PLATFORM_LDFLAGS=
#Reset flags. These flags will be updated in the arch, cpu, Soc and boardspecific makefiles.
HOSTCFLAGS = -Wall -Wstrict-prototypes -O2-fomit-frame-pointer \
$(HOSTCPPFLAGS)
HOSTSTRIP = strip
#gcc option: -Wall is a short for “warn all”, it enables almost all warning message.
–Wstrict-prototypes: warn if a function is declaredor defined without specifying argument types.
–O2: optimization level. In this level, GCC performsnearly all supported optimization that do not involve a space-speed tradeoff.
-fomit-frame-pointer:it’s also an optimization option. Don’t keep the frame pointer in a registerfor functions that don’t need one.
strip:Remove debug info from binary.
#
# Mac OS X /Darwin's C preprocessor is Apple specific. It
# generatesnumerous errors and warnings. We want tobypass it
# and use GNUC's cpp. To do this we pass the-traditional-cpp
# option tothe compiler. Note that the-traditional-cpp flag
# DOES NOThave the same semantics as GNU C's flag, all it does
# is invokethe GNU preprocessor in stock ANSI/ISO C fashion.
#
# Apple'slinker is similar, thanks to the new 2 stage linking
# multiplesymbol definitions are treated as errors, hence the
#-multiply_defined suppress option to turn off this error.
#
ifeq($(HOSTOS),darwin)
# get majorand minor product version (e.g. '10' and '6' for Snow Leopard)
DARWIN_MAJOR_VERSION = $(shell sw_vers -productVersion | cut -f 1-d '.')
DARWIN_MINOR_VERSION = $(shell sw_vers -productVersion | cut -f 2-d '.')
before-snow-leopard = $(shell if [ $(DARWIN_MAJOR_VERSION) -le 10-a \
$(DARWIN_MINOR_VERSION) -le 5 ] ; then echo"$(1)"; else echo "$(2)"; fi ;)
# SnowLeopards build environment has no longer restrictions as described above
HOSTCC = $(call before-snow-leopard,"cc", "gcc")
HOSTCFLAGS += $(call before-snow-leopard,"-traditional-cpp")
HOSTLDFLAGS += $(call before-snow-leopard,"-multiply_defined suppress")
else
HOSTCC = gcc
endif
ifeq($(HOSTOS),cygwin)
HOSTCFLAGS += -ansi
endif
#We are in linux. Thus the above make file is not executed.
# We buildsome files with extra pedantic flags to try to minimize things
# that won'tbuild on some weird host compiler -- though there are lots of
# exceptionsfor files that aren't complaint.
HOSTCFLAGS_NOPED= $(filter-out -pedantic,$(HOSTCFLAGS))
HOSTCFLAGS += -pedantic
#filter-out returns all options in HOSTCFLAGS_NOPED expect –pedantic. Thus,HOSTCFLAGS_NOPED is all options in HOSTCFLAGS expect –pedantic.
-pedantic:It will issue all the warnings demanded by strict ISO C and ISO C++, reject allprograms that use forbidden extensions, and some other programs that do notfollow ISO C and ISO C++.
cc-option =$(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
> /dev/null 2>&1; then echo"$(1)"; else echo "$(2)"; fi ;)
#cc-option is recursively expanded variables. So, the command for shell functionis not executed at this point.
–S: The outputis in the form of an assembler code file for each non-assembler input filespecified.
-o:specified the output file is /dev/null.
-xc:Specify explicitly the c language for the following input file.
>/dev/null: Redirect standard output to null device.
2>&1:Redirect standard err to standard output.
Thusit will discard any output and error.
Itwill be used to test whether the cross compiler supports specified flags ornot. It $(1) is not supported, then it returns $(2), otherwise, it returns$(2).
#
# Include themake variables (CC, etc...)
#
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
LDR = $(CROSS_COMPILE)ldr
STRIP = $(CROSS_COMPILE)strip
OBJCOPY =$(CROSS_COMPILE)objcopy
OBJDUMP =$(CROSS_COMPILE)objdump
RANLIB = $(CROSS_COMPILE)RANLIB
#Set cross compile tools.
# Loadgenerated board configuration
sinclude $(OBJTREE)/include/autoconf.mk
#Try to load ./include/autoconf.mk. I think there is a bug. It should besinclude $(obj)include/autoconf.mk. The reason is that we have a rule to update$(obj)include/autoconf.mk in the top make file, however we don’t have a rule toupdate $(OBJTREE)/include/autoconf.mk, because $(obj) is empty, while$(OBJTREE) = ~/Src/u-boot-2010.06 in my example.
Ifwe change sinclude to include, an error will occur to stop the make if wecommand make all.
# Somearchitecture config.mk files need to know what CPUDIR is set to,
# so calculateCPUDIR before including ARCH/SOC/CPU config.mk files.
# Check ifarch/$ARCH/cpu/$CPU exists, otherwise assume arch/$ARCH/cpu contains
# CPU-specificcode.
CPUDIR=arch/$(ARCH)/cpu/$(CPU)
ifneq($(SRCTREE)/$(CPUDIR),$(wildcard $(SRCTREE)/$(CPUDIR)))
CPUDIR=arch/$(ARCH)/cpu
endif
#Here CPUDIR is ./arch/arm/cpu/arm920t.
sinclude$(TOPDIR)/arch/$(ARCH)/config.mk #include architecture dependend rules
./arch/arm/config.mk:
CROSS_COMPILE?= arm-linux-
#Set cross compiler.
ifeq($(BOARD),omap2420h4)
STANDALONE_LOAD_ADDR= 0x80300000
else
ifeq($(SOC),omap3)
STANDALONE_LOAD_ADDR= 0x80300000
else
STANDALONE_LOAD_ADDR= 0xc100000
endif
endif
#Set STANDLONE_LOAD_ADDR to 0x100000.
PLATFORM_CPPFLAGS+= -DCONFIG_ARM -D__ARM__
#Add predefined macro CONFIG_ARM and __ARM__ to CPPFLAGS.
# Explicitlyspecifiy 32-bit ARM ISA since toolchain default can be -mthumb:
PLATFORM_CPPFLAGS+= $(call cc-option,-marm,)
#-marm–thumb: Select between generating code that executes in ARM and Thumb states.
# Try if EABIis supported, else fall back to old API,
# i. e. forexample:
# - with ELDK4.2 (EABI supported), use:
# -mabi=aapcs-linux -mno-thumb-interwork
# - with ELDK4.1 (gcc 4.x, no EABI), use:
# -mabi=apcs-gnu -mno-thumb-interwork
# - with ELDK3.1 (gcc 3.x), use:
# -mapcs-32 -mno-thumb-interwork
PLATFORM_CPPFLAGS+= $(call cc-option,\
-mabi=aapcs-linux-mno-thumb-interwork,\
$(call cc-option,\
-mapcs-32,\
$(call cc-option,\
-mabi=apcs-gnu,\
)\
) $(callcc-option,-mno-thumb-interwork,)\
)
#-mabi=name: Generate code for the specified ABI.
-mno-thumb-interwork:Do not generate code that supports calling between the ARM and Thumbinstruction sets.
-mapcs-frame:Generating a stack frame that is compliant with the ARM Procedure Call Standardfor all functions. Without this option, on pre-v5 architectures the twoinstruction sets cannot be reliably used inside one program.
-mapcs-32:Generate code for a processor running with a 32-bit program counter, andconforming to the function calling standards for the APCS 32-bit option.
# For EABI,make sure to provide raise()
ifneq(,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS)))
# This file isparsed several times; make sure to add only once.
ifeq(,$(findstring arch/arm/lib/eabi_compat.o,$(PLATFORM_LIBS)))
PLATFORM_LIBS+= $(OBJTREE)/arch/arm/lib/eabi_compat.o
endif
endif
LDSCRIPT :=$(SRCTREE)/$(CPUDIR)/u-boot.lds
#Set LDSRIPT to ./arch/arm/cpu/arm920t/u-boot.lds
sinclude$(TOPDIR)/$(CPUDIR)/config.mk #include CPU specific rules
./arch/arm/cpu/arm920t/config.mk:
PLATFORM_RELFLAGS+= -fno-common -ffixed-r8 -msoft-float
PLATFORM_CPPFLAGS+= -march=armv4
#=========================================================================
#
# Supply optionsaccording to compiler version
#
#=========================================================================
PLATFORM_RELFLAGS+=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,))
#-fno-common:In C code, controls the placement of uninitialized global variables.
-ffixed-r8-msoft-float:Not found in GCC option.
-march=armv4:This specifies the name for the target ARM architecture.
-mshort-load-btypes:Not found in gcc options.
-malignment-traps:Not found in gcc options.
ifdef SOC
sinclude$(TOPDIR)/$(CPUDIR)/$(SOC)/config.mk #include SoC specific rules
endif
#There is no ./arch/arm/cpu/arm920t/s3c24x0/config.mk.
ifdef VENDOR
BOARDDIR =$(VENDOR)/$(BOARD)
else
BOARDDIR =$(BOARD)
endif
ifdef BOARD
sinclude$(TOPDIR)/board/$(BOARDDIR)/config.mk #include board specific rules
endif
./board/Samsung/smdk2410/config.mk:
TEXT_BASE =0x33F80000
ifneq(,$(findstring s,$(MAKEFLAGS)))
ARFLAGS = cr
else
ARFLAGS = crv
endif
RELFLAGS=$(PLATFORM_RELFLAGS)
DBGFLAGS= -g #-DDEBUG
OPTFLAGS= -Os#-fomit-frame-pointer
ifndefLDSCRIPT
#LDSCRIPT :=$(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug
ifeq($(CONFIG_NAND_U_BOOT),y)
LDSCRIPT :=$(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds
else
LDSCRIPT :=$(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
endif
endif
#LDSCRIPTwas defined in ./arch/arm/config.mk.
OBJCFLAGS +=--gap-fill=0xff
gccincdir :=$(shell $(CC) -print-file-name=include)
#-print-file-name=include: Print the full absolute name of the library fileinclude that would be used when linking.
Gccincdiris all files in the library: include.
CPPFLAGS :=$(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) \
-D__KERNEL__
ifneq($(TEXT_BASE),)
CPPFLAGS +=-DTEXT_BASE=$(TEXT_BASE)
endif
#TEXT_BASE was defined in ./board/Samsung/smdk2410/config.mk.
ifneq($(RESET_VECTOR_ADDRESS),)
CPPFLAGS +=-DRESET_VECTOR_ADDRESS=$(RESET_VECTOR_ADDRESS)
endif
ifneq($(OBJTREE),$(SRCTREE))
CPPFLAGS +=-I$(OBJTREE)/include2 -I$(OBJTREE)/include
endif
CPPFLAGS +=-I$(TOPDIR)/include
CPPFLAGS +=-fno-builtin -ffreestanding -nostdinc \
-isystem $(gccincdir) -pipe$(PLATFORM_CPPFLAGS)
ifdefBUILD_TAG
CFLAGS :=$(CPPFLAGS) -Wall -Wstrict-prototypes \
-DBUILD_TAG='"$(BUILD_TAG)"'
else
CFLAGS :=$(CPPFLAGS) -Wall -Wstrict-prototypes
endif
CFLAGS +=$(call cc-option,-fno-stack-protector)
# $(CPPFLAGS)sets -g, which causes gcc to pass a suitable -g<format>
# option tothe assembler.
AFLAGS_DEBUG:=
# turn jbsrinto jsr for m68k
ifeq($(ARCH),m68k)
ifeq($(findstring 3.4,$(shell $(CC) --version)),3.4)
AFLAGS_DEBUG:= -Wa,-gstabs,-S
endif
endif
AFLAGS :=$(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS)
LDFLAGS +=-Bstatic -T $(obj)u-boot.lds $(PLATFORM_LDFLAGS)
ifneq($(TEXT_BASE),)
LDFLAGS +=-Ttext $(TEXT_BASE)
endif
# Location ofa usable BFD library, where we define "usable" as
# "builtfor ${HOST}, supports ${TARGET}". Sensible values are
# - Whencross-compiling: the root of the cross-environment
# - Linux/ppc(native): /usr
# - NetBSD/ppc(native): you lose ... (must extract these from the
# binutils build directory, plus the nativeand U-Boot include
# files don't like each other)
#
# So far, thisis used only by tools/gdb/Makefile.
ifeq($(HOSTOS),darwin)
BFD_ROOT_DIR = /usr/local/tools
else
ifeq($(HOSTARCH),$(ARCH))
# native
BFD_ROOT_DIR = /usr
else
#BFD_ROOT_DIR= /LinuxPPC/CDK #Linux/i386
#BFD_ROOT_DIR= /usr/pkg/cross # NetBSD/i386
BFD_ROOT_DIR = /opt/powerpc
endif
endif
#########################################################################
export HOSTCC HOSTCFLAGS HOSTLDFLAGS PEDCFLAGSHOSTSTRIP CROSS_COMPILE \
AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMPMAKE
export TEXT_BASE PLATFORM_CPPFLAGSPLATFORM_RELFLAGS CPPFLAGS CFLAGS AFLAGS
#Define and export various flags.
3.Define patterns rules.
# Allow boardsto use custom optimize flags on a per dir/file basis
BCURDIR =$(subst $(SRCTREE)/,,$(CURDIR:$(obj)%=%))
$(obj)%.s: %.S
$(CPP) $(AFLAGS) $(AFLAGS_$(BCURDIR)/$(@F))$(AFLAGS_$(BCURDIR)) \
-o $@ $<
$(obj)%.o: %.S
$(CC) $(AFLAGS) $(AFLAGS_$(BCURDIR)/$(@F)) $(AFLAGS_$(BCURDIR)) \
-o $@ $< -c
$(obj)%.o: %.c
$(CC) $(CFLAGS) $(CFLAGS_$(BCURDIR)/$(@F)) $(CFLAGS_$(BCURDIR)) \
-o $@ $< -c
$(obj)%.i: %.c
$(CPP) $(CFLAGS) $(CFLAGS_$(BCURDIR)/$(@F))$(CFLAGS_$(BCURDIR)) \
-o $@ $< -c
$(obj)%.s: %.c
$(CC) $(CFLAGS) $(CFLAGS_$(BCURDIR)/$(@F)) $(CFLAGS_$(BCURDIR)) \
-o $@ $< -c -S
#Define pattern rules. If more than one pattern has the shortest stem, make willchoose the first one found in the make file. While, if the prerequisites of thefirst rule don’t exist, then the second rule is used. Thus, if %.S doesn’t exist,then %.c is used to update %.s.
Inconclusion:
1../config.mkdetermines compile tool’s flags by including specific arch, cpu, and board’sconfig.mk.
2.It also defines pattern rules for various object files.
2.4.4make all analysis
Inthe following we analyze the make file needed by make all line by line.
Line 146: #Include autoconf.mk before config.mk so that the config options are available
# to all toplevel build files. We need the dummyall: target to prevent the
# dependencytarget in autoconf.mk.dep from being the default.
all:
#Default goal is the first target (not starting with a period) in the make file.This line let “all” be the default goal. In line 298, all: $(ALL), this saysthere are multiple rules for one target (all). All prerequisites in these 2rules are merged into one list of prerequisites for the target all. Refer toGnu make manual: Multiple rules for one target for more details.
sinclude$(obj)include/autoconf.mk.dep
sinclude$(obj)include/autoconf.mk
#Try to include these 2 make files. sinclude means just ignore and doesn't giveerror message, if to be included make file doesn't exist or can't be remade.
# load ARCH,BOARD, and CPU configuration
include$(obj)include/config.mk
export ARCH CPU BOARD VENDOR SOC
# include./include/config.mk generated by make <board_type>_config../include/config.mk only defines variables: ARCH CPU BOARD VERDOR SOC. Thesevariables are exported to make them known by sub-make, refer to GNU makemanual: Recursive Use of make for more details.
# set defaultto nothing for native builds
ifeq($(HOSTARCH),$(ARCH))
CROSS_COMPILE?=
endif
ifeq($(ARCH),arm)
CROSS_COMPILE= arm-none-linux-gnueabi-
endif
#If the CROSS_COMPILE isn't defined, we don't set cross compiler for nativebuilds. If the arch is arm, I explictly set the cross compiler to bearm-none-linux-gnueabi- to avoid setting CROSS_COMPILE repeatedly beforecompiling uboot.
# load otherconfiguration
include$(TOPDIR)/config.mk
#It was analyzed in the previous section.
Line 257: #Add GCC lib
ifdefUSE_PRIVATE_LIBGCC
ifeq("$(USE_PRIVATE_LIBGCC)", "yes")
PLATFORM_LIBGCC= -L $(OBJTREE)/arch/$(ARCH)/lib -lgcc
else
PLATFORM_LIBGCC= -L $(USE_PRIVATE_LIBGCC) -lgcc
endif
else
PLATFORM_LIBGCC= -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
endif
PLATFORM_LIBS+= $(PLATFORM_LIBGCC)
exportPLATFORM_LIBS
#dirnameis a standard Unix program. When it’s given a pathname, it will delete anysuffix beginning with the last slash ‘/’ and return result.
Detailscan be found at:
http://en.wikipedia.org/wiki/Dirname
-print-libgcc-file-name:Same as –print-file-name=libgcc.a
ADDlibgcc to PLATFORM_LIBS.
ifeq($(CONFIG_NAND_U_BOOT),y)
NAND_SPL =nand_spl
U_BOOT_NAND =$(obj)u-boot-nand.bin
endif
ifeq($(CONFIG_ONENAND_U_BOOT),y)
ONENAND_IPL =onenand_ipl
U_BOOT_ONENAND= $(obj)u-boot-onenand.bin
ONENAND_BIN ?=$(obj)onenand_ipl/onenand-ipl-2k.bin
endif
#For smdk2410, these 2 macros are undefined.
Line 295: #Always append ALL so that arch config.mk's can add custom ones
ALL +=$(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)$(U_BOOT_ONENAND)
all: $(ALL)
#These targets will be updated, when make all.
Line 340:GEN_UBOOT = \
UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD)$(LIBS) | \
sed -n -e 's/.*\($(SYM_PREFIX)__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
$(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS)$(LDSCRIPT) $(obj)u-boot.lds
$(GEN_UBOOT)
ifeq($(CONFIG_KALLSYMS),y)
smap=`$(call SYSTEM_MAP,u-boot) | \
awk '$$2 ~ /[tTwW]/ {printf $$1$$3 "\\\\000"}'` ; \
$(CC) $(CFLAGS)-DSYSTEM_MAP="\"$${smap}\"" \
-c common/system_map.c -o$(obj)common/system_map.o
$(GEN_UBOOT) $(obj)common/system_map.o
endif
#$(OBJDUMP) = arm-none-linux-gnueabi-objdump.
-xfor objdump: Display all available header information, including the systemtable and relocation entries.
sed–n: sed only produces output when explicitly told to via the p command.
-e script: Add the commands in script to the set of commands to be runwhile processing the input.
$(SYM_PREFIX):is empty.
s/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p:
.*matches very string (including empty string).
-u\1:add –u before the first match of the regexp (__u_boot_cmd.*).
sort|unique: is the same as sort –u.
$(LD):arm-none-linux-gnueabi-ld.
-T$(obj)u-boot.lds: Use script file as the linker script.
Thedetails can be found at GNU Linker docs.
# Explicitlymake _depend in subdirs containing multiple targets to prevent
# parallelsub-makes creating .depend files simultaneously.
depend dep: $(TIMESTAMP_FILE) $(VERSION_FILE)$(obj)include/autoconf.mk
for dir in $(SUBDIRS) $(CPUDIR) $(dir$(LDSCRIPT)) ; do \
$(MAKE) -C $$dir _depend ; done
#SUBDIRS:tools, examples\standalone, example\api
CPUDIR:./arch/arm/cpu/arm920t
$(dir,$(LDSCRIPT)):
$(LDSCRIPT)is $(CPUDIR)/u-boot.lds, which is set in ./arch/arm/config.mk.
Thusit is the same as $(CPUDIR): ./arch/arm/cpu/arm920t.
Itenters the following directory and make _depend:
tools/
examples/standalone
examples/api
arch/arm/cpu/arm920t
Note:_depend target is defined in ./rules.mk, which is eventually included by Makefileunder above directories.
_depend: $(obj).depend
$(obj).depend: $(src)Makefile $(TOPDIR)/config.mk $(SRCS)$(HOSTSRCS)
@rm -f $@
@for f in $(SRCS); do \
g=`basename $$f | sed -e's/\(.*\)\.\w/\1.o/'`; \
$(CC) -M $(CPPFLAGS) -MQ $(obj)$$g$$f >> $@ ; \
done
@for f in $(HOSTSRCS); do \
g=`basename $$f | sed -e's/\(.*\)\.\w/\1.o/'`; \
$(HOSTCC) -M $(HOSTCPPFLAGS) -MQ$(obj)$$g $$f >> $@ ; \
done
#basename:it delete any prefix up to the last slash character of a given a pathname, andreturn the result.
-M,-MQ: It outputs a rule suitable for make describing the dependency of each filein $(SRCS), with the target specified by –MQ option.
Thegenerated makefile $(obj).depend is finally included by Makefile in abovedirectories.
$(OBJS): depend
$(MAKE) -C $(CPUDIR) $(if$(REMOTE_BUILD),$@,$(notdir $@))
#Enter CPUDIR: ./arch/arm/cpu/arm920t, and make start.o.
$(LIBS): depend $(SUBDIRS)
$(MAKE) -C $(dir $(subst $(obj),,$@))
#Enter all lib dirs, and make.
$(LIBBOARD): depend $(LIBS)
$(MAKE) -C $(dir $(subst $(obj),,$@))
#Enter board/<board_type>, and make.
$(SUBDIRS): depend
$(MAKE) -C $@ all
#$(SUBDIRS): tools examples/standalone examples/api.
$@:is the target file of the rule.
So,this is a rule with multiple targets.
Entereach sub directory and make all.
$(LDSCRIPT): depend
$(MAKE) -C $(dir $@) $(notdir $@)
#Enter CPUDIR and make u-boot.lds.
$(obj)u-boot.lds:$(LDSCRIPT)
$(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi-D__ASSEMBLY__ -P - <$^ >$@
#-ansi:It turns of certain features of GCC that are incompatible with ISO C90.
-P:Inhibit generation of linemarkers in the output from the preprocessor.
-: input is from standard input.
Itpreprocesses $(CPUDIR)/u-boot.lds and output it to ./u-boot.lds.
2.4.5Rearranged and added source code by make
Inabove sections, we know that some source code are added, and some directoriesin source directory are linked. In order to study the uboot code completely, weneed to know these changes. Thus, we take smdk2410 as an example, and list allchange here.
Coderearranged:
./include/asm--> ./arch/arm/include/asm
./include/asm/arch--> ./include/asm/arch-s3c24x0
./include/asm/proc--> ./include/asm/proc-armv
CodeAdded:
./include/config.h:
/*Automatically generated - do not edit */
#defineCONFIG_BOARDDIR board/samsung/smdk2410
#include<config_defaults.h>
#include<configs/smdk2410.h>
#include<asm/config.h>
./include/autoconf.mk(This file is used by Makefile)
CONFIG_BOOTM_NETBSD=y
CONFIG_SYS_CLK_FREQ=12000000
CONFIG_CMD_ITEST=y
CONFIG_RTC_S3C24X0=y
CONFIG_CMD_EDITENV=y
CONFIG_SYS_GBL_DATA_SIZE=128
CONFIG_SYS_LONGHELP=y
CONFIG_SYS_LOAD_ADDR="0x33000000"
CONFIG_CMD_XIMG=y
CONFIG_CMD_CACHE=y
CONFIG_STACKSIZE="(128*1024)"
CONFIG_BOOTDELAY=3
CONFIG_SYS_HELP_CMD_WIDTH=8
CONFIG_NR_DRAM_BANKS=y
CONFIG_BOOTM_RTEMS=y
CONFIG_SYS_CBSIZE=256
CONFIG_BOOTM_LINUX=y
CONFIG_CMD_CONSOLE=y
CONFIG_CMD_MISC=y
CONFIG_SMDK2410=y
CONFIG_RELOC_FIXUP_WORKS=y
CONFIG_ENV_OVERWRITE=y
CONFIG_CMD_NET=y
CONFIG_CMD_NFS=y
CONFIG_ENV_SIZE="0x10000"
CONFIG_AMD_LV400=y
CONFIG_SYS_MALLOC_LEN="(CONFIG_ENV_SIZE+ 128*1024)"
CONFIG_CS8900=y
CONFIG_CMD_FLASH=y
CONFIG_CMD_SAVEENV=y
CONFIG_S3C2410=y
CONFIG_ENV_ADDR="(CONFIG_SYS_FLASH_BASE+ 0x070000)"
CONFIG_CS8900_BUS16=y
CONFIG_CMD_MEMORY=y
CONFIG_SYS_MAXARGS=16
CONFIG_CMD_RUN=y
CONFIG_IPADDR="10.0.0.110"
CONFIG_SYS_PBSIZE="(CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16)"
CONFIG_BOOTP_HOSTNAME=y
CONFIG_BOARDDIR="board/samsung/smdk2410"
CONFIG_BOARDDIR="board/samsung/smdk2410"
CONFIG_CMD_SETGETDCR=y
CONFIG_ZLIB=y
CONFIG_S3C24X0=y
CONFIG_SYS_FLASH_WRITE_TOUT="(5*CONFIG_SYS_HZ)"
CONFIG_BOOTP_BOOTFILESIZE=y
CONFIG_CMD_BOOTD=y
CONFIG_NET_MULTI=y
CONFIG_SYS_BARGSIZE="CONFIG_SYS_CBSIZE"
CONFIG_SYS_HZ=1000
CONFIG_GZIP=y
CONFIG_CMD_FPGA=y
CONFIG_SYS_BAUDRATE_TABLE="{9600, 19200, 38400, 57600, 115200 }"
CONFIG_ENV_IS_IN_FLASH=y
CONFIG_CMD_ECHO=y
CONFIG_BOOTP_GATEWAY=y
CONFIG_S3C24X0_SERIAL=y
CONFIG_BAUDRATE=115200
CONFIG_NETMASK="255.255.255.0"
CONFIG_ARM920T=y
CONFIG_SYS_DEF_EEPROM_ADDR=0
CONFIG_SYS_MEMTEST_END="0x33F00000"
CONFIG_CMD_ELF=y
CONFIG_CMD_DATE=y
CONFIG_SYS_FLASH_BASE="PHYS_FLASH_1"
CONFIG_SYS_MAX_FLASH_BANKS=y
CONFIG_CMD_IMLS=y
CONFIG_CMD_SOURCE=y
CONFIG_SYS_PROMPT="SMDK2410# "
CONFIG_BOOTP_BOOTPATH=y
CONFIG_SERIAL1=y
CONFIG_SYS_MEMTEST_START="0x30000000"
CONFIG_CMD_LOADB=y
CONFIG_CMD_LOADS=y
CONFIG_CMD_IMI=y
CONFIG_ARM=y
CONFIG_CS8900_BASE="0x19000300"
CONFIG_SYS_MAX_FLASH_SECT="(11)"
CONFIG_CMD_BDI=y
CONFIG_SERVERIP="10.0.0.1"
CONFIG_SYS_FLASH_ERASE_TOUT="(5*CONFIG_SYS_HZ)"
Useful uboot source code:
arch/arm
arch/arm/cpu/arm920t
arch/arm/cpu/arm920t/s3c24x0
arch/arm/include
arch/arm/include/asm
arch/arm/include/asm/arch-s3c24x0
arch/arm/include/asm/proc-armv
arch/arm/lib
board/samsung/smdk2410
Allother folders.
References
1.Learning the bash shell, 3rd.
2.Gnu make manual
3.Gcc docs:
http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Option-Summary.html#Option-Summary
4.GNU Linker docs:
http://m68hc11.serveftp.org/doc/ld.html
5.Sed docs:
http://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command