📄 loadyaffs.c
字号:
/* * YAFFS: Yet another FFS. A NAND-flash specific file system. * mkyaffs.c Format a chunk of NAND for YAFFS. * * Copyright (C) 2002 Aleph One Ltd. * for Toby Churchill Ltd and Brightstar Engineering * * Created by Charles Manning <charles@aleph1.co.uk> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Acknowledgement: * This file is crafted from nandtest.c by Miguel Freitas (miguel@cetuc.puc-rio.br) * and Steven J. Hill (sjhill@cotw.com) * * Overview: * Formatting a YAFFS device is very simple. Just erase all undamaged blocks. * NB Don't erase blocks maked as damaged. */#define _GNU_SOURCE#include "config.h"#include "command.h"#include "machine.h"#include <priv_data.h>#include "mtd/mtd.h"#include "printk.h"#include "serial.h"#include "vivi_string.h"#include "md5.h"#include "xmodem.h"#include "ymodem.h"#include <string.h>#include "mtd/cfi.h"#include "mtd/bonfs.h"/*#include "memory.h"#include "serial.h"#include "vivi_string.h"#include <types.h>#include <errno.h>*/#define LOAD_TO_FLASH 1#define LOAD_TO_RAM 2extern struct mtd_info *mymtd; /*struct mtd_info defined at include/mtd/mtd.h*/const char *mkyaffs_c_version = "$Id: mkyaffs.c,v 1.9 2005/10/11 23:39:56 charles Exp $";const char *vivi_loadyaffs_c_version = "thisway.diy@163.com, 2006.02.21";// countBits is a quick way of counting the number of bits in a byte.// ie. countBits[n] holds the number of 1 bits in a byte with the value n.static const char countBits[256] ={0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};static int modem_is(const char *mt){ if (strncmp("x", mt, 1) == 0) { return X_MODEM; } else if (strncmp("y", mt, 1) == 0) { return Y_MODEM; } else if (strncmp("z", mt, 1) == 0) { return Z_MODEM; } else { return UNKNOWN_MODEM; }}static size_tdownload_file(char *buf, size_t size, int modem, char *name){ switch (modem) { case X_MODEM:#ifdef CONFIG_SERIAL_XMODEM printk("Ready for downloading using xmodem...\n"); printk("Waiting...\n"); return xmodem_receive(buf, size);#else printk("Not support XMODEM protocol by this vivi\n");#endif break; case Y_MODEM:#ifdef CONFIG_SERIAL_YMODEM printk("Ready for downloading using ymodem...\n"); printk("Waiting...\n"); return ymodem_receive(buf, size, name);#else printk("Not support YMODEM protocol by this vivi\n");#endif break; case Z_MODEM: printk("Not support zmodem yet.\n"); break; default: printk("Not support this modem\n"); break; } return 0;}/* * loadyaffs_to_flash(): write buffer to MTD device, format as yaffs * * Arguments: * ofs: offset to write. * len: length of data to write. * buf: location of buffers. * flag: a flag of a mtd partiton. * usemtdecc: use ecc of mtd, or ecc of yaffs */static int loadyaffs_to_flash(loff_t ofs, size_t len, const u_char *buf, int flag, int usemtdecc, size_t part_size){ unsigned long addr = 0; unsigned long bad_addr = 0; unsigned long erase_addr = 0; unsigned long offset; unsigned long flash_addr; unsigned char oobbuf[16]; unsigned char ecc_code[6]; unsigned char* imgpage = NULL; int eraseblocks = 0; int badblocks = 0; size_t retlen; int imglen = 0; int delay = 0; struct mtd_oob_buf oob = {0, 16, (unsigned char *) &oobbuf}; struct mtd_info *mtd = mymtd; struct erase_info instr; if (mtd == NULL) { printk("Error. invalid MTD informations\n"); return -1; } if (mtd->type != MTD_NANDFLASH) { printk("Can't create yaffs on this flash, it isn't a nand flash\n"); return -1; } /* 打开文件 */ if (buf == NULL) { printk("Image not a found\n"); return -1; } /* xmodem以512字节为单位传输 * yaffs映象文件长度是528字节的整数倍 */ imglen = len - (len % 528); /* 确定烧写位置 */ flash_addr = ofs; imgpage = buf; /* 确定flash的参数正确 */ if( !(mtd->oobsize == 16 && mtd->oobblock == 512)) { printk("flash's params error: oobsize = %d, oobblcok = %d\n", mtd->oobsize, mtd->oobblock); return -1; } printk("Flash params: oobsize = %d, oobblock = %d, erasesize = %d, partition size = %d\n", mtd->oobsize, mtd->oobblock, mtd->erasesize, part_size); printk("Erasing and programming NAND with yaffs image\n"); printk(" Block erasing(addr/count) --- Block bad(addr/count) --- All count\n"); printk("-------------------------------------------------------------------\n"); for(addr = flash_addr; addr < flash_addr + part_size; addr += mtd->erasesize) { /* Read the OOB data to determine if the block is valid. * If the block is damaged, then byte 5 of the OOB data will * have at least 2 zero bits. */ oob.start = addr; oob.length = 16; oob.ptr = oobbuf; /* read oob */ mtd->read_oob(mtd, oob.start, oob.length, &retlen, oob.ptr); if(countBits[oobbuf[5]] < 7) { badblocks++; bad_addr = addr; printk(" 0x%08x/%05d 0x%08x/%05d %05d\r", erase_addr, eraseblocks, bad_addr, badblocks, eraseblocks + badblocks); delay = 100; while(delay--); } else { /* Erase this block */ instr.addr = addr; instr.len = mtd->erasesize; if (!(flag & MF_BONFS)) { eraseblocks++; erase_addr = addr; printk(" 0x%08x/%05d 0x%08x/%05d %05d\r", erase_addr, eraseblocks, bad_addr, badblocks, eraseblocks + badblocks); retlen = mtd->erase(mtd, &instr); if (retlen) { printk(" ... failed\n"); return -1; } printk("\r"); } /* Do some programming, but not in the first block */ if(addr != flash_addr){ for(offset = 0; offset < mtd->erasesize; offset+=512) { if(imgpage < buf + imglen){ if (usemtdecc) { nand_calculate_ecc(imgpage, ecc_code); nand_calculate_ecc(&imgpage[256], &ecc_code[3]); imgpage[512+8] = ecc_code[0]; imgpage[512+9] = ecc_code[1]; imgpage[512+10] = ecc_code[2]; imgpage[512+13] = ecc_code[3]; imgpage[512+14] = ecc_code[4]; imgpage[512+15] = ecc_code[5]; } oob.start = addr+offset; oob.length=16; oob.ptr=&imgpage[512]; /* write oob */ mtd->write_oob(mtd, oob.start, oob.length, &retlen, oob.ptr); mtd->write(mtd, oob.start, 512, &retlen, imgpage); imgpage += 528; } } } } } /* All the tests succeeded */ printk("\nLoad yaffs OK:\n"); printk("Blocks scanned: %d, Blocks erased: %d, Blocks is bad: %d\n", eraseblocks + badblocks, eraseblocks, badblocks); return 0;}/* * vivi command: * loadyaffs [-e] [ <partname> | <addr> ] <x|y|z> */void command_loadyaffs(int argc, const char **argv){ char *buf = (char *)RAM_BASE; //loff_t to; unsigned long to; /* is declared to long-long type ? */ size_t size; int modem = 0; int where_to = 0; int ret; size_t retlen; mtd_partition_t *dst_part; int flag; char file_name[255] = { 0, }; int usemtdecc = 0; if (argc == 3) usemtdecc = 0; else if ((argc == 4) && (strcmp(argv[1], "-e") == 0)) usemtdecc = 1; else { goto invalid_cmd; } dst_part = get_mtd_partition(argv[(argc == 3)?1:2]); if (dst_part == NULL) { printk("Can't find partition %s\n", argv[(argc == 3)?1:2]); return; } to = dst_part->offset; size = dst_part->size; flag = dst_part->flag; modem = modem_is((const char*)argv[(argc == 3)?2:3]); where_to = LOAD_TO_FLASH; /* download a file */ retlen = download_file(buf, size, modem, file_name); /* hacked by nandy. delay for serial output */ { int i = 0x10000; while (i > 0) i--; } if (retlen == 0) { printk("Failed downloading file\n"); return; } printk("Downloaded file at 0x%08lx, size = %d bytes\n", buf, retlen); switch (where_to) { case LOAD_TO_FLASH: if (retlen > size) { printk("An image size is too large to write flash. \ wanted = 0x%08lx, loaded = 0x%08lx\n", size, retlen); return; } if (flag & MF_ISRAM) { printk("Ooops, actually this partition is ram. It's tweak...!\n"); return; } ret = loadyaffs_to_flash((loff_t)to, retlen, buf, flag, usemtdecc, size); break; case LOAD_TO_RAM: break; } if (modem == Y_MODEM) check_md5sum(buf, retlen, file_name); return;invalid_cmd: printk("invalid 'loadyaffs' command: too few(many) arguments\n"); printk("\nUsage:\n"); printk(" loadyaffs [-e] <partname> <x|y|z>\n"); printk(" -e: use ecc of mtd\n"); return;}user_command_t loadyaffs_cmd = { "loadyaffs", command_loadyaffs, NULL, "loadyaffs {...}\t\t\t-- Load a yaffs image to Flash"};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -