diff --git a/tulip-common/sunxi-nand-part/Android.mk b/tulip-common/sunxi-nand-part/Android.mk new file mode 100644 index 0000000..10ab48a --- /dev/null +++ b/tulip-common/sunxi-nand-part/Android.mk @@ -0,0 +1,12 @@ +## +## Sources are taken from https://github.com/linux-sunxi/sunxi-tools +## + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := nand-part-main.c nand-part.c +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ +LOCAL_CFLAGS := -DA64 +LOCAL_MODULE = sunxi-nand-part +include $(BUILD_HOST_EXECUTABLE) diff --git a/tulip-common/sunxi-nand-part/include/list.h b/tulip-common/sunxi-nand-part/include/list.h new file mode 100644 index 0000000..88185ce --- /dev/null +++ b/tulip-common/sunxi-nand-part/include/list.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2012 Alejandro Mery + * + * 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, see . + */ +#ifndef _SUNXI_TOOLS_LIST_H +#define _SUNXI_TOOLS_LIST_H + +/* + * list + */ + +/** a list hook */ +struct list_entry { + struct list_entry *prev; + struct list_entry *next; +}; + +/** initialize an empty list hook */ +static inline void list_init(struct list_entry *self) +{ + self->prev = self->next = self; +} + +/** puts an entry between two other on a list */ +static inline void list_inject(struct list_entry *l, + struct list_entry *prev, + struct list_entry *next) +{ + l->prev = prev; + l->next = next; + + next->prev = l; + prev->next = l; +} + +#define list_insert(H, E) list_inject((E), (H), (H)->next) +#define list_append(H, E) list_inject((E), (H)->prev, (H)) + +/** removes an entry for the list where it's contained */ +static inline void list_remove(struct list_entry *l) +{ + struct list_entry *prev = l->prev, *next = l->next; + next->prev = prev; + prev->next = next; +} + +/** returns first element of a list */ +static inline struct list_entry *list_first(struct list_entry *l) +{ + return (l->next == l) ? NULL : l->next; +} + +/** returns last element of a list */ +static inline struct list_entry *list_last(struct list_entry *l) +{ + return (l->prev == l) ? NULL : l->prev; +} + +/** returns next element on a list */ +static inline struct list_entry *list_next(struct list_entry *l, + struct list_entry *e) +{ + return (e->next == l) ? NULL : e->next; +} + +/** is list empty? */ +static inline int list_empty(struct list_entry *l) +{ + return (l->prev == l); +} + +#endif /* _SUNXI_TOOLS_LIST_H */ diff --git a/tulip-common/sunxi-nand-part/include/portable_endian.h b/tulip-common/sunxi-nand-part/include/portable_endian.h new file mode 100644 index 0000000..2b43378 --- /dev/null +++ b/tulip-common/sunxi-nand-part/include/portable_endian.h @@ -0,0 +1,118 @@ +// "License": Public Domain +// I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like. +// In case there are jurisdictions that don't support putting things in the public domain you can also consider it to +// be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it +// an example on how to get the endian conversion functions on different platforms. + +#ifndef PORTABLE_ENDIAN_H__ +#define PORTABLE_ENDIAN_H__ + +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) + +# define __WINDOWS__ + +#endif + +#if defined(__linux__) || defined(__CYGWIN__) + +# include + +#elif defined(__APPLE__) + +# include + +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) + +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) + +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#elif defined(__OpenBSD__) + +# include + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) + +# include + +# define be16toh(x) betoh16(x) +# define le16toh(x) letoh16(x) + +# define be32toh(x) betoh32(x) +# define le32toh(x) letoh32(x) + +# define be64toh(x) betoh64(x) +# define le64toh(x) letoh64(x) + +#elif defined(__WINDOWS__) + +# include +# include + +# if BYTE_ORDER == LITTLE_ENDIAN + +# define htobe16(x) htons(x) +# define htole16(x) (x) +# define be16toh(x) ntohs(x) +# define le16toh(x) (x) + +# define htobe32(x) htonl(x) +# define htole32(x) (x) +# define be32toh(x) ntohl(x) +# define le32toh(x) (x) + +# define htobe64(x) htonll(x) +# define htole64(x) (x) +# define be64toh(x) ntohll(x) +# define le64toh(x) (x) + +# elif BYTE_ORDER == BIG_ENDIAN + + /* that would be xbox 360 */ +# define htobe16(x) (x) +# define htole16(x) __builtin_bswap16(x) +# define be16toh(x) (x) +# define le16toh(x) __builtin_bswap16(x) + +# define htobe32(x) (x) +# define htole32(x) __builtin_bswap32(x) +# define be32toh(x) (x) +# define le32toh(x) __builtin_bswap32(x) + +# define htobe64(x) (x) +# define htole64(x) __builtin_bswap64(x) +# define be64toh(x) (x) +# define le64toh(x) __builtin_bswap64(x) + +# else + +# error byte order not supported + +# endif + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#else + +# error platform not supported + +#endif + +#endif diff --git a/tulip-common/sunxi-nand-part/include/types.h b/tulip-common/sunxi-nand-part/include/types.h new file mode 100644 index 0000000..de37eae --- /dev/null +++ b/tulip-common/sunxi-nand-part/include/types.h @@ -0,0 +1,46 @@ +/* + * (C) Copyright 2012 Henrik Nordstrom + * (C) Copyright 2012 Alejandro Mery + * + * 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 SUNXI_TYPES_H +#define SUNXI_TYPES_H + +#include + +#define __s8 int8_t +#define __s16 int16_t +#define __s32 int32_t +#define __s64 int64_t + +#define s8 int8_t +#define s16 int16_t +#define s32 int32_t +#define s64 int64_t + +#define __u8 uint8_t +#define __u16 uint16_t +#define __u32 uint32_t +#define __u64 uint64_t + +#define u8 uint8_t +#define u16 uint16_t +#define u32 uint32_t +#define u64 uint64_t + +#endif diff --git a/tulip-common/sunxi-nand-part/nand-common.h b/tulip-common/sunxi-nand-part/nand-common.h new file mode 100644 index 0000000..56767e5 --- /dev/null +++ b/tulip-common/sunxi-nand-part/nand-common.h @@ -0,0 +1,29 @@ +/* + * (C) Copyright 2013 + * Patrick H Wood, All rights reserved. + * + * 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 + * + */ + +#include "types.h" + +extern int nand_part_a10 (int argc, char **argv, const char *cmd, int fd, int force); +extern int nand_part_a20 (int argc, char **argv, const char *cmd, int fd, int force); +extern int checkmbrs_a10 (int fd); +extern int checkmbrs_a20 (int fd); +extern void usage (const char *cmd); +extern __u32 calc_crc32(void * buffer, __u32 length); diff --git a/tulip-common/sunxi-nand-part/nand-part-a64.h b/tulip-common/sunxi-nand-part/nand-part-a64.h new file mode 100644 index 0000000..b7a83bf --- /dev/null +++ b/tulip-common/sunxi-nand-part/nand-part-a64.h @@ -0,0 +1,83 @@ +/* + * 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 "softw411" +#define MBR_VERSION 0x200 +#define nand_part nand_part_a64 +#define checkmbrs checkmbrs_a64 + +#define MAX_PART_COUNT 120 //max part count +#define MBR_COPY_NUM 4 //mbr backup count + +#define MBR_START_ADDRESS (20*1024*1024) //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/tulip-common/sunxi-nand-part/nand-part-main.c b/tulip-common/sunxi-nand-part/nand-part-main.c new file mode 100644 index 0000000..5b144a5 --- /dev/null +++ b/tulip-common/sunxi-nand-part/nand-part-main.c @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2013 + * Patrick H Wood, All rights reserved. + * + * 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 + * + */ + +#include +#include +#include +#include +#include +#include "nand-common.h" + +int checkmbrs_a64(int fd); +int nand_part_a64(int argc, char **argv, const char *cmd, int fd, int force); + +void usage(const char *cmd) +{ + printf("usage: %s [-f a64] nand-device\n", cmd); + printf(" %s nand-device 'name2 len2 [usertype2]' ['name3 len3 [usertype3]'] ...\n", cmd); + printf(" %s [-f a64] nand-device start1 'name1 len1 [usertype1]' ['name2 len2 [usertype2]'] ...\n", cmd); +} + +typedef struct tag_CRC32_DATA +{ + __u32 CRC; //int的大小是32位 + __u32 CRC_32_Tbl[256]; //用来保存码表 +}CRC32_DATA_t; + +__u32 calc_crc32(void * buffer, __u32 length) +{ + __u32 i, j; + CRC32_DATA_t crc32; // + __u32 CRC32 = 0xffffffff; //设置初始值 + crc32.CRC = 0; + + for( i = 0; i < 256; ++i)//用++i以提高效率 + { + crc32.CRC = i; + for( j = 0; j < 8 ; ++j) + { + //这个循环实际上就是用"计算法"来求取CRC的校验码 + if(crc32.CRC & 1) + crc32.CRC = (crc32.CRC >> 1) ^ 0xEDB88320; + else //0xEDB88320就是CRC-32多项表达式的值 + crc32.CRC >>= 1; + } + crc32.CRC_32_Tbl[i] = crc32.CRC; + } + + CRC32 = 0xffffffff; //设置初始值 + for( i = 0; i < length; ++i) + { + CRC32 = crc32.CRC_32_Tbl[(CRC32^((unsigned char*)buffer)[i]) & 0xff] ^ (CRC32>>8); + } + //return CRC32; + return CRC32^0xffffffff; +} + +int main (int argc, char **argv) +{ + char *nand = "/dev/nand"; + const char *cmd = argv[0]; + int fd; + int force = 0; // force write even if magics and CRCs don't match + + argc--; + argv++; + + if (argc > 1) { + if (!strcmp(argv[0], "-f")) { + if (!strcasecmp(argv[1], "a64")) + force = 64; + else { + usage(cmd); + return -1; + } + argc -= 2; + argv += 2; + } + } + + if (argc > 0) { + nand = argv[0]; + argc--; + argv++; + } + fd = open(nand, O_RDWR); + if (fd < 0) { + fprintf(stderr, "failed to open %s: %s\n", nand, strerror(errno)); + usage(cmd); + return -2; + } + + if (force == 64) + return nand_part_a64 (argc, argv, cmd, fd, force); + + if (checkmbrs_a64(fd)) + return nand_part_a64 (argc, argv, cmd, fd, force); + + return -1; +} diff --git a/tulip-common/sunxi-nand-part/nand-part.c b/tulip-common/sunxi-nand-part/nand-part.c new file mode 100644 index 0000000..b337494 --- /dev/null +++ b/tulip-common/sunxi-nand-part/nand-part.c @@ -0,0 +1,329 @@ +/* + * mbr.c + * (C) Copyright 2012 + * Patrick H Wood, All rights reserved. + * Heavily modified from the Allwinner file drivers/block/sun4i_nand/nfd/mbr.c. + * (Allwinner copyright block retained below.) + * + * 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 + * + */ + +/* + * drivers/block/sun4i_nand/nfd/mbr.c + * (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 + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef __linux__ +# include +# include /* BLKRRPART */ +#endif +#include "nand-common.h" + +// so far, only known formats are for A10 and A20 +#if defined(A10) +# include "nand-part-a10.h" +#elif defined(A20) +# include "nand-part-a20.h" +#elif defined(A64) +# include "nand-part-a64.h" +#endif + +#define MAX_NAME 16 + +static void printmbrheader(MBR *mbr) +{ + printf("mbr: version 0x%08x, magic %8.8s\n", mbr->version, mbr->magic); +} + +static MBR *_get_mbr(int fd, int mbr_num, int force) +{ + MBR *mbr; + + /*request mbr space*/ + mbr = malloc(sizeof(MBR)); + if(mbr == NULL) + { + printf("%s : request memory fail\n",__FUNCTION__); + return NULL; + } + + /*get mbr from nand device*/ + lseek(fd,MBR_START_ADDRESS + MBR_SIZE*mbr_num,SEEK_SET); + if(read(fd,mbr,MBR_SIZE) == MBR_SIZE) + { + /*checksum*/ + printf("check partition table copy %d: ", mbr_num); + printmbrheader(mbr); + if (force) { + strncpy((char *)mbr->magic, MBR_MAGIC, 8); + mbr->version = MBR_VERSION; + return mbr; + } + if(strncmp((char *)mbr->magic, MBR_MAGIC, 8)) + { + printf("magic %8.8s is not %8s\n", mbr->magic, MBR_MAGIC); + return NULL; + } + if(mbr->version != MBR_VERSION) + { + printf("version 0x%08x is not 0x%08x\n", mbr->version, MBR_VERSION); + return NULL; + } + if(*(__u32 *)mbr == calc_crc32((__u32 *)mbr + 1,MBR_SIZE - 4)) + { + printf("OK\n"); + return mbr; + } + printf("BAD!\n"); + } + return NULL; +} + +static __s32 _free_mbr(MBR *mbr) +{ + if(mbr) + { + free(mbr); + mbr = 0; + } + + return 0; +} + +static void printmbr(MBR *mbr) +{ + unsigned int part_cnt; + + printmbrheader(mbr); + printf("%d partitions\n", mbr->PartCount); + for(part_cnt = 0; part_cnt < mbr->PartCount && part_cnt < MAX_PART_COUNT; part_cnt++) + { + printf("partition %2d: class = %12s, name = %12s, partition start = %8d, partition size = %8d user_type=%d\n", + part_cnt + 1, + mbr->array[part_cnt].classname, + mbr->array[part_cnt].name, + mbr->array[part_cnt].addrlo, + mbr->array[part_cnt].lenlo, + mbr->array[part_cnt].user_type); + } +} +int checkmbrs(int fd) +{ + 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, 0); + if (mbrs[i]) + mbr = mbrs[i]; + } + if (!mbr) { + printf("all partition tables are bad!\n"); + for (i = 0; i < MBR_COPY_NUM; i++) { + if (mbrs[i]) + _free_mbr(mbrs[i]); + } + return 0; + } + + printmbr(mbr); + for (i = 0; i < MBR_COPY_NUM; i++) { + if (mbrs[i]) + _free_mbr(mbrs[i]); + } + return 1; +} + +static int writembrs(int fd, char names[][MAX_NAME], __u32 start, __u32 *lens, unsigned int *user_types, int nparts, int partoffset, int force) +{ + unsigned int part_cnt = 0; + int i; + char yn = 'n'; + MBR *mbrs[MBR_COPY_NUM]; + MBR *mbr = NULL; + FILE *backup; + + memset((void *) mbrs, 0, sizeof(mbrs)); + for (i = 0; i < MBR_COPY_NUM; i++) { + mbrs[i] = _get_mbr(fd, i, force); + if (mbrs[i]) + mbr = mbrs[i]; + } + if (!mbr) { + printf("all partition tables are bad!\n"); + for (i = 0; i < MBR_COPY_NUM; i++) { + if (mbrs[i]) + _free_mbr(mbrs[i]); + } + return 0; + } + // back up mbr data + backup = fopen("nand_mbr.backup", "w"); + if (!backup) { + printf("can't open nand_mbr.backup to back up mbr data\n"); + for (i = 0; i < MBR_COPY_NUM; i++) { + if (mbrs[i]) + _free_mbr(mbrs[i]); + } + return 0; + } + + 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 %d' ", mbr->array[part_cnt].name, + mbr->array[part_cnt].lenlo, mbr->array[part_cnt].user_type); + } + fprintf(backup, "\n"); + fclose(backup); + + mbr->PartCount = nparts + partoffset; + if (partoffset) + start = mbr->array[0].addrlo + mbr->array[0].lenlo; + for(i = 0; i < nparts; i++) { + strcpy((char *)mbr->array[i+partoffset].name, names[i]); + strcpy((char *)mbr->array[i+partoffset].classname, "DISK"); + memset((void *) mbr->array[i+partoffset].res, 0, sizeof(mbr->array[i+partoffset].res)); + mbr->array[i+partoffset].user_type = user_types[i]; + mbr->array[i+partoffset].ro = 0; + mbr->array[i+partoffset].addrhi = 0; + mbr->array[i+partoffset].lenhi = 0; + mbr->array[i+partoffset].addrlo = start; + mbr->array[i+partoffset].lenlo = lens[i]; + start += lens[i]; + } + + printf("\nready to write new partition tables:\n"); + printmbr(mbr); + for (i = 0; i < MBR_COPY_NUM; i++) { + if (mbrs[i]) + _free_mbr(mbrs[i]); + } + printf("\nwrite new partition tables? (Y/N)\n"); + read(0, &yn, 1); + if (yn != 'Y' && yn != 'y') { + printf("aborting\n"); + return 0; + } + + for (i = 0; i < MBR_COPY_NUM; i++) { + mbr->index = i; + // calculate new checksum + *(__u32 *)mbr = calc_crc32((__u32 *)mbr + 1,MBR_SIZE - 4); + lseek(fd,MBR_START_ADDRESS + MBR_SIZE*i,SEEK_SET); + write(fd,mbr,MBR_SIZE); + } + +#ifdef __linux__ + if (ioctl(fd, BLKRRPART, NULL)) + perror("Failed rereading partition table"); +#endif + + return 1; +} + +int nand_part (int argc, char **argv, const char *cmd, int fd, int force) +{ + int partoffset = 0; + int i; + char names[MAX_PART_COUNT][MAX_NAME]; + __u32 lens[MAX_PART_COUNT]; + unsigned int user_types[MAX_PART_COUNT]; + __u32 start; + + + // parse name/len arguments + memset((void *) user_types, 0, sizeof(user_types)); + if (argc > 0) { + if (sscanf(argv[0], "%u", &start) != 1) { + partoffset++; + if (force) { + printf("if using -f, must set info for first partition\n"); + usage(cmd); + close(fd); + return -3; + } + } + else { + argc--; + argv++; + } + + if (start < MBR_SIZE * MBR_COPY_NUM / 512) { + printf("Partition 1 starting offset must be at least %d\n", MBR_SIZE * MBR_COPY_NUM / 512); + close(fd); + return -3; + } + + 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"); + usage(cmd); + close(fd); + return -3; + } + } + } + + checkmbrs(fd); + + if (argc > MAX_PART_COUNT - partoffset) { + printf("too many partitions specified (MAX 14)\n"); + usage(cmd); + close(fd); + return -2; + } + + + if (argc > 0) { + if (writembrs(fd, names, start, lens, user_types, argc, partoffset, force)) { + printf("\nverifying new partition tables:\n"); + checkmbrs(fd); +#ifdef __linux__ + printf("rereading partition table... returned %d\n", ioctl(fd, BLKRRPART, 0)); +#endif + } + } + close(fd); + + return 0; +} diff --git a/tulip-common/tulip-common.mk b/tulip-common/tulip-common.mk index 6ae90ff..35484d5 100755 --- a/tulip-common/tulip-common.mk +++ b/tulip-common/tulip-common.mk @@ -12,7 +12,9 @@ PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \ libion \ - setmacaddr + setmacaddr \ + sunxi-nand-part + # add for bluetooth addr PRODUCT_PROPERTY_OVERRIDES += \ ro.bt.bdaddr_path=/data/btaddr.txt