uboot自定认命令学习笔记

================================================================================================
uboot的命令实现
================================================================================================
按照步骤烧写uboot到开发板
测试命令
#显示环境变量
MINI6410 # print
bootargs=root=/dev/mtdblock2 rootfstype=yaffs2 init=/linuxrc console=ttySAC0,115200 androidboot.console=s3c2410_serial0
bootcmd=nand read.i c0008000 80000 500000;bootm c0008000
bootdelay=1
baudrate=115200
ethaddr=08:90:90:90:90:90
ipaddr=192.168.1.230
serverip=192.168.1.88
gatewayip=192.168.1.1
netmask=255.255.255.0
stdin=serial
stdout=serial
stderr=serial
#打印内个存地址的内容
MINI6410 # md.w 0
00000000: 002b ea00 0006 ea00 000b ea00 0010 ea00 +...............
00000010: 0015 ea00 fffe eaff 0019 ea00 001e ea00 ................
00000020: fffe eaff d004 e24d 0001 e92d 02ac e59f ......M...-.....
00000030: 0000 e590 0004 e58d 8001 e8bd d004 e24d ..............M.
00000040: 0001 e92d 0298 e59f 0000 e590 0004 e58d ..-.............
00000050: 8001 e8bd d004 e24d 0001 e92d 0284 e59f ......M...-.....
00000060: 0000 e590 0004 e58d 8001 e8bd d004 e24d ..............M.
00000070: 0001 e92d 0270 e59f 0000 e590 0004 e58d ..-.p...........

命令的执行步骤
1 命令行输入命令字符
2 将命令转化为函数

查看命令的结构体
以下是common/main.c的部分代码:

int run_command (const char *cmd, int flag)
{
cmd_tbl_t *cmdtp;
char cmdbuf[CONFIG_SYS_CBSIZE];/* working copy of cmd*/
char *token;/* start of token in cmdbuf*/
char *sep;/* end of token (separator) in cmdbuf */
char finaltoken[CONFIG_SYS_CBSIZE];
char *str = cmdbuf;
char *argv[CONFIG_SYS_MAXARGS + 1];/* NULL terminated*/
int argc, inquotes;
int repeatable = 1;
int rc = 0;

#ifdef DEBUG_PARSER
printf ("[RUN_COMMAND] cmd[%p]=\"", cmd);
puts (cmd ? cmd : "NULL");/* use puts - string may be loooong */
puts ("\"\n");
#endif

clear_ctrlc();/* forget any previous Control C */

if (!cmd || !*cmd) {
return -1;/* empty command */
}

if (strlen(cmd) >= CONFIG_SYS_CBSIZE) {
puts ("## Command too long!\n");
return -1;
}

strcpy (cmdbuf, cmd);

/* Process separators and check for invalid
* repeatable commands
*/

#ifdef DEBUG_PARSER
printf ("[PROCESS_SEPARATORS] %s\n", cmd);
#endif
while (*str) {

/*
* Find separator, or string end
* Allow simple escape of ';' by writing "\;"
*/
for (inquotes = 0, sep = str; *sep; sep++) {
if ((*sep=='\'') &&
(*(sep-1) != '\\'))
inquotes=!inquotes;

/*多个命令的情况,分号隔开*/
if (!inquotes &&
(*sep == ';') &&/* separator*/
( sep != str) &&/* past string start*/
(*(sep-1) != '\\'))/* and NOT escaped*/
break;
}

/*
* Limit the token to data between separators
*/
token = str;
if (*sep) {
str = sep + 1;/* start of command for next pass */
*sep = '\0';
}
else
str = sep;/* no more commands for next pass */
#ifdef DEBUG_PARSER
printf ("token: \"%s\"\n", token);
#endif

/* find macros in this token and replace them */
process_macros (token, finaltoken);

/*解析命令数组*/
/* Extract arguments */
if ((argc = parse_line (finaltoken, argv)) == 0) {
rc = -1;/* no command at all */
continue;
}

/*从命令表中查找命令*/
/* Look up command in command table */
/*cmdtp就为命令的结构体cmd_tbl_s*/
if ((cmdtp = find_cmd(argv[0])) == NULL) {
printf ("Unknown command '%s' - try 'help'\n", argv[0]);
rc = -1;/* give up after bad command */
continue;
}

/* found - check max args */
if (argc > cmdtp->maxargs) {
cmd_usage(cmdtp);
rc = -1;
continue;
}

#if defined(CONFIG_CMD_BOOTD)
/* avoid "bootd" recursion */
if (cmdtp->cmd == do_bootd) {
#ifdef DEBUG_PARSER
printf ("[%s]\n", finaltoken);
#endif
if (flag & CMD_FLAG_BOOTD) {
puts ("'bootd' recursion detected\n");
rc = -1;
continue;
} else {
flag |= CMD_FLAG_BOOTD;
}
}
#endif

/* OK - call function to do the command */
if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
rc = -1;
}

repeatable &= cmdtp->repeatable;

/* Did the user stop this? */
if (had_ctrlc ())
return -1;/* if stopped then not repeatable */
}

