U-Boot(合集)

来源:互联网 发布:java object类 编辑:程序博客网 时间:2024/04/19 16:29

U-Boot的常用命令详解

U-Boot 还提供了更加详细的命令帮助,通过 help 命令还可以查看每个命令的参数说明。由于开发过程的需要,有必要先把 U-Boot 命令的用法弄清楚。接下来,根据每一条命令的帮助信息,
  

U-Boot还提供了更加详细的命令帮助,通过help命令还可以查看每个命令的参数说明。由于开发过程的需要,有必要先把U-Boot命令的用法弄清楚。接下来,根据每一条命令的帮助信息,解释一下这些命令的功能和参数。


1、bootm
bootm [addr [arg ...]]

    - boot application image stored in memory

          passing arguments 'arg ...'; when booting a Linux kernel,

          'arg' can be the address of an initrd image

bootm命令可以引导启动存储在内存中的程序映像。这些内存包括RAM和可以永久保存的Flash。

第1个参数addr是程序映像的地址,这个程序映像必须转换成U-Boot的格式。

第2个参数对于引导Linux内核有用,通常作为U-Boot格式的RAMDISK映像存储地址;也可以是传递给Linux内核的参数(缺省情况下传递bootargs环境变量给内核)。


2、bootp

bootp [loadAddress] [bootfilename]

bootp命令通过bootp请求,要求DHCP服务器分配IP地址,然后通过TFTP协议下载指定的文件到内存。

第1个参数是下载文件存放的内存地址。

第2个参数是要下载的文件名称,这个文件应该在开发主机上准备好。

 

3、cmp

cmp [.b, .w, .l] addr1 addr2 count

     - compare memory

cmp命令可以比较2块内存中的内容。.b以字节为单位;.w以字为单位;.l以长字为单位。注意:cmp.b中间不能保留空格,需要连续敲入命令。

第1个参数addr1是第一块内存的起始地址。

第2个参数addr2是第二块内存的起始地址。

第3个参数count是要比较的数目,单位按照字节、字或者长字。

 

4、cp

cp [.b, .w, .l] source target count

       - copy memory

cp命令可以在内存中复制数据块,包括对Flash的读写操作。

第1个参数source是要复制的数据块起始地址。

第2个参数target是数据块要复制到的地址。这个地址如果在Flash中,那么会直接调用写Flash的函数操作。所以U-Boot写Flash就使用这个命令,当然需要先把对应Flash区域擦干净。

第3个参数count是要复制的数目,根据cp.b cp.w cp.l分别以字节、字、长字为单位。

 

5、crc32

crc32 address count [addr]

     - compute CRC32 checksum [save at addr]  

crc32命令可以计算存储数据的校验和。

第1个参数address是需要校验的数据起始地址。

第2个参数count是要校验的数据字节数。

第3个参数addr用来指定保存结果的地址。

 

6、echo

echo [args..]

      - echo args to console; c suppresses newline

echo命令回显参数。


7、erase

erase start end

      - erase FLASH from addr 'start' to addr 'end'

erase N:SF[-SL]

      - erase sectors SF-SL in FLASH bank # N

erase bank N

      - erase FLASH bank # N

erase all

      - erase all FLASH banks

 

erase命令可以擦Flash。

参数必须指定Flash擦除的范围。

按照起始地址和结束地址,start必须是擦除块的起始地址;end必须是擦除末尾块的结束地址。这种方式最常用。举例说明:擦除0x20000 – 0x3ffff区域命令为erase 20000 3ffff。

按照组和扇区,N表示Flash的组号,SF表示擦除起始扇区号,SL表示擦除结束扇区号。另外,还可以擦除整个组,擦除组号为N的整个Flash组。擦除全部Flash只要给出一个all的参数即可。

 

8、flinfo

flinfo

       - print information for all FLASH memory banks

flinfo N

       - print information for FLASH memory bank # N

 

flinfo命令打印全部Flash组的信息,也可以只打印其中某个组。一般嵌入式系统的Flash只有一个组。

 

9、go

go addr [arg ...]

      - start application at address 'addr'

        passing 'arg' as arguments

 

go命令可以执行应用程序。

第1个参数是要执行程序的入口地址。

第2个可选参数是传递给程序的参数,可以不用。

 

10、minfo

iminfo addr [addr ...]

      - print header information for application image starting at

         address 'addr' in memory; this includes verification of the

         image contents (magic number, header and payload checksums)

 

iminfo可以打印程序映像的开头信息,包含了映像内容的校验(序列号、头和校验和)。

第1个参数指定映像的起始地址。

可选的参数是指定更多的映像地址。

 

11、loadb

loadb [ off ] [ baud ]

     - load binary file over serial line with offset 'off' and baudrate 'baud'


loadb命令可以通过串口线下载二进制格式文件。


12、loads

loads [ off ]

    - load S-Record file over serial line with offset 'off'

 

loads命令可以通过串口线下载S-Record格式文件。

 

13、mw

mw [.b, .w, .l] address value [count]

     - write memory


mw命令可以按照字节、字、长字写内存,.b .w .l的用法与cp命令相同。

第1个参数address是要写的内存地址。

第2个参数value是要写的值。

第3个可选参数count是要写单位值的数目。

 

14、nfs

nfs [loadAddress] [host ip addr:bootfilename]

nfs命令可以使用NFS网络协议通过网络启动映像。

 

15、nm

nm [.b, .w, .l] address

     - memory modify, read and keep address

 

nm命令可以修改内存,可以按照字节、字、长字操作。

参数address是要读出并且修改的内存地址。

 

16、printenv

printenv

      - print values of all environment variables

printenv name ...

      - print value of environment variable 'name'

 

printenv命令打印环境变量。

可以打印全部环境变量,也可以只打印参数中列出的环境变量。

 

17、protect

protect on  start end

      - protect Flash from addr 'start' to addr 'end'

protect on  N:SF[-SL]

      - protect sectors SF-SL in Flash bank # N

protect on  bank N

      - protect Flash bank # N

protect on  all

      - protect all Flash banks

protect off start end

      - make Flash from addr 'start' to addr 'end' writable

protect off N:SF[-SL]

     - make sectors SF-SL writable in Flash bank # N

protect off bank N

     - make Flash bank # N writable

protect off all

     - make all Flash banks writable

 

protect命令是对Flash写保护的操作,可以使能和解除写保护。

第1个参数on代表使能写保护;off代表解除写保护。

第2、3参数是指定Flash写保护操作范围,跟擦除的方式相同。

 

18、rarpboot

rarpboot [loadAddress] [bootfilename]

 

rarboot命令可以使用TFTP协议通过网络启动映像。也就是把指定的文件下载到指定地址,然后执行。

第1个参数是映像文件下载到的内存地址。

第2个参数是要下载执行的映像文件。

 

19、run

run var [...]

      - run the commands in the environment variable(s) 'var'

run命令可以执行环境变量中的命令,后面参数可以跟几个环境变量名。

 

20、setenv

setenv name value ...

      - set environment variable 'name' to 'value ...'

setenv name

      - delete environment variable 'name'

 

setenv命令可以设置环境变量。

第1个参数是环境变量的名称。

第2个参数是要设置的值,如果没有第2个参数,表示删除这个环境变量。

 

21、sleep

sleep N

      - delay execution for N seconds (N is _decimal_ !!!)

sleep命令可以延迟N秒钟执行,N为十进制数。

 

22、tftpboot

tftpboot [loadAddress] [bootfilename]

tftpboot命令可以使用TFTP协议通过网络下载文件。按照二进制文件格式下载。另外使用这个命令,必须配置好相关的环境变量。例如serverip和ipaddr。

第1个参数loadAddress是下载到的内存地址。

第2个参数是要下载的文件名称,必须放在TFTP服务器相应的目录下。

这些U-Boot命令为嵌入式系统提供了丰富的开发和调试功能。在Linux内核启动和调试过程中,都可以用到U-Boot的命令。但是一般情况下,不需要使用全部命令。比如已经支持以太网接口,可以通过tftpboot命令来下载文件,那么还有必要使用串口下载的loadb吗?反过来,如果开发板需要特殊的调试功能,也可以添加新的命令。




========================================================================================


转自 http://blog.chinaunix.net/uid-9543173-id-3571668.html


 linux下内存大小、起始地址的解析与修改 


在实际的工作中,由于产品型号的不同,经常需要调整linux所管理的内存的大小,而内核在启动阶段,会两次去解析从uboot传递过来的关于内存的信息,具体如下:


一、解析从uboot传递过来的tag(parse_tags中处理)

ubootdo_bootm_linux()函数中,会创建一系列需要传递给内核的tag,所有的tag以链表形式链接到指定的物理内存中。setup_start_tag用来建立起始的tag,而起始的物理地址由bd->bi_boot_params指定,

  1. static void setup_start_tag (bd_t *bd)
  2. {
  3.     params = (struct tag *) bd->bi_boot_params;

  4.     params->hdr.tag = ATAG_CORE;
  5.     params->hdr.size = tag_size (tag_core);

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

  9.     params = tag_next (params);
  10. }

bi_boot_params是在board_init中初始化的,此地址是与内核协商一致的用来存放tag的基址。

int board_init (void)

{

…………

    gd->bd->bi_boot_params = CFG_BOOT_PARAMS;

…………

}

而内存的tag是在setup_memory_tags()函数中创建的,其hdr.tag指定了tag的类型为ATAG_MEM

  1. static int __init parse_tag_mem32(const struct tag *tag)
  2. {
  3.     if (meminfo.nr_banks >= NR_BANKS) {
  4.         printk(KERN_WARNING
  5.          "Ignoring memory bank 0x%08x size %dKB\n",
  6.             tag->u.mem.start, tag->u.mem.size / 1024);
  7.         return -EINVAL;
  8.     }
  9.     arm_add_memory(tag->u.mem.start, tag->u.mem.size);
  10.     return 0;
  11. }

  12. __tagtable(ATAG_MEM, parse_tag_mem32);


在内核中,会通过__tagtable 宏来建立起相关的struct tagtable 的数据结构,并放入".taglist.init" 段中,

#define __tag __used __attribute__((__section__(".taglist.init")))

#define __tagtable(tag, fn) \

static struct tagtable __tagtable_##fn __tag = { tag, fn }


  1. static int __init parse_tag_mem32(const struct tag *tag)
  2. {
  3.     return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
  4. }

  5. __tagtable(ATAG_MEM, parse_tag_mem32);

而在start_kernel()->setup_arch()->parse_tags()函数中会根据从指定的物理内存中解析出来的tag的类型(即在uboot中写入的hdr.tag)去解析不同的tag

在内核中此物理内存地址是在MACHINE_START中定义的,其中的boot_paramsuboot中的bi_boot_params数据段指向相同的物理内存地址。因此是在uboot中写入tag,在内核中此地址解析tag

  1. MACHINE_START(hi3520v100, "hi3520v100")
  2.     .phys_io    = IO_SPACE_PHYS_START,
  3.     .io_pg_offst    = (IO_ADDRESS(IO_SPACE_PHYS_START) >> 18) & 0xfffc, 
  4.     .boot_params    = PHYS_OFFSET + 0x100,
  5.     .map_io        = hisilicon_map_io,
  6.     .init_irq    = hisilicon_init_irq,
  7.     .timer        = &hisilicon_timer,
  8.     .init_machine    = hisilicon_init_machine,
  9. MACHINE_END
  1. struct tagtable {
  2.     __u32 tag;
  3.     int (*parse)(const struct tag *);
  4. };

parse_tags()中,会根据读出来的tag的类型,即hdr.tag与从".taglist.init"段中的struct tagtable中的tag字段比较,如果相等,便执行struct tagtable中的parse()函数,对内存的tag来讲,其类型是ATAG_MEM,解析函数是parse_tag_mem32();

  1. static int __init parse_tag_mem32(const struct tag *tag)
  2. {
  3.     if (meminfo.nr_banks >= NR_BANKS) {
  4.         printk(KERN_WARNING
  5.          "Ignoring memory bank 0x%08x size %dKB\n",
  6.             tag->u.mem.start, tag->u.mem.size / 1024);
  7.         return -EINVAL;
  8.     }
  9.     arm_add_memory(tag->u.mem.start, tag->u.mem.size);
  10.     return 0;
  11. }

  12. __tagtable(ATAG_MEM, parse_tag_mem32);

