bool find_mirror_pt_from_bottom(u64 *start_addr, struct mtd_info *mtd)
{
	int mpt_locate, i;
	u64 mpt_start_addr;
	u64 current_start_addr = 0;
	u8 pmt_spare[4];
	struct mtd_oob_ops ops_pt;

	mpt_start_addr = ((mtd->size) + block_size);
	/* mpt_start_addr=MPT_LOCATION*block_size-page_size; */
	memset(page_buf, 0xFF, page_size + mtd->oobsize);

	ops_pt.datbuf = (uint8_t *) page_buf;
	ops_pt.mode = MTD_OPS_AUTO_OOB;
	ops_pt.len = mtd->writesize;
	ops_pt.retlen = 0;
	ops_pt.ooblen = 16;
	ops_pt.oobretlen = 0;
	ops_pt.oobbuf = page_buf + page_size;
	ops_pt.ooboffs = 0;
	pr_debug("find_mirror find begain at %llx\n", mpt_start_addr);

	for (mpt_locate = ((block_size / page_size) - 1),
		i = ((block_size / page_size) - 1); mpt_locate >= 0; mpt_locate--) {
		memset(pmt_spare, 0xFF, PT_SIG_SIZE);

		current_start_addr = mpt_start_addr + mpt_locate * page_size;
		if (mtd->_read_oob(mtd, (loff_t) current_start_addr, &ops_pt) != 0) {
			pr_debug("find_mirror read  failed %llx %x\n", current_start_addr,
			       mpt_locate);
		}
		memcpy(pmt_spare, &page_buf[page_size], PT_SIG_SIZE);	/* auto do need skip bad block */
		/* need enhance must be the larget sequnce number */
#if 0
		{
			int i;

			for (i = 0; i < 8; i++)
				pr_debug("%x %x\n", page_buf[i], page_buf[2048 + i]);
		}
#endif
		if (is_valid_mpt(page_buf) && is_valid_mpt(pmt_spare)) {
			/* if no pt, pt.has space is 0; */
			pi.sequencenumber = page_buf[PT_SIG_SIZE + page_size];
			pr_debug("find_mirror find valid pt at %llx sq %x\n",
			       current_start_addr, pi.sequencenumber);
			break;
		}
		continue;
	}
	if (mpt_locate == -1) {
		pr_debug("no valid mirror page\n");
		pi.sequencenumber = 0;
		return FALSE;
	}
	*start_addr = current_start_addr;
	return TRUE;
}
示例#2
0
static int load_pt_from_fixed_addr(u8 *buf, part_dev_t *dev)
{
    int reval = ERR_NO_EXIST;
    u64 pt_start; 
    u64 mpt_start; 
    int pt_size = PMT_REGION_SIZE; 
    int buffer_size = pt_size; 

    pt_start = g_emmc_size - PMT_REGION_OFFSET;
    mpt_start = pt_start + PMT_REGION_SIZE;

    printf("============func=%s===scan pmt from %llx=====\n", __func__, pt_start);
    /* try to find the pmt at fixed address, signature:0x50547631 */

    dev->read(dev, pt_start, (u8*)page_buf, buffer_size); 
    if (is_valid_pt(page_buf)) {
        if (!memcmp(page_buf + PT_SIG_SIZE, PMT_VER_V1, PMT_VER_SIZE)) {
            if (is_valid_pt(&page_buf[pt_size - PT_SIG_SIZE])) {
                printf("find pt at %llx\n", pt_start); 
                memcpy(buf, page_buf + PT_SIG_SIZE + PMT_VER_SIZE, PART_MAX_COUNT * sizeof(pt_resident));
                reval = DM_ERR_OK;
                return reval;
            } else {
                printf("invalid tail pt format\n");
                reval = ERR_NO_EXIST;
            }
        } else {
            printf("invalid pt version %s\n", page_buf + PT_SIG_SIZE);
            reval = ERR_NO_EXIST;
        }
    }

    
    dev->read(dev, mpt_start, (u8*)page_buf, buffer_size); 
    if (is_valid_mpt(page_buf)) { 
        if (!memcmp(page_buf + PT_SIG_SIZE, PMT_VER_V1, PMT_VER_SIZE)) {
            if (is_valid_mpt(&page_buf[pt_size - PT_SIG_SIZE])) {
                printf("find mpt at %llx\n", mpt_start); 
                memcpy(buf, page_buf + PT_SIG_SIZE + PMT_VER_SIZE, PART_MAX_COUNT * sizeof(pt_resident));
                reval = DM_ERR_OK;
                return reval;
            } else {
                printf("invalid tail mpt format\n");
                reval = ERR_NO_EXIST;
            }
        } else {
            printf("invalid mpt version %s\n", page_buf + PT_SIG_SIZE);
            reval = ERR_NO_EXIST;
        }
    }

	return reval;      
}
示例#3
0
bool find_mirror_pt_from_bottom(int *start_addr)
{
	int mpt_locate;
	int mpt_start_addr= total_size +BLOCK_SIZE;//MPT_LOCATION*BLOCK_SIZE-PAGE_SIZE;
	int current_start_addr=0;
	char pmt_spare[4];
	
	for(mpt_locate=(BLOCK_SIZE/PAGE_SIZE);mpt_locate>0;mpt_locate--)
	{
		memset(pmt_spare,0xFF,PT_SIG_SIZE);
		memset(g_nand_spare,0xFF,64);
		current_start_addr = mpt_start_addr+mpt_locate*PAGE_SIZE;
		if(!mtk_nand_read_page_hwecc(current_start_addr, page_readbuf))
		{
			MSG (INIT, "find_mirror read  failed %x %x \n",current_start_addr,mpt_locate);
		}
		memcpy(pmt_spare,&g_nand_spare[1] ,PT_SIG_SIZE);
		//need enhance must be the larget sequnce number
		#if 0
		{
			int i;
			for(i=0;i<4;i++)
			MSG (INIT, " %x %x \n",page_readbuf[i],g_nand_spare[1+i]);	
			MSG (INIT,"%x %x " , *((u32*)page_readbuf), *((u32*)pmt_spare));
			MSG (INIT,"%x " , is_valid_mpt(page_readbuf));
			MSG (INIT,"%x \n" , is_valid_mpt(pmt_spare));
		}
		#endif
		if(is_valid_mpt(page_readbuf)&&is_valid_mpt(&pmt_spare))
		{
		      //if no pt, pt.has space is 0;
			pi.sequencenumber =  g_nand_spare[5];
			MSG (INIT, "find_mirror find valid pt at %x sq %x \n",current_start_addr,pi.sequencenumber);
			break;
		}
		else
		{
			continue;
		}
	}
	if(mpt_locate==0)
	{
		MSG (INIT, "no valid mirror page\n");
		pi.sequencenumber =  0;
		return FALSE;
	}
	else
	{
		*start_addr = current_start_addr;
		return TRUE;
	}
}
示例#4
0
bool find_mirror_pt_from_bottom(int *start_addr,part_dev_t *dev)
{
	int mpt_locate;
	int mpt_start_addr;
	int current_start_addr=0;
	char pmt_spare[4];
	mpt_start_addr = total_size+block_size;
	//mpt_start_addr=MPT_LOCATION*block_size-page_size;
	for(mpt_locate=(block_size/page_size);mpt_locate>0;mpt_locate--)
	{
		memset(pmt_spare,0xFF,PT_SIG_SIZE);
		
		current_start_addr = mpt_start_addr+mpt_locate*page_size;
		if(!dev->read(dev,current_start_addr, page_buf,page_size))
		{
			printf ("find_mirror read  failed %x %x \n",current_start_addr,mpt_locate);
		}
		memcpy(&page_buf[page_size],g_kCMD.au1OOB,16);
		memcpy(pmt_spare,&page_buf[page_size] ,PT_SIG_SIZE);
		//need enhance must be the larget sequnce number
		
		if(is_valid_mpt(page_buf)&&is_valid_mpt(&pmt_spare))
		{
		      //if no pt, pt.has space is 0;
			pi.sequencenumber = page_buf[PT_SIG_SIZE+page_size];
			printf ("find_mirror find valid pt at %x sq %x \n",current_start_addr,pi.sequencenumber);
			break;
		}
		else
		{
			continue;
		}
	}
	if(mpt_locate==0)
	{
		printf ("no valid mirror page\n");
		pi.sequencenumber =  0;
		return FALSE;
	}
	else
	{
		*start_addr = current_start_addr;
		return TRUE;
	}
}
示例#5
0
int load_exist_part_tab(u8 *buf,part_dev_t *dev)
{
		#ifdef MTK_EMMC_SUPPORT
			int reval = ERR_NO_EXIST;
			int index = 0;
			int i,j;
			int len=0;
			char *buf_p;
			int pt_start = g_user_virt_addr + 1024;
			int mpt_start = pt_start + 2048;
		
		
			int PAGE_SIZE = 512;
			pt_resident* lp_pmt;
		
		
			printf("============func=%s===scan pmt from %x=====\n", __func__,pt_start);
			/* try to find the pmt at fixed address, signature:0x50547631 */
			for(i=0;i<CFG_EMMC_PMT_SIZE/4096;i++)
			{
				buf_p = page_buf;
			  	dev->read(dev,pt_start + i*4096,(u8*)page_buf,4096);
			  	for(j=0;j<4096/PAGE_SIZE;j++){
			  	
			//	printf("search %x %x\n",buf_p,pt_start + i*4096+j*PAGE_SIZE);
					if(is_valid_pt(buf_p)){
				
						printf("find h-pt at %x \n",pt_start + i*4096+j*PAGE_SIZE);
						if(j*PAGE_SIZE > 2048){
							len = 4096- j*PAGE_SIZE;
							printf("left %d j=%d\n",len,j);
							memcpy(backup_buf,&buf_p[PT_SIG_SIZE],len-PT_SIG_SIZE);
							dev->read(dev,pt_start + (i+1)*4096,(u8*)page_buf,2048);
							if(is_valid_pt(&page_buf[2048-4-len])){
								printf("find pt at %x \n",pt_start + i*4096+j*PAGE_SIZE);
								memcpy(&backup_buf[len-PT_SIG_SIZE],page_buf,sizeof(lastest_part)-len+PT_SIG_SIZE);
								memcpy(buf,backup_buf,sizeof(lastest_part));
								reval=DM_ERR_OK;
								goto find;//return reval;
							}
							
						}else{
							if(is_valid_pt(&buf_p[2048-4])){
								printf("find pt at %x \n",pt_start + i*4096+j*PAGE_SIZE);
								memcpy(buf,&buf_p[PT_SIG_SIZE],sizeof(lastest_part));
								reval=DM_ERR_OK;
								goto find;//return reval;
							}
						}
						break;
					}
				buf_p += PAGE_SIZE;
			  }
			}
			if(i == CFG_EMMC_PMT_SIZE/4096)
			{
				for(i=0;i<CFG_EMMC_PMT_SIZE/4096;i++){
				/* try to find the backup pmt at fixed address, signature:0x4d505431 */
				buf_p = page_buf;
				dev->read(dev,mpt_start + i*4096,(u8*)page_buf,4096);
				
				for(j=0;j<4096/PAGE_SIZE;j++){

					if(is_valid_mpt(buf_p)){
				
						printf("find h-pt at %x \n",mpt_start + i*4096+j*PAGE_SIZE);
						if(j*PAGE_SIZE > 2048){
							len = 4096- j*PAGE_SIZE;
							printf("left %d j=%d\n",len,j);
							memcpy(backup_buf,&buf_p[PT_SIG_SIZE],len-PT_SIG_SIZE);
							dev->read(dev,mpt_start + (i+1)*4096,(u8*)page_buf,2048);
							if(is_valid_mpt(&page_buf[2048-4-len])){
								printf("find mpt at %x \n",pt_start + i*4096+j*PAGE_SIZE);
								memcpy(&backup_buf[len-PT_SIG_SIZE],page_buf,sizeof(lastest_part)-len+PT_SIG_SIZE);
								memcpy(buf,backup_buf,sizeof(lastest_part));
								reval=DM_ERR_OK;
								goto find;//return reval;
							}
							
						}else{
							if(is_valid_mpt(&buf_p[2048-4])){
								printf("find mpt at %x \n",mpt_start + i*4096+j*PAGE_SIZE);
								memcpy(buf,&buf_p[PT_SIG_SIZE],sizeof(lastest_part));
								reval=DM_ERR_OK;
								goto find;//return reval;
							}
						}
						break;
					}
					buf_p += PAGE_SIZE;
				}
				}
				
				}
			if(i == CFG_EMMC_PMT_SIZE/4096)
				printf("find no pt or mpt\n");
			return reval;
		find:

		if(g_emmc_size<0x100000000){ //32bit
			printf("32bit parse PMT\n");
			memcpy(&lastest_part32,buf,PART_MAX_COUNT*sizeof(pt_resident32));
			
			memset(&lastest_part,0,PART_MAX_COUNT*sizeof(pt_resident));
			for(i=0;i<PART_MAX_COUNT;i++)
			{
				if(lastest_part32[i].size!=0){
					memcpy(lastest_part[i].name,lastest_part32[i].name,MAX_PARTITION_NAME_LEN);
					lastest_part[i].size= lastest_part32[i].size;
					lastest_part[i].offset= lastest_part32[i].offset;
					lastest_part[i].mask_flags= lastest_part32[i].mask_flags;
				}
			}
		}else{
			printf("64bit parse PMT, size pt = %d\n",sizeof(pt_resident));
		}

	return reval;
		
		
#else
	int pt_start_addr;
	int pt_cur_addr;
	int pt_locate;
	int reval=DM_ERR_OK;
	int mirror_address;
	char pmt_spare[PT_SIG_SIZE];

	block_size= devinfo.blocksize*1024;
	page_size = devinfo.pagesize;
	
	//page_buf = malloc(page_size);	 

	pt_start_addr = total_size;
	printf("load_pt from 0x%x \n",pt_start_addr);
	//pt_start_addr=PT_LOCATION*block_size;
	for(pt_locate=0;pt_locate<(block_size/page_size);pt_locate++)
	{
		pt_cur_addr = pt_start_addr+pt_locate*page_size;
		memset(pmt_spare,0xFF,PT_SIG_SIZE);

		if(!dev->read(dev,pt_cur_addr, page_buf,page_size))
		{
			printf ("load_pt read pt failded: %x\n",pt_cur_addr);
		}
             memcpy(&page_buf[page_size],g_kCMD.au1OOB,16);
		#if 0
		{
			int i;
			for(i=0;i<8;i++)
			{
				printf ("%x %x \n",page_buf[i],page_buf[2048+i]);
			}

		}
		#endif
		memcpy(pmt_spare,&page_buf[page_size] ,PT_SIG_SIZE); //skip bad block flag
		if(is_valid_pt(page_buf)&&is_valid_pt(pmt_spare))
		{
			pi.sequencenumber = page_buf[PT_SIG_SIZE+page_size];
			printf("load_pt find valid pt at %x sq %x \n",pt_start_addr,pi.sequencenumber);
			break;
		}
		else
		{
			continue;
		}
	}
	//for test 
	//pt_locate==(block_size/page_size);
	if(pt_locate==(block_size/page_size))
	{
		//first download or download is not compelte after erase or can not download last time
		printf ("load_pt find pt failed \n");
		pi.pt_has_space = 0; //or before download pt power lost
		
		if(!find_mirror_pt_from_bottom(&mirror_address,dev))
		{
			printf ("First time download \n");
			reval=ERR_NO_EXIST;
			return reval;
		}
		else
		{
			//used the last valid mirror pt, at lease one is valid.
			dev->read(dev,mirror_address, page_buf,page_size);
		}
	}
	memcpy(buf,&page_buf[PT_SIG_SIZE],sizeof(lastest_part));

	return reval;
#endif
}
示例#6
0
static int load_pt_from_fixed_addr(u8 * buf)
{
    int reval = ERR_NO_EXIST;
    u64 pt_start;
    u64 mpt_start;

    int pt_size = PMT_REGION_SIZE;

    pt_start = emmc_size - PMT_REGION_OFFSET - 0x600000;		
    mpt_start = pt_start + PMT_REGION_SIZE;

    printk(KERN_NOTICE "============func=%s===scan pmt from %llx=====\n", __func__,pt_start);

    reval = eMMC_rw_x(pt_start, (u32 *)pmt_buf, 0, 0, PMT_REGION_SIZE, 1, USER);
    if (reval) {
        printk(KERN_ERR "read pt error\n");
        goto try;
    }

    if (is_valid_pt(pmt_buf)) {
        if (!memcmp(pmt_buf + PT_SIG_SIZE, PMT_VER_V1, PMT_VER_SIZE)) {
            if (is_valid_pt(&pmt_buf[pt_size - PT_SIG_SIZE])) {
                memcpy(buf, pmt_buf + PT_SIG_SIZE + PMT_VER_SIZE, PART_MAX_COUNT * sizeof(pt_resident));
                reval = DM_ERR_OK;
                printk(KERN_NOTICE "find pt at %llx\n", pt_start);
                return reval;
            } else {
                reval = ERR_NO_EXIST;
                printk(KERN_ERR "invalid tail pt format\n");
            }
        } else {
            reval = ERR_NO_EXIST;
            printk(KERN_ERR "invalid pt version %s\n", pmt_buf + PT_SIG_SIZE);
        }
    }

try:
    reval = eMMC_rw_x(mpt_start, (u32 *)pmt_buf, 0, 0, PMT_REGION_SIZE, 1, USER);
    if (reval) {
        printk(KERN_ERR "read mpt error\n");
        reval = ERR_NO_EXIST;
        return reval;
    }

    if (is_valid_mpt(pmt_buf)) {
        if (!memcmp(pmt_buf + PT_SIG_SIZE, PMT_VER_V1, PMT_VER_SIZE)) {
            if (is_valid_mpt(&pmt_buf[pt_size - PT_SIG_SIZE])) {
                memcpy(buf, pmt_buf + PT_SIG_SIZE + PMT_VER_SIZE, PART_MAX_COUNT * sizeof(pt_resident));
                reval = DM_ERR_OK;
                printk(KERN_NOTICE "find mpt at %llx\n", mpt_start);
                return reval;
            } else {
                reval = ERR_NO_EXIST;
                printk(KERN_ERR "invalid tail mpt format\n");
            }
        } else {
            reval = ERR_NO_EXIST;
            printk(KERN_ERR "invalid mpt version %s\n", pmt_buf + PT_SIG_SIZE);
        }
    }

    return reval;
}

