uboot流程简单分析

  uboot的最终目的是要启动内核,所以需要为内核准备必要的环境。先分析uboot配置和编译时,做了哪些事情。
  uboot版本:u-boot-2010.03

1 配置过程

  在配置uboot时,执行make smdk2410_config,在uboot顶层目录的Makefile中看到

SRCTREE		:= $(CURDIR)
...
MKCONFIG	:= $(SRCTREE)/mkconfig
...
smdk2410_config	:	unconfig
	@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 samsung s3c24x0

  此时实际执行:

./mkconfig smdk2410 arm arm920t smdk2410 NULL s3c24x0
#   $0       $1     $2    $3       $4     $5    $6

  分析mkconfig文件。

#!/bin/sh -e

APPEND=no	# Default: Create new config file
BOARD_NAME=""	# Name to print in make output
TARGETS=""

while [ $# -gt 0 ] ; do         # $#参数个数,-gt大于,此处判断参数个数大于0
	case "$1" in                # $1是smdk2410,选项中都没有,所以break
	--) 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

[ "${BOARD_NAME}" ] || BOARD_NAME="$1"  # BOARD_NAME此时是空,所以赋值$1,即BOARD_NAME=smdk2410 

[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1

if [ "${ARCH}" -a "${ARCH}" != "$2" ]; then #在makefile中,ARCH=arm
	echo "Failed: \$ARCH=${ARCH}, should be '$2' for ${BOARD_NAME}" 1>&2
	exit 1
fi

echo "Configuring for ${BOARD_NAME} board..."

# SRCTREE在makefile中为CURDIR
# OBJTREE为OBJTREE:= $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
# 直接在源代码目录下编译,没有配置目标目录,这里不等
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   #建立连接文件asm-arm
fi

rm -f asm-$2/arch

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
fi

if [ "$2" = "arm" ] ; then
	rm -f asm-$2/proc
	ln -s ${LNPREFIX}proc-armv asm-$2/proc  #ln -s proc-armv asm-arm/proc
fi

# 新建config.mk文件
# 写入到config.mk
#
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

# Assign board directory to BOARDIR variable
if [ -z "$5" -o "$5" = "NULL" ] ; then
    BOARDDIR=$4
else
    BOARDDIR=$5/$4
fi

#
# Create board specific header file
#
if [ "$APPEND" = "yes" ]	# APPEND=no
then
	echo >> config.h
else
	> config.h		# 建立新的文件config.h
fi
echo "/* Automatically generated - do not edit */" >>config.h

for i in ${TARGETS} ; do
	echo "#define CONFIG_MK_${i} 1" >>config.h ;  #写入到config.h
done

cat << EOF >> config.h   #写入到config.h
#define CONFIG_BOARDDIR board/$BOARDDIR
#include <config_defaults.h>
#include <configs/$1.h>
#include <asm/config.h>
EOF

exit 0

  在上面配置过程中建立了一些平台相关的链接文件。这样的好处是,因为平台不同,在代码中若包含头文件,例如#include <arm/xxx.h>,不需要写成包含具体目录下的头文件。
  生成了include/config.h,config.h内容。

/* Automatically generated - do not edit */
#define CONFIG_BOARDDIR board/samsung/smdk2410
#include <config_defaults.h>
#include <configs/smdk2410.h>
#include <asm/config.h>

  #include <configs/smdk2410.h>与平台相关,因此,在移植时,针对不同的芯片,需要在include/configs目录下建立平台所需的配置文件。

2 编译

  执行make时,会进入各子目录进行编译、链接,最终生成uboot.bin。
  在cpu/arm920t/U-Boot.lds中,指定了内存的布局。

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
	. = 0x00000000;

	. = ALIGN(4);
	.text :
	{
		cpu/arm920t/start.o	(.text)
		*(.text)
	}

	. = ALIGN(4);
	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

	. = ALIGN(4);
	.data : { *(.data) }

	. = ALIGN(4);
	.got : { *(.got) }

	. = .;
	__u_boot_cmd_start = .;
	.u_boot_cmd : { *(.u_boot_cmd) }
	__u_boot_cmd_end = .;

	. = ALIGN(4);
	__bss_start = .;
	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
	_end = .;
}

  从上述内存布局中看出,start.o放在了最前面,对应cpu/$(cpu)/start.s文件,是启动最开始执行的文件。

3 源码分析

  uboot的启动可分为两个阶段:
  1)硬件初始化,时钟、MMU等,并为第二阶段准备RAM空间。cpu/arm920t/start.s和board/smdk2410/lowlevel_init.s。
  2)外设等初始化,从lib_arm/board.c中的start_armboot开始。

3.1 第一阶段

  主要功能:
  1)关闭看门狗、中断
  2)设置时钟
  3)SDRAM初始化,复制代码到SDRAM
  4)堆栈初始化
  此时内存使用情况如下:
在这里插入图片描述

3.2 第二阶段

  在start_armboot中可以看到:
  1)xxx_init(),一些初始化函数,包括时钟、串口、网络等;
  2)getenv(),获取设置好的启动参数,通过run_command()执行。

3.3 启动内核

  内核文件为uImage,格式为image_header+真正的内核。
  根据环境变量中的bootm,实际执行do_bootm()->do_bootm_linux(),根据读取的image_header中ep指针,得到真正的内核入口地址。

void (*kernel)(void) = (void (*)(void))images->ep;

  由此启动内核。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值