return rc ? rc : repeatable;
}

以下为include/Commond.h头文件部分内容
/*命令的结构体*/
/*
* Monitor Command Table
*/

struct cmd_tbl_s {
char*name;/* Command Name命令名*/
intmaxargs;/* maximum number of arguments最大参数*/
intrepeatable;/* autorepeat allowed?是否重复,命令行直接输入回车,命令会再次执行*/
/* Implementation function*/
int(*cmd)(struct cmd_tbl_s *, int, int, char * const []);
char*usage;/* Usage message(short)短的帮助信息*/
#ifdefCONFIG_SYS_LONGHELP
char*help;/* Help message(long)长的帮助信息*/
#endif
#ifdef CONFIG_AUTO_COMPLETE
/* do auto completion on the arguments */
int(*complete)(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);
#endif
};


以下是/common/command.c的部分内容
/*查找命令*/
cmd_tbl_t *find_cmd (const char *cmd)
{
/*以下两个值是从链接角本中传入*/
int len = &__u_boot_cmd_end - &__u_boot_cmd_start;
return find_cmd_tbl(cmd, &__u_boot_cmd_start, len);
}

/* 查找命令
* find command table entry for a command
*/
cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len)
{
cmd_tbl_t *cmdtp;
cmd_tbl_t *cmdtp_temp = table;/*Init value */
const char *p;
int len;
int n_found = 0;

if (!cmd)
return NULL;
/*
* Some commands allow length modifiers (like "cp.b");
* compare command name only until first dot.
*/
len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);
/*遍历命令表*/
for (cmdtp = table;
cmdtp != table + table_len;
cmdtp++) {
/*首先匹配命令名称*/
if (strncmp (cmd, cmdtp->name, len) == 0) {
if (len == strlen (cmdtp->name))
return cmdtp;/* full match */

cmdtp_temp = cmdtp;/* abbreviated command ? */
n_found++;
}
}
if (n_found == 1) {/* exactly one match */
return cmdtp_temp;
}

return NULL;/* not found or ambiguous command */
}


以下是/arch/arm/cpu/arm1176/U-boot.lds中全部内容
/*
* (C) Copyright 2002-2004
* Gary Jennejohn, DENX Software Engineering,
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

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

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

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

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

#以下便是查找命令中用到的两个值
. = .;
__u_boot_cmd_start = .;
#查看u_boot_cmd中存放内容
#在include/Command.h中定义如下
##define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
#命令行输入print 得到bootcmd=nand read.i c0008000 80000 500000;bootm c0008000 启动命令
#bootm c0008000 启动命令
#在common\Cmd_bootm.c下找到该命令
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;

. = ALIGN(4);

.rel.dyn : {
__rel_dyn_start = .;
*(.rel*)
__rel_dyn_end = .;
}

.dynsym : {
__dynsym_start = .;
*(.dynsym)
}

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

/DISCARD/ : { *(.dynstr*) }
/DISCARD/ : { *(.dynamic*) }
/DISCARD/ : { *(.plt*) }
/DISCARD/ : { *(.interp*) }
/DISCARD/ : { *(.gnu*) }
}


以下是common\Cmd_bootm.c部分代码
U_BOOT_CMD(
bootm,CONFIG_SYS_MAXARGS,1,do_bootm,
"boot application image from memory",
"[addr [arg ...]]\n - boot application image stored in memory\n"
"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
"\t'arg' can be the address of an initrd image\n"
#if defined(CONFIG_OF_LIBFDT)
"\tWhen booting a Linux kernel which requires a flat device-tree\n"
"\ta third argument is required which is the address of the\n"
"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
"\tuse a '-' for the second argument. If you do not pass a third\n"
"\ta bd_info struct will be passed instead\n"
#endif
#if defined(CONFIG_FIT)
"\t\nFor the new multi component uImage format (FIT) addresses\n"
"\tmust be extened to include component or configuration unit name:\n"
"\taddr: - direct component image specification\n"
"\taddr# - configuration specification\n"
"\tUse iminfo command to get the list of existing component\n"
"\timages and configurations.\n"
#endif
"\nSub-commands to do part of the bootm sequence. The sub-commands "
"must be\n"
"issued in the order below (it's ok to not issue all sub-commands):\n"
"\tstart [addr [arg ...]]\n"
"\tloados - load OS image\n"
#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC)
"\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
#endif
#if defined(CONFIG_OF_LIBFDT)
"\tfdt - relocate flat device tree\n"
#endif
"\tcmdline - OS specific command line processing/setup\n"
"\tbdt - OS specific bd_t processing\n"
"\tprep - OS specific prep before relocation or go\n"
"\tgo - start OS"
);

以下是include/Command.h中部分代码
/*U_BOOT_CMD在此定义*/
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tb1_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage}

/*将以上宏定义展开*/
cmd_tbl_t __u_boot_cmd_bootm Struct_Section __attribute__ ((unused,section (".u_boot_cmd"))) =
{bootm, CONFIG_SYS_MAXARGS, 1,do_bootm, "boot application image from memory"}


自定义命令
1 [root@localhost common]# cd /mnt/sda3/FriendlyARM/mini6410/android/u-boot-mini6410/common
2 新建 vi cmd_hello.c
3 找个同类型文件,如/common/Cmd_bootm.c
复制其头文件
示例代码如下:

/*custom command hello*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int do_hello(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int i;
printf("hello world!,%d\n",argc);
/*print the argv params*/
for(i=0;i printf("argv[%d]: %s\n",argv[i]);
}
return 0;
}

U_BOOT_CMD(
hello, CFG_MAXARGS, 1, do_hello,
"hello - just for test! the short!\n",
"hello - just for test! the long!\n"
);
4 修改common下的Makefile文件
示例代码如下:
#
# (C) Copyright 2004-2006
# Wolfgang Denk, DENX Software Engineering, [email protected].
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#

include $(TOPDIR)/config.mk

LIB= $(obj)libcommon.a

AOBJS=

COBJS= main.o ACEX1K.o altera.o bedbug.o circbuf.o \
cmd_ace.o cmd_autoscript.o \
cmd_bdinfo.o cmd_bedbug.o cmd_bmp.o cmd_boot.o cmd_bootm.o \
cmd_cache.o cmd_console.o \
cmd_date.o cmd_dcr.o cmd_diag.o cmd_display.o cmd_doc.o cmd_dtt.o \
cmd_eeprom.o cmd_elf.o cmd_ext2.o \
cmd_fat.o cmd_fdc.o cmd_fdos.o cmd_flash.o cmd_fpga.o \
cmd_i2c.o cmd_ide.o cmd_immap.o cmd_itest.o cmd_jffs2.o \
cmd_load.o cmd_log.o \
cmd_mem.o cmd_mii.o cmd_misc.o cmd_mmc.o \
cmd_nand.o cmd_net.o cmd_nvedit.o \
cmd_pci.o cmd_pcmcia.o cmd_portio.o \
cmd_reginfo.o cmd_reiser.o cmd_scsi.o cmd_spi.o cmd_universe.o \
cmd_usb.o cmd_vfd.o \
command.o console.o cyclon2.o devices.o dlmalloc.o docecc.o \
environment.o env_common.o \
env_nand.o env_dataflash.o env_flash.o env_eeprom.o \
env_nvram.o env_nowhere.o env_movi.o env_onenand.o \
exports.o \
flash.o fpga.o ft_build.o \
hush.o kgdb.o lcd.o lists.o lynxkdi.o \
memsize.o miiphybb.o miiphyutil.o \
s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \
usb.o usb_kbd.o usb_storage.o \
virtex2.o xilinx.o crc16.o xyzModem.o cmd_mac.o cmd_onenand.o \
cmd_usbd.o cmd_movi.o cmd_hello.o

SRCS:= $(AOBJS:.o=.S) $(COBJS:.o=.c)
OBJS:= $(addprefix $(obj),$(AOBJS) $(COBJS))

CPPFLAGS += -I..

all:$(LIB) $(AOBJS)

$(LIB): $(obj).depend $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)

$(obj)environment.o: $(src)environment.c $(obj)../tools/envcrc
$(CC) $(AFLAGS) -Wa,--no-warn \
-DENV_CRC=$(shell $(obj)../tools/envcrc) \
-c -o $@ $(src)environment.c

$(obj)../tools/envcrc:
$(MAKE) -C ../tools

#########################################################################

# defines $(obj).depend target
include $(SRCTREE)/rules.mk

sinclude $(obj).depend

#########################################################################

5 清除
[root@localhost u-boot-mini6410]# make distclean
6 配置重新编译
mini6410_nand_config-ram256
注:以上为正常方法,?(mini6410给的uboot中命令全部定义在command.c中,是不是需在此文件中添加自定义命令)

===============================================================================
uboot启动内核
===============================================================================
命令行中输入print 得到信息bootcmd=nand read.i c0008000 80000 500000;bootm c0008000

mini6410.h中定义的部分代码:

#ifdef CONFIG_ENABLE_MMU
#define CONFIG_SYS_MAPPED_RAM_BASE0xc0000000
#define CONFIG_BOOTCOMMAND"nand read 0xc0018000 0x60000 0x1c0000;" \
"bootm 0xc0018000"
#else
#define CONFIG_SYS_MAPPED_RAM_BASECONFIG_SYS_SDRAM_BASE
#define CONFIG_BOOTCOMMAND"nand read 0x50018000 0x60000 0x1c0000;" \
"bootm 0x50018000"



1 从NAND读出内核:bootcmd=nand read.i c0008000 80000 500000
flash上存的内核:uImage
头部+真正的内核

头部的结构体:在/include/Image.h中
示例代码如下:
/*
* Legacy format image header,
* all data in network byte order (aka natural aka bigendian).
*/
typedef struct image_header {
uint32_tih_magic;/* Image Header Magic Number*/
uint32_tih_hcrc;/* Image Header CRC Checksum*/
uint32_tih_time;/* Image Creation Timestamp*/
uint32_tih_size;/* Image Data Size*/
uint32_tih_load;/* Data Load Address加载地址*/
uint32_tih_ep;/* Entry Point Address入口地址*/
uint32_tih_dcrc;/* Image Data CRC Checksum*/
uint8_tih_os;/* Operating System*/
uint8_tih_arch;/* CPU architecture*/
uint8_tih_type;/* Image Type*/
uint8_tih_comp;/* Compression Type*/
uint8_tih_name[IH_NMLEN];/* Image Name*/
} image_header_t;
2 启动内核: bootm c0008000
(1)bootm根据头部,将内核移动到合适的地方
(2)启动
bootm的部分代码在/common/cmd_bootm.c文件中
部分代码如下:
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulongiflag;
ulongaddr;
ulongdata, len, checksum;
ulong *len_ptr = NULL; /* not to make warning. by scsuh */
uintunc_len = CFG_BOOTM_LEN;
inti, verify;
char*name, *s;
int(*appl)(int, char *[]);
image_header_t *hdr = &header;

s = getenv ("verify");
verify = (s && (*s == 'n')) ? 0 : 1;

if (argc < 2) {
addr = load_addr;
} else {
addr = simple_strtoul(argv[1], NULL, 16);
}

#ifdef CONFIG_ZIMAGE_BOOT
#define LINUX_ZIMAGE_MAGIC0x016f2818
if (*(ulong *)(addr + 9*4) == LINUX_ZIMAGE_MAGIC) {//如果加载地址等于内核地址直接启动
printf("Boot with zImage\n");
addr = virt_to_phys(addr);
hdr->ih_os = IH_OS_LINUX;
hdr->ih_ep = ntohl(addr);
goto after_header_check;
}
#endif

SHOW_BOOT_PROGRESS (1);
printf ("## Booting image at %08lx ...\n", addr);

/* Copy header so we can blank CRC field for re-calculation */
#ifdef CONFIG_HAS_DATAFLASH
if (addr_dataflash(addr)){
read_dataflash(addr, sizeof(image_header_t), (char *)&header);
} else
#endif
memmove (&header, (char *)addr, sizeof(image_header_t));//否则将内核移动到合适的位置(addr 加载地址)

if (ntohl(hdr->ih_magic) != IH_MAGIC) {
#ifdef __I386__/* correct image format not implemented yet - fake it */
if (fake_header(hdr, (void*)addr, -1) != NULL) {
/* to compensate for the addition below */
addr -= sizeof(image_header_t);
/* turnof verify,
* fake_header() does not fake the data crc
*/
verify = 0;
} else
#endif/* __I386__ */
{
#ifdef CONFIG_IMAGE_BOOT
printf("Boot with Image\n");
addr = virt_to_phys(addr);
hdr->ih_os = IH_OS_LINUX;
hdr->ih_ep = ntohl(addr);
hdr->ih_comp = IH_COMP_NONE;
goto after_header_check;
#endif
puts ("Bad Magic Number\n");
SHOW_BOOT_PROGRESS (-1);
return 1;
}
}
SHOW_BOOT_PROGRESS (2);

data = (ulong)&header;
len = sizeof(image_header_t);

checksum = ntohl(hdr->ih_hcrc);
hdr->ih_hcrc = 0;

if (crc32 (0, (uchar *)data, len) != checksum) {
puts ("Bad Header Checksum\n");
SHOW_BOOT_PROGRESS (-2);
return 1;
}
SHOW_BOOT_PROGRESS (3);

#ifdef CONFIG_HAS_DATAFLASH
if (addr_dataflash(addr)){
len = ntohl(hdr->ih_size) + sizeof(image_header_t);
read_dataflash(addr, len, (char *)CFG_LOAD_ADDR);
addr = CFG_LOAD_ADDR;
}
#endif


/* for multi-file images we need the data part, too */
print_image_hdr ((image_header_t *)addr);

data = addr + sizeof(image_header_t);
len = ntohl(hdr->ih_size);

if (verify) {
puts (" Verifying Checksum ... ");
if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) {
printf ("Bad Data CRC\n");
SHOW_BOOT_PROGRESS (-3);
return 1;
}
puts ("OK\n");
}
SHOW_BOOT_PROGRESS (4);

len_ptr = (ulong *)data;

