关于Uboot自己选的版本是目前最新的2011.06,官方网址为:http://www.denx.de/wiki/U-Boot/WebHome,下面的一些内容主要翻译自顶层目录的 README 。
U-Boot是一种基于PowerPC, ARM, MIPS 或者其他处理器架构的嵌入式开发板的启动引导程序(boot loader),boot loader是可以被安装在作为引导的ROM上,实现初始化和测试硬件,和下载与运行应用的代码。
U-Boot的开发与Linux紧密相连:部分代码是取自Linux的源代码,比如我们使用共同的头文件定义,同时特别提供了可以用于启动Linux内核的功能。
DENX注重于去使这个软件很容易去配置和拓展。比如,为了便于用户增加新的命令,所以的监视命令都是用同样的接口和架构实现的。另外,很少使用的命令可以动态地进行加载执行,比如硬件测试功能。
下面介绍目录结构:
/arch /存放特定架构的实现文件,系统的启动代码一般在这里的start.S中
/arm /Arm架构
/cpu /CPU相关文件
/arm720t /ARM 720 CPUs
/arm920t /ARM 920 CPUs
/at91rm9200/Atmel AT91RM9200 CPU
/imx /Freescale MC9328 i.MX CPUs
/s3c24x0 /Samsung S3C24X0 CPUs
/arm925t /ARM 925 CPUs
/arm926ejs /ARM 926 CPUs
/arm1136 /ARM 1136 CPUs
/ixp /Intel XScale IXP CPUs
/pxa /Intel XScale PXA CPUs
/s3c44b0 /Samsung S3C44B0 CPUs
/sa1100 /Intel StrongARM SA1100 CPUs
/lib /CPU library files
/avr32 /AVR32架构
/cpu /CPU specific files
/lib /CPU library files
/blackfin /Blackfin架构
/x86 /x86 架构
/m68k /m68k 架构
/microblaze /microblaze 架构
/mips /MIPS 架构
/nios2 /NIOS2 架构
/powerpc /PowerPC 架构
/sh /SH 架构
/sparc /SPARC 架构
/api /为拓展应用准备的,与硬件和架构无关的接口定义文件
/board /常用主板的文件,我们增加的主板文件也需要在这里新增目录后进行开发
/common /与架构无关的通用接口
/disk /实现磁盘分区的接口
/doc /常见功能和问题的说明文档
/drivers /常用的设备驱动程序
/examples /Demo Example code
/fs /文件系统(cramfs, ext2, jffs2, etc.)
/include /全局需要的头文件定义在这儿
/lib /所以架构通用的ib
/libfdt Library files to support flattened device trees
/lzma Library files to support LZMA decompression
/lzo Library files to support LZO decompression
/net /网络相关代码
/post /Power On Self Test 开机自检
/rtc /实时时钟驱动
/tools /Tools to build S-Record or U-Boot images, etc.
README再往下就是介绍各个功能宏,便于我们进行裁剪。
下面通过smdk2410的编译来分析MAKEFILE关系。
我们知道编译smdk2410要先执行make smdk2410_config,然后执行make,生成该主板的u-boot.bin,
如果不先进行配置,直接make会报错:System not configured - see README
所以主makefile有如下大的框架:
ifeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk)) #line 145 include/config.mk文件存在 wildcard : 扩展通配符,找到所有通配的文件并返回
else # !config.mk #line 530 include/config.mk文件不存在
@echo "System not configured - see README" >&2
@ exit 1
所以我们先看如何执行make smdk2410_config,要先找到目标smdk2410_config定义的地方,makefile中定义很多配置的目标,但没有这个目标,所以我们注意到
%_config:: unconfig
@$(MKCONFIG) -A $(@:_config=)
sinclude $(obj).boards.depend
$(obj).boards.depend: boards.cfg #读取boards.cfg,生成所有XXXX_config,SMDK2410_Config就在这里产生
awk '(NF && $$1 !~ /^#/) { print $$1 ": " $$1 "_config; $$(MAKE)" }' $< > $@
注意到主目录下的.boards.depend文件和boards.cfg文件,MKCONFIG由
MKCONFIG := $(SRCTREE)/mkconfig
export MKCONFIG
定义
所以主目录下mkconfig文件来生成include下config.mk和config.h,注意里面有一个 cd ./include,来进入include文件夹的。
进行到此,例如生成了如下config.mk:
ARCH = arm
CPU = arm920t
BOARD = smdk2410
VENDOR = samsung
SOC = s3c24x0
生成了如下config.h:
/* Automatically generated - do not edit */
#define CONFIG_BOADDIR board/samsung/smdk2410 // BOARDDIR=${vendor}/${board}
#include <config_cmd_defaults.h>
#include <config_default.h>
#include <configs/smdk2410.h>
#include <asm/config.h> // ln -s ${SRCTREE}/arch/${arch}/include/asm asm
config.h约束了全局使用到的功能。
下面分析make命令:
先创建两个实目标(非.PHONY ):
TIMESTAMP_FILE = $(obj)include/timestamp_autogenerated.h
$(TIMESTAMP_FILE):
@LC_ALL=C date +'#define U_BOOT_DATE "%b %d %C%y"' > $@
@LC_ALL=C date +'#define U_BOOT_TIME "%T"' >> $@
VERSION_FILE = $(obj)include/version_autogenerated.h
$(VERSION_FILE):
@( localvers='$(shell $(TOPDIR)/tools/setlocalversion $(TOPDIR))' ; \
printf '#define PLAIN_VERSION "%s%s"\n' \
"$(U_BOOT_VERSION)" "$${localvers}" ; \
printf '#define U_BOOT_VERSION "U-Boot %s%s"\n' \
"$(U_BOOT_VERSION)" "$${localvers}" ; \
) > $@.tmp
@( printf '#define CC_VERSION_STRING "%s"\n' \
'$(shell $(CC) --version | head -n 1)' )>> $@.tmp
@( printf '#define LD_VERSION_STRING "%s"\n' \
'$(shell $(LD) -v | head -n 1)' )>> $@.tmp
@cmp -s $@ $@.tmp && rm -f $@.tmp || mv -f $@.tmp $@
然后执行第一个目标:
all: $(ALL)
ALL目标又依赖与:
# 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
ifeq ($(CONFIG_NAND_U_BOOT),y)
ALL += $(obj)u-boot-nand.bin
endif
ifeq ($(CONFIG_ONENAND_U_BOOT),y)
ALL += $(obj)u-boot-onenand.bin
ONENAND_BIN ?= $(obj)onenand_ipl/onenand-ipl-2k.bin
endif
ifeq ($(CONFIG_MMC_U_BOOT),y)
ALL += $(obj)mmc_spl/u-boot-mmc-spl.bin
endif
各目标又依赖与:
$(obj)u-boot.hex: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@
$(obj)u-boot.srec: $(obj)u-boot
$(OBJCOPY) -O srec $< $@
$(obj)u-boot.bin: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
$(BOARD_SIZE_CHECK)
$(obj)u-boot.ldr: $(obj)u-boot
$(CREATE_LDR_ENV)
$(LDR) -T $(CONFIG_BFIN_CPU) -c $@ $< $(LDR_FLAGS)
$(BOARD_SIZE_CHECK)
$(obj)u-boot.ldr.hex: $(obj)u-boot.ldr
$(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ -I binary
$(obj)u-boot.ldr.srec: $(obj)u-boot.ldr
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ -I binary
$(obj)u-boot.img: $(obj)u-boot.bin
$(obj)tools/mkimage -A $(ARCH) -T firmware -C none \
-a $(CONFIG_SYS_TEXT_BASE) -e 0 \
-n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
sed -e 's/"[]*$$/ for $(BOARD) board"/') \
-d $< $@
$(obj)u-boot.imx: $(obj)u-boot.bin
$(obj)tools/mkimage -n $(CONFIG_IMX_CONFIG) -T imximage \
-e $(CONFIG_SYS_TEXT_BASE) -d $< $@
$(obj)u-boot.kwb: $(obj)u-boot.bin
$(obj)tools/mkimage -n $(CONFIG_SYS_KWD_CONFIG) -T kwbimage \
-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) -d $< $@
$(obj)u-boot.sha1: $(obj)u-boot.bin
$(obj)tools/ubsha1 $(obj)u-boot.bin
$(obj)u-boot.dis: $(obj)u-boot
$(OBJDUMP) -d $< > $@
$(obj)u-boot目标又依赖与:
$(obj)u-boot: depend \
$(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
$(GEN_UBOOT)
SUBDIRS目标:
# The "tools" are needed early, so put this first
# Don't include stuff already done in $(LIBS)
SUBDIRS = tools \
examples/standalone \
examples/api
$(SUBDIRS): depend
$(MAKE) -C $@ all
OBJS目标:
OBJS = $(CPUDIR)/start.o #这个是系统总入口
ifeq ($(CPU),x86)
OBJS += $(CPUDIR)/start16.o
OBJS += $(CPUDIR)/resetvec.o
endif
ifeq ($(CPU),ppc4xx)
OBJS += $(CPUDIR)/resetvec.o
endif
ifeq ($(CPU),mpc85xx)
OBJS += $(CPUDIR)/resetvec.o
endif
OBJS := $(addprefix $(obj),$(OBJS))
$(OBJS): depend
$(MAKE) -C $(CPUDIR) $(if $(REMOTE_BUILD),$@,$(notdir $@)) #编译notdir OBJS各项
LIBBOARD目标:
LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).o
LIBBOARD := $(addprefix $(obj),$(LIBBOARD))
$(LIBBOARD): depend $(LIBS)
$(MAKE) -C $(dir $(subst $(obj),,$@)) #将$(obj)和LIBBOARD联合后取目录编译
LIBS目标:
LIBS = lib/libgeneric.o
LIBS += lib/lzma/liblzma.o
LIBS += lib/lzo/liblzo.o
LIBS += lib/zlib/libz.o
LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \
"board/$(VENDOR)/common/lib$(VENDOR).o"; fi)
LIBS += $(CPUDIR)/lib$(CPU).o
ifdef SOC
LIBS += $(CPUDIR)/$(SOC)/lib$(SOC).o
endif
ifeq ($(CPU),ixp)
LIBS += arch/arm/cpu/ixp/npe/libnpe.o
endif
LIBS += arch/$(ARCH)/lib/lib$(ARCH).o
LIBS += fs/cramfs/libcramfs.o fs/fat/libfat.o fs/fdos/libfdos.o fs/jffs2/libjffs2.o \
fs/reiserfs/libreiserfs.o fs/ext2/libext2fs.o fs/yaffs2/libyaffs2.o \
fs/ubifs/libubifs.o
LIBS += net/libnet.o
LIBS += disk/libdisk.o
LIBS += drivers/bios_emulator/libatibiosemu.o
LIBS += drivers/block/libblock.o
LIBS += drivers/dma/libdma.o
LIBS += drivers/fpga/libfpga.o
LIBS += drivers/gpio/libgpio.o
LIBS += drivers/hwmon/libhwmon.o
LIBS += drivers/i2c/libi2c.o
LIBS += drivers/input/libinput.o
LIBS += drivers/misc/libmisc.o
LIBS += drivers/mmc/libmmc.o
LIBS += drivers/mtd/libmtd.o
LIBS += drivers/mtd/nand/libnand.o
LIBS += drivers/mtd/onenand/libonenand.o
LIBS += drivers/mtd/ubi/libubi.o
LIBS += drivers/mtd/spi/libspi_flash.o
LIBS += drivers/net/libnet.o
LIBS += drivers/net/phy/libphy.o
LIBS += drivers/pci/libpci.o
LIBS += drivers/pcmcia/libpcmcia.o
LIBS += drivers/power/libpower.o
LIBS += drivers/spi/libspi.o
ifeq ($(CPU),mpc83xx)
LIBS += drivers/qe/libqe.o
LIBS += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
endif
ifeq ($(CPU),mpc85xx)
LIBS += drivers/qe/libqe.o
LIBS += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
LIBS += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
endif
ifeq ($(CPU),mpc86xx)
LIBS += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
LIBS += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
endif
LIBS += drivers/rtc/librtc.o
LIBS += drivers/serial/libserial.o
LIBS += drivers/twserial/libtws.o
LIBS += drivers/usb/eth/libusb_eth.o
LIBS += drivers/usb/gadget/libusb_gadget.o
LIBS += drivers/usb/host/libusb_host.o
LIBS += drivers/usb/musb/libusb_musb.o
LIBS += drivers/usb/phy/libusb_phy.o
LIBS += drivers/video/libvideo.o
LIBS += drivers/watchdog/libwatchdog.o
LIBS += common/libcommon.o
LIBS += lib/libfdt/libfdt.o
LIBS += api/libapi.o
LIBS += post/libpost.o
ifeq ($(SOC),omap3)
LIBS += $(CPUDIR)/omap-common/libomap-common.o
endif
ifeq ($(SOC),omap4)
LIBS += $(CPUDIR)/omap-common/libomap-common.o
endif
ifeq ($(SOC),s5pc1xx)
LIBS += $(CPUDIR)/s5p-common/libs5p-common.o
endif
ifeq ($(SOC),s5pc2xx)
LIBS += $(CPUDIR)/s5p-common/libs5p-common.o
endif
LIBS := $(addprefix $(obj),$(sort $(LIBS)))
$(LIBS): depend $(SUBDIRS)
$(MAKE) -C $(dir $(subst $(obj),,$@)) #将$(obj)和LIBS联合后取目录编译
其他的目标比较好找。
依此往上,最后生成u-boot.bin
后续希望自己能完成:
Uboot硬件启动 u-boot-2011.06\arch\arm\cpu\arm920t\start.S
Uboot系统各模块初始化
各模块Command交互
Uboot优美代码赏析1.1:分散加载表u-boot.lds
1.位置:
board\samsung\smdk6410\u-boot.lds
2.内容分析:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
//代码段
. = ALIGN(4);
.text :
{
cpu/s3c64xx/start.o (.text)
cpu/s3c64xx/s3c6410/cpu_init.o (.text)
cpu/s3c64xx/onenand_cp.o (.text)
cpu/s3c64xx/nand_cp.o (.text)
cpu/s3c64xx/movi.o (.text)
*(.text)
lib_arm/div0.o
}
// const 常量数据段
. = ALIGN(4);
.rodata : { *(.rodata) }
// staitc/global 常量段
. = ALIGN(4);
.data : { *(.data) }
//这个未使用
. = ALIGN(4);
.got : { *(.got) }
//命令定义段
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
//mmudata段 mmu_table
. = ALIGN(4);
.mmudata : { *(.mmudata) }
//堆栈段/内部临时变量段
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}
下面结合 编译后根目录下生成的u-boot.map和System.map分析:
3 .text 段分析
只分析cpu/s3c64xx/start.o (.text)
u-boot.map中:
Name Origin Length Attributes
cpu/s3c64xx/start.o(.text)
.text 0xc7e00000 0x480 cpu/s3c64xx/start.o
0xc7e00040 _end_vect
0xc7e0017c theLastJump
0xc7e00460 arm1136_cache_flush
0xc7e0004c _bss_start
0xc7e00050 _bss_end
0xc7e00048 _armboot_start
0xc7e00120 copy_from_nand
0xc7e00000 _start
cpu/s3c64xx/s3c6410/cpu_init.o(.text)
.text 0xc7e00480 0x15c cpu/s3c64xx/s3c6410/cpu_init.o
0xc7e005b0 cleanFlushCache
0xc7e005a4 cleanFlushDCache
0xc7e00480 mem_ctrl_asm_init
0xc7e00598 cleanDCache
cpu/s3c64xx/onenand_cp.o(.text)
.text 0xc7e005dc 0x0 cpu/s3c64xx/onenand_cp.o
其中cpu_init.o的起始地址0xc7e00480 - start.o的起始地址0xc7e00000 = start.o的长度0x480
start.o的起始地址定义在board\samsung\smdk6410\config.mk的TEXT_BASE
System.map中:
c7e00000 T _start
c7e00020 t _undefined_instruction
c7e00024 t _software_interrupt
c7e00028 t _prefetch_abort
c7e0002c t _data_abort
c7e00030 t _not_used
c7e00034 t _irq
c7e00038 t _fiq
c7e0003c t _pad
c7e00040 T _end_vect
c7e00040 t _TEXT_BASE
c7e00044 t _TEXT_PHY_BASE
c7e00048 T _armboot_start
c7e0004c T _bss_start
c7e00050 T _bss_end
c7e00054 t reset
c7e00064 t cpu_init_crit
c7e000b8 t after_copy
c7e000b8 t enable_mmu
c7e000d8 t mmu_on
c7e000f4 t skip_hw_init
c7e000f4 t stack_setup
c7e000f8 t clear_bss
c7e00104 t clbss_l
c7e00118 t _start_armboot
c7e0011c t _mmu_table_base
c7e00120 T copy_from_nand
c7e0016c t copy_failed
c7e00174 t compare_failed
c7e0017c T theLastJump
c7e00198 t phy_last_jump
c7e001c0 t undefined_instruction
c7e00220 t software_interrupt
c7e00280 t prefetch_abort
c7e002e0 t data_abort
c7e00340 t not_used
c7e003a0 t irq
c7e00400 t fiq
c7e00460 T arm1136_cache_flush
c7e00480 T mem_ctrl_asm_init
T代表是public的,t代表是local/static的
4.其他段的定义和生成逻辑同理通过u-boot.map去查
.text 段存放代码.o (.text)的起始地址,长度,与未声明为static的函数符号地址(同上)
.rodata 段存放声明为const的变量及其他预先声明在等号右边的字串数据(.rodata.str1.1 )
.rodata 0xc7e238a4 0x33 lib_arm/libarm.a(board.o)
0xc7e238a4 version_string
.rodata.str1.1
0xc7e245c8 0x78 lib_arm/libarm.a(board.o)
0x7a (size before relaxing)
.data 数据存放那些全局定义的变量
.data 0xc7e2a5a4 0x34 lib_arm/libarm.a(board.o)
0xc7e2a5a4 init_sequence
.bss 需要进堆或进栈去申请的数据
.bss 0xc7e3400c 0x10 lib_arm/libarm.a(board.o)
0xc7e34018 monitor_flash_len
.bss 0xc7e3401c 0x25cc net/libnet.a(net.o)
0xc7e34078 NetArpWaitTry
0xc7e34054 NetArpWaitPacketMAC
0xc7e3402c NetOurEther
0xc7e34028 NetOurIP
0xc7e34034 NetPingIP
0xc7e34060 NetServerIP
0xc7e3405c NetArpWaitTxPacketSize
0xc7e34048 NetArpWaitReplyIP
0xc7e34058 NetArpWaitTxPacket
0xc7e35eac NetRxPackets
0xc7e364e4 NetOurNISDomain
0xc7e3403c NetArpWaitPacketIP
0xc7e3401c NetState
0xc7e36566 BootFile
0xc7e34064 NetServerEther
0xc7e34040 NetOurSubnetMask
0xc7e36564 NetBootFileSize
0xc7e34024 NetIPID
0xc7e36504 NetOurHostName
0xc7e3404c NetRxPkt
0xc7e34044 NetOurGatewayIP
0xc7e34070 NetEtherNullAddr
0xc7e35ebc NetArpWaitPacketBuf
0xc7e34050 NetRxPktLen
0xc7e34038 NetTxPacket
0xc7e364dc NetBootFileXferSize
0xc7e364e0 NetOurDNSIP
0xc7e3408c PktBuf
0xc7e36524 NetOurRootPath
0xc7e3407c NetArpWaitTimerStart
5。下面重点说说.u_boot_cmd段:
先看u-boot.map中生成:
0xc7e2c980 __u_boot_cmd_start = .
.u_boot_cmd 0xc7e2c980 0x480
*(.u_boot_cmd)
.u_boot_cmd 0xc7e2c980 0x18 common/libcommon.a(cmd_bdinfo.o)
0xc7e2c980 __u_boot_cmd_bdinfo
.u_boot_cmd 0xc7e2c998 0x30 common/libcommon.a(cmd_boot.o)
0xc7e2c9b0 __u_boot_cmd_reset
0xc7e2c998 __u_boot_cmd_go
.u_boot_cmd 0xc7e2c9c8 0x30 common/libcommon.a(cmd_bootm.o)
0xc7e2c9c8 __u_boot_cmd_bootm
0xc7e2c9e0 __u_boot_cmd_imls
.u_boot_cmd 0xc7e2c9f8 0x48 common/libcommon.a(cmd_cache.o)
0xc7e2ca10 __u_boot_cmd_dcache
0xc7e2ca28 __u_boot_cmd_branch
0xc7e2c9f8 __u_boot_cmd_icache
.u_boot_cmd 0xc7e2ca40 0x18 common/libcommon.a(cmd_date.o)
0xc7e2ca40 __u_boot_cmd_date
.u_boot_cmd 0xc7e2ca58 0x30 common/libcommon.a(cmd_elf.o)
0xc7e2ca70 __u_boot_cmd_bootvx
0xc7e2ca58 __u_boot_cmd_bootelf
.u_boot_cmd 0xc7e2ca88 0x48 common/libcommon.a(cmd_flash.o)
0xc7e2ca88 __u_boot_cmd_flinfo
0xc7e2caa0 __u_boot_cmd_erase
0xc7e2cab8 __u_boot_cmd_protect
.u_boot_cmd 0xc7e2cad0 0x18 common/libcommon.a(cmd_itest.o)
0xc7e2cad0 __u_boot_cmd_itest
.u_boot_cmd 0xc7e2cae8 0x48 common/libcommon.a(cmd_load.o)
0xc7e2cb18 __u_boot_cmd_loady
0xc7e2cb00 __u_boot_cmd_loadb
0xc7e2cae8 __u_boot_cmd_loads
.u_boot_cmd 0xc7e2cb30 0xf0 common/libcommon.a(cmd_mem.o)
0xc7e2cb30 __u_boot_cmd_md
0xc7e2cba8 __u_boot_cmd_cmp
0xc7e2cb78 __u_boot_cmd_mw
0xc7e2cbf0 __u_boot_cmd_loop
0xc7e2cbd8 __u_boot_cmd_base
0xc7e2cb48 __u_boot_cmd_mm
0xc7e2cbc0 __u_boot_cmd_crc32
0xc7e2cb60 __u_boot_cmd_nm
0xc7e2cc08 __u_boot_cmd_mtest
0xc7e2cb90 __u_boot_cmd_cp
.u_boot_cmd 0xc7e2cc20 0x18 common/libcommon.a(cmd_misc.o)
0xc7e2cc20 __u_boot_cmd_sleep
.u_boot_cmd 0xc7e2cc38 0x30 common/libcommon.a(cmd_nand.o)
0xc7e2cc38 __u_boot_cmd_nand
0xc7e2cc50 __u_boot_cmd_nboot
.u_boot_cmd 0xc7e2cc68 0x78 common/libcommon.a(cmd_net.o)
0xc7e2ccb0 __u_boot_cmd_nfs
0xc7e2ccc8 __u_boot_cmd_ping
0xc7e2cc98 __u_boot_cmd_rarpboot
0xc7e2cc80 __u_boot_cmd_tftpboot
0xc7e2cc68 __u_boot_cmd_bootp
.u_boot_cmd 0xc7e2cce0 0x48 common/libcommon.a(cmd_nvedit.o)
0xc7e2cd10 __u_boot_cmd_saveenv
0xc7e2cce0 __u_boot_cmd_printenv
0xc7e2ccf8 __u_boot_cmd_setenv
.u_boot_cmd 0xc7e2cd28 0x30 common/libcommon.a(cmd_usb.o)
0xc7e2cd28 __u_boot_cmd_usb
0xc7e2cd40 __u_boot_cmd_usbboot
.u_boot_cmd 0xc7e2cd58 0x90 common/libcommon.a(command.o)
0xc7e2cda0 __u_boot_cmd_exit
0xc7e2cd70 __u_boot_cmd_echo
0xc7e2cdd0 __u_boot_cmd_question_mark
0xc7e2cd58 __u_boot_cmd_version
0xc7e2cdb8 __u_boot_cmd_help
0xc7e2cd88 __u_boot_cmd_test
.u_boot_cmd 0xc7e2cde8 0x18 common/libcommon.a(cmd_usbd.o)
0xc7e2cde8 __u_boot_cmd_dnw
0xc7e2ce00 __u_boot_cmd_end = .
0xc7e2ce00 . = ALIGN (0x4)
在include/command.h中,
#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
#ifdef CFG_LONGHELP
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
#else /* no long help info */
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage}
#endif /* CFG_LONGHELP */
所以我们新增指令后直接用U_BOOT_CMD声明,即可将数据放入.u_boot_cmd段,搜索段开始标志符__u_boot_cmd_start和段结束标志符__u_boot_cmd_end,得到此段数据的检测位于:command.c中的find_cmd,执行的入口位于:common/main.c中的run_command函数,此函数的调用位于uboot主循环main_loop的for (;;){……} 代码段内。
作者:Anpher Zhang QQ:275000205 转载请注明出处:http://www.cnblogs.com/zhangsufeng/