diff --git a/Makefile b/Makefile index 5f8fb69..2086b9f 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CFLAGS += -std=c99 -D_POSIX_C_SOURCE=200112L CFLAGS += -Iinclude/ TOOLS = fexc bin2fex fex2bin bootinfo fel pio -TOOLS += nand-part +TOOLS += nand-part nand-part-a20 MISC_TOOLS = phoenix_info @@ -40,6 +40,9 @@ fel: fel.c %: %.c $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(filter %.c,$^) $(LIBS) +nand-part-a20: nand-part.c nand-part-a20.h + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ nand-part.c -D A20 $(LIBS) + fel-pio.bin: fel-pio.elf fel-pio.nm $(CROSS_COMPILE)objcopy -O binary fel-pio.elf fel-pio.bin diff --git a/nand-part-a20.h b/nand-part-a20.h new file mode 100644 index 0000000..6c4fe2a --- /dev/null +++ b/nand-part-a20.h @@ -0,0 +1,80 @@ +/* + * drivers/block/sun4i_nand/nfd/mbr.h + * + * (C) Copyright 2007-2012 + * Allwinner Technology Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __MBR_H__ +#define __MBR_H__ + +#include "types.h" + +#define MBR_MAGIC "" + +#define MAX_PART_COUNT 120 //max part count +#define MBR_COPY_NUM 4 //mbr backup count + +#define MBR_START_ADDRESS 0x0 //mbr start address +#define MBR_SIZE 1024*16 //mbr size +#define MBR_RESERVED (MBR_SIZE - 32 - (MAX_PART_COUNT * 128)) //mbr reserved space + +// extern struct __NandDriverGlobal_t NandDriverInfo; + +// extern struct __NandStorageInfo_t NandStorageInfo; + +#define DiskSize (SECTOR_CNT_OF_SINGLE_PAGE * PAGE_CNT_OF_PHY_BLK * BLOCK_CNT_OF_DIE * \ + DIE_CNT_OF_CHIP * NandStorageInfo.ChipCnt / 1024 * DATA_BLK_CNT_OF_ZONE) + + +struct nand_disk{ + unsigned long size; + unsigned long offset; + unsigned char type; +}; + +/* part info */ +typedef struct nand_tag_PARTITION{ + unsigned int addrhi; //起始地址, 以扇区为单位 + unsigned int addrlo; // + unsigned int lenhi; //长度 + unsigned int lenlo; // + unsigned char classname[16]; //次设备名 + unsigned char name[16]; //主设备名 + unsigned int user_type; //用户类型 + unsigned int keydata; //关键数据,要求量产不丢失 + unsigned int ro; //读写属性 + unsigned char res[68]; //保留数据,匹配分区信息128字节 +}__attribute__ ((packed))PARTITION; + +/* mbr info */ +typedef struct nand_tag_MBR{ + unsigned int crc32; // crc 1k - 4 + unsigned int version; // 版本信息, 0x00000100 + unsigned char magic[8]; //"softw411" + unsigned int copy; //分数 + unsigned int index; //第几个MBR备份 + unsigned int PartCount; //分区个数 + unsigned int stamp[1]; //对齐 + PARTITION array[MAX_PART_COUNT]; // + unsigned char res[MBR_RESERVED]; +}__attribute__ ((packed)) MBR; + +int mbr2disks(struct nand_disk* disk_array); + +#endif //__MBR_H__ diff --git a/nand-part.c b/nand-part.c index a7db88e..9645ff4 100644 --- a/nand-part.c +++ b/nand-part.c @@ -52,11 +52,18 @@ #include #include #include /* BLKRRPART */ -#include "nand-part.h" +#ifdef A20 +# include "nand-part-a20.h" +#else +# include "nand-part.h" +#endif #define MAX_NAME 16 -void printmbrheader(MBR *mbr); +static void printmbrheader(MBR *mbr) +{ + printf("mbr: version 0x%08x, magic %8.8s\n", mbr->version, mbr->magic); +} typedef struct tag_CRC32_DATA { @@ -94,11 +101,9 @@ __u32 calc_crc32(void * buffer, __u32 length) return CRC32^0xffffffff; } -MBR *_get_mbr(int fd, int mbr_num) +MBR *_get_mbr(int fd, int mbr_num, int force) { MBR *mbr; - const char * magic = "softw311"; - unsigned version = 0x100; /*request mbr space*/ mbr = malloc(sizeof(MBR)); @@ -115,16 +120,25 @@ MBR *_get_mbr(int fd, int mbr_num) /*checksum*/ printf("check partition table copy %d: ", mbr_num); printmbrheader(mbr); - if(strncmp((char *)mbr->magic, magic, 8)) + if (force) { + strncpy((char *)mbr->magic, MBR_MAGIC, 8); +#ifdef MBR_VERSION + mbr->version = MBR_VERSION; +#endif + return mbr; + } + if(strncmp((char *)mbr->magic, MBR_MAGIC, 8)) { - printf("magic %8.8s is not %8s\n", mbr->magic, magic); + printf("magic %8.8s is not %8s\n", mbr->magic, MBR_MAGIC); return NULL; } - if(mbr->version != version) +#ifdef MBR_VERSION + if(mbr->version != MBR_VERSION) { - printf("version 0x%08x is not 0x%08x\n", mbr->version, version); + printf("version 0x%08x is not 0x%08x\n", mbr->version, MBR_VERSION); return NULL; } +#endif if(*(__u32 *)mbr == calc_crc32((__u32 *)mbr + 1,MBR_SIZE - 4)) { printf("OK\n"); @@ -146,14 +160,9 @@ __s32 _free_mbr(MBR *mbr) return 0; } -void printmbrheader(MBR *mbr) -{ - printf("mbr: version 0x%08x, magic %8.8s\n", mbr->version, mbr->magic); -} - void printmbr(MBR *mbr) { - int part_cnt; + unsigned int part_cnt; printmbrheader(mbr); for(part_cnt = 0; part_cnt < mbr->PartCount && part_cnt < MAX_PART_COUNT; part_cnt++) @@ -172,14 +181,14 @@ void printmbr(MBR *mbr) } void checkmbrs(int fd) { - int part_cnt = 0; + unsigned int part_cnt = 0; int i; MBR *mbrs[MBR_COPY_NUM]; MBR *mbr = NULL; memset((void *) mbrs, 0, sizeof(mbrs)); for (i = 0; i < MBR_COPY_NUM; i++) { - mbrs[i] = _get_mbr(fd, i); + mbrs[i] = _get_mbr(fd, i, 0); if (mbrs[i]) mbr = mbrs[i]; } @@ -192,14 +201,7 @@ void checkmbrs(int fd) return; } - for(part_cnt = 0; part_cnt < mbr->PartCount && part_cnt < MAX_PART_COUNT; part_cnt++) - { - printf("partition %2d: name = %12s, partition start = %8d, partition size = %8d\n", - part_cnt, - mbr->array[part_cnt].name, - mbr->array[part_cnt].addrlo, - mbr->array[part_cnt].lenlo); - } + printmbr(mbr); for (i = 0; i < MBR_COPY_NUM; i++) { if (mbrs[i]) _free_mbr(mbrs[i]); @@ -207,11 +209,10 @@ void checkmbrs(int fd) printf("%d partitions\n", part_cnt); } -int writembrs(int fd, char names[][MAX_NAME], __u32 *lens, unsigned int *user_types, int nparts) +int writembrs(int fd, char names[][MAX_NAME], __u32 start, __u32 *lens, unsigned int *user_types, int nparts, int force) { - int part_cnt = 0; + unsigned int part_cnt = 0; int i; - __u32 start; char yn = 'n'; MBR *mbrs[MBR_COPY_NUM]; MBR *mbr = NULL; @@ -219,7 +220,7 @@ int writembrs(int fd, char names[][MAX_NAME], __u32 *lens, unsigned int *user_ty memset((void *) mbrs, 0, sizeof(mbrs)); for (i = 0; i < MBR_COPY_NUM; i++) { - mbrs[i] = _get_mbr(fd, i); + mbrs[i] = _get_mbr(fd, i, force); if (mbrs[i]) mbr = mbrs[i]; } @@ -242,39 +243,31 @@ int writembrs(int fd, char names[][MAX_NAME], __u32 *lens, unsigned int *user_ty return 0; } - for(part_cnt = 1; part_cnt < mbr->PartCount && part_cnt < MAX_PART_COUNT; part_cnt++) + fprintf(backup, "%d ", mbr->array[0].addrlo); + for(part_cnt = 0; part_cnt < mbr->PartCount && part_cnt < MAX_PART_COUNT; part_cnt++) { - fprintf(backup, "'%s %d' ", mbr->array[part_cnt].name, - mbr->array[part_cnt].lenlo); + fprintf(backup, "'%s %d %d' ", mbr->array[part_cnt].name, + mbr->array[part_cnt].lenlo, mbr->array[part_cnt].user_type); } fprintf(backup, "\n"); fclose(backup); - // don't muck with first partition - mbr->PartCount = nparts + 1; - start = mbr->array[0].addrlo + mbr->array[0].lenlo; + mbr->PartCount = nparts; for(i = 0; i < nparts; i++) { - strcpy((char *)mbr->array[i+1].name, names[i]); - strcpy((char *)mbr->array[i+1].classname, "DISK"); - memset((void *) mbr->array[i+1].res, 0, sizeof(mbr->array[i+1].res)); - mbr->array[i+1].user_type = user_types[i]; - mbr->array[i+1].ro = 0; - mbr->array[i+1].addrhi = 0; - mbr->array[i+1].lenhi = 0; - mbr->array[i+1].addrlo = start; - mbr->array[i+1].lenlo = lens[i]; + strcpy((char *)mbr->array[i].name, names[i]); + strcpy((char *)mbr->array[i].classname, "DISK"); + memset((void *) mbr->array[i].res, 0, sizeof(mbr->array[i].res)); + mbr->array[i].user_type = user_types[i]; + mbr->array[i].ro = 0; + mbr->array[i].addrhi = 0; + mbr->array[i].lenhi = 0; + mbr->array[i].addrlo = start; + mbr->array[i].lenlo = lens[i]; start += lens[i]; } printf("\nready to write new partition tables:\n"); - for(part_cnt = 0; part_cnt < mbr->PartCount && part_cnt < MAX_PART_COUNT; part_cnt++) - { - printf("partition %2d: name = %12s, partition start = %8d, partition size = %8d\n", - part_cnt, - mbr->array[part_cnt].name, - mbr->array[part_cnt].addrlo, - mbr->array[part_cnt].lenlo); - } + printmbr(mbr); for (i = 0; i < MBR_COPY_NUM; i++) { if (mbrs[i]) _free_mbr(mbrs[i]); @@ -304,16 +297,26 @@ int writembrs(int fd, char names[][MAX_NAME], __u32 *lens, unsigned int *user_ty int main (int argc, char **argv) { int fd; + int force = 0; // force write even if magics and CRCs don't match int i; char *nand = "/dev/nand"; char *cmd = argv[0]; char names[MAX_PART_COUNT][MAX_NAME]; __u32 lens[MAX_PART_COUNT]; unsigned int user_types[MAX_PART_COUNT]; + __u32 start; argc--; argv++; + if (argc > 0) { + if (!strcmp(argv[0], "-f")) { + force++; + argc--; + argv++; + } + } + if (argc > 0) { nand = argv[0]; argc--; @@ -321,17 +324,25 @@ int main (int argc, char **argv) } fd = open(nand, O_RDWR); if (fd < 0) { - printf("usage: %s nand-device 'name2 len2 [usertype2]' ['name3 len3 [usertype3]'] ...\n", cmd); + printf("usage: %s nand-device start1 'name1 len1 [usertype1]' ['name2 len2 [usertype2]'] ...\n", cmd); return -1; } // parse name/len arguments memset((void *) user_types, 0, sizeof(user_types)); if (argc > 0) { + if (sscanf(argv[0], "%u", &start) != 1) { + printf("bad start argument\n"); + printf("usage: %s nand-device start1 'name1 len1 [usertype1]' ['name2 len2' [usertype2]] ...\n", cmd); + close(fd); + return -1; + } + argc--; + argv++; for (i = 0; i < argc; i++) { if (sscanf(argv[i], "%s %d %d", names[i], &lens[i], &user_types[i]) < 2) { printf("bad 'name len' argument\n"); - printf("usage: %s nand-device 'name2 len2 [usertype2]' ['name3 len3 [usertype3]'] ...\n", cmd); + printf("usage: %s nand-device start1 'name1 len1 [usertype1]' ['name2 len2' [usertype2]] ...\n", cmd); close(fd); return -3; } @@ -340,16 +351,16 @@ int main (int argc, char **argv) checkmbrs(fd); - if (argc > MAX_PART_COUNT - 1) { + if (argc > MAX_PART_COUNT) { printf("too many partitions specified (MAX 14)\n"); - printf("usage: %s nand-device 'name2 len2 [usertype2]' ['name3 len3 [usertype3]'] ...\n", cmd); + printf("usage: %s nand-device start1 'name1 len1 [usertype1]' ['name2 len2 [usertype2]'] ...\n", cmd); close(fd); return -2; } if (argc > 0) { - if (writembrs(fd, names, lens, user_types, argc)) { + if (writembrs(fd, names, start, lens, user_types, argc, force)) { printf("\nverifying new partition tables:\n"); checkmbrs(fd); printf("rereading partition table... returned %d\n", ioctl(fd, BLKRRPART, 0)); diff --git a/nand-part.h b/nand-part.h index 2cac1bb..c35b458 100644 --- a/nand-part.h +++ b/nand-part.h @@ -25,6 +25,9 @@ #include "types.h" +#define MBR_MAGIC "softw311" +#define MBR_VERSION 0x100 + #define MAX_PART_COUNT 15 //max part count #define MBR_COPY_NUM 4 //mbr backup count