Add tool to repartition the NAND (WIP)
This commit is contained in:
parent
efc7efbf7a
commit
c8ae7438a7
321
mbr.c
Normal file
321
mbr.c
Normal file
@ -0,0 +1,321 @@
|
||||
/*
|
||||
* 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 "mbr.h"
|
||||
|
||||
#define MAX_NAME 16
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
MBR *_get_mbr(int fd, int mbr_num)
|
||||
{
|
||||
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);
|
||||
if(*(__u32 *)mbr == calc_crc32((__u32 *)mbr + 1,MBR_SIZE - 4))
|
||||
{
|
||||
printf("OK\n");
|
||||
return mbr;
|
||||
}
|
||||
printf("BAD!\n");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__s32 _free_mbr(MBR *mbr)
|
||||
{
|
||||
if(mbr)
|
||||
{
|
||||
free(mbr);
|
||||
mbr = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void checkmbrs(int fd)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
for(part_cnt = 0; part_cnt < mbr->PartCount && part_cnt < MAX_PART_COUNT; part_cnt++)
|
||||
{
|
||||
if((mbr->array[part_cnt].user_type == 2) || (mbr->array[part_cnt].user_type == 0))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MBR_COPY_NUM; i++) {
|
||||
if (mbrs[i])
|
||||
_free_mbr(mbrs[i]);
|
||||
}
|
||||
printf("%d partitions\n", part_cnt);
|
||||
}
|
||||
|
||||
int writembrs(int fd, char names[][MAX_NAME], __u32 *lens, int nparts)
|
||||
{
|
||||
int part_cnt = 0;
|
||||
int i;
|
||||
__u32 start;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
for(part_cnt = 1; part_cnt < mbr->PartCount && part_cnt < MAX_PART_COUNT; part_cnt++)
|
||||
{
|
||||
if((mbr->array[part_cnt].user_type == 2) || (mbr->array[part_cnt].user_type == 0))
|
||||
{
|
||||
fprintf(backup, "'%s %d' ", mbr->array[part_cnt].name,
|
||||
mbr->array[part_cnt].lenlo);
|
||||
}
|
||||
}
|
||||
fprintf(backup, "\n");
|
||||
fclose(backup);
|
||||
|
||||
// don't muck with first partition
|
||||
mbr->PartCount = nparts + 1;
|
||||
start = mbr->array[0].addrlo + mbr->array[0].lenlo;
|
||||
for(i = 0; i < nparts; i++) {
|
||||
strcpy((char *)mbr->array[i+1].name, names[i]);
|
||||
strcpy((char *)mbr->array[i+1].classname, "DISK");
|
||||
memset(mbr->array[i+1].res, 0, sizeof(mbr->array[i+1].res));
|
||||
mbr->array[i+1].user_type = 0;
|
||||
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];
|
||||
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++)
|
||||
{
|
||||
if((mbr->array[part_cnt].user_type == 2) || (mbr->array[part_cnt].user_type == 0))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MBR_COPY_NUM; i++) {
|
||||
if (mbrs[i])
|
||||
_free_mbr(mbrs[i]);
|
||||
}
|
||||
printf("%d partitions\n", part_cnt);
|
||||
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);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
int i;
|
||||
char *nand = "/dev/nand";
|
||||
char *cmd = argv[0];
|
||||
char names[MAX_PART_COUNT][MAX_NAME];
|
||||
__u32 lens[MAX_PART_COUNT];
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (argc > 0) {
|
||||
nand = argv[0];
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
fd = open(nand, O_RDWR);
|
||||
if (fd < 0) {
|
||||
printf("usage: %s nand-device \'name2 len2\' [\'name3 len3\'] ...\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// parse name/len arguments
|
||||
if (argc > 0) {
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (sscanf(argv[i], "%s %d", names[i], &lens[i]) != 2) {
|
||||
printf("bad 'name len' argument\n");
|
||||
printf("usage: %s nand-device \'name2 len2\' [\'name3 len3\'] ...\n", cmd);
|
||||
close(fd);
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkmbrs(fd);
|
||||
|
||||
if (argc > MAX_PART_COUNT - 1) {
|
||||
printf("too many partitions specified (MAX 14)\n");
|
||||
printf("usage: %s nand-device \'name2 len2\' [\'name3 len3\'] ...\n", cmd);
|
||||
close(fd);
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
if (argc > 0) {
|
||||
if (writembrs(fd, names, lens, argc)) {
|
||||
printf("\nverifying new partition tables:\n");
|
||||
checkmbrs(fd);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
76
mbr.h
Normal file
76
mbr.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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 "type_def.h"
|
||||
|
||||
#define MAX_PART_COUNT 15 //max part count
|
||||
#define MBR_COPY_NUM 4 //mbr backup count
|
||||
|
||||
#define MBR_START_ADDRESS 0x0 //mbr start address
|
||||
#define MBR_SIZE 1024 //mbr size
|
||||
#define MBR_RESERVED (MBR_SIZE - 20 - (MAX_PART_COUNT * 64)) //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 tag_PARTITION{
|
||||
__u32 addrhi; //start address high 32 bit
|
||||
__u32 addrlo; //start address low 32 bit
|
||||
__u32 lenhi; //size high 32 bit
|
||||
__u32 lenlo; //size low 32 bit
|
||||
__u8 classname[12]; //major device name
|
||||
__u8 name[12]; //minor device name
|
||||
unsigned int user_type; //标志当前盘符所属于的用户
|
||||
unsigned int ro; //标志当前盘符的读写属性
|
||||
__u8 res[16]; //reserved
|
||||
}PARTITION;
|
||||
|
||||
/* mbr info */
|
||||
typedef struct tag_MBR{
|
||||
__u32 crc32; // crc, from byte 4 to mbr tail
|
||||
__u32 version; // version
|
||||
__u8 magic[8]; // magic number
|
||||
__u8 copy; // mbr backup count
|
||||
__u8 index; // current part no
|
||||
__u16 PartCount; // part counter
|
||||
PARTITION array[MAX_PART_COUNT];// part info
|
||||
__u8 res[MBR_RESERVED]; // reserved space
|
||||
}MBR;
|
||||
|
||||
int mbr2disks(struct nand_disk* disk_array);
|
||||
|
||||
#endif //__MBR_H__
|
||||
59
type_def.h
Executable file
59
type_def.h
Executable file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* drivers/block/sun4i_nand/include/type_def.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 TYPE_DEF_H
|
||||
#define TYPE_DEF_H
|
||||
|
||||
//#include "sunii.h"
|
||||
// #include <linux/kernel.h>
|
||||
|
||||
//typedef signed char s8;
|
||||
//typedef unsigned char u8;
|
||||
//
|
||||
//typedef signed short s16;
|
||||
//typedef unsigned short u16;
|
||||
//
|
||||
//typedef signed int s32;
|
||||
//typedef unsigned int u32;
|
||||
//
|
||||
//typedef signed long s64;
|
||||
//typedef unsigned long u64;
|
||||
//
|
||||
typedef signed char __s8;
|
||||
typedef unsigned char __u8;
|
||||
//
|
||||
typedef signed short __s16;
|
||||
typedef unsigned short __u16;
|
||||
//
|
||||
typedef signed int __s32;
|
||||
typedef unsigned int __u32;
|
||||
//
|
||||
typedef signed long __s64;
|
||||
typedef unsigned long __u64;
|
||||
|
||||
typedef unsigned int __hdle;
|
||||
|
||||
#define EPDK_OK 0
|
||||
#define EPDK_FAIL -1
|
||||
|
||||
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user