BSP开发之ubootuboot常用命令以及代码分析

Posted 与光同程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BSP开发之ubootuboot常用命令以及代码分析相关的知识,希望对你有一定的参考价值。

文章目录

uboot 使用

uboot命令

通用 UBOOT 命令

信息查看命令
  • bdinfo 板级信息
  • printenv 环境变量
  • version 当前版本
环境变量操作命令
  • setenv 设置环境变量
  • saveenv 保存环境变量
内存操作命令
命令作用使用
md显示内存值.b.w.l 显示内存长度 md.b addr length
nm修改内存值.b.w.l nm.b addr
mm修改内存值.b.w.l 带自增
mw数据填充.b.w.l mw.l addr xxxxx length
cp内存拷贝.b.w.l cp.l addr1 addr2 length
cmp内存比较.b.w.l cp.l addr1 addr2 length
网络操作命令

相关环境变量

环境变量描述
ipaddr本机IP地址
ethaddrmac地址
gatewayip网关地址
netmask子网掩码
serverip服务器IP地址
命令作用使用
ping测试网络ping ip uboot只能ping 外部机器 外部机器无法ping uboot!
dhcp获取ip地址
nfsnfs下载文件nfs addr netfile
tftptftp下载文件tftp addr netfile
磁盘操作命令
命令作用使用
mmc info输出mmc 设备信息
mmc read读mmc 数据
mmc write写mmc 数据
mmc rescan扫描mmc 设备
mmc part输出mmc 分区
mmc dev切换mmc 设备
mmc list列出mmc 设备
boot操作命令
  • bootz bootm
    bootz addr initrd:size fdt

    addr: zimage地址
    initrd :initrd 地址
    fdt: 设备树文件地址

  • boot
    按照bootcmd 命令启动

其他操作命令
  • reset 重启命令
  • go 跳转到指定地址执行
  • run 运行环境变量中定义的命令

Uboot 编译流程学习

顶层Makefile分析

版本号
VERSION = 2016
PATCHLEVEL = 01
SUBLEVEL =
EXTRAVERSION =
NAME =
# 编译参数
MAKEFLAGS += -rR --include-dir=$(CURDIR)

#避免和环境变量冲突
unexport GREP_OPTIONS

# V是哪里来的 如果是从命令行中定义的那么将KBUILD_VERBOSE 设置为1 否则默认0
ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif


#如果用户正在运行make -s(静默模式),则禁止echo of  

ifneq ($(filter 4.%,$(MAKE_VERSION)),)	# make-4
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
  quiet=silent_
endif
else					# make-3.8x
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
  quiet=silent_
endif
endif

export quiet Q KBUILD_VERBOSE

# 命令中是否指定输出目录
ifeq ("$(origin O)", "command line")
  KBUILD_OUTPUT := $(O)
endif

PHONY := _all
_all:
$(CURDIR)/Makefile Makefile: ;

# 如果输出目录不空
ifneq ($(KBUILD_OUTPUT),)
saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \\
								&& /bin/pwd)
$(if $(KBUILD_OUTPUT),, \\
     $(error failed to create output directory "$(saved-output)"))

PHONY += $(MAKECMDGOALS) sub-make


#是否使能代码检查
ifeq ("$(origin C)", "command line")
  KBUILD_CHECKSRC = $(C)
endif
ifndef KBUILD_CHECKSRC
  KBUILD_CHECKSRC = 0
endif

#使用make M=dir指定要构建的外部模块目录  
#旧语法make… 仍然支持SUBDIRS=$PWD  
#设置环境变量KBUILD_EXTMOD优先 
ifdef SUBDIRS
  KBUILD_EXTMOD ?= $(SUBDIRS)
endif

ifeq ("$(origin M)", "command line")
  KBUILD_EXTMOD := $(M)
endif

#如果构建一个外部模块,我们不需要考虑all:规则而_all依赖于模块 
PHONY += all
ifeq ($(KBUILD_EXTMOD),)
_all: all
else
_all: modules
endif

ifeq ($(KBUILD_SRC),)
        srctree := .
else
        ifeq ($(KBUILD_SRC)/,$(dir $(CURDIR)))
                srctree := ..
        else
                srctree := $(KBUILD_SRC)
        endif
endif
objtree		:= .
src		:= $(srctree)
obj		:= $(objtree)

VPATH		:= $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))

export srctree objtree VPATH
unexport CDPATH

# 获取主机架构以及对应操作系统
HOSTARCH := $(shell uname -m | \\
	sed -e s/i.86/x86/ \\
	    -e s/sun4u/sparc64/ \\
	    -e s/arm.*/arm/ \\
	    -e s/sa110/arm/ \\
	    -e s/ppc64/powerpc/ \\
	    -e s/ppc/powerpc/ \\
	    -e s/macppc/powerpc/\\
	    -e s/sh.*/sh/)

HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \\
	    sed -e 's/\\(cygwin\\).*/cygwin/')

export	HOSTARCH HOSTOS

# 判断主机和编译系统是否是同一架构,如果不是 许哟啊采用交叉编译器
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=arm-linux-gnueabi-
endif

KCONFIG_CONFIG	?= .config
export KCONFIG_CONFIG


scripts/Kbuild.include: ;
include scripts/Kbuild.include

# 定义编译套件
AS		= $(CROSS_COMPILE)as
ifneq ($(shell $(CROSS_COMPILE)ld.bfd -v 2> /dev/null),)
LD		= $(CROSS_COMPILE)ld.bfd
else
LD		= $(CROSS_COMPILE)ld
endif
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
AWK		= awk
PERL		= perl
PYTHON		= python
DTC		= dtc
CHECK		= sparse


# 导出其他变量
export VERSION PATCHLEVEL SUBLEVEL UBOOTRELEASE UBOOTVERSION
export ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR
export CONFIG_SHELL HOSTCC HOSTCFLAGS HOSTLDFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM LDR STRIP OBJCOPY OBJDUMP
export MAKE AWK PERL PYTHON
export HOSTCXX HOSTCXXFLAGS DTC CHECK CHECKFLAGS
export KBUILD_CPPFLAGS NOSTDINC_FLAGS UBOOTINCLUDE OBJCOPYFLAGS LDFLAGS
export KBUILD_CFLAGS KBUILD_AFLAGS



# 定义自动生成的版本号文件
version_h := include/generated/version_autogenerated.h
timestamp_h := include/generated/timestamp_autogenerated.h

libs-y += lib/
libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
libs-$(CONFIG_OF_EMBED) += dts/
libs-y += fs/
libs-y += net/
libs-y += disk/
libs-y += drivers/
libs-y += drivers/dma/
libs-y += drivers/gpio/
libs-y += drivers/i2c/
libs-y += drivers/mmc/
libs-y += drivers/mtd/
libs-$(CONFIG_CMD_NAND) += drivers/mtd/nand/
libs-y += drivers/mtd/onenand/
libs-$(CONFIG_CMD_UBI) += drivers/mtd/ubi/
libs-y += drivers/mtd/spi/
libs-y += drivers/net/
libs-y += drivers/net/phy/
libs-y += drivers/pci/
libs-y += drivers/power/ \\
	drivers/power/fuel_gauge/ \\
	drivers/power/mfd/ \\
	drivers/power/pmic/ \\
	drivers/power/battery/ \\
	drivers/power/regulator/
libs-y += drivers/spi/
libs-$(CONFIG_FMAN_ENET) += drivers/net/fm/
libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
libs-$(CONFIG_ALTERA_SDRAM) += drivers/ddr/altera/
libs-y += drivers/serial/
libs-y += drivers/usb/dwc3/
libs-y += drivers/usb/emul/
libs-y += drivers/usb/eth/
libs-y += drivers/usb/gadget/
libs-y += drivers/usb/gadget/udc/
libs-y += drivers/usb/host/
libs-y += drivers/usb/musb/
libs-y += drivers/usb/musb-new/
libs-y += drivers/usb/phy/
libs-y += drivers/usb/ulpi/
libs-y += common/
libs-$(CONFIG_API) += api/
libs-$(CONFIG_HAS_POST) += post/
libs-y += test/
libs-y += test/dm/
libs-$(CONFIG_UT_ENV) += test/env/

libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)

libs-y := $(sort $(libs-y))

u-boot-dirs	:= $(patsubst %/,%,$(filter %/, $(libs-y))) tools examples

u-boot-alldirs	:= $(sort $(u-boot-dirs) $(patsubst %/,%,$(filter %/, $(libs-))))

libs-y		:= $(patsubst %/, %/built-in.o, $(libs-y))

u-boot-init := $(head-y)
u-boot-main := $(libs-y)

再分析哪些代码是被编译的

_all --> all --> ALL-y -->u-boot.bin --> u-boot-nodtb.bin --> uboot --> u-boot-init u-boot-main u-boot.lds

u-boot.lds --> LDSCRIPT

下面的脚本不难看出其现在根目录寻找lds文件 ,如果没有分别到 board CPUDIR ARCH目录寻找链接文件

经过分析uboot vexpress最终使用了arch/arm/cpu/lds文件

u-boot-init --> head -y --> arch/arm/cpu/start.o

u-boot-main --> lib -y --> 大量子目录中带lib -y的源码 变成build-in.o

uboot启动流程

从链接脚本分析代码从_start开始 定义与arch/xxx/lib/vectors.S中


_start:

#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG

    .word   CONFIG_SYS_DV_NOR_BOOT_CFG

#endif


    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

从uboot.map找找到.vectors段

*(.__image_copy_start)

.__image_copy_start

0x0000000060800000        0x0 arch/arm/lib/built-in.o

0x0000000060800000                __image_copy_start

*(.vectors)

.vectors 0x0000000060800000 0x2e8 arch/arm/lib/built-in.o

0x0000000060800000                _start

0x0000000060800020                _undefined_instruction

0x0000000060800024                _software_interrupt

0x0000000060800028                _prefetch_abort

0x000000006080002c                _data_abort

0x0000000060800030                _not_used

0x0000000060800034                _irq

0x0000000060800038                _fiq

0x0000000060800040                IRQ_STACK_START_IN

可以看出vexpress的uboot 从内存的60800000开始

每个机器的这个地址都可能不同,一开始的时候是由硬件将一段代码拷贝到内存中执行的,而硬件所拷贝的地址一定是固定的,不同的硬件这个地址就可能不同。

我们是怎么指定这个地址的呢 在vexpress的头文件中 我们发现CONFIG_SYS_TEXT_BASE变量为60800000

而顶层Makefile中正好通过下面的方式指定text地址

-Ttext=$(CONFIG_SYS_TEXT_BASE)

arch/arm/cpu/armv7/start.o(.text*)

.text 0x00000000608002e8 0xb0 arch/arm/cpu/armv7/start.o

0x00000000608002e8                reset

0x00000000608002ec             save_boot_params_ret

0x0000000060800328             c_runtime_cpu_setup

0x0000000060800338                save_boot_params

0x000000006080033c                cpu_init_cp15

0x0000000060800390                cpu_init_crit

紧接着的代码就是从arch/arm/cpu/armv7/start.s开始

下面所有平台的代码都会运行一个reset的函数

在这个start.s的过程中发生这样的函数调用

reset -->save_boot_params–>save_boot_params_ret(设置处理器工作模式)–>cpu_init_cp15(设置CP15)、cpu_init_crit、_main

cpu_init_crit–>lowlevel_init–>s_init

lowlevel_init


ENTRY(lowlevel_init)

    ldr sp, =CONFIG_SYS_INIT_SP_ADDR

    bic sp, sp, #7

#ifdef CONFIG_SPL_DM

    mov r9, #0

#else

#ifdef CONFIG_SPL_BUILD

    ldr r9, =gdata

#else

    sub sp, sp, #GD_SIZE

    bic sp, sp, #7

    mov r9, sp

#endif

#endif

    push    ip, lr

    bl  s_init

    pop ip, pc

