U-Boot 启动参数

因为这部分内容是启动参数的设置,所以我们可以用如下的方式来搜索源码信息

譬如我像查找 mtdparts 的源码信息

1
grep -rn 'MODULE_PARM_DESC(parts'

其他的启动参数也可仿照如上方式来进行查询

mtd_id

1
mtd_id:size1(name1),size2(name2)

一般这样使用

1
2
3
mtdparts=mtd-id:<size1>@<offset1>(<name1>), \
                <size2>@<offset2>(<name2>); \
mtd_id:size1(name1),size2(name2)

mtdparts

我们自己编写的时候,可以在实机上运行 dmesg 来查看 mtd 分区在内核中的地址

再以此编写仿真时所需要的 mydparts 参数

需要注意的是,内核要打开几个必要的宏:

  • Config 1

    • CONFIG_CMD_MTD

    • CONFIG_CMD_MTDPARTS

  • Config 2

    • CONFIG_MTD_CMDLINE_PARTS

格式

mtdparts 的格式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 * mtdparts=<mtddef>[;<mtddef]
 * <mtddef>  := <mtd-id>:<partdef>[,<partdef>]
 * <partdef> := <size>[@<offset>][<name>][ro][lk][slc]
 * <mtd-id>  := unique name used in mapping driver/device (mtd->name)
 * <size>    := standard linux memsize OR "-" to denote all remaining space
 *              size is automatically truncated at end of device
 *              if specified or truncated size is 0 the part is skipped
 * <offset>  := standard linux memsize
 *              if omitted the part will immediately follow the previous part
 *              or 0 if the first part
 * <name>    := '(' NAME ')'
 *              NAME will appear in /proc/mtd
 *
 * <size> and <offset> can be specified such that the parts are out of order
 * in physical memory and may even overlap.
 *
 * The parts are assigned MTD numbers in the order they are specified in the
 * command line regardless of their order in physical memory.
 *
 * Examples:
 *
 * 1 NOR Flash, with 1 single writable partition:
 * edb7312-nor:-
 *
 * 1 NOR Flash with 2 partitions, 1 NAND with one
 * edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)

mtdparts 可以由一个或多个 mtddef 组成。每个mtddef定义如下:

1
<mtddef> := <mtd-id>:<partdef>[,<partdef>]

mtddef 可以由mtd-id 和一个或多个partdef组成,每个partdef定义如下:

因此在使用的时候,需要按照下面的格式来设置:

1
mtdparts=mtd-id:<size1>@<offset1>(<name1>),<size2>@<offset2>(<name2>)

这里需要注意的地方如下:

  • mtd-id 必须跟当前平台 flash 的 mtd-id 一致,不然整个 mtdparts会失效

    • 在 bootarg 参数中,可以指定当前 falsh 的 mtd-id

    • 指定mtdids:nand0=gen_nand.1,前面的 nand0 则表示第一个flash

  • size 在设置的时候,可以为实际的 size (xxM,xxK,xx),也可以为-,表示剩余的所有空间,相关信息可以查看drivers/mtd/cmdlinepart.c中注释找到相关描述

  • mtdparts 里mtd_id的值为nandnand,那么 kernel 的平台代码中也必须有一个名为nandnand的分区表,平台代码中的那张分区表可以为空,因为 mtdparts 中已经有了,就不会解析平台代码中设置的分区表,但是分区表的名字还是要匹配的。kernel 中默认的分区表的名字是 Nand

样例

arm

  • CONFIG_ARCH_VERSATILE
1
mtdparts=armflash:0x80000@0(boot),0x180000@0x80000(nvram),0x3e00000@0x200000(linux),0x19d3ac@0x4000000(rootfs),0x3ec0000@0x4000000(brcmnand),0x140000@0x7ec0000(asus)
  • CONFIG_ARCH_IPROC
1
mtdparts=nand_iproc.0:1024k(nboot),1024k(nenv),8192k(nsystem),1038336k(ndata)

mips

  • nor flash
1
mtdparts=physmap-flash.0:0x30000@0x0(Bootloader)0x10000@0x30000(nvram)0x10000@0x40000(Factory)0xeb0000@0x50000(linux)0xd847c0@0x17b840(rootfs)0x100000@0xf00000(jffs2)0x1000000@0x0(ALL)

mtd 分区内核地址

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Concatenating MTD devices:
(0): "armflash-0"
(1): "armflash-1"
into device "armflash"
6 cmdlinepart partitions found on MTD device armflash
Creating 6 MTD partitions on "armflash":
0x000000000000-0x000000080000 : "boot"
0x000000080000-0x000000200000 : "nvram"
0x000000200000-0x000004000000 : "linux"
0x000004000000-0x00000419d3ac : "rootfs"
0x000004000000-0x000007ec0000 : "brcmnand"
0x000007ec0000-0x000008000000 : "asus"

解析脚本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import os

parser = argparse.ArgumentParser()
parser.add_argument('file', help='boot info file')
args = parser.parse_args()

if args.file:
    with open(args.file, "rb") as fd:
        data = fd.read().strip()

output = b'mtdparts=armflash:'
data = data.split(b'\n')
for i in range(0, len(data)):
    line = data[i][data[i].find(b'0x'):].split(b' : ')
    addr = line[0].split(b'-')
    name = line[1].strip(b'"')
    output += hex(int(addr[1], 16) - int(addr[0], 16)).encode()
    output += b'@'
    output += hex(int(addr[0], 16)).encode()
    output += b'(' + name + b')'

print(output)

with open(os.path.dirname(args.file) + "/mtdparts", "wb") as fd:
    fd.write(output + b'\n')

/proc/mtd

1
2
3
4
5
6
7
8
/ # cat /proc/mtd 
dev:    size   erasesize  name
mtd0: 00080000 00010000 "boot"
mtd1: 00180000 00010000 "nvram"
mtd2: 03e00000 00010000 "linux"
mtd3: 0019d3ac 00010000 "rootfs"
mtd4: 03ec0000 00010000 "brcmnand"
mtd5: 00140000 00010000 "asus"

nandsim.parts

格式如下

1
nandsim.parts=64,64,64,64,64,64,64,64,64,64

开启方式

  1. 内核配置
  • CONFIG_MTD_NAND_NANDSIM
  1. 用户手动开启
1
2
3
4
5
6
modprobe nandsim first_id_byte=0xc8 \
                 second_id_byte=0xd1 \
                 third_id_byte=0x80 \
                 fourth_id_byte=0x95 \
                 cache_file=/root/nandsim.bin \
\                parts=8,8,8,20,20,256,256,224,220

开启后内核启动后会打印出模拟 NAND 芯片的名字,一般如下

1
Manufacturer ID: 0x98, Chip ID: 0x39 (Toshiba NAND 128MiB 1,8V 8-bit)

但是模仿出来的 mtd 块名字不能更改,内部获取名字的函数如下

1
2
3
4
static char __init *ns_get_partition_name(int i)
{
    return kasprintf(GFP_KERNEL, "NAND simulator partition %d", i);
}

参考链接