#if defined(__PPC__)
if (hdr->ih_arch != IH_CPU_PPC)
#elif defined(__ARM__)
if (hdr->ih_arch != IH_CPU_ARM)
#elif defined(__I386__)
if (hdr->ih_arch != IH_CPU_I386)
#elif defined(__mips__)
if (hdr->ih_arch != IH_CPU_MIPS)
#elif defined(__nios__)
if (hdr->ih_arch != IH_CPU_NIOS)
#elif defined(__M68K__)
if (hdr->ih_arch != IH_CPU_M68K)
#elif defined(__microblaze__)
if (hdr->ih_arch != IH_CPU_MICROBLAZE)
#elif defined(__nios2__)
if (hdr->ih_arch != IH_CPU_NIOS2)
#elif defined(__blackfin__)
if (hdr->ih_arch != IH_CPU_BLACKFIN)
#elif defined(__avr32__)
if (hdr->ih_arch != IH_CPU_AVR32)
#else
# error Unknown CPU type
#endif
{
printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch);
SHOW_BOOT_PROGRESS (-4);
return 1;
}
SHOW_BOOT_PROGRESS (5);

switch (hdr->ih_type) {
case IH_TYPE_STANDALONE:
name = "Standalone Application";
/* A second argument overwrites the load address */
if (argc > 2) {
hdr->ih_load = htonl(simple_strtoul(argv[2], NULL, 16));
}
break;
case IH_TYPE_KERNEL:
name = "Kernel Image";
break;
case IH_TYPE_MULTI:
name = "Multi-File Image";
len = ntohl(len_ptr[0]);
/* OS kernel is always the first image */
data += 8; /* kernel_len + terminator */
for (i=1; len_ptr[i]; ++i)
data += 4;
break;
default: printf ("Wrong Image Type for %s command\n", cmdtp->name);
SHOW_BOOT_PROGRESS (-5);
return 1;
}
SHOW_BOOT_PROGRESS (6);

/*
* We have reached the point of no return: we are going to
* overwrite all exception vector code, so we cannot easily
* recover from any failures any more...
*/

iflag = disable_interrupts();

#ifdef CONFIG_AMIGAONEG3SE
/*
* We've possible left the caches enabled during
* bios emulation, so turn them off again
*/
icache_disable();
invalidate_l1_instruction_cache();
flush_data_cache();
dcache_disable();
#endif

switch (hdr->ih_comp) {
case IH_COMP_NONE:
if(ntohl(hdr->ih_load) == addr) {
printf (" XIP %s ... ", name);
} else {
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
size_t l = len;
void *to = (void *)ntohl(hdr->ih_load);
void *from = (void *)data;

printf (" Loading %s ... ", name);

while (l > 0) {
size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
WATCHDOG_RESET();
memmove (to, from, tail);
to += tail;
from += tail;
l -= tail;
}
#else/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
#endif/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
}
break;
case IH_COMP_GZIP:
printf (" Uncompressing %s ... ", name);
if (gunzip ((void *)ntohl(hdr->ih_load), unc_len,
(uchar *)data, &len) != 0) {
puts ("GUNZIP ERROR - must RESET board to recover\n");
SHOW_BOOT_PROGRESS (-6);
do_reset (cmdtp, flag, argc, argv);
}
break;
#ifdef CONFIG_BZIP2
case IH_COMP_BZIP2:
printf (" Uncompressing %s ... ", name);
/*
* If we've got less than 4 MB of malloc() space,
* use slower decompression algorithm which requires
* at most 2300 KB of memory.
*/
i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load),
&unc_len, (char *)data, len,
CFG_MALLOC_LEN < (4096 * 1024), 0);
if (i != BZ_OK) {
printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i);
SHOW_BOOT_PROGRESS (-6);
udelay(100000);
do_reset (cmdtp, flag, argc, argv);
}
break;
#endif /* CONFIG_BZIP2 */
default:
if (iflag)
enable_interrupts();
printf ("Unimplemented compression type %d\n", hdr->ih_comp);
SHOW_BOOT_PROGRESS (-7);
return 1;
}
puts ("OK\n");
SHOW_BOOT_PROGRESS (7);

switch (hdr->ih_type) {
case IH_TYPE_STANDALONE:
if (iflag)
enable_interrupts();

/* load (and uncompress), but don't start if "autostart"
* is set to "no"
*/
if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0)) {
char buf[32];
sprintf(buf, "%lX", len);
setenv("filesize", buf);
return 0;
}
appl = (int (*)(int, char *[]))ntohl(hdr->ih_ep);
(*appl)(argc-1, &argv[1]);
return 0;
case IH_TYPE_KERNEL:
case IH_TYPE_MULTI:
/* handled below */
break;
default:
if (iflag)
enable_interrupts();
printf ("Can't boot image type %d\n", hdr->ih_type);
SHOW_BOOT_PROGRESS (-8);
return 1;
}
SHOW_BOOT_PROGRESS (8);

#if defined(CONFIG_ZIMAGE_BOOT) || defined(CONFIG_IMAGE_BOOT)
after_header_check:
#endif
switch (hdr->ih_os) {
default:/* handled by (original) Linux case */
case IH_OS_LINUX://启动linux内核
#ifdef CONFIG_SILENT_CONSOLE
fixup_silent_linux();
#endif
do_bootm_linux (cmdtp, flag, argc, argv,
addr, len_ptr, verify); //启动内核的方法: 1 设置启动参数 2 跳到入口地址启动内核
break;
case IH_OS_NETBSD:
do_bootm_netbsd (cmdtp, flag, argc, argv,
addr, len_ptr, verify);
break;

#ifdef CONFIG_LYNXKDI
case IH_OS_LYNXOS:
do_bootm_lynxkdi (cmdtp, flag, argc, argv,
addr, len_ptr, verify);
break;
#endif

case IH_OS_RTEMS:
do_bootm_rtems (cmdtp, flag, argc, argv,
addr, len_ptr, verify);
break;

#if (CONFIG_COMMANDS & CFG_CMD_ELF)
case IH_OS_VXWORKS:
do_bootm_vxworks (cmdtp, flag, argc, argv,
addr, len_ptr, verify);
break;
case IH_OS_QNX:
do_bootm_qnxelf (cmdtp, flag, argc, argv,
addr, len_ptr, verify);
break;
#endif /* CFG_CMD_ELF */
#ifdef CONFIG_ARTOS
case IH_OS_ARTOS:
do_bootm_artos (cmdtp, flag, argc, argv,
addr, len_ptr, verify);
break;
#endif
}

SHOW_BOOT_PROGRESS (-9);
#ifdef DEBUG
puts ("\n## Control returned to monitor - resetting...\n");
do_reset (cmdtp, flag, argc, argv);
#endif
return 1;
}

do_bootm_linux定义在arch/arm/lib/Bootm.c中
部分代码如下:
int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
{
bd_t*bd = gd->bd;
char*s;
intmachid = bd->bi_arch_number;
void(*kernel_entry)(int zero, int arch, uint params);

#ifdef CONFIG_CMDLINE_TAG
char *commandline = getenv ("bootargs");
#endif

if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
return 1;

s = getenv ("machid");
if (s) {
machid = simple_strtoul (s, NULL, 16);
printf ("Using machid 0x%x from environment\n", machid);
}

show_boot_progress (15);

#ifdef CONFIG_OF_LIBFDT
if (images->ft_len)
return bootm_linux_fdt(machid, images);
#endif
/*函数指针指向入口地址*/
kernel_entry = (void (*)(int, int, uint))images->ep;

debug ("## Transferring control to Linux (at address %08lx) ...\n",
(ulong) kernel_entry);
/*1 设置启动参数*/
/*将参数按照指定格式(tag)保存到指定地址(bi_boot_params = PHYS_SDRAM_1 + 0x100;)*/
#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
defined (CONFIG_CMDLINE_TAG) || \
defined (CONFIG_INITRD_TAG) || \
defined (CONFIG_SERIAL_TAG) || \
defined (CONFIG_REVISION_TAG)
setup_start_tag (bd);
#ifdef CONFIG_SERIAL_TAG
setup_serial_tag (¶ms);
#endif
#ifdef CONFIG_REVISION_TAG
setup_revision_tag (¶ms);
#endif
#ifdef CONFIG_SETUP_MEMORY_TAGS
setup_memory_tags (bd);
#endif
#ifdef CONFIG_CMDLINE_TAG
setup_commandline_tag (bd, commandline);
#endif
#ifdef CONFIG_INITRD_TAG
if (images->rd_start && images->rd_end)
setup_initrd_tag (bd, images->rd_start, images->rd_end);
#endif
setup_end_tag(bd);
#endif

announce_and_cleanup();
/*2 启动内核*/
/*machid 机器id*/
/*定义在mini6410.h中#define MACH_TYPE2520*/
/*bi_boot_params 启动参数*/
kernel_entry(0, machid, bd->bi_boot_params);
/* does not return */

return 1;
}

