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地址 |
ethaddr | mac地址 |
gatewayip | 网关地址 |
netmask | 子网掩码 |
serverip | 服务器IP地址 |
命令 | 作用 | 使用 |
---|---|---|
ping | 测试网络 | ping ip uboot只能ping 外部机器 外部机器无法ping uboot! |
dhcp | 获取ip地址 | |
nfs | nfs下载文件 | nfs addr netfile |
tftp | tftp下载文件 | 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 fdtaddr: 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-0x80000000的512M空间 ,
# 可以发现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常用命令以及代码分析的主要内容,如果未能解决你的问题,请参考以下文章
自学总结redis第二部分(redis常用命令高级命令特性以及与java代码的结合)