Add sunxi-nand-part
This commit is contained in:
parent
4e229831d5
commit
783b5ce307
9 changed files with 821 additions and 1 deletions
12
tulip-common/sunxi-nand-part/Android.mk
Normal file
12
tulip-common/sunxi-nand-part/Android.mk
Normal file
|
@ -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)
|
84
tulip-common/sunxi-nand-part/include/list.h
Normal file
84
tulip-common/sunxi-nand-part/include/list.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Alejandro Mery <amery@geeks.cl>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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 */
|
118
tulip-common/sunxi-nand-part/include/portable_endian.h
Normal file
118
tulip-common/sunxi-nand-part/include/portable_endian.h
Normal file
|
@ -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 <endian.h>
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
# include <libkern/OSByteOrder.h>
|
||||
|
||||
# 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 <sys/endian.h>
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
|
||||
# include <sys/endian.h>
|
||||
|
||||
# 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 <winsock2.h>
|
||||
# include <sys/param.h>
|
||||
|
||||
# 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
|
46
tulip-common/sunxi-nand-part/include/types.h
Normal file
46
tulip-common/sunxi-nand-part/include/types.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
|
||||
* (C) Copyright 2012 Alejandro Mery <amery@geeks.cl>
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
|
||||
#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
|
29
tulip-common/sunxi-nand-part/nand-common.h
Normal file
29
tulip-common/sunxi-nand-part/nand-common.h
Normal file
|
@ -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);
|
83
tulip-common/sunxi-nand-part/nand-part-a64.h
Normal file
83
tulip-common/sunxi-nand-part/nand-part-a64.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* drivers/block/sun4i_nand/nfd/mbr.h
|
||||
*
|
||||
* (C) Copyright 2007-2012
|
||||
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
||||
*
|
||||
* 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__
|
117
tulip-common/sunxi-nand-part/nand-part-main.c
Normal file
117
tulip-common/sunxi-nand-part/nand-part-main.c
Normal file
|
@ -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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#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;
|
||||
}
|
329
tulip-common/sunxi-nand-part/nand-part.c
Normal file
329
tulip-common/sunxi-nand-part/nand-part.c
Normal file
|
@ -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. <www.allwinnertech.com>
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#ifdef __linux__
|
||||
# include <sys/ioctl.h>
|
||||
# include <sys/mount.h> /* 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;
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue