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; }
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; }
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; } }
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; } }
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 }
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; }