【轉】U-BOOT支援燒寫yaffs2檔案系統
U-BOOT 支援yaffs2檔案系統的燒寫。
其實移植這步燒寫很簡單,只是將打包的檔案系統一次寫入NAND即可,以頁為單位,一次寫入2K+64B。
包含main和spare區,其中spare的ECC資料等在yaffs2檔案系統製作時就已經寫好了。是通過軟體ECC
每256B產生3B的規則進行的。所以必須保證mkyaffs2image工具能正確製作YAFFS2檔案系統。否則系統是
啟動不了。
具體移植步驟:
1.在include/configs/xxxxx.h增加巨集
#define CONFIG_MTD_NAND_YAFFS2
2.新增write.yaffs2燒寫命令,U-BOOT只需要寫命令即可
vim common/cmd_nand.c中
501 #if defined(CONFIG_MTD_NAND_YAFFS2)
502 "nand read.yaffs2 - addr off|partition size\n"
503 "nand write.yaffs2 - addr off|partiton size\n"
504 #endif
新增以上幫助說明資訊
增加解析yaffs2命令的函式
344 #if defined(CONFIG_MTD_NAND_YAFFS2)
345 else if(s != NULL && !strcmp(s, ".yaffs2") ) {
346 if (read) {
347 /* nand->rw_oob = 1;
348 nand->skipfirstblk = 1;
349 ret = nand_read_skip_bad(nand,off,&size,(u_ chat *)addr);
350 nand->skipfirstblk = 0;
351 nand->rw_oob = 0;
352 */
353 }
354 else {/* 主要關心寫命令 */
355 nand->rw_oob = 1;
356 nand->skipfirstblk = 1;
357 ret = nand_write_skip_bad(nand, off, &size, (u_char *)addr);
358 nand->skipfirstblk = 0;
359 nand->rw_oob = 0;
360 }
361 }
362 #endif
nand->rw_oob 和 nand->skipfirstblk 一個作為燒寫YAFFS的標誌,檔案系統跳過的塊,因為YAFFS2檔案系統燒寫時需要跳過
第一塊。這是由於其特性決定的,第一塊用於構建BBT(bad block table)
這兩個新成員需要新增在include/linux/mtd/mtd.h的mtd_info結構體中
128 #if defined(CONFIG_MTD_NAND_YAFFS2)
129 u_char rw_oob;
130 u_char skipfirstblk;
131 #endif
3.由於寫操作會呼叫nand_write_skip_bad()函式,這裡也需要修改,位於nand_util.c
474 #if defined(CONFIG_MTD_NAND_YAFFS2)
475 if (nand->rw_oob == 1) {/* 燒寫的YAFFS2檔案 */
476
477 size_t oobsize = nand->oobsize;
478 size_t datasize = nand->writesize;
479 int datapages = 0;
480 datapages = (*length)/(datasize+oobsize);/* 注意這裡是整個長度 */
481 *length = datapages*datasize; /* 實際main區大小 */
482 left_to_write = *length; /* 在具體燒寫時會以left_to_write做引數 */
483 }
484 #endif
傳入這個函式的size 是nand命令引數給的,對於YAFFS2為實際大小,即2112的倍數,off也是經由命令列傳遞來的
而addr是對應記憶體BUF的地址
466 int nand_write_skip_bad(nand_info_t *nand, ulong offset, size_t *length,
467 u_char *buffer)
這是函式原型
所以以上新增程式碼的意思是,如註釋,也就是從yaffs2檔案大小中提取main區的資料大小
在以下程式碼新增如是巨集,避免影響其他燒寫
498 #if !defined (CONFIG_MTD_NAND_YAFFS2)
499 if (len_incl_bad == *length) {
500 rval = nand_write (nand, offset, length, buffer);
501 if (rval != 0)
502 printf ("NAND write to offset %x failed %d\n",
503 offset, rval);
504
505 return rval;
506 }
507 #endif
518 #if defined(CONFIG_MTD_NAND_YAFFS2)
519 if (nand->skipfirstblk == 1) {/* 需要跳過第一塊 */
520 nand->skipfirstblk = 0;
521 printf("Skip the first good block 0x%08x\n",offset &
522 ~(nand->erasesize - 1));
523 offset += nand->erasesize - block_offset;/* 故偏移地址 + 1block */
524 continue;
525 }
526 #endif
527
542 #if defined(CONFIG_MTD_NAND_YAFFS2)
543 if (nand->rw_oob == 1)
544 p_buffer += write_size+(write_size/nand->writesize*nand->oobsize);
/* 注意因為是一次燒寫main和spare 故指向映象的指標編譯量要加上OOB區的大小,一次寫入一塊,不足一塊以頁寫入*/
545 else
546 p_buffer += write_size;
547 #else
548
549 p_buffer += write_size;
550 #endif
551 }
552
553 return 0;
554 }
4.下面看nand_write()的實現
536 rval = nand_write (nand, offset, &write_size, p_buffer);
這是傳遞的引數,函式位於nand_base.c中
2011 #if defined(CONFIG_MTD_NAND_YAFFS2)
2012 int oldopsmode = 0;
2013 if (mtd->rw_oob != 1)
2014 chip->ops.oobbuf = NULL;
2015 else {
2016 chip->ops.oobbuf = (uint8_t *)(buf+mtd->writesize);/* oob資料起始地址 */
2017 chip->ops.ooblen = mtd->oobsize; /* 64B */
2018 chip->ops.ooboffs = 0;
2019 oldopsmode = chip->ops.mode;
2020 chip->ops.mode =MTD_OOB_RAW; /* 原始模式,不進行ECC計算 */
2021 }
2022 #else
2023 chip->ops.oobbuf = NULL;
2024 #endif
其實這個函式只是填充nand_chip這個結構體然後呼叫
2053 ret = nand_do_write_ops(mtd, to, &chip->ops);
函式原型如下
1887 /**
1888 * nand_do_write_ops - [Internal] NAND write with ECC
1889 * @mtd: MTD device structure
1890 * @to: offset to write to
1891 * @ops: oob operations description structure
1892 *
1893 * NAND write with ECC
1894 */
1895 static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1896 struct mtd_oob_ops *ops)
這個函式功能,選擇具體的一片NAND,當然大多情況只有一片,然後會處理OOB區資料
根據chip->ops.mode,這裡為原始模式,即不進行處理,則將OOB區資料複製到對應的ops
這是裡面新增的內容
然後會呼叫具體的write_page寫一頁資料
1972 #if defined(CONFIG_MTD_NAND_YAFFS2)
1973 if (mtd->rw_oob == 1) {
1974 oob = oob + bytes;
1975 buf = buf + ops->ooblen;
1976 }
1977 #endif
每寫一次oob和databuf都移動2112B。
1962 ret = chip->write_page(mtd, chip, wbuf, page, cached,
1963