不好意思哈,这里只是贴出了目录,是看不到具体内容的。下面贴出5.5.1小结的实际内容,供大家参考:
5.5.1 启动内核之映像拷贝
实现内核拷贝的命令为:
nand read 0x30007fc0 0x60000 0x200000;
其中,nand read表示使用nand操作命令,也说明内核保存在nand flash中;0x30007fc0表示要拷贝到内存的目标位置;0x60000表示内核在nand flash的偏移量;0x200000表示内核的大小。这里需要说明,0x60000 0x200000可以使用分区的名字代替,比如:
nand read 0x30007fc0 kernel;
对于PC机而言每块硬盘的开始都有一块分区表,而嵌入式的nand flash是没有分区表的,那么nand flash的分区实现就只能在源代码中写死固定。因此,我们关心的是各个分区的起始地址(便宜地址)和大小,因此以上两种写法都是可以的。下面是一个分区的定义方法include/configs/xxxx.h配置文件中:
#define MTDPARTS_DEFAULT “mtdparts=nandflash0:256k@0(bootloader)”
“128k(params)”
“2m(kernel)”
“-(root)”
那么如上命令是如何将内核拷贝到内存中去的呢?接下来看nand命令的函数实现do_bootm()。命令定义如下:
/* common/cmd_nand.c */
U_BOOT_CMD(nand, 5, 1, do_nand,
"nand - NAND sub-system\n",
"info - show available NAND devices\n"
"nand device [dev] - show or set current device\n"
"nand read[.jffs2] - addr off|partition size\n"
"nand write[.jffs2] - addr off|partiton size - read/write `size' bytes starting\n"
" at offset `off' to/from memory address `addr'\n"
"nand erase [clean] [off size] - erase `size' bytes from\n"
" offset `off' (entire device if not specified)\n"
"nand bad - show bad blocks\n"
"nand dump[.oob] off - dump page\n"
"nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
"nand markbad off - mark bad block at offset (UNSAFE)\n"
"nand biterr off - make a bit error at offset (UNSAFE)\n"
"nand lock [tight] [status] - bring nand to lock state or display locked pages\n"
"nand unlock [offset] [size] - unlock section\n");
-------------------------------do_nand()函数开始-------------------------------------------
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
int i, dev, ret;
ulong addr, off, size;
char *cmd, *s;
nand_info_t *nand;
int quiet = 0;
const char *quiet_str = getenv("quiet");
/* at least two arguments please */
if (argc < 2)
goto usage;
if (quiet_str)
quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
cmd = argv[1]; //获取命令的第二个参数
. . .
/* 第二参数验证 */
if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
strncmp(cmd, "dump", 4) != 0 &&
strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
strcmp(cmd, "biterr") != 0 &&
strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 )
goto usage;
/* the following commands operate on the current device */
if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
!nand_info[nand_curr_device].name) {
puts("\nno devices available\n");
return 1;
}
/* 获取当前的nand flash */
nand = &nand_info[nand_curr_device];
. . .
/* read write :读写操作 */
if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
int read; /* 用于保存是读还是写操作 */
if (argc < 4)
goto usage;
/* 取出内存目标地址 */
addr = (ulong)simple_strtoul(argv[2], NULL, 16);
/* 判断是读还是写 */
read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
printf("\nNAND %s: ", read ? "read" : "write");
/* 取出偏移量和大小 */
if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
return 1;
s = strchr(cmd, '.'); /* 取出第二个参数的后半部 */
if (s != NULL &&
(!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {
if (read) {
/* read */
nand_read_options_t opts;
memset(&opts, 0, sizeof(opts));
opts.buffer = (u_char*) addr;
opts.length = size;
opts.offset = off;
opts.quiet = quiet;
ret = nand_read_opts(nand, &opts);
} else {
/* write */
nand_write_options_t opts;
memset(&opts, 0, sizeof(opts));
opts.buffer = (u_char*) addr;
opts.length = size;
opts.offset = off;
/* opts.forcejffs2 = 1; */
opts.pad = 1;
opts.blockalign = 1;
opts.quiet = quiet;
ret = nand_write_opts(nand, &opts);
}
} else {
if (read)
ret = nand_read(nand, off, &size, (u_char *)addr);
else
ret = nand_write(nand, off, &size, (u_char *)addr);
}
printf(" %d bytes %s: %s\n", size,
read ? "read" : "written", ret ? "ERROR" : "OK");
return ret == 0 ? 0 : 1;
} /* nand read write 执行完毕 */
. . .
}
最终调用nand_read_opts()/nand_read()函数将Linux内核从Nand Flash中的off处读取off长度的数据到内存的addr地址。详细的nand_read()函数在这里不讲解。
|