U-boot transplant--5, support burn write Yaffs file system image

Source: Internet
Author: User
Tags strcmp
Often say that they are the memory of the elderly, because the things I have seen quickly forget. It is certainly better to see what you write than to see what other people are writing to understand. Write down this series of u-boot transplants, but also deepen your understanding. In fact, there are a lot of great gods on the Internet, and a lot of solutions are given. I also use them as a reference. In contrast, I would add some of my own understanding of some places to deal with. Hope to be helpful to everyone.
Development board: Days embedded TQ2440
u-boot:u-boot-1.1.6

The hand of the Development Board is a TQ2440, read the book is Vedon Teacher's "Embedded Linux Development Complete manual", some Xu different places, increased the transplant sleepy, when should also deeper their understanding.


Why do you support burning write Yaffs file system images? (Excerpt a section of the book)

In the actual production, the kernel, file system image can be burned into the solid-state storage equipment by means of the bootloader, and the burning writing function is not required. However, in order to facilitate the development, usually in the bootloader to add the burning of the kernel, file system image files function.

u-boot1.1.6, which has added NAND flash functionality, has been able to burn the kernel, write Cramfs, JFFS2 file system image files by "Nand write ...", "Nand write.jaffs2 ...", but in NAND Flash, the Yaffs file system performance is better, the following increase "NAND write.yaffs ..." command to burn write Yaffs file system image file.


To add commands you need to use the U-boot-cmd function, let's take a look at this function first. The definition of this function is implemented in Include/command.h. Let's take one step at a glance. The definition of U-boot-cmd is shown below. Determines whether a help item is included, depending on whether the cfg_longhelp is defined.

#ifdef  cfg_longhelp

#define U_BOOT_CMD (name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_## Name struct_section = {#name, Maxargs, rep, cmd, usage, help}

#else/	* No long help info */

#define U_boot_cmd (name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_# #name struct_section = {#name, Maxargs, rep, cmd, usage }

#endif/	* CFG_LONGHELP * *

We will explain in detail the definition of the second line

#define U_BOOT_CMD (name,maxargs,rep,cmd,usage,help)    cmd_tbl_t __u_boot_cmd_# #name struct_section = {#name, Maxargs, rep, cmd, usage, help}

You can see that U_boot_cmd uses the form definition of a macro definition, which contains 6 parameters. It actually points to the cmd_tbl_t struct variable, that is, using the definition u_boot_cmd command to define the process of populating a complete cmd_tbl_t structure. The above instruction we have three places to explain: # #name, Struct_section, #name.

First of all, the definition of struct_section is that the source file (include/command.h) has been defined, as shown below.

#define Struct_section  __attribute__ (Unused,section (". U_boot_cmd"))

This indicates that the filled structure is placed into a. U_boot_cmd segment.

# #name将字符直接跟在后面,

#name会将name这个字符中以 "..." to be placed in the form of a string.

To illustrate, in one example,

U_boot_cmd (boot, 0, 0, fun, "boot xxx");
After it is expanded, the result is

