2. Uboot Makefile详细分析

时间:2021-04-14 16:47:42

由于所找到的资料均是英语的,故此文也直接用英语。

转载请注明。
作者: Lithocntlor
邮箱: lithocntlor@gmail.com

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