ENDPROC(lowlevel_init)

ldr sp, =CONFIG_SYS_INIT_SP_ADDR

这个变量定义于#include/configs/vexpress_common.h

#define CONFIG_SYS_GBL_DATA_OFFSET (CONFIG_SYS_SDRAM_BASE + \\

CONFIG_SYS_INIT_RAM_SIZE - \\

GENERATED_GBL_DATA_SIZE)

理解这个宏定义非常重要

CONFIG_SYS_SDRAM_BASE=0x60000000//RAM基地址

CONFIG_SYS_INIT_RAM_SIZE=0x1000 //内部RAM大小

GENERATED_GBL_DATA_SIZE=256 //不知道干嘛的地址空间

简单的总结来说就是这段代码将内存

0x60000000 - 0x60001000 作为一个栈空间

有一些处理器会使用内部ram作为栈空间 ,而非常明显vexpress代码段和栈空间使用了同一个ram 代码段0x60800000 开始

这个栈空间一开始就向其中压入了一个256字节的空间 然后有压进去一个gd_size

分析这个时候的内存结构就可以发现

这个时候0x60000000 - 0x60001000 作为栈

0x60800000  - ~ 放代码

有栈了之后就可以使用C语言了所以s_init 理论上是第一个使用了C语言的函数

当然这个函数也不一定有 vexpress就直接跳到_main执行

gd结构体如下


typedef struct global_data 

    bd_t *bd;

    unsigned long flags;

    unsigned int baudrate;

    unsigned long cpu_clk;  /* CPU clock in Hz!     */

    unsigned long bus_clk;

    /* We cannot bracket this with CONFIG_PCI due to mpc5xxx */

    unsigned long pci_clk;

    unsigned long mem_clk;

#ifdefined(CONFIG_LCD) ||defined(CONFIG_VIDEO)

    unsigned longfb_base;  /* Base address of framebuffer mem */

#endif

#ifdefined(CONFIG_POST) ||defined(CONFIG_LOGBUFFER)

    unsigned longpost_log_word;  /* Record POST activities */

    unsigned longpost_log_res; /* success of POST test */

    unsigned longpost_init_f_time;  /* When post_init_f started */

#endif

#ifdefCONFIG_BOARD_TYPES

    unsigned long board_type;

#endif

    unsigned long have_console; /* serial_init() was called */

#ifdefCONFIG_PRE_CONSOLE_BUFFER

    unsigned long precon_buf_idx;   /* Pre-Console buffer index */

#endif

#ifdefCONFIG_MODEM_SUPPORT

    unsigned long do_mdm_init;

    unsigned long be_quiet;

#endif

    unsigned long env_addr; /* Address  of Environment struct */

    unsigned long env_valid;    /* Checksum of Environment valid? */


    unsigned long ram_top;  /* Top address of RAM used by U-Boot */


    unsigned long relocaddr;    /* Start address of U-Boot in RAM */

    phys_size_t ram_size;   /* RAM size */

#ifdef CONFIG_SYS_MEM_RESERVE_SECURE

#define MEM_RESERVE_SECURE_SECURED  0x1

#define MEM_RESERVE_SECURE_MAINTAINED   0x2

#define MEM_RESERVE_SECURE_ADDR_MASK    (~0x3)

    /*

     * Secure memory addr

     * This variable needs maintenance if the RAM base is not zero,

     * or if RAM splits into non-consecutive banks. It also has a

     * flag indicating the secure memory is marked as secure by MMU.

     * Flags used: 0x1 secured

     *             0x2 maintained

     */

    phys_addr_tsecure_ram;

#endif

    unsigned long mon_len;  /* monitor len */

    unsigned long irq_sp;       /* irq stack pointer */

    unsigned long start_addr_sp;    /* start_addr_stackpointer */

    unsigned long reloc_off;

    struct global_data *new_gd; /* relocated global data */


#ifdefCONFIG_DM

    structu device  *dm_root;   /* Root instance for Driver Model */

    structu device  *dm_root_f; /* Pre-relocation root instance */

    struct list_head uclass_root;   /* Head of core tree */