cmd_tbl_t __u_boot_cmd_boot __attribute___ ((Unused, section (". U_boot_cmd")) = {"Boot", 0, 0, fun, "Boot XXX"}
(Here is the use of the __attribute__ is a description of the attributes, what meaning.) GNU C allows special attributes of functions, variables, and types to be declared for manual code optimization and more careful code checking. To specify a declared property, write __attribute__ (attributes) after the declaration attribute is a property description, and multiple attributes are separated by commas.

In short: Declare + attribute, take our example above to explain namely:
cmd_tbl_t __u_boot_cmd_boot + attributes = {"Boot", 0, 0, fun, "Boot XXX"}
cmd_tbl_t __u_boot_cmd_boot __attribute___ ((Unused, section (". U_boot_cmd")) = {"Boot", 0, 0, fun, "Boot XXX"}

So the meaning of this sentence is to define a structural body __u_boot_cmd_boot, which is put into the. U_boot_cmd segment, the component properties of the structure are {"boot", 0, 0, fun, "Boot XXX"}

Next we paste the definition of cmd_tbl_t, the province to go to the code. The definition of this structure is also implemented in the Include/command.h function. Specifically as follows:

struct cmd_tbl_s {
	char		*name;		/* Command			Name
	*		/int maxargs;	/* Maximum number of	arguments
	*		/int repeatable;	* * AutoRepeat allowed?		*/
					* Implementation	function		/int (*cmd) (struct cmd_tbl_s *, int, int, char *[]);
	Char		*usage;		/* Usage message	(short)	*/
#ifdef	cfg_longhelp
	char		*help;		/* Help message	(long)	*/
#endif
#ifdef config_auto_complete/* Do
	AUTO completion on The arguments */
	int		(*complete) (int argc, char *argv[], char Last_char, int maxv, char *cmdv[]);
#endif
};

typedef struct CMD_TBL_S	cmd_tbl_t;
As you can see, traceability to the fundamental, actually cmd_tbl_t is defined by the cmd_tbl_s structure, in addition, we mentioned above the description of the structure of the attributes {"boot", 0, 0, fun, "Boot xxx"} of the order and attributes of the contents are also determined by this structure. Here we focus on a point, which is the fourth argument cmd, which actually points to a function, and this function is the real handler for the command we want to execute.

OK, let's take a look at the end. U_boot_cmd this segment, which is described in/board/tq2440/u-boot.lds, as shown below.

	. = .;
	__u_boot_cmd_start =.;
	U_boot_cmd: {* (. u_boot_cmd)}
	__u_boot_cmd_end =.;

That is, he defines a __u_boot_cmd_start as the beginning, a __u_boot_cmd_end as the end. The middle is the command stored in the. U_boot_cmd.

For U-boot.lds This file is primarily used to define the location of the code snippet, you can refer to references 9 and 10 for a specific explanation of this document.


OK, digress so long, we still come back to see how to add "NAND write.yaffs ..." command to burn write Yaffs file system image file.

"NAND" is a specific order "write.yaffs", "write.yaffs ..." is a parameter. The NAND command is implemented in the COMMON/CMD_NAND.C file (the command rule about the file we'll find that all the U-boot-cmd command's definition files start with cmd, such as CMD_NAND.C), in Cmd_ NAND.C file already has NAND command he is mainly used to burn write JFFS2, Cramfs file system image files, we only need to slightly modify, add support. Here's a question to note, we used the model of not macro-defined cfg_nand_legacy in the last lecture on NAND Flash's porting. So we're modifying the code so that it's also for code that doesn't define cfg_nand_legacy.

In U_boot_cmd, we add the corresponding description string in the help position. The added u_boot_cmd is shown below

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 ' "Nand read.yaffs addr off Size-read the ' size ' byte yaffs image starting\n "" at offset ' from ' to memory address ' addr ' \ n ' "Nand write.yaffs addr off Size-write the ' Size ' byte yaffs image starting\n "at offset ' off ' to memory address ' addr ' \" at offset ' off ' to/from add Ress ' addr ' "" NAND erase [clean] [off size]-erase ' size ' bytes from\n ' ' Offset ' off ' (entire device if not speci  fied) \ 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 blocks at offset (UNSAFE) \ n "" Nand biterr off-make a bit error at offs ET (UNSAFE) \ n "" Nand loCK [tight] [status]-bring NAND to lock state or display locked pages\n "" NAND unlock [offset] [size]-unlock section\n ");

In fact, we can see that NAND still supports more commands, such as NAND bad, NAND lock, and so on. Above we added a description of the string in the help position that describes the string NAND read.yaffs and NAND write.yaffs. And then we're going to really implement these two commands. We know from the above u_boot_cmd that this implementation function is the Do_nand function. Then let's go ahead and modify the Do_nand function. In the Do_nand function, the code snippet that adds the read-write Yaffs File System command is shown below. Where the else if segment is added support for yaffs.

/* 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) {/* rea
				d */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 ' (S!= NULL && (!strcmp (S, ". Yaffs"))) {if (read) {*/* Read/nand_read_options_t opts
				;
				memset (&opts, 0, sizeof (opts));
				Opts.buffer = (u_char*) addr;
				Opts.length = size;
				Opts.readoob = 1;
				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;              /* yaffs file system Image Storage Address * * opts.length = size;               /* Length */opts.offset = off; * * to burn write to NAND flash offset address * * OPTS.FORCEJFFS2 = 1;                 * * * The method of calculating ECC code, no use * * OPTS.NOECC = 1;                 /* Do not compute OOB data in ecc,yaffs image */Opts.writeoob = 1;                 /* Write OOB area * * opts.blockalign = 1;             /* Each logical block size is 1 physical blocks/opts.quiet = quiet; /* Whether to printHint Message * * opts.skipfirstblk = 1;
			/* Skip the first available block * * 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; }

The so-called OOB area is the meaning of out of band. NAND flash each page size is (2k+64) byte (this we introduced in the NAND flash transplant article, there are other forms of NAND flash, such as each page size (256+8) (512+16)) where 2k bytes is the area where the data is stored. 16 bytes is the main store of bad block mark in the Oob area, the front 2k byte ECC check code. Cramfs, JFFS2 file system mapping a file does not have OOB content if they are burned to nor flash in the "tile" relationship, if you burn them in NAND flash, then according to the mark of the OOB skip the bad block, The 2k data is then written to compute their ECC checksum and finally write them into the OOB area, so that it loops. Cramfs, JFFS2 file system image files are usually multiples of 512.

Yaffs file system image files are not the same format as they are. In order to read the province, it contains the data of the OOB area. (There are usually bad block marks inside.) ECC checksum code, other Yaffs related information, so when burning write, do not need to calculate ECC value, first check whether there is a bad block (is skipped), and then write 2k bytes of data, and finally write 64 bytes of OOB data. So loops, the size of the Yaffs file system image file is an integer multiple of (2k+64).

Note: The first available (not bad block) block on the partition when burning the Yaffs file system image is skipped.

This is also reflected in our code, that is, the OPTS.SKIPFIRSTBLK = 1 mentioned in the preceding code; /* Skip the first available block * *

However, because the u-boot written in Nand_write_options itself is not considered yaffs, so nand_write_options does not have skipfirstblk items, so we need to manually add. So we need to make the following modifications in the Incclude/nand.h to add SKIPFIRSTBLK members. The modified code is shown below.

struct Nand_write_options {
        U_char *buffer;         /* memory block containing image to write * * *
        ulong length;           /* Number of bytes to write *
        /ULONG offset;           /* Start address in NAND *
        /int quiet;              /* don ' t display progress messages *
        /int autoplace;          /* If true use Auto OOB layout *
        /int forcejffs2;         /* Force JFFS2 OOB layout *
        /int forceyaffs;         /* Force yaffs OOB layout *
        /int noecc;              /* Write without ECC *
        /int writeoob;           /* Image contains OOB data *
        /int pad;                /* PAD to page size *
        /int blockalign;         /* 1|2|4 set multiple
                                 of Eraseblocks * to align to */
        int skipfirstblk/*        new Add, to skip c25/>};
The next step is to modify the Nand_write_opts function to increase support for SKIPFIRSTBLK members. It is in the drivers/nand/nand_util.c file, the No. 301 line below, the No. 430 to No. 434 Act of the new addition.
285 int nand_write_opts (nand_info_t *meminfo, const nand_write_options_t *opts) 286 {287 int imglen = 0; 288
int Pagelen;
289 int baderaseblock;
290 int blockstart =-1;
291 loff_t offs;
292 int Readlen;
293 int oobinfochanged = 0;
294 int percent_complete =-1;
295 struct Nand_oobinfo old_oobinfo;
296 ULONG Mtdoffset = opts->offset;
297 ULONG Erasesize_blockalign;
298 U_char *buffer = opts->buffer;
299 size_t written;
int result;
skipfirstblk int = opts->skipfirstblk;
302 303 if (Opts->pad && opts->writeoob) {...
397 while (Blockstart!= (Mtdoffset & (~erasesize_blockalign+1)) ...                         430 if (skipfirstblk) {431 Mtdoffset + = erasesize_blockalign; 432
skipfirstblk = 0;
433 continue; 434}


Then we can compile it, make all.

After downloading, we can see that our command has been successfully identified. But because I don't know much about yaffs. So there is no follow-up action. Let's get this blog post here.







References: 3, http://www.360doc.com/content/12/0905/20/4186481_234492334.shtml

4, http://blog.csdn.net/shengzhadon/article/details/52766263

5, http://blog.csdn.net/yuzeze/article/details/51754541

6, http://blog.csdn.net/tongdh/article/details/24471325

7, http://blog.sina.com.cn/s/blog_6276db0e0101b1qs.html

8, http://blog.sina.com.cn/s/blog_89fa41ef0100xysl.html

9, http://www.linuxidc.com/Linux/2011-08/41809.htm

10, http://blog.csdn.net/qiaoliang328/article/details/5891913

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.