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; }
//int load_exist_part_tab(u8 *buf,struct mtd_info *mtd) int load_exist_part_tab(u8 * buf) { int pt_start_addr; int pt_cur_addr; int pt_locate; int reval = DM_ERR_OK; int mirror_address; //u8 pmt_spare[PT_SIG_SIZE]; struct mtd_oob_ops ops_pt; struct mtd_info *mtd; mtd = &host->mtd; block_size = mtd->erasesize; // devinfo.blocksize*1024; page_size = mtd->writesize; // devinfo.pagesize; pt_start_addr = (int)(mtd->size); //pt_start_addr=PT_LOCATION*block_size; printk(KERN_INFO "load_exist_part_tab %x\n", pt_start_addr); 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; printk(KERN_INFO "ops_pt.len %x \n", ops_pt.len); if (mtd->_read_oob == NULL) { printk(KERN_INFO "shoud not happpen \n"); } 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); //printk (KERN_INFO "load_pt read pt %x \n",pt_cur_addr); if (mtd->_read_oob(mtd, (loff_t) pt_cur_addr, &ops_pt) != 0) { printk(KERN_INFO "load_pt read pt failded: %x\n", (u32) pt_cur_addr); } #if 0 { int i; for (i = 0; i < 8; i++) { printk(KERN_INFO "%x %x \n", *(page_buf + i), *(page_buf + 2048 + i)); } } #endif //memcpy(pmt_spare,&page_buf[LPAGE] ,PT_SIG_SIZE); //do not need skip bad block flag if (is_valid_pt(page_buf) && is_valid_pt(page_buf + mtd->writesize)) { pi.sequencenumber = page_buf[PT_SIG_SIZE + page_size]; printk(KERN_INFO "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 printk(KERN_INFO "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, mtd)) { printk(KERN_INFO "First time download \n"); reval = ERR_NO_EXIST; return reval; } else { //used the last valid mirror pt, at lease one is valid. mtd->_read_oob(mtd, (loff_t) mirror_address, &ops_pt); } } memcpy(&lastest_part, &page_buf[PT_SIG_SIZE], sizeof(lastest_part)); return reval; }
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 }
/* int load_exist_part_tab(u8 *buf,struct mtd_info *mtd) */ int load_exist_part_tab(u8 *buf) { u64 pt_start_addr; u64 pt_cur_addr; int pt_locate, i; int reval = DM_ERR_OK; u64 mirror_address; /* u8 pmt_spare[PT_SIG_SIZE]; */ struct mtd_oob_ops ops_pt; struct mtd_info *mtd; mtd = &host->mtd; block_size = mtd->erasesize; /* gn_devinfo.blocksize*1024; */ page_size = mtd->writesize; /* gn_devinfo.pagesize; */ /* if(host->hw->nand_sec_shift == 10) //MLC */ /* block_size = block_size >> 1; */ pt_start_addr = (mtd->size); /* pt_start_addr=PT_LOCATION*block_size; */ pr_debug("load_exist_part_tab %llx\n", pt_start_addr); 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("ops_pt.len %x\n", ops_pt.len); if (mtd->_read_oob == NULL) pr_debug("should not happpen\n"); for (pt_locate = 0, i = 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); */ /* pr_err( (KERN_INFO "load_pt read pt %x\n",pt_cur_addr); */ if (mtd->_read_oob(mtd, (loff_t) pt_cur_addr, &ops_pt) != 0) pr_debug("load_pt read pt failded: %llx\n", (u64) pt_cur_addr); /* memcpy(pmt_spare,&page_buf[LPAGE] ,PT_SIG_SIZE); //do not need skip bad block flag */ if (is_valid_pt(page_buf) && is_valid_pt(page_buf + mtd->writesize)) { pi.sequencenumber = page_buf[PT_SIG_SIZE + page_size]; pr_debug("load_pt find valid pt at %llx sq %x\n", pt_start_addr, pi.sequencenumber); break; } 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 */ pr_debug("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, mtd)) { pr_debug("First time download\n"); reval = ERR_NO_EXIST; return reval; } /* used the last valid mirror pt, at lease one is valid. */ mtd->_read_oob(mtd, (loff_t) mirror_address, &ops_pt); } memcpy(&lastest_part, &page_buf[PT_SIG_SIZE], sizeof(lastest_part)); return reval; }
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; }
int load_exist_part_tab(u8 *buf,part_dev_t *dev) { #ifndef MTK_EMMC_SUPPORT u64 pt_start_addr; u64 pt_cur_addr; u64 pt_locate; int reval=DM_ERR_OK; u64 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); 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 return DM_ERR_OK; //should not happen }
int load_exist_part_tab(u8 *buf) { #ifndef MTK_EMMC_SUPPORT 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]; PAGE_SIZE = (u32) g_nand_chip.page_size; BLOCK_SIZE = (u32) g_nand_chip.erasesize; total_size = (int)(g_nand_chip.chipsize); pt_start_addr = total_size; MSG (INIT, "load_pt from %x\n",pt_start_addr); memset(&pi,0xFF,sizeof(pi)); 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); memset(g_nand_spare,0xFF,64); if(!mtk_nand_read_page_hwecc(pt_cur_addr, page_readbuf)) { MSG (INIT, "load_pt read pt failded\n"); } memcpy(pmt_spare,&g_nand_spare[1] ,PT_SIG_SIZE); if(is_valid_pt(page_readbuf)&&is_valid_pt(pmt_spare)) { pi.sequencenumber = g_nand_spare[5]; MSG (INIT, "load_pt find valid pt at %x sq %x \n",pt_start_addr,pi.sequencenumber); break; } else { continue; } } if(pt_locate==(BLOCK_SIZE/PAGE_SIZE)) { //first download or download is not compelte after erase or can not download last time MSG (INIT, "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)) { MSG (INIT, "First time download \n"); reval=ERR_NO_EXIST; return reval; } else { //used the last valid mirror pt, at lease one is valid. mtk_nand_read_page_hwecc(mirror_address, page_readbuf); } } memcpy(buf,&page_readbuf[PT_SIG_SIZE],sizeof(lastest_part)); return reval; #endif }