#endif

#ifdefCONFIG_TIMER

    structudevice  *timer; /* Timer instance for Driver Model */

#endif


    constvoid*fdt_blob;   /* Our device tree, NULL if none */

    void*new_fdt;      /* Relocated FDT */

    unsignedlong fdt_size; /* Space reserved for relocated FDT */

    struct jt_funcs *jt;        /* jump table */

    charenv_buf[32];   /* buffer for getenv() before reloc. */

#ifdefCONFIG_TRACE

    void        *trace_buff;    /* The trace buffer */

#endif

#ifdefined(CONFIG_SYS_I2C)

    int     cur_i2c_bus;    /* current used i2c bus */

#endif

#ifdefCONFIG_SYS_I2C_MXC

    void *srdata[10];

#endif

    unsigned long timebase_h;

    unsigned long timebase_l;

#ifdefCONFIG_SYS_MALLOC_F_LEN

    unsigned long malloc_base;  /* base address of early malloc() */

    unsigned long malloc_limit; /* limit address */

    unsigned long malloc_ptr;   /* current address */

#endif

#ifdefCONFIG_PCI

    struct pci_controller*hose;    /* PCI hose for early use */

    phys_addr_t pci_ram_top;    /* top of region accessible to PCI */

#endif

#ifdefCONFIG_PCI_BOOTDELAY

    int pcidelay_done;

#endif

    struct udevice *cur_serial_dev; /* current serial device */

    struct arch_global_data arch;   /* architecture-specific data */

#ifdefCONFIG_CONSOLE_RECORD

    struct membuffconsole_out; /* console output */

    struct membuffconsole_in;  /* console input */

#endif

 gd_t;

#endif

_main (uboot/arch/arm/lib/crt0.S)

这个函数中uboot完成了基本所有的工作非常关键其位于

arch/arm/lib/crt0.S中

这个函数不会返回board_init_r会完成之后所有的工作直到启动