static int new_pmt(pt_resident *new_part, int table_size)
{
	int ret = -1;
	u64 mpt_addr = 0;
	char sig_buf[PT_SIG_SIZE];

    mpt_addr = emmc_size - PMT_REGION_OFFSET - 0x600000 + PMT_REGION_SIZE;

	pi.pt_changed = 1;
	pi.tool_or_sd_update = 2;
	pi.sequencenumber += 1;

	memset(pmt_buf, 0x00, PMT_REGION_SIZE);
	
	ret = eMMC_rw_x(mpt_addr, (u32 *)pmt_buf, 0, 1, PMT_REGION_SIZE, 1, USER);
	if (ret) {
        printk("clear mpt error\n");
		goto end;
	}
	
	*(int *)sig_buf = MPT_SIG;
	memcpy(pmt_buf, &sig_buf, PT_SIG_SIZE);
    memcpy(pmt_buf + PT_SIG_SIZE, PMT_VER_V1, PMT_VER_SIZE);
	memcpy(pmt_buf + PT_SIG_SIZE + PMT_VER_SIZE, &new_part[0], (table_size * sizeof(pt_resident)));
	memcpy(pmt_buf + PMT_REGION_SIZE - PT_SIG_SIZE - sizeof(pi), &pi, sizeof(pi));
	memcpy(pmt_buf + PMT_REGION_SIZE - PT_SIG_SIZE, &sig_buf, PT_SIG_SIZE);

	ret = eMMC_rw_x(mpt_addr,(u32 *)pmt_buf, 0, 1, PMT_REGION_SIZE, 1, USER);
    if(ret) {
		printk("write mpt error\n");
	}

end:
	return ret;
}