#include #include #include #include #include #include #include #include #include "flash_interface.h" static int mmc_secure_storage_read_key(int item, unsigned char *buf, unsigned int len); static int mmc_secure_storage_read_map(int item, unsigned char *buf, unsigned int len); static struct mmc *mmc_boot,*mmc_sprite; static int mmc_no; static unsigned char _inner_buffer[4096+64]; /*align temp buffer*/ //-------------------------------------noraml interface-------------------------------------------- static int sunxi_flash_mmc_read(unsigned int start_block, unsigned int nblock, void *buffer) { debug("mmcboot read: start 0x%x, sector 0x%x\n", start_block, nblock); return mmc_boot->block_dev.block_read(mmc_boot->block_dev.dev, start_block + CONFIG_MMC_LOGICAL_OFFSET, nblock, buffer); } static int sunxi_flash_mmc_write(unsigned int start_block, unsigned int nblock, void *buffer) { debug("mmcboot write: start 0x%x, sector 0x%x\n", start_block, nblock); return mmc_boot->block_dev.block_write(mmc_boot->block_dev.dev, start_block + CONFIG_MMC_LOGICAL_OFFSET, nblock, buffer); } static uint sunxi_flash_mmc_size(void){ return mmc_boot->block_dev.lba; } static int sunxi_flash_mmc_init(int stage){ return 0; } static int sunxi_flash_mmc_exit(int force){ return mmc_exit(); //return 0; } int sunxi_flash_mmc_phyread(unsigned int start_block, unsigned int nblock, void *buffer) { return mmc_boot->block_dev.block_read_mass_pro(mmc_boot->block_dev.dev, start_block, nblock, buffer); } int sunxi_flash_mmc_phywrite(unsigned int start_block, unsigned int nblock, void *buffer) { return mmc_boot->block_dev.block_write_mass_pro(mmc_boot->block_dev.dev, start_block, nblock, buffer); } //-------------------------------------sprite interface-------------------------------------------- static int sunxi_sprite_mmc_read(unsigned int start_block, unsigned int nblock, void *buffer) { debug("mmcsprite read: start 0x%x, sector 0x%x\n", start_block, nblock); return mmc_sprite->block_dev.block_read(mmc_sprite->block_dev.dev, start_block + CONFIG_MMC_LOGICAL_OFFSET, nblock, buffer); } static int sunxi_sprite_mmc_write(unsigned int start_block, unsigned int nblock, void *buffer) { debug("mmcsprite write: start 0x%x, sector 0x%x\n", start_block, nblock); return mmc_sprite->block_dev.block_write(mmc_sprite->block_dev.dev, start_block + CONFIG_MMC_LOGICAL_OFFSET, nblock, buffer); } static int sunxi_sprite_mmc_erase(int erase, void *mbr_buffer) { return card_erase(erase, mbr_buffer); } static uint sunxi_sprite_mmc_size(void){ return mmc_sprite->block_dev.lba; } static int sunxi_sprite_mmc_init(int stage){ return 0; } static int sunxi_sprite_mmc_exit(int force){ return 0; } int sunxi_sprite_mmc_phyread(unsigned int start_block, unsigned int nblock, void *buffer) { return mmc_sprite->block_dev.block_read_mass_pro(mmc_sprite->block_dev.dev, start_block, nblock, buffer); } int sunxi_sprite_mmc_phywrite(unsigned int start_block, unsigned int nblock, void *buffer) { return mmc_sprite->block_dev.block_write_mass_pro(mmc_sprite->block_dev.dev, start_block, nblock, buffer); } int sunxi_sprite_mmc_phyerase(unsigned int start_block, unsigned int nblock, void *skip) { if (nblock == 0) { printf("%s: @nr is 0, erase from @from to end\n", __FUNCTION__); nblock = mmc_sprite->block_dev.lba - start_block - 1; } return mmc_sprite->block_dev.block_mmc_erase(mmc_sprite->block_dev.dev, start_block, nblock, skip); } int sunxi_sprite_mmc_phywipe(unsigned int start_block, unsigned int nblock, void *skip) { if (nblock == 0) { printf("%s: @nr is 0, wipe from @from to end\n", __FUNCTION__); nblock = mmc_sprite->block_dev.lba - start_block - 1; } return mmc_sprite->block_dev.block_secure_wipe(mmc_sprite->block_dev.dev, start_block, nblock, skip); } int sunxi_sprite_mmc_force_erase(int erase, void *mbr_buffer) { if (mbr_buffer == NULL) return 0; card_erase(1, mbr_buffer); return 0; } //-----------------------------secure interface--------------------------------------- int sunxi_flash_mmc_secread( int item, unsigned char *buf, unsigned int nblock) { return mmc_boot->block_dev.block_read_secure(mmc_no, item, (u8 *)buf, nblock); } int sunxi_flash_mmc_secread_backup( int item, unsigned char *buf, unsigned int nblock) { return mmc_boot->block_dev.block_read_secure_backup(mmc_no, item, (u8 *)buf, nblock); } int sunxi_flash_mmc_secwrite( int item, unsigned char *buf, unsigned int nblock) { return mmc_boot->block_dev.block_write_secure(mmc_no, item, (u8 *)buf, nblock); } int sunxi_sprite_mmc_secwrite(int item ,unsigned char *buf,unsigned int nblock) { if(mmc_sprite->block_dev.block_write_secure(mmc_no, item, (u8 *)buf, nblock) >=0) return 0; else return -1; } int sunxi_sprite_mmc_secread(int item ,unsigned char *buf,unsigned int nblock) { if(mmc_sprite->block_dev.block_read_secure(mmc_no, item, (u8 *)buf, nblock) >=0) return 0; else return -1; } int sunxi_sprite_mmc_secread_backup(int item ,unsigned char *buf,unsigned int nblock) { if(mmc_sprite->block_dev.block_read_secure_backup(mmc_no, item, (u8 *)buf, nblock) >=0) return 0; else return -1; } int mmc_secure_storage_read(int item, unsigned char *buf, unsigned int len) { if (item == 0) return mmc_secure_storage_read_map(item, buf, len); else return mmc_secure_storage_read_key(item, buf, len); } int mmc_secure_storage_write(int item, unsigned char *buf, unsigned int len) { unsigned char * align ; unsigned int blkcnt; int workmode; if(((unsigned int)buf%32)){ // input buf not align align = (unsigned char *)(((unsigned int)_inner_buffer + 0x20)&(~0x1f)) ; memcpy(align, buf, len); }else align=buf; blkcnt = (len+511)/512 ; workmode = uboot_spare_head.boot_data.work_mode; if(workmode == WORK_MODE_BOOT || workmode == WORK_MODE_SPRITE_RECOVERY) { return (sunxi_flash_mmc_secwrite(item, align, blkcnt) == blkcnt) ? 0 : -1; } else if((workmode & WORK_MODE_PRODUCT) || (workmode == 0x30)) { return sunxi_sprite_mmc_secwrite(item, align, blkcnt); } else { printf("workmode=%d is err\n", workmode); return -1; } } //-----------------------------------end ------------------------------------------------------ int sdmmc_init_for_boot(int workmode, int card_no) { tick_printf("MMC: %d\n", card_no); board_mmc_set_num(card_no); debug("set card number\n"); board_mmc_pre_init(card_no); debug("begin to find mmc\n"); mmc_boot = find_mmc_device(card_no); mmc_no = card_no; if(!mmc_boot){ printf("fail to find one useful mmc card\n"); return -1; } debug("try to init mmc\n"); if (mmc_init(mmc_boot)) { puts("MMC init failed\n"); return -1; } debug("mmc %d init ok\n", card_no); sunxi_flash_init_pt = sunxi_flash_mmc_init; sunxi_flash_read_pt = sunxi_flash_mmc_read; sunxi_flash_write_pt = sunxi_flash_mmc_write; sunxi_flash_size_pt = sunxi_flash_mmc_size; sunxi_flash_exit_pt = sunxi_flash_mmc_exit; sunxi_flash_phyread_pt = sunxi_flash_mmc_phyread; sunxi_flash_phywrite_pt = sunxi_flash_mmc_phywrite; //for fastboot sunxi_sprite_phyread_pt = sunxi_flash_mmc_phyread; sunxi_sprite_phywrite_pt = sunxi_flash_mmc_phywrite; sunxi_sprite_read_pt = sunxi_flash_read_pt; sunxi_sprite_write_pt = sunxi_flash_write_pt; /* for secure stoarge */ sunxi_secstorage_read_pt = mmc_secure_storage_read; sunxi_secstorage_write_pt = mmc_secure_storage_write; return 0; } int sdmmc_init_for_sprite(int workmode) { printf("try card 1\n"); board_mmc_pre_init(1); mmc_sprite = find_mmc_device(1); mmc_no = 1; set_boot_storage_type(STORAGE_SD1); if(!mmc_sprite){ printf("try card 2\n"); board_mmc_pre_init(2); mmc_sprite = find_mmc_device(2); mmc_no = 2; set_boot_storage_type(STORAGE_EMMC); } if(!mmc_sprite){ printf("fail to find one useful mmc card2\n"); #ifdef CONFIG_MMC3_SUPPORT printf("try to find card3 \n"); board_mmc_pre_init(3); mmc_sprite = find_mmc_device(3); mmc_no = 3; if(!mmc_sprite) { printf("try card3 fail \n"); return -1; } else { set_boot_storage_type(STORAGE_EMMC3); } #else return -1; #endif } if (mmc_init(mmc_sprite)) { printf("MMC init failed\n"); return -1; } sunxi_sprite_init_pt = sunxi_sprite_mmc_init; sunxi_sprite_exit_pt = sunxi_sprite_mmc_exit; sunxi_sprite_read_pt = sunxi_sprite_mmc_read; sunxi_sprite_write_pt = sunxi_sprite_mmc_write; sunxi_sprite_erase_pt = sunxi_sprite_mmc_erase; sunxi_sprite_size_pt = sunxi_sprite_mmc_size; sunxi_sprite_phyread_pt = sunxi_sprite_mmc_phyread; sunxi_sprite_phywrite_pt = sunxi_sprite_mmc_phywrite; sunxi_sprite_force_erase_pt = sunxi_sprite_mmc_force_erase; /* for secure stoarge */ sunxi_secstorage_read_pt = mmc_secure_storage_read; sunxi_secstorage_write_pt = mmc_secure_storage_write; debug("sunxi sprite has installed sdcard2 function\n"); return 0; } int sdmmc_init_card0_for_sprite(void) { //init card0 board_mmc_pre_init(0); mmc_boot = find_mmc_device(0); if(!mmc_boot) { printf("fail to find one useful mmc card\n"); return -1; } if (mmc_init(mmc_boot)) { printf("MMC sprite init failed\n"); return -1; } else { printf("mmc init ok\n"); } sunxi_flash_init_pt = sunxi_flash_mmc_init; sunxi_flash_read_pt = sunxi_flash_mmc_read; sunxi_flash_write_pt = sunxi_flash_mmc_write; sunxi_flash_size_pt = sunxi_flash_mmc_size; sunxi_flash_phyread_pt = sunxi_flash_mmc_phyread; sunxi_flash_phywrite_pt = sunxi_flash_mmc_phywrite; sunxi_flash_exit_pt = sunxi_flash_mmc_exit; return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int card_read_boot0( void *buffer, uint length ) { int ret; int storage_type; storage_type = get_boot_storage_type(); if(STORAGE_EMMC == storage_type) { ret = sunxi_sprite_phyread(BOOT0_SDMMC_START_ADDR, (length+511)/512, buffer); } else if(STORAGE_SD1 == storage_type) { ret = sunxi_sprite_phyread(BOOT0_SDMMC_START_ADDR, (length+511)/512, buffer); } else { ret = sunxi_sprite_phyread(BOOT0_EMMC3_BACKUP_START_ADDR, (length+511)/512, buffer); } if(!ret) { printf("%s: call fail\n", __func__); return -1; } return 0; } static int check_secure_storage_key(unsigned char *buffer) { store_object_t *obj = (store_object_t *)buffer; if( obj->magic != STORE_OBJECT_MAGIC ){ printf("Input object magic fail [0x%x]\n", obj->magic); return -1 ; } if( obj->crc != crc32( 0 , (void *)obj, sizeof(*obj)-4 ) ){ printf("Input object crc fail [0x%x]\n", obj->crc); return -1 ; } return 0; } static int check_secure_storage_map(unsigned char *buffer) { struct map_info *map_buf = (struct map_info *)buffer; if (map_buf->magic != STORE_OBJECT_MAGIC) { printf("Item0 (Map) magic is bad\n"); return 2; } if (map_buf->crc != crc32( 0 , (void *)map_buf, sizeof(struct map_info)-4 )) { printf("Item0 (Map) crc is fail [0x%x]\n", map_buf->crc); return -1; } return 0; } static int mmc_secure_storage_read_key(int item, unsigned char *buf, unsigned int len) { unsigned char *align ; unsigned int blkcnt; int ret ,workmode; if(((unsigned int)buf%32)){ align = (unsigned char *)(((unsigned int)_inner_buffer + 0x20)&(~0x1f)) ; memset(align,0,4096); }else { align = buf ; } blkcnt = (len+511)/512 ; workmode = uboot_spare_head.boot_data.work_mode; if(workmode == WORK_MODE_BOOT || workmode == WORK_MODE_SPRITE_RECOVERY) { ret = (sunxi_flash_mmc_secread(item, align, blkcnt) == blkcnt) ? 0 : -1; } else if ((workmode & WORK_MODE_PRODUCT) || (workmode == 0x30)) { ret = sunxi_sprite_mmc_secread(item, align, blkcnt); } else { printf("workmode=%d is err\n", workmode); return -1; } if (!ret) { /*check copy 0 */ if (!check_secure_storage_key(align)){ printf("the secure storage item%d copy0 is good\n",item); goto ok ; /*copy 0 pass*/ } printf("the secure storage item%d copy0 is bad\n", item); } // read backup memset(align, 0x0, len); printf("read item%d copy1\n", item); if(workmode == WORK_MODE_BOOT || workmode == WORK_MODE_SPRITE_RECOVERY) { ret = (sunxi_flash_mmc_secread_backup(item, align, blkcnt) == blkcnt) ? 0 : -1; } else if ((workmode & WORK_MODE_PRODUCT) || (workmode == 0x30)) { ret = sunxi_sprite_mmc_secread_backup(item, align, blkcnt); } else { printf("workmode=%d is err\n", workmode); return -1; } if (!ret) { /*check copy 1 */ if (!check_secure_storage_key(align)){ printf("the secure storage item%d copy1 is good\n",item); goto ok ; /*copy 1 pass*/ } printf("the secure storage item%d copy1 is bad\n", item); } printf("sunxi_secstorage_read fail\n"); return -1; ok: if(((unsigned int)buf%32)) memcpy(buf,align,len); return 0 ; } static int mmc_secure_storage_read_map(int item, unsigned char *buf, unsigned int len) { int have_map_copy0 ; unsigned char *align ; unsigned int blkcnt; int ret ,workmode; char * map_copy0_buf; if(((unsigned int)buf%32)){ align = (unsigned char *)(((unsigned int)_inner_buffer + 0x20)&(~0x1f)) ; memset(align,0,4096); }else { align = buf ; } blkcnt = (len+511)/512 ; map_copy0_buf=(char *)malloc(blkcnt*512); if(!map_copy0_buf){ printf("out of memory\n"); return -1 ; } printf("read item%d copy0\n", item); workmode = uboot_spare_head.boot_data.work_mode; if(workmode == WORK_MODE_BOOT || workmode == WORK_MODE_SPRITE_RECOVERY) { ret = (sunxi_flash_mmc_secread(item, align, blkcnt) == blkcnt) ? 0 : -1; } else if ((workmode & WORK_MODE_PRODUCT) || (workmode == 0x30)) { ret = sunxi_sprite_mmc_secread(item, align, blkcnt); } else { printf("workmode=%d is err\n", workmode); free(map_copy0_buf); return -1; } if (!ret) { /*read ok*/ ret = check_secure_storage_map(align); if (ret == 0) { printf("the secure storage item0 copy0 is good\n"); goto ok ; /*copy 0 pass*/ }else if (ret == 2){ memcpy(map_copy0_buf, align, len); have_map_copy0 = 1; printf("the secure storage item0 copy0 is bad\n"); }else printf("the secure storage item0 copy 0 crc fail, the data is bad\n"); } // read backup memset(align, 0x0, len); printf("read item%d copy1\n", item); if(workmode == WORK_MODE_BOOT || workmode == WORK_MODE_SPRITE_RECOVERY) { ret = (sunxi_flash_mmc_secread(item, align, blkcnt) == blkcnt) ? 0 : -1; } else if ((workmode & WORK_MODE_PRODUCT) || (workmode == 0x30)) { ret = sunxi_sprite_mmc_secread(item, align, blkcnt); } else { printf("workmode=%d is err\n", workmode); free(map_copy0_buf); return -1; } if (!ret) { ret = check_secure_storage_map(align); if (ret == 0){ printf("the secure storage item0 copy1 is good\n"); goto ok ; }else if (ret == 2){ if (have_map_copy0 && !memcmp(map_copy0_buf, align, len)) { printf("the secure storage item0 copy0 == copy1, the data is good\n"); goto ok ; /*copy have no magic and crc*/ } else { printf("the secure storage item0 copy0 != copy1, the data is bad\n"); free(map_copy0_buf); return -1; } }else{ printf("the secure storage item0 copy 1 crc fail, the data is bad\n"); free(map_copy0_buf); return -1; } } printf("unknown error happen in item 0 read\n"); free(map_copy0_buf); return -1 ; ok: if(((unsigned int)buf%32)) memcpy(buf,align,len); free(map_copy0_buf); return 0 ; }