内核


    # sp指针重新指向栈底

    ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)

    bic sp, sp,

    mov r0, sp

    # 调用board_init_f_mem

    # 留出早期 malloc 和 gd 内存区域 同时将gd的地址写到r9之中 r9通过DECLARE_GLOBAL_DATA_PTR

    ##define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r9") 指定(uboot/arch/arm/include/asm/global_data.h)

    #(common/init/board_init.c)

    bl  board_init_f_mem

    movsp, r0#重新设置栈指针 相当于将之前计算的malloc gd 空间压栈

    movr0, #0

    # 调用一个初始化列表(common/board_f.c) 后面分析

    bl  board_init_f

    #获取 gd->start_addr_sp 的值赋给 sp

    #这个时候 gd->start_addr_sp=0x7fee2ee0

    # 我们查看数据手册发现vexpressDDR2 是从0x60000000-0x80000000512M空间 ,

    # 可以发现gd就是被挪到了整个内存的最后面

    ldrsp, [r9, #GD_START_ADDR_SP]

    movr3, sp

    bicr3, r3, #7

    movsp, r3

    bicsp, sp, 

    #重新设置r9的数值

    ldr  r9, [r9, #GD_BD]        /* r9 = gd->bd */

    sub r9, r9, #GD_SIZE

    adr lr, here

    ldr r0, [r9, #GD_RELOC_OFF]

    add lr, lr, r0

    ldr r0, [r9, #GD_RELOCADDR]

    #拷贝uboot代码到ddr的最后面

    b   relocate_code

here:

    bl  relocate_vectors


    bl  c_runtime_cpu_setup

#endif

    ldr r0, =__bss_start

#ifdef CONFIG_USE_ARCH_MEMSET

    ldr r3, =__bss_end

    mov r1, #0x00000000

    subs    r2, r3, r0      /*r2=memsetlen*/

    bl  memset

#else

    ldr r1, =__bss_end  

    mov r2, #0x00000000 

clbss_l:cmpr0, r1  

    str lo   r2, [r0]        /*clear32-bitBSSword*/

    add lo   r0, r0, #4      /* move to next */

    blocl bss_l

#endif

    mov     r0, r9               

    ldr r1, [r9, #GD_RELOCADDR] 

    #调用board_init_r

    ldr pc, =board_init_r   

#endif

relocate_vectors relocate_code (uboot/arch/arm/lib/relocate.S)


#include <asm-offsets.h>

#include <config.h>

#include <linux/linkage.h>

#ifdef CONFIG_CPU_V7M

#include <asm/armv7m.h>

#endif

    .section    .text.relocate_vectors,"ax",%progbits

    .weak       relocate_vectors


ENTRY(relocate_vectors)

#ifdef CONFIG_CPU_V7M

    /*

     *OnARMv7-Mweonlyhavetowritethenewvectoraddress

     *toVTORregister.

     */

    ldrr0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */

    ldrr1, =V7M_SCB_BASE

    strr0, [r1, V7M_SCB_VTOR]

#else

#ifdef CONFIG_HAS_VBAR

    /*

     *IftheARMprocessorhasthesecurityextensions,

     *useVBARtorelocatetheexceptionvectors.

     */

    ldrr0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */

    mcr     p15, 0, r0, c12, c0, 0  /*SetVBAR*/

#else

    /*

     *Copytherelocatedexceptionvectorstothe

     *correctaddress

     *CP15c1Vbitgivesusthelocationofthevectors:

     *0x00000000or0xFFFF0000.

     */

    ldrr0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */

    mrcp15, 0, r2, c1, c0, 0   /*Vbit (bit[13])inCP15c1*/

    ands    r2, r2, #(1 << 13)

    ldreq   r1, =0x00000000     /*IfV=0*/

    ldrne   r1, =0xFFFF0000     /*IfV=1*/

    ldmia   r0!, r2-r8,r10

    stmia   r1!, r2-r8,r10

    ldmia   r0!, r2-r8,r10

    stmia   r1!, r2-r8,r10

#endif

#endif

    bx  lr


ENDPROC(relocate_vectors)


ENTRY(relocate_code)

    # 当前代码段首地址 0x60800000

    ldrr1, =__image_copy_start/*r1<-SRC&__image_copy_start*/

    # 偏移地址

    subs    r4, r0, r1      /*r4<-relocationoffset*/

    # 如果相等不用拷贝 直接结束

    beqrelocate_done       /*skiprelocation*/

    # 保存代码结束地址

    ldrr2, =__image_copy_end   /*r2<-SRC&__image_copy_end*/

    # 比较r1 是否到了 r2 到了就完成了拷贝

copy_loop:

    ldmia   r1!, r10-r11      /*copyfromsourceaddress [r1]    */

    stmia   r0!, r10-r11      /*copyto   targetaddress [r0]    */

    cmpr1, r2          /*untilsourceendaddress [r2]    */

    blocopy_loop

    # 重定位自身到另外一个地方

    ldrr2, =__rel_dyn_start    /*r2<-SRC&__rel_dyn_start*/

    ldrr3, =__rel_dyn_end  /*r3<-SRC&__rel_dyn_end*/

fixloop:

    ldmia   r2!, r0-r1        /* (r0,r1) <- (SRClocation,fixup) */

    andr1, r1, #0xff

    cmpr1, #23         /* relative fixup? */

    bnefixnext

    addr0, r0, r4

    ldrr1, [r0]

    addr1, r1, r4

    strr1, [r0]

fixnext:

    cmpr2, r3

    blofixloop


relocate_done:

    bx  lr

ENDPROC(relocate_code)


为了验证重定位的效果我写了这样两个函数


int hik_board_f_init(void) 



    hik_board_f_show_gd_info();

    printf("vexpress_timer_init addr 0x%x\\n",(int)vexpress_timer_init);

    return0;



int hik_board_r_init(void) 



    hik_board_f_show_gd_info();

    printf("vexpress_timer_init addr 0x%x\\n",(int)vexpress_timer_init);

    return0;



这两个函数分别定义于重定位之前和重定位之后

是不是非常神奇 同一个函数指针 竟然发生了变化

vexpress_timer_init addr 0x60800ecc

vexpress_timer_init addr 0x7ff83ecc

run_main_loop

在board_init_r 之中就会执行run_main_loop

这个函数的执行流程如下:

run_main_loop -->main_loop(u-boot\\common\\main.c)

–>cli_loop (common\\cli.c)–>run_list(common\\cli_hush.c)–>run_list_real–>run_pipe_real

–>cmd_process–>cmd_call

uboot引导内核过程分析

与引导相关代码大多位于cmd_bootm.c 中

启动Linux用到一个关键全局变量

images 在文件cmd_bootm.c 中。


typedefstruct bootm_headers 

    /*

     * Legacy os image header, if it is a multi component image

     * then boot_get_ramdisk() and get_fdt() will attempt to get

     * data from second and third component accordingly.

     */

    image_header_t  *legacy_hdr_os;     /* image header pointer */

    image_header_t  legacy_hdr_os_copy; /* header copy */

    ulong       legacy_hdr_valid;

#ifdefined(CONFIG_FIT)

    constchar  *fit_uname_cfg; /* configuration node unit name */

    void        *fit_hdr_os;    /* os FIT image header */

    constchar  *fit_uname_os;  /* os subimage node unit name */

    int     fit_noffset_os; /* os subimage node offset */

    void        *fit_hdr_rd;    /* init ramdisk FIT image header */

    constchar  *fit_uname_rd;  /* init ramdisk subimage node unit name */

    int     fit_noffset_rd; /* init ramdisk subimage node offset */

    void        *fit_hdr_fdt;   /* FDT blob FIT image header */

    constchar  *fit_uname_fdt; /* FDT blob subimage node unit name */

    int     fit_noffset_fdt;/* FDT blob subimage node offset */


    void        *fit_hdr_setup; /* x86 setup FIT image header */

    constchar  *fit_uname_setup; /* x86 setup subimage node name */

    int     fit_noffset_setup;/* x86 setup subimage node offset */

#endif

#ifndefUSE_HOSTCC

    image_info_t    os;     //os信息

    ulong       ep;         //os入口

    ulong       rd_start, rd_end;// ramdisk位置

    char        *ft_addr;        // 设备树位置

    ulong       ft_len;   

    ulong       initrd_start;    //initrd位置

    ulong       initrd_end;

    ulong       cmdline_start;   //cmdline(bootargs)位置

    ulong       cmdline_end;

    bd_t        *kbd;

#endif

    int     verify;     /* getenv("verify")[0] != 'n' */

#define BOOTM_STATE_START   (0x00000001)

#define BOOTM_STATE_FINDOS  (0x00000002)

#define BOOTM_STATE_FINDOTHER   (0x00000004)

#define BOOTM_STATE_LOADOS  (0x00000008)

#define BOOTM_STATE_RAMDISK (0x00000010)

#define BOOTM_STATE_FDT     (0x00000020)

#define BOOTM_STATE_OS_CMDLINE  (0x00000040)

#define BOOTM_STATE_OS_BD_T (0x00000080)

#define BOOTM_STATE_OS_PREP (0x00000100)

#define BOOTM_STATE_OS_FAKE_GO  (0x00000200)    /* 'Almost' run the OS */

#define BOOTM_STATE_OS_GO   (0x00000400)

    int     state;

#ifdefCONFIG_LMB

    structlmb  lmb;        /* for memory mgmt */

#endif

 bootm_headers_t;

typedef struct image_info 

    ulong       start, end;     /* start

以上是关于BSP开发之ubootuboot常用命令以及代码分析的主要内容,如果未能解决你的问题,请参考以下文章

BSP开发之kernelLinux启动流程以及编译流程分析

BSP开发之kernelLinux启动流程以及编译流程分析

BSP开发之kernelLinux启动流程以及编译流程分析

自学总结redis第二部分(redis常用命令高级命令特性以及与java代码的结合)

ubootuboot 2020.04 DM驱动模式 -- Demo体验

ubootuboot 2020.04 DM驱动模式 -- 架构分析