启动参数的设置:
1 setup_start_tag (bd);
位于bootm.c中,部分代码如下:
static void setup_start_tag (bd_t *bd){
/*bi_boot_params定义在board/samsung/mini6410/mini6410.c中*/
/*gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;*/
/*PHYS_SDRAM_1定义在include/config/mini6410.h中*/
/*#define PHYS_SDRAM_1CONFIG_SYS_SDRAM_BASE/* SDRAM Bank #1*/*/
/*首先存放的是一个tag*/
params = (struct tag *) bd->bi_boot_params;
/*teg_header的tag值为 0x54410001*/
params->hdr.tag = ATAG_CORE;
/*
* struct tag_core {
*u32 flags;/* bit 0 = read-only */
*u32 pagesize;
*u32 rootdev;
*};
*/
params->hdr.size = tag_size (tag_core);

params->u.core.flags = 0;
params->u.core.pagesize = 0;
params->u.core.rootdev = 0;

params = tag_next (params);
}
2 setup_revision_tag (¶ms);
同理
3 setup_memory_tags (bd);
也位于bootm.c中,同理:
static void setup_memory_tags (bd_t *bd)
{
int i;

for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
params->hdr.tag = ATAG_MEM;
/*
*struct tag_mem32 {
*u32size;
*u32start;/* physical start address */
*};
*/
params->hdr.size = tag_size (tag_mem32);

/*开始位置和大小定义在board/samsung\mini6410\mini6410.c中*/
/*int dram_init(void)
*{
*DECLARE_GLOBAL_DATA_PTR;
* gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
*gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
* return 0;
*}
*/

params->u.mem.start = bd->bi_dram[i].start;
params->u.mem.size = bd->bi_dram[i].size;

params = tag_next (params);
}
}

如下图

4 setup_commandline_tag (bd, commandline);
同理
bootargs=root=/dev/mtdblock2 rootfstype=yaffs2 init=/linuxrc console=ttySAC0,115200 androidboot.console=s3c2410_serial0
5 setup_initrd_tag (bd, images->rd_start, images->rd_end);
同理
6 setup_end_tag(bd);
同理










-----------
-----------
----------- <----------------params
start
-----------
size 0x10000000
-----------
tag 0x54410002 定义在arch/arm/include/asm中#define ATAG_MEM0x54410002
-----------
size 4
----------- <--------------params
rootdev 0
-----------
pagesize 0 tag_core
-----------
flags 0
-----------
tag 0x54410001 params = (struct tag *) bd->bi_boot_params;
-----------
size 5 #define tag_size(type)((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
-----------











参数存放的格式:
struct tag {
/* 定义在arch/arm/include/asm/setup.h
* struct tag_header {
* u32 size;
* u32 tag;
* };
*/
struct tag_header hdr;
union {
struct tag_corecore;
struct tag_mem32mem;
struct tag_videotextvideotext;
struct tag_ramdiskramdisk;
struct tag_initrdinitrd;
struct tag_serialnrserialnr;
struct tag_revisionrevision;
struct tag_videolfbvideolfb;
struct tag_cmdlinecmdline;

/*
* Acorn specific
*/
struct tag_acornacorn;

/*
* DC21285 specific
*/
struct tag_memclkmemclk;
} u;
};

你可能感兴趣的:(uboot自定认命令学习笔记)