第1阶段——uboot通过nand命令读内核分析(8)

本节主要学习:
详细分析UBOOT中"bootcmd=nand read.jffs2 0x30007FC0 kernel;bootm 0x30007FC0"
怎么实现nand命令读内核.

1. nand read.jffs2 0x30007FC0 kernel
步骤a: 从NAND FILSHE中kernel分区读出
步骤b: 放到0x30007FC0去

1.1 kernel分区: 是flash中内核区
其中在flash中定义了4大分区:
| bootloader | :一开机直接运行u-boot
|boot parameters | :存放一些可以设置的参数,供u-boot使用
| kernel | :存放内核区
|root filesystem | :根文件系统,挂载(mount)后才能使用文件系统中的应用程序

这几个分区通过配置文件已在flash地址上是写好了,位于 u-boot-1.1.6/include/configs/100ask24x0.h:

#define MTDIDS_DEFAULT "nand0=nandflash0"
#define MTDPARTS_DEFAULT "mtdparts=nandflash0:[email protected](bootloader)," \
"128k(params)," \
"2m(kernel)," \
"-(root)"

在100ask24x0.h里定义了一个MTDPARTS_DEFAULT宏定义,
“mtdparts=nandflash0:”表示mtdparts分区位于nandflash上
"[email protected](bootloader),"表示从0开始共256kb是bootloader分区
"128k(params),"表示接下来128kb用来存放参数,是params分区
"2m(kernel)," 表示接下来2Mb用来存放内核,是kernel分区
"-(root)" 表示剩下的容量存放根文件系统,是root分区

1.2 可以通过在uboot界面输入"mtd"命令,查看4个分区的位置情况:
#: name size offset mask_flags
0:bootloader 0X00040000 0X00000000 0
1:params 0X00020000 0X00040000 0
2:kernel 0X00200000 0X00060000 0
3:root 0X0fda0000 0X00260000 0

从上面可以看出bootloader基地址是0x0000 0000,该分区大小为0x0004 000,所以结束地址为0X0003 FFFF。
为什么0X00040000等于256kb?
因为在ARM920t中,每隔4个地址保存了一个32位数据(4个字节)
所以0X00040000=0X00040000个字节=0x100(256)*0x400(1024)=256Kb

1.3 所以 nand read.jffs2 0x30007FC0 kernel 最终扩展开为:
nand read.jffs2 0x30007FC0 0X00060000 0X00200000

1.4 nand命令位于./common/cmd_nand.c(所有命令文件都是存在common中,以cmd_xx.c形式保存)
其中nand命令执行时调用的是do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])函数
进入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"); //获取环境变量quiet

if (argc < 2) //判断nand命令参数个数若小于2,将goto到usage,打印cmdtp->usage(nand命令短的帮助说明)
goto usage;
...
cmd = argv[1]; //cmd="read.jffs2"
...
if (strcmp(cmd, "info") == 0) //cmd不等于"info",不执行
{...}
...
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; //若argv[1]都不满足的话,表示使用命令在语法上有错误,打印短的帮助说明
....
if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) //cmd==read为真
{
int read;

if (argc < 4) // "nand read.jffs2 0x30007FC0 0X00060000 0X00200000"共5个参数,这里不执行
goto usage;

addr = (ulong)simple_strtoul(argv[2], NULL, 16); //将argv[2]的"0x30007FC0"字符型转换成数值型

read = strncmp(cmd, "read", 4) == 0;
//strncmp():判断cmd和"read"前4个字节若相等返回0,不相等返回大于0的数
//这里cmd与"read"相等,所以strncmp()返回0,read=(0==0)为真,所以read=1
printf("\nNAND %s: ", read ? "read" : "write"); //由于read=1,所以打印"\nNAND read:" 

if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
return 1;

s = strchr(cmd, ‘.‘); //strchr():查找‘.‘字符,若没找到返回NULL。
if (s != NULL &&
(!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) //if为真,argv[1]=read.jffs2
{
if (read) { //read==1,执行if
/* read */
nand_read_options_t opts;
memset(&opts, 0, sizeof(opts));
opts.buffer = (u_char*) addr; //设置buffer=0x30007FC0
opts.length = size; //设置size=0X00200000=2097152 byte
opts.offset = off; //设置offset=0X00060000
opts.quiet = quiet;
ret = nand_read_opts(nand, &opts);
//nand_read_opts():读取nandflash的kernel分区到 buffer地址,如读取成功返回0
} else {
/* write */
...
}
}
else if ( s != NULL && !strcmp(s, ".yaffs")){
...
}else if ( s != NULL && !strcmp(s, ".raw")){
...
} else {
...
}

printf(" %d bytes %s: %s\n", size,
read ? "read" : "written", ret ? "ERROR" : "OK"); //打印"2097152 bytes read : OK\n"

return ret == 0 ? 0 : 1; //read读取kernel分区成功返回0,失败返回1
}
时间: 2024-10-10 02:37:46

第1阶段——uboot通过nand命令读内核分析(8)的相关文章

第1阶段——uboot查找命令run_command函数和命令定义分析(6)

本节主要学习,run_command函数命令查找过程,命令生成过程 1.run_command函数命令查找过程分析:在u-boot界面中(main_loop();位于u-boot-1.1.6/common/main.c ):a 输入命令字符串b 将命令字符串代入函数run_command()c run_command():判断命令字符串,在argv[0]里保存命令名,并调用find_cmd(argv[0]))函数查找内存中该命令结构体,判断各个参数,执行命令等d find_cmd(argv[0]

第1阶段——uboot启动函数bootm命令分析(9)

本节主要学习: 详细分析UBOOT中"bootcmd=nand read.jffs2 0x30007FC0 kernel;bootm 0x30007FC0"中怎么实现bootm命令启动内核. 其中bootm要做的事情:a 读取头部,把内核拷贝到合适的地方(0X30008000)b 在do_boom_linux()中把参数给内核准备好,并告诉内核参数的首地址c 在do_boom_linux()中最后使用theKernel () 引导内核. {注意:当在cmd_bootm.C中没有定义宏C

U-BOOT 对 Nand Flash 命令的支持

U-BOOT 对 Nand Flash 命令的支持 在 U­BOOT 下对 Nand Flash 的支持主要是在命令行下实现对 nand flash 的操作.对 nand flash 实现的命令 为:nand info.nand device.nand read.nand write.nand erease.nand bad. 用到的主要数据结构有:struct nand_flash_dev.struct nand_chip.前者包括主要的芯片型号.存储容量. 设备 ID.I/O 总线宽度等信息

uboot启动 及命令分析(3)

u-boot命令 先贴一个重要结构,位于uboot/include/command.h,这个结构代表每个uboot命令 struct cmd_tbl_s { char     *name;   /* Command Name       */ int      maxargs;    /* maximum number of arguments*/ int      repeatable;/* autorepeat allowed?   */ /* Implementation function

u-boot从nand 启动时的问题解决记录

u-boot从nand 启动时的问题解决记录 问题描述: 使用u-boot-1.1.6版本u-boot移植到JZ2440开发板上,当前已经能够从Nor启动,但是不能从Nand正常启动(u-boot大小为95.8k,已经超过的2440从Nand启动时所能拷贝的4k大小),当前代码中只具备从Nor启动时,重定位代码到SDRam的功能,所以需要添加从Nand启动时将u-boot代码重定位到SDRam中,之后跳到SDRam中运行: 针对上述需求中Nand操作部分增加代码如下: /* s3c2440中na

在U-Boot中添加自定义命令以实现自动下载程序【转】

本文转载自:https://gaomf.cn/2016/06/26/%E5%9C%A8U-Boot%E4%B8%AD%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E5%91%BD%E4%BB%A4%E4%BB%A5%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E4%B8%8B%E8%BD%BD%E7%A8%8B%E5%BA%8F/ U-Boot中通过NFS下载程序是一种很普遍的方式,然而下载程序的过程并不能只用一条命令实现

如何利用JLINK烧写U-boot到NAND Flash中

原文:http://blog.csdn.net/yanghao23/article/details/7689534  很多同学使用笔记本作为自己的ARM开发和学习的平台,绝大多数笔记本都没有并口,也就是无法使用JTag调试和烧写程序到Nand Flash中,幸好我们还有JLINK,用JLINK烧写U-boot到Nor Flash中很简单,大部分NOR Flash都已经被JLink的软件SEGGER所支持,而新手在学习的时候经常会实验各种各样的命令,最悲剧的莫过于将NAND Flash中原有的bo

uboot之添加命令

1.添加命令 若要向Uboot中添加自己的命令,而自己又不想知道命令实现的原理,可以按照以下做法: 1.在uboot/common目录下,随便找一个cmd_xxx.c文件,将cmd_xxx.c文件拷贝一下,并重新命名为cmd_hello.c cp cmd_xxx.c cmd_hello.c 2.进入到cmd_hello.c中,修改 a:修改宏U_BOOT_CMD U_BOOT_CMD宏参数有6个: 第一个参数:添加的命令的名字 第二个参数:添加的命令最多有几个参数(注意,假如你设置的参数个数是3

uboot自定义添加命令

1.添加命令 1.u-boot的命令格式: U_BOOT_CMD(name,maxargs,repeatable,command,"usage","help") name:命令的名字,不是一个字符串: maxargs:最大的参数个数: repeatable:命令是可重复的: command:对应的函数指针 2.在uboot/common目录下,随便找一个cmd_xxx.c文件,将cmd_xxx.c文件拷贝一下,并重新命名为cmd_hello.c cp cmd_xxx