在内核中,物理内存的起始地址和大小存放在一个struct meminfo meminfo的全局变量中,

  1. struct meminfo {
  2.     int nr_banks;
  3.     struct membank bank[NR_BANKS];
  4. };
  1. struct membank {
  2.     unsigned long start;
  3.     unsigned long size;
  4.     int node;
  5. };

nr_banks表示内核总共管理了多少个bank

struct membank记录了内核中各个bank的信息,start表示起始地址,size表示此bank的大小,node表示此bank属于哪个内存结点。

Linux内核可以管理多个不连续的物理内存,每段连续的物理内存的大小和起始地址存在一个struct membank结构体中,有多少段物理内存,就有多少个bank

parse_tag_mem32解析在uboot中建立的关于内存的tag,把其中的物理内存地址和大小填充到bank中。


二、解析从uboot传递过来的boot_command_line(parse_cmdline函数中解析)

boot_command_line命令行是在ubootfix_bootargs()函数里建立的。即在uboot中看到的bootargs的环境变量

  1. static void fix_bootargs(char *cmdline)
  2. {
  3. .……
  4.     /* fix "mem=" params */
  5.     p = strstr(cmdline,"mem=");
  6.     if(!p) {
  7.         sprintf(args," mem=%dM",gd->bd->bi_dram[0].size/0x200000);
  8.         strcat(cmdline,args);
  9.     }
  10. ……………
  11. }

在内核中是通过early_mem()来解析boot_command_line中有关内存大小的参数行的。

  1. static void __init early_mem(char **p)
  2. {
  3.     static int usermem __initdata = 0;
  4.     unsigned long size, start;

  5.     /*
  6.      * If the user specifies memory size, we
  7.      * blow away any automatically generated
  8.      * size.
  9.      */
  10.     if (usermem == 0) {
  11.         usermem = 1;
  12.         meminfo.nr_banks = 0;
  13.     }

  14.     start = PHYS_OFFSET;
  15.     size = memparse(*p, p);
  16.     if (**== '@')
  17.         start = memparse(*+ 1, p);

  18.     arm_add_memory(start, size);
  19. }
  20. __early_param("mem=", early_mem);

该函数解析从uboot传递进来的boot_command_line命令行参数中以“mem=”开头的命令行,如果boot_command_line中有以“mem=”开头的命令行,就调用该函数解析“mem=”之后的关于内存的信息,

把内存的大小写到对应的bank中去,内存的基地址在此处是一个默认值。如果有两段不连续的物理内存,可以在boot_command_line中设置如下内容即可:

mem=72M@0xe2000000 mem=128M@0xe8000000

在此处,定义了static int usermem __initdata = 0,从而设置meminfo.nr_banks = 0,这样把前面解析uboottag所赋值的bank内容又重写了,所以相当于前面解析tag的操作没有生效,起作用的还是此处的解析boot_command_line的操作。


三、以上是内核启动过程中所做的两次解析内存参数的操作,在实际应用中需要修改linux内存大小时可以采取相应的方法:

1、 修改uboot中内存相关的tags或者bootargs的命令行参数。这种做法虽然可以修改linux管理的内存的大小,但是由于要修改uboot,这样会对产品生产中增加困难,而且bootloader在原则上是要尽量少做改动,防止由于修改bootloader造成板子无法启动等问题,所以此方法不推荐使用。

2、 通过在解析boot_command_line之前修改其中的”mem=”之后的相关内容来修改linux所管理的内存大小,这样可以做到不同产品间的兼容性,而且后续的产品升级等方面也比较简单容易操作。


在海思平台上实现了这种做法。

void __init hikio_fix_meminfo(char *cmdline,struct meminfo *mi)

{

……………….

    strcpy(p,p+8);

    strcat(cmdline," mem=72M");

    mi->bank[0].size = 72*0x100000;

}

然后在解析cmdline之前执行此函数。
hikio_fix_meminfo(from,&meminfo);/* wangqian fix for cost-down boards*/

memcpy(boot_command_line, from, COMMAND_LINE_SIZE);

boot_command_line[COMMAND_LINE_SIZE-1] = '\0';

parse_cmdline(cmdline_p, from);

这种方法可以很方便的根据不同的产品型号修改内存的大小,而且只需要修改内核部分,不用去对uboot进行改动,所以是最方便快捷的方式。

0 0
原创粉丝点击