static int write_env_area(char *env_buf) { #ifdef MTK_EMMC_SUPPORT int reval; #endif int i,checksum = 0; memcpy(env_buf,ENV_SIG,sizeof(g_env.sig)); memcpy(env_buf+CFG_ENV_SIG_1_OFFSET,ENV_SIG,sizeof(g_env.sig)); for(i=0;i<(CFG_ENV_DATA_SIZE);i++){ checksum += *(env_buf+CFG_ENV_DATA_OFFSET+i); } *((int *)env_buf+CFG_ENV_CHECKSUM_OFFSET/4) = checksum; #ifdef MTK_EMMC_SUPPORT #ifdef MTK_NEW_COMBO_EMMC_SUPPORT reval = eMMC_rw_x((loff_t)env_addr,(u32*)env_buf,0,1,CFG_ENV_SIZE,1,EMMC_PART_USER); #else reval = eMMC_rw_x((loff_t)env_addr,(u32*)env_buf,0,1,CFG_ENV_SIZE,1,USER); #endif if (reval) { return -EIO; } #endif return 0; }
static int read_env_area(char *env_buf) { #ifdef MTK_EMMC_SUPPORT int reval; #ifdef MTK_NEW_COMBO_EMMC_SUPPORT reval = eMMC_rw_x((loff_t)env_addr,(u32*)env_buf,0,0,CFG_ENV_SIZE,1,EMMC_PART_USER); #else reval = eMMC_rw_x((loff_t)env_addr,(u32*)env_buf,0,0,CFG_ENV_SIZE,1,USER); #endif if (reval) { return -EIO; } #endif return 0; }
static int pmt_region_write(struct pmt_region *region, void *buf) { int err; err = eMMC_rw_x(region->base_addr, (unsigned int *)buf, 0, 1, region->size, 1, EMMC_PART_USER); if (err) { pmt_err("[%s]write %s error\n", __func__, region->name); } return err; }
static int pmt_region_read(struct pmt_region *region, void *buf) { int err; err = eMMC_rw_x(region->base_addr, (unsigned int *)buf, 0, 0, region->size, 1, USER); if (err) { pmt_err("[%s]read %s error\n", __func__, region->name); } //pmt_info("pmt_region_read 0x%x",(unsigned int *)buf); return err; }
static int update_pmt(pt_resident *new_part, int table_size) { int ret = -1; u64 pt_addr = 0; char sig_buf[PT_SIG_SIZE]; pt_addr = emmc_size - PMT_REGION_OFFSET - 0x600000; if ((pi.pt_changed != 1) && (pi.pt_has_space == 1)) { printk("pt may be not update\n"); return 0; } memset(pmt_buf, 0x00, PMT_REGION_SIZE); ret = eMMC_rw_x(pt_addr, (u32 *)pmt_buf, 0, 1, PMT_REGION_SIZE, 1, USER); if (ret) { printk("clear pt error\n"); goto end; } *(int *)sig_buf = PT_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(pt_addr,(u32 *)pmt_buf, 0, 1, PMT_REGION_SIZE, 1, USER); if (ret) { printk("write pt error\n"); } end: return ret; }
static int __update_msdos_partition(int px, unsigned long long start, unsigned long long size) { int err = 0; int i, slot; int xbr_idx = 0; char *this_name = NULL; unsigned long long this_addr; unsigned char *buf = NULL; struct partition *p; buf = kzalloc(512, GFP_KERNEL); if (!buf) { err = -ENOMEM; pmt_err("update_msdos_partition: malloc buf fail\n"); goto fail_malloc; } //find px in which mbr/ebr. for (i = 0;i < MBR_COUNT; i++) { for (slot = 0; slot < 4; slot++) { if (MBR_EBR_px[i].part_index[slot] == px) { /* this_name is mbr or ebrx */ xbr_idx = i; this_name = MBR_EBR_px[i].part_name; goto found; } } } if (slot >= 4) { pmt_err("p%d can not be found in mbr\n", px); err = -EINVAL; goto out; } found: pmt_info("update %s\n", this_name); /* check mbr or ebrx partition info */ for (i = 0; i < PART_NUM; i++) { if (!strcmp(this_name, PartInfo[i].name)) { this_addr = PartInfo[i].start_address; pmt_info("update %s addr %llx\n", this_name, this_addr); break; } } if (i == PART_NUM) { pmt_err("can not find %s\n", this_name); err = -EINVAL; goto out; } /* read mbr or ebr into buf */ err = eMMC_rw_x(this_addr, (u32*)buf, 0, 0, 512, 1, EMMC_PART_USER); if (err || !msdos_magic_present(buf + 510)) { pmt_err("read %s error\n", this_name); err = -EIO; goto out; } if (!msdos_magic_present(buf + 510)) { pmt_err("read MBR/EBR fail\n"); err = -1; goto out; } p = (struct partition *) (buf + 0x1be); p[slot].start_sect = (unsigned int)((start - this_addr) / 512); p[slot].nr_sects = (unsigned int)(size / 512); err = eMMC_rw_x(this_addr, (u32*)buf, 0, 1, 512, 1, EMMC_PART_USER); if (err) { pmt_err("write %s error\n", this_name); err = -EIO; goto out; } out: kfree(buf); fail_malloc: return err; }
static int update_MBR_or_EBR(int px, u64 start_addr, u64 length) { int i,ret,j; int found_mbr = 0; loff_t update_addr = 0; int index_in_mbr = 0; int mbr_index = 0; char *change_pt_name = NULL; struct partition *p; u8 *page_buf = NULL; ret =0; page_buf = kmalloc(512, GFP_KERNEL); if (!page_buf) { ret = -ENOMEM; printk("update_MBR_or_EBR: malloc page_buf fail\n"); goto fail_malloc; } //data -1MB /* for(i=0;i<PART_NUM;i++){ if((PartInfo[i].partition_idx == px)&&((!strncmp(PartInfo[i].name,"usrdata",7))||(!strncmp(PartInfo[i].name,"sec_ro",6))||(!strncmp(PartInfo[i].name,"android",7))||(!strncmp(PartInfo[i].name,"cache",5)))){ printk("update %s,need reduce 1MB in MBR\n",PartInfo[i].name); length -= 0x100000; } }*/ //find px in which mbr/ebr. for(i=0;i<MBR_COUNT;i++){ for(j=0;j<SLOT_PER_MBR;j++){ if(MBR_EBR_px[i].part_index[j]==px){ found_mbr = 1; change_pt_name = MBR_EBR_px[i].part_name; index_in_mbr = j; mbr_index = i; } } } if(found_mbr!=1){ printk("p%d can not be found in mbr\n",px); ret = -1; goto end; } printk("update %s\n",change_pt_name); for(i=0; i<PART_NUM;i++){ if(!strcmp(change_pt_name,PartInfo[i].name)){ update_addr = PartInfo[i].start_address - MBR_START_ADDR; printk("update %s addr %llx\n",change_pt_name,update_addr); break; } } if(i==PART_MAX_COUNT){ printk("can not find %s\n",change_pt_name); ret = -1; goto end; } ret = eMMC_rw_x(update_addr,(u32*)page_buf,0,0,512,1,USER); if(ret){ printk("read %s error\n",change_pt_name); goto end; } if (!msdos_magic_present(page_buf + 510)) { printk("read MBR/EBR fail\n"); ret = -1; goto end; } p = (struct partition *) (page_buf + 0x1be); for(i=0;i<4;i++){ if(MBR_EBR_px[mbr_index].part_index[i]!=0){ printk("p%d: %x %x\n",MBR_EBR_px[mbr_index].part_index[i],p[i].start_sect,p[i].nr_sects); if(i==index_in_mbr){ printk("p%d: change to %x %x\n",MBR_EBR_px[mbr_index].part_index[i],(u32)((start_addr-update_addr)/512),(u32)(length/512)); p[i].start_sect = (u32)((start_addr-update_addr)/512); p[i].nr_sects = (u32)(length/512); } } } ret = eMMC_rw_x(update_addr,(u32*)page_buf,0,1,512,1,USER); if(ret){ printk("write %s error\n",change_pt_name); goto end; } end: kfree(page_buf); fail_malloc: return ret; }
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; }