📄 cmd_bon.c
字号:
/* * vivi/drivers/mtd/nand/bon.c * * Based on vivi/util/imagewrite * * $Id: bon.c,v 1.12 2003/03/10 10:32:56 nandy Exp $ * * 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. * * Description: Simple management routines for the bon file system. * */#include <common.h>#include <command.h>#include <malloc.h>#include <asm/io.h>#if (CONFIG_COMMANDS & CFG_CMD_NAND)#include <linux/mtd/nand.h>#include <linux/mtd/nand_ids.h>#include <jffs2/jffs2.h>#include <linux/ctype.h>#define NANDRW_READ 0x01#define NANDRW_WRITE 0x00#define NANDRW_JFFS2 0x02extern struct nand_chip nand_dev_desc[];extern int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len, size_t * retlen, const u_char * buf);extern int nand_rw (struct nand_chip* nand, int cmd, size_t start, size_t len, size_t * retlen, u_char * buf);extern int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean);extern int check_block1(struct nand_chip* nand, unsigned long pos);extern void getchar(void);#define MAX_PART 5#define PARTITION_OFFSET (~0)#define IS_MTD 1#define IS_BON 0#define PARTNAMELEN 12typedef struct { char PartName[PARTNAMELEN]; unsigned long offset; unsigned long size; unsigned long flag; unsigned long num_bad_block; unsigned short *bad_blocks;} bon_partition_t;const char bon_part_magic[8] = {'M', 0, 0, 'I', 0, 'Z', 'I', 0};bon_partition_t parts[MAX_PART];int num_part = 0;#define NAND_SECTOR_SIZE 512#define NAND_OOB_SIZE 16static void mark_bad(struct nand_chip *mtd, unsigned long offset){ char oobbuf[NAND_OOB_SIZE]; int retlen; memset (oobbuf, 0xff, NAND_OOB_SIZE); oobbuf[5]=0; nand_write_oob(mtd, offset, NAND_OOB_SIZE, &retlen, oobbuf);}int erase_bon(struct nand_chip *mtd, int bonnum){ if(!(bonnum >= 0 && bonnum < num_part)) return -1; nand_erase (mtd, parts[bonnum].offset, parts[bonnum].size, 1); return 0;}int write_bon_image(struct nand_chip *mtd, int PartNum, char *src, long size){ int bad_block_nr = 0; /* NAND_SECTOR_SIZE*32 > meminfo.erasesize */ char buf[NAND_SECTOR_SIZE*32]; int retlen; int i; long offset; printf("size = %lx bon=%d\n", size, PartNum - 1); if(!(PartNum >= 1 && PartNum <= num_part)) { printf("bad bon num!\n"); return -1; } i = PartNum - 1; if (size > parts[i].offset + parts[i].size - parts[i].num_bad_block * 32 * NAND_SECTOR_SIZE) { printf("image is too big for this partition\n"); return -1; } erase_bon(mtd, i); offset = parts[i].offset; memcpy(buf, src, mtd->erasesize); while (size > 0) { if(nand_rw(mtd, NANDRW_WRITE, offset, mtd->erasesize, &retlen, buf) == 0) { size -= mtd->erasesize; src += mtd->erasesize; if (size > 0) memcpy(buf, src, mtd->erasesize); } else { int k; int block_nr = (offset - parts[i].offset) / mtd->erasesize; for (k = 0; k < parts[i].num_bad_block; k++) { if (block_nr == parts[i].bad_blocks[k]) break; } if (k == parts[i].num_bad_block) printf("*** warning: new bad block in %d\n", block_nr); bad_block_nr++; } offset += mtd->erasesize; } printf("bad_block = %d\n", bad_block_nr); return 0;}int read_bon_image(struct nand_chip *mtd, int PartNum, char *src, long size){ int bad_block_nr = 0; int retlen; int i; long offset; printf("size = %lx\n", size); if(!(PartNum >= 1 && PartNum <= num_part)) { printf("bad bon num!\n"); return -1; } i = PartNum - 1; if (size > parts[i].offset + parts[i].size - parts[i].num_bad_block * 32 * NAND_SECTOR_SIZE) { printf("image is too big for this partition\n"); return -1; } offset = parts[i].offset; while (size > 0) { if(nand_rw(mtd, NANDRW_READ, offset, mtd->erasesize, &retlen, src) == 0) { size -= mtd->erasesize; src += mtd->erasesize; } else { int k; int block_nr = (offset - parts[i].offset) / mtd->erasesize; for (k = 0; k < parts[i].num_bad_block; k++) { if (block_nr == parts[i].bad_blocks[k]) break; } if (k == parts[i].num_bad_block) printf("*** warning: new bad block in %d\n", block_nr); bad_block_nr++; } offset += mtd->erasesize; } printf("bad_block = %d\n", bad_block_nr); return 0;}#define MAXTRY 5int read_bon_partition(struct nand_chip *mtd){ int i, k; char buf[NAND_SECTOR_SIZE]; unsigned int *s; unsigned long offset = PARTITION_OFFSET; int retlen; if (offset > mtd->totlen - mtd->erasesize) offset = mtd->totlen - mtd->erasesize; for(i = 0;i < MAXTRY; i++) { if(nand_rw(mtd, NANDRW_READ, offset, NAND_SECTOR_SIZE, &retlen, buf)) { printf("read error: mark bad: offset = %lX\n", offset); offset -= mtd->erasesize; continue; } break; } if (strncmp(buf, bon_part_magic, 8) != 0) { num_part = 0; return -1; } s = (unsigned int *)(buf + 8); num_part = *s++; for (i = 0; i < num_part; i++) { strncpy(parts[i].PartName, (char *)s, PARTNAMELEN-1); parts[i].PartName[PARTNAMELEN - 1] = 0; s += PARTNAMELEN / sizeof(int); parts[i].offset = *s++; parts[i].size = *s++; parts[i].flag = *s++; } for (i = 0; i < num_part; i++) { parts[i].num_bad_block = *s++; if (parts[i].num_bad_block) { parts[i].bad_blocks = mmalloc(parts[i].num_bad_block * sizeof(unsigned int)); for (k = 0; k < parts[i].num_bad_block;k++) { parts[i].bad_blocks[k] = *s++; } } else { parts[i].bad_blocks = 0; } } return 0;}int read_size(char *s, unsigned long *size){ int is_ok = -1; while (isdigit(*s)) { is_ok = 0; (*size) = (*size) * 10 + *s - '0'; s++; } if (is_ok < 0) return -1; if (*s == 'M' || *s == 'm') (*size) *= 1024*1024; else if (*s == 'K' || *s == 'k') (*size) *= 1024; return 0;}int write_partition(struct nand_chip *mtd, unsigned long offset, unsigned long *PartInfoOff){ char buf[NAND_SECTOR_SIZE]; unsigned int *s; int i, k; size_t retlen; *PartInfoOff = 1; for(i = 0; i < MAXTRY; i++) { if(nand_rw(mtd, NANDRW_READ, offset, NAND_SECTOR_SIZE, &retlen, buf)) { if(nand_rw(mtd, NANDRW_READ, offset, NAND_SECTOR_SIZE, &retlen, buf)) { printf("read error: mark bad: offset = %lX\n", offset); offset -= mtd->erasesize; *PartInfoOff ++; continue; } } break; } if(nand_erase (mtd, offset, mtd->erasesize, 1) == -2){ if(nand_erase (mtd, offset, mtd->erasesize, 1) == -2){ printf("erase error: mark bad: offset = %lX\n", offset); mark_bad(mtd, offset); return -1; } } memcpy(buf, bon_part_magic, 8); s = (unsigned int *)(buf+8); *s++ = num_part; for (i = 0; i < num_part; i++) { for(k = 0; k < PARTNAMELEN / sizeof(int); k++) *s++ = *((int *)(parts[i].PartName + k * sizeof(int))); *s++ = parts[i].offset; *s++ = parts[i].size; *s++ = parts[i].flag; } for (i = 0; i < num_part; i++) { *s++ = parts[i].num_bad_block; for (k = 0; k < parts[i].num_bad_block; k++) { *s++ = parts[i].bad_blocks[k]; printf("k = %d block = %d\n", k, parts[i].bad_blocks[k]); } } //read two if(nand_rw(mtd, NANDRW_WRITE, offset, NAND_SECTOR_SIZE, &retlen, buf)) { return -1; } if (retlen != NAND_SECTOR_SIZE) { printf("write error: offset = %lu %x %x\n", offset, retlen, NAND_SECTOR_SIZE); return -1; } return 0;}int write_partition_table(struct nand_chip *mtd){ int i, k; unsigned long offset = PARTITION_OFFSET; unsigned long PartInfoOff; if (offset > mtd->totlen - mtd->erasesize) offset = mtd->totlen - mtd->erasesize; if (write_partition(mtd, offset, &PartInfoOff) != 0) { printf("can not write bon partition info\n"); return -1; } for (i = 0; i < num_part; i++) { printf("\t\t---part:%d----\n", i+1); printf("\tpartname= %s\n", parts[i].PartName); printf("\toffset = %ld\n", parts[i].offset); if(!num_part) parts[i].size -= 32 * NAND_SECTOR_SIZE; printf("\tsize = %ld\n", parts[i].size - parts[i].num_bad_block * 32 * NAND_SECTOR_SIZE); printf("\tbad_block_count = %ld\n", parts[i].num_bad_block); printf("\tflag = %ld\n", parts[i].flag); if(parts[i].num_bad_block) { printf("\tbad_block_num = "); for (k = 0; k < parts[i].num_bad_block; k++) { printf(" %d", parts[i].bad_blocks[k]); } printf("\n"); } } return 0;}void display_partition_table(void){ int i = 0; if (read_bon_partition(nand_dev_desc)) { printf("Invalid partition table info\n"); return; } printf("BON info. (%d partitions)\n", num_part); printf("No: name offset size(BYTE) flags bad size(K)\n"); printf("-----------------------------------------------------------------------\n"); for (i = 0; i < num_part; i++) { printf("%2d: %12s 0x%8lx\t %8ld %-7s %3ld %ld\n", i + 1, parts[i].PartName, parts[i].offset, parts[i].size, parts[i].flag ? "bon":"non_bon", parts[i].num_bad_block, parts[i].size / 1024); }}static void display_help(void){ printf("Usage:\n"); printf("\tsjpgpart info: show available part on nand\n"); printf("\tsjpgpart creat partsize(unit = M or K) partname {non_bon_flag = 1}: craet bon partion\n"); printf("\tsjpgpart write partnum srcoff writesize: write image to bon partion, unit = byte\n"); printf("\tsjpgpart read partnum objoff readsize: read image form bon partion, unit = byte\n");}void check_bad_block(struct nand_chip *mtd){ int i; unsigned short bad_block[1024]; for (i = 0; i < num_part; i++) { ulong offset = parts[i].offset; ulong end = parts[i].size + parts[i].offset; int num_bad = 0; int bad; if(end > mtd->totlen - mtd->erasesize) { end = mtd->totlen - mtd->erasesize; parts[i].size = end - parts[i].offset; } printf("part = %d end = %ld\n", i, end); while (offset < end) { bad = check_block1(mtd, offset); if (bad) { bad_block[num_bad] = (offset - parts[i].offset) /\ mtd->erasesize; num_bad++; printf("%lX: is bad\n", offset); } offset += mtd->erasesize; } parts[i].num_bad_block = num_bad;#if 0 // ???? - bushi parts[i].flag = 0;#endif if (num_bad) { parts[i].bad_blocks = mmalloc(num_bad * sizeof(unsigned short)); memcpy(parts[i].bad_blocks, bad_block, num_bad * 2); parts[i].size = end - parts[i].offset - num_bad * mtd->erasesize; } else parts[i].bad_blocks = NULL; }}static void command_part(int argc, const char **argv){ struct nand_chip *mtd = nand_dev_desc; unsigned long ret; int partnum; long offset; long size; if ((argc == 2) && ((strncmp("info", argv[1], 4) == 0) || (strncmp("show", argv[1], 4) == 0))) { display_partition_table(); return; } read_bon_partition(nand_dev_desc); /* write partition table */ if(strncmp("creat", argv[1], 5) == 0) { if(num_part >= 10) { printf("only can create 10 partitions!\n"); return; } printf("creating partition\n"); ret = 0; if(read_size((char *)argv[2], &ret) < 0) return; parts[num_part].size = ret; if(!num_part) parts[num_part].offset = mtd->totlen - mtd->erasesize - ret; else parts[num_part].offset = parts[num_part - 1].offset - ret; printf("size = %ld\n", parts[num_part].size); memset(parts[num_part].PartName, 0, PARTNAMELEN); strncpy(parts[num_part].PartName, argv[3], PARTNAMELEN - 1); printf("name - %s\n", parts[num_part].PartName, argc); if(argc > 4) parts[num_part].flag = 0; else parts[num_part].flag = 1; num_part++; printf("check bad block\n"); check_bad_block(mtd); write_partition_table(mtd); } else if(strncmp("write", argv[1], 5) == 0) { printf("Writing Image to partition\n"); partnum = (int)simple_strtoul(argv[2], NULL, 10); offset = (int)simple_strtoul(argv[3], NULL, 16); size = (int)simple_strtoul(argv[4], NULL, 16); printf("part num =%d\n", partnum); printf("source offset = %lx\n", offset); write_bon_image(mtd, partnum, (char *)offset, size); } else if(strncmp("read", argv[1], 4) == 0) { printf("reading Image form partition\n"); partnum = (int)simple_strtoul(argv[2], NULL, 10); offset = (int)simple_strtoul(argv[3], NULL, 16); size = (int)simple_strtoul(argv[4], NULL, 16); printf("source offset = %lx\n", offset); read_bon_image(mtd, partnum, (char *)offset, size); } else printf("invalid sjpgpart command\n");}void command_bon(cmd_tbl_t *cmdtp, int flag, int argc, const char **argv){ if (strncmp("help", argv[1], 4) == 0) { display_help(); return; } if (argc == 1) { display_help(); return; } command_part(argc, argv); return;}U_BOOT_CMD( part, 6, 1, command_bon, "part- part sub-system\n", " info: show available part on nand\n" " creat partsize(unit = M or K) partname {non_bon_flag = 1}: craet bon partion\n" " write partnum srcoff size: write image to bon partion, unit = byte\n" " read partnum objoff size: read image from bon partion, unit = byte\n");#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -