/* * 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 #include #include #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= 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_iu16_PartCnt; u16_i++) { for(u16_j=0; u16_jrecords[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_iu16_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;ndev, 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; ndev, 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;ndev, 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