580 lines
15 KiB
C
Executable File
580 lines
15 KiB
C
Executable File
/*
|
|
* See also Linux sources, fs/partitions/mac.h
|
|
*
|
|
* This file describes structures and values related to the standard
|
|
* Apple SCSI disk partitioning scheme. For more information see:
|
|
* http://developer.apple.com/techpubs/mac/Devices/Devices-126.html#MARKER-14-92
|
|
* Refined by rui.wang@mstarsemi.com
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <command.h>
|
|
#include <ide.h>
|
|
#include "part_emmc.h"
|
|
#include "../drivers/mstar/emmc/inc/api/drv_eMMC.h"
|
|
#include "../drivers/mstar/emmc/inc/common/eMMC.h"
|
|
|
|
/*
|
|
#if defined(CONFIG_CMD_IDE) || \
|
|
defined(CONFIG_CMD_MG_DISK) || \
|
|
defined(CONFIG_CMD_SCSI) || \
|
|
defined(CONFIG_CMD_SATA) || \
|
|
defined(CONFIG_CMD_USB) || \
|
|
defined(CONFIG_CMD_eMMC) || \
|
|
defined(CONFIG_SYSTEMACE)
|
|
*/
|
|
#if 1
|
|
|
|
/* stdlib.h causes some compatibility problems; should fixe these! -- wd */
|
|
#ifndef __ldiv_t_defined
|
|
typedef struct {
|
|
long int quot; /* Quotient */
|
|
long int rem; /* Remainder */
|
|
} ldiv_t;
|
|
extern ldiv_t ldiv (long int __numer, long int __denom);
|
|
# define __ldiv_t_defined 1
|
|
#endif
|
|
|
|
static int part_emmc_read_ddb (block_dev_desc_t *dev_desc, emmc_driver_desc_t *ddb_p);
|
|
static int part_emmc_read_pdb (block_dev_desc_t *dev_desc, int part, emmc_partition_t *pdb_p);
|
|
|
|
static int part_emmc_write_ddb (block_dev_desc_t *dev_desc, emmc_driver_desc_t *ddb_p);
|
|
static int part_emmc_write_pdb (block_dev_desc_t *dev_desc, int part, emmc_partition_t *pdb_p);
|
|
|
|
|
|
extern int get_NVRAM_start_sector(U32 *u32_startsector);
|
|
extern int get_NVRAM_max_part_count(void);
|
|
extern U32 eMMC_SearchDevNodeStartSector(void);
|
|
|
|
/*
|
|
* read Driver Descriptor Block
|
|
*/
|
|
static int part_emmc_read_ddb (block_dev_desc_t *dev_desc, emmc_driver_desc_t *ddb_p)
|
|
{
|
|
u32 u32_err;
|
|
|
|
#if defined(eMMC_FCIE_LINUX_DRIVER) && eMMC_FCIE_LINUX_DRIVER
|
|
if(0 == g_eMMCDrv.u32_PartDevNodeStartSector){
|
|
u32_err = eMMC_SearchDevNodeStartSector();
|
|
if(eMMC_ST_SUCCESS != u32_err){
|
|
printf ("** Err, %s **\n", __func__);
|
|
return (-1);
|
|
}
|
|
}
|
|
#endif
|
|
printf("read_ddb from: 0x%Xh\n", (unsigned int)g_eMMCDrv.u32_PartDevNodeStartSector);
|
|
|
|
u32_err = eMMC_ReadData((uchar*)ddb_p, 512, g_eMMCDrv.u32_PartDevNodeStartSector);
|
|
if(eMMC_ST_SUCCESS != u32_err){
|
|
printf ("** Can't read Driver Desriptor Block **\n");
|
|
return (-1);
|
|
}
|
|
|
|
if (ddb_p->signature != EMMC_DRIVER_MAGIC) {
|
|
printf ("** Bad Signature: expected 0x%04x, got 0x%04x\n",
|
|
EMMC_DRIVER_MAGIC, ddb_p->signature);
|
|
return (-1);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* read Partition Descriptor Block
|
|
*/
|
|
static int part_emmc_read_pdb (block_dev_desc_t *dev_desc, int part_index, emmc_partition_t *pdb_p)
|
|
{
|
|
u32 u32_err;
|
|
int part=part_index+=1;
|
|
|
|
u32_err = eMMC_ReadData((uchar*)pdb_p, 512,
|
|
g_eMMCDrv.u32_PartDevNodeStartSector + part);
|
|
|
|
if(eMMC_ST_SUCCESS != u32_err){
|
|
printf ("** Can't read Driver Desriptor Block **\n");
|
|
return (-1);
|
|
}
|
|
|
|
// if (pdb_p->signature != EMMC_PARTITION_MAGIC) {
|
|
// //printf ("** Bad Signature: "
|
|
// // "expected 0x%04x, got 0x%04x\n",
|
|
// // EMMC_PARTITION_MAGIC, pdb_p->signature);
|
|
// return (-1);
|
|
// }
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int part_emmc_write_ddb (block_dev_desc_t *dev_desc, emmc_driver_desc_t *ddb_p)
|
|
{
|
|
u32 u32_err;
|
|
|
|
if(ddb_p->signature != EMMC_DRIVER_MAGIC){
|
|
printf ("** Bad Signature: expected 0x%04x, try to write 0x%04x **\n",
|
|
EMMC_DRIVER_MAGIC, ddb_p->signature);
|
|
return (-1);
|
|
}
|
|
|
|
printf("write_ddb into: 0x%Xh\n",(unsigned int) g_eMMCDrv.u32_PartDevNodeStartSector);
|
|
u32_err = eMMC_WriteData((uchar*)ddb_p, 512, g_eMMCDrv.u32_PartDevNodeStartSector);
|
|
if(eMMC_ST_SUCCESS != u32_err){
|
|
printf ("** Can't read Driver Desriptor Block **\n");
|
|
return (-1);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int part_emmc_write_pdb (block_dev_desc_t *dev_desc, int part_index, emmc_partition_t *pdb_p)
|
|
{
|
|
u32 u32_err;
|
|
int part=part_index+=1;
|
|
|
|
printf("part_emmc_write_pdb : 0x%X\r\n",(unsigned int) g_eMMCDrv.u32_PartDevNodeStartSector + part);
|
|
|
|
u32_err = eMMC_WriteData((uchar*)pdb_p, 512,
|
|
g_eMMCDrv.u32_PartDevNodeStartSector + part);
|
|
|
|
if(eMMC_ST_SUCCESS != u32_err){
|
|
printf ("** Can't read Driver Desriptor Block **\n");
|
|
return (-1);
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
static emmc_driver_desc_t ddesc;
|
|
static emmc_partition_t mpart;
|
|
|
|
int test_part_emmc (block_dev_desc_t *dev_desc)
|
|
{
|
|
if (part_emmc_read_ddb (dev_desc, &ddesc)) {
|
|
/* error reading Driver Desriptor Block, or no valid Signature */
|
|
return (-1);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
|
|
|
|
void print_part_emmc (block_dev_desc_t *dev_desc)
|
|
{
|
|
ulong u32_i;
|
|
ulong bytes;
|
|
char c;
|
|
|
|
if(part_emmc_read_ddb (dev_desc, &ddesc)) {
|
|
return;
|
|
}
|
|
|
|
|
|
for(u32_i=0; u32_i<get_NVRAM_max_part_count(); u32_i++)
|
|
{
|
|
if(part_emmc_read_pdb(dev_desc, u32_i, &mpart) )
|
|
return;
|
|
|
|
if( mpart.signature == EMMC_PARTITION_MAGIC)
|
|
{
|
|
c = 'k';
|
|
bytes = mpart.block_count;
|
|
bytes /= (1024 / 512); /* kB; assumes blk_size == 512 */
|
|
if (bytes >= 1024) {
|
|
bytes >>= 10;
|
|
c = 'M';
|
|
}
|
|
if (bytes >= 1024) {
|
|
bytes >>= 10;
|
|
c = 'G';
|
|
}
|
|
printf("%20.32s %-18.32s %4u %10u @ %-10u (%3ld%c)\n",
|
|
mpart.type, mpart.name, (unsigned int)(u32_i+1), (unsigned int)(mpart.block_count),
|
|
mpart.start_block, bytes, c);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int get_partition_info_emmc (block_dev_desc_t *dev_desc, int part_index, disk_partition_t *info)
|
|
{
|
|
|
|
if(part_index < 0){
|
|
printf("err, part number: %d\n", part_index);
|
|
return -1;
|
|
}
|
|
|
|
if(part_emmc_read_ddb (dev_desc, &ddesc)) {
|
|
return (-1);
|
|
}
|
|
|
|
if (part_emmc_read_pdb (dev_desc, part_index, &mpart)) {
|
|
return (-1);
|
|
}
|
|
|
|
if(mpart.signature != EMMC_PARTITION_MAGIC)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
info->blksz = ddesc.blk_size;
|
|
info->start = mpart.start_block;
|
|
info->size = mpart.block_count;
|
|
memcpy (info->type, mpart.type, sizeof(info->type));
|
|
memcpy (info->name, mpart.name, sizeof(info->name));
|
|
|
|
return (0);
|
|
}
|
|
|
|
#if 0
|
|
extern char *gpas8_eMMCPartName[];
|
|
int add_emmc_partitions(block_dev_desc_t *dev_desc, disk_partition_t *info)
|
|
{
|
|
int ret;
|
|
eMMC_PNI_t *pPartInfo = (eMMC_PNI_t*)gau8_eMMC_PartInfoBuf;
|
|
u16 u16_i, u16_j, u16_pdb_cnt=0;
|
|
u8 u8_i;
|
|
|
|
//printf("%X %X\n", sizeof(emmc_driver_desc_t), sizeof(emmc_partition_t));
|
|
printf("add_emmc_partitions\r\n");
|
|
|
|
if(part_emmc_read_ddb(dev_desc, &ddesc)){
|
|
printf("Need write new driver description table!\n");
|
|
|
|
|
|
|
|
ddesc.signature = EMMC_DRIVER_MAGIC;
|
|
ddesc.blk_size = 0x200;
|
|
ddesc.blk_count = g_eMMCDrv.u32_SEC_COUNT;
|
|
ret = part_emmc_write_ddb(dev_desc, &ddesc);
|
|
if(ret){
|
|
printf("Error during write new driver description table!\n");
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
u8_i = 0;
|
|
for(u16_i=0; u16_i<pPartInfo->u16_PartCnt; u16_i++)
|
|
{
|
|
for(u16_j=0; u16_j<EMMC_RESERVED_FOR_MAP; u16_j++)
|
|
{
|
|
if((u16_j|eMMC_LOGI_PART) == pPartInfo->records[u16_i].u16_PartType
|
|
)//||(u16_i|eMMC_LOGI_PART|eMMC_HIDDEN_PART) == pPartInfo->records[u16_j].u16_PartType)
|
|
{
|
|
mpart.signature = EMMC_PARTITION_MAGIC;
|
|
sprintf((char *)mpart.name, "%s",
|
|
gpas8_eMMCPartName[u8_i]);//, pPartInfo->records[u16_j].u16_PartType);
|
|
u8_i++;
|
|
mpart.start_block =
|
|
pPartInfo->records[u16_i].u16_StartBlk * pPartInfo->u16_BlkPageCnt;
|
|
mpart.block_count =
|
|
pPartInfo->records[u16_i].u16_BlkCnt * pPartInfo->u16_BlkPageCnt;
|
|
|
|
u16_pdb_cnt++;
|
|
ret = part_emmc_write_pdb(dev_desc, u16_pdb_cnt, &mpart);
|
|
if(ret)
|
|
{
|
|
printf("Error during write new partition description table! %Xh\n",
|
|
u16_pdb_cnt);
|
|
return ret;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int remove_emmc_partitions(block_dev_desc_t *dev_desc, disk_partition_t *info)
|
|
{
|
|
int ret;
|
|
|
|
eMMC_PNI_t *pPartInfo = (eMMC_PNI_t*)gau8_eMMC_PartInfoBuf;
|
|
u16 u16_i, u16_pdb_cnt=0;
|
|
|
|
if(part_emmc_read_ddb(dev_desc, &ddesc)){
|
|
printf("Haven't driver description table!\n");
|
|
return (-1);
|
|
}
|
|
|
|
for(u16_i=0; u16_i<pPartInfo->u16_PartCnt; u16_i++){
|
|
if(pPartInfo->records[u16_i].u16_PartType & eMMC_LOGI_PART)
|
|
{
|
|
mpart.signature = ~EMMC_PARTITION_MAGIC;
|
|
|
|
u16_pdb_cnt++;
|
|
ret = part_emmc_write_pdb(dev_desc, u16_pdb_cnt, &mpart);
|
|
if(ret){
|
|
printf("Error during write new partition description table! %Xh\n",
|
|
u16_pdb_cnt);
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
int init_NVRAM_pdb(void)
|
|
{
|
|
|
|
int ret;
|
|
ddesc.signature = EMMC_DRIVER_MAGIC;
|
|
ddesc.blk_size = 0x200;
|
|
ddesc.blk_count = g_eMMCDrv.u32_SEC_COUNT;
|
|
ret = part_emmc_write_ddb(NULL, &ddesc);
|
|
if(ret){
|
|
printf("Error during write new driver description table!\n");
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int add_NVRAM_pdb (block_dev_desc_t *dev_desc, emmc_partition_t *pdb_p)
|
|
{
|
|
int n = 0;
|
|
int part_idx=-1;
|
|
emmc_partition_t exist_pdb;
|
|
BOOLEAN vacancy_found=FALSE;
|
|
// ulong special_start;
|
|
ulong start_block, nvram_start_sector = 0;//EMMC_PARTITION_START;
|
|
|
|
if(0!=get_NVRAM_start_sector(&start_block))
|
|
{
|
|
printf("get EMMC NVRAM partition start_sector failed...\n");
|
|
return -1;
|
|
}
|
|
|
|
nvram_start_sector=start_block;
|
|
|
|
if(pdb_p->signature != EMMC_PARTITION_MAGIC){
|
|
printf ("** Bad Signature: expected 0x%04x, try to write 0x%04x **\n",
|
|
EMMC_PARTITION_MAGIC, pdb_p->signature);
|
|
return (-1);
|
|
}
|
|
|
|
// special_start = pdb_p->start_block;
|
|
vacancy_found=FALSE;
|
|
part_idx=-1;
|
|
//let us loop to found the correct start_block...
|
|
for (n=0;n<get_NVRAM_max_part_count();n++) {
|
|
|
|
if (0!=part_emmc_read_pdb(dev_desc, n, &exist_pdb)) {
|
|
printf ("** Can't read Partition Map on %d:%d **\n",
|
|
dev_desc->dev, n);
|
|
return (-1);
|
|
}
|
|
|
|
if(exist_pdb.signature == EMMC_PARTITION_MAGIC){
|
|
if(!strcmp((const char *)pdb_p->name, (const char *)exist_pdb.name)){
|
|
printf("** Partition %s existed...**\n", exist_pdb.name);
|
|
return -1;
|
|
}
|
|
// if(pdb_p->block_count > exist_pdb.block_count){
|
|
// printf("** The new size of the partition is too big!\n");
|
|
// return (-1);
|
|
// }
|
|
//
|
|
// if(special_start != 0)
|
|
// pdb_p->start_block = special_start;
|
|
// else
|
|
// pdb_p->start_block = exist_pdb.start_block;
|
|
//
|
|
// if(pdb_p->start_block + pdb_p->block_count > dev_desc->lba){
|
|
// printf("** Partition exceed emmc capacity**\n");
|
|
// return (-1);
|
|
// }
|
|
//
|
|
// if(dev_desc->block_write(dev_desc->dev, n, 1, (ulong *)pdb_p) != 1){
|
|
// printf("** Can't write Driver Desiptor Block **\n");
|
|
// return (-1);
|
|
// }
|
|
// return (0);
|
|
// }
|
|
//
|
|
if(exist_pdb.start_block < start_block)
|
|
{
|
|
if( exist_pdb.start_block < nvram_start_sector)
|
|
{
|
|
printf("** Invalid start_block 0x%X of partition %s **\n",exist_pdb.start_block, exist_pdb.name);
|
|
return -1;
|
|
}
|
|
|
|
continue; //check next partition
|
|
}
|
|
|
|
if((exist_pdb.start_block-start_block) >= pdb_p->block_count)
|
|
{
|
|
// vacancy found!!
|
|
vacancy_found=TRUE;
|
|
}
|
|
else if(!vacancy_found)
|
|
{
|
|
start_block=exist_pdb.start_block+exist_pdb.block_count;
|
|
}
|
|
|
|
}
|
|
else if(-1==part_idx)
|
|
{
|
|
part_idx=n;
|
|
if(vacancy_found)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if(-1 == part_idx){
|
|
printf("** No vacancy record entry in NVRAM partition map...**\n");
|
|
return (-1);
|
|
}
|
|
|
|
pdb_p->start_block = start_block;
|
|
|
|
if(pdb_p->start_block + pdb_p->block_count > dev_desc->lba)
|
|
{
|
|
printf("** Partition exceed EMMC capacity**\n");
|
|
return (-1);
|
|
}
|
|
|
|
|
|
if(0!=part_emmc_write_pdb(dev_desc,part_idx,pdb_p) ){
|
|
printf("** Can't write Partition Map Block **\n");
|
|
return (-1);
|
|
}
|
|
return (0);
|
|
|
|
}
|
|
|
|
int create_new_NVRAM_partition(block_dev_desc_t *dev_desc, disk_partition_t *info)
|
|
{
|
|
|
|
|
|
int ret;
|
|
//eMMC_PNI_t *pPartInfo = (eMMC_PNI_t*)gau8_eMMC_PartInfoBuf;
|
|
emmc_partition_t pdb_base;
|
|
|
|
//printf("%X %X\n", sizeof(emmc_driver_desc_t), sizeof(emmc_partition_t));
|
|
//printf("add_emmc_partitions\r\n");
|
|
|
|
if(part_emmc_read_ddb(dev_desc, &ddesc)){
|
|
printf("Need write correct CIS first!!\n");
|
|
|
|
return -1;
|
|
}
|
|
|
|
pdb_base.signature = EMMC_PARTITION_MAGIC;
|
|
|
|
strcpy((char *)pdb_base.name, (const char *)info->name);
|
|
pdb_base.block_count = info->size;
|
|
pdb_base.start_block = info->start;
|
|
|
|
ret = add_NVRAM_pdb(dev_desc, &pdb_base);
|
|
if(ret){
|
|
printf("Error during create new partition record!\n");
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
int delete_NVRAM_all_partition(block_dev_desc_t *dev_desc)
|
|
{
|
|
|
|
int n = 0;
|
|
// emmc_driver_desc_t ddb;
|
|
emmc_partition_t exist_pdb, pdb;
|
|
|
|
memset(&pdb, 0, sizeof(emmc_partition_t));
|
|
|
|
if(part_emmc_read_ddb(dev_desc, &ddesc)){
|
|
printf("Need write correct CIS first!!\n");
|
|
|
|
return -1;
|
|
}
|
|
|
|
for (n=0; n<get_NVRAM_max_part_count(); n++)
|
|
{
|
|
|
|
if (0 != part_emmc_read_pdb(dev_desc, n, &exist_pdb))
|
|
{
|
|
printf ("** Can't read Partition Map on %d:%d for partition remove **\n", dev_desc->dev, n);
|
|
continue;
|
|
}
|
|
if(exist_pdb.signature == EMMC_PARTITION_MAGIC)
|
|
{
|
|
if( 0!= part_emmc_write_pdb(dev_desc,n,&pdb) )
|
|
{
|
|
printf("** failed to remove the partition %s **\n", exist_pdb.name);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
int remove_NVRAM_partition(block_dev_desc_t *dev_desc, disk_partition_t *info)
|
|
{
|
|
int n = 0;
|
|
// emmc_driver_desc_t ddb;
|
|
emmc_partition_t exist_pdb, pdb;
|
|
|
|
memset(&pdb,0,sizeof(emmc_partition_t));
|
|
|
|
if(part_emmc_read_ddb(dev_desc, &ddesc)){
|
|
printf("Need write correct CIS first!!\n");
|
|
|
|
return -1;
|
|
}
|
|
|
|
for (n=0;n<get_NVRAM_max_part_count();n++)
|
|
{
|
|
|
|
if (0!=part_emmc_read_pdb(dev_desc, n, &exist_pdb))
|
|
{
|
|
printf ("** Can't read Partition Map on %d:%d for partition remove **\n", dev_desc->dev, n);
|
|
return (-1);
|
|
}
|
|
if(exist_pdb.signature == EMMC_PARTITION_MAGIC){
|
|
if(!strcmp((const char *)info->name, (const char *)exist_pdb.name)){
|
|
if(0!=part_emmc_write_pdb(dev_desc,n,&pdb) )
|
|
{
|
|
printf("** failed to remove the partition %s **\n", exist_pdb.name);
|
|
return (-1);
|
|
}
|
|
return (0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(n == get_NVRAM_max_part_count()){
|
|
printf("partition %s not existed...**\n", info->name);
|
|
return (-1);
|
|
}
|
|
|
|
|
|
return (0);
|
|
}
|
|
|
|
|
|
#endif
|