/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
int sunxi_sprite_store_part_data(void *buffer)
{
	int i, j;

	j = 0;
	sunxi_mbr_t  *mbr = (sunxi_mbr_t *)buffer;
	for(i=0;i<mbr->PartCount;i++)
	{
		printf("part name %s\n", mbr->array[i].name);
		printf("keydata = 0x%x\n", mbr->array[i].keydata);
		if( (!strcmp((const char *)mbr->array[i].name, SUNXI_SPRITE_PROTECT_PART)) || (mbr->array[i].keydata == 0x8000))
		{
			printf("find keypart %s\n", mbr->array[i].name);
			printf("keypart read start: 0x%x, sectors 0x%x\n", mbr->array[i].addrlo, mbr->array[i].lenlo);

			part_info[j].part_buf = (char *)malloc(mbr->array[i].lenlo * 512);
			if(!part_info[j].part_buf)
			{
				printf("sprite protect private data fail: cant malloc memory for part %s, sectors 0x%x\n", mbr->array[i].name, mbr->array[i].lenlo);

				goto __sunxi_sprite_store_part_data_fail;
			}
			if(!sunxi_sprite_read(mbr->array[i].addrlo, mbr->array[i].lenlo, (void *)part_info[j].part_buf))
			{
				printf("sunxi sprite error : read private data error\n");

				goto __sunxi_sprite_store_part_data_fail;
			}
			printf("keypart part %s read end: 0x%x, sectors 0x%x\n", mbr->array[i].name, mbr->array[i].addrlo, mbr->array[i].lenlo);

			part_info[j].part_sectors = mbr->array[i].lenlo;
			strcpy(part_info[j].part_name, (const char *)mbr->array[i].name);

			j ++;
		}
	}
	if(!j)
	{
		printf("there is no keypart part on local flash\n");
	}

	return 0;

__sunxi_sprite_store_part_data_fail:
	for(i=0;i<j;i++)
	{
		if(part_info[i].part_buf)
		{
			free(part_info[i].part_buf);
		}
		else
		{
			break;
		}
	}

	return -1;
}
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
int sunxi_sprite_force_erase_key(void)
{
	char buf[SUNXI_MBR_SIZE * SUNXI_MBR_COPY_NUM];
	if(sunxi_sprite_init(1))
	{
		printf("sunxi sprite pre init fail\n");
		return -1;
	}
	//读出量产介质上的MBR
	if(!sunxi_sprite_read(0, (SUNXI_MBR_SIZE * SUNXI_MBR_COPY_NUM)/512, buf))
	{
		printf("read local mbr on flash failed\n");
		sunxi_sprite_exit(1);

		return -1;
	}
	//校验MBR
	if(sunxi_sprite_verify_mbr(buf))
	{
		printf("the mbr on flash is bad\n");
		sunxi_sprite_exit(1);

		return -1;
	}
	if(sunxi_sprite_erase_private_key(buf))
	{
		printf("erase key fail \n");
		return -1;
	}
#ifdef CONFIG_SUNXI_SECURE_STORAGE
    if(sunxi_secure_storage_init())
        return -1;	
	if(sunxi_secure_storage_erase("key_burned_flag") == -1)
        return -1;
#endif
	printf("erase key success \n");
	return 0;
}
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
int sunxi_sprite_erase_flash(void  *img_mbr_buffer)
{
	uint32_t need_erase_flag = 0;
	char buf[SUNXI_MBR_SIZE * SUNXI_MBR_COPY_NUM];
	//int  ret;
	int nodeoffset;
    

	if(sunxi_sprite_erase(0, img_mbr_buffer) > 0)
	{
		printf("flash already erased\n");
		return 0;
	}
	//获取擦除信息,查看是否需要擦除flash
	//ret = script_parser_fetch("platform", "eraseflag", &need_erase_flag, 1);
	nodeoffset =  fdt_path_offset(working_fdt,FDT_PATH_PLATFORM);
	if(nodeoffset > 0)
	{
		fdt_getprop_u32(working_fdt,nodeoffset,"eraseflag",&need_erase_flag);
	}

	if(need_erase_flag)
	{
		printf("do need erase flash\n");
	}
	else
	{
		printf("not need erase flash\n");
	}

	//当要求强制擦除,不处理私有数据
	if(need_erase_flag == 0x11)
	{
		printf("force erase flash\n");
		sunxi_sprite_erase(1, img_mbr_buffer);

		return 0;
	}
	//检测不到private分区,即不用保护用户数据
	if(!sunxi_sprite_probe_prvt(img_mbr_buffer))
	{
		printf("no part need to protect user data\n");
		sunxi_sprite_erase(need_erase_flag, img_mbr_buffer);

		return 0;
	}
	//当初始化失败的时候,直接擦除,不处理私有数据
	if(sunxi_sprite_init(1))
	{
		debug("sunxi sprite pre init fail, we have to erase it\n");
		sunxi_sprite_exit(1);
		sunxi_sprite_erase(need_erase_flag, img_mbr_buffer);

		return 0;
	}
	debug("nand pre init ok\n");
	//读出量产介质上的MBR
	if(!sunxi_sprite_read(0, (SUNXI_MBR_SIZE * SUNXI_MBR_COPY_NUM)/512, buf))
	{
		printf("read local mbr on flash failed\n");
		sunxi_sprite_exit(1);
		sunxi_sprite_erase(need_erase_flag, img_mbr_buffer);

		return 0;
	}
	//校验MBR
	if(sunxi_sprite_verify_mbr(buf))
	{
		printf("the mbr on flash is bad\n");
		sunxi_sprite_exit(1);
		sunxi_sprite_erase(need_erase_flag, img_mbr_buffer);

		return 0;
	}
	printf("begin to store data\n");
	if(sunxi_sprite_store_part_data(buf) < 0)
	{
		sunxi_sprite_exit(1);

		return -1;
	}
	sunxi_sprite_exit(1);
	printf("need_erase_flag = %d\n", need_erase_flag);
	//开始擦除
	printf("begin to erase\n");
	sunxi_sprite_erase(need_erase_flag, img_mbr_buffer);
	//开始回写private
	printf("finish erase\n");
	sunxi_sprite_init(0);
	printf("rewrite\n");
	if(sunxi_sprite_restore_part_data(img_mbr_buffer))
    {
    	sunxi_sprite_exit(0);

    	return -1;
    }
	printf("flash exit\n");
	sunxi_sprite_exit(0);

    return 0;
}
/*
************************************************************************************************************
*
*                                             function
*
*    name          :
*
*    parmeters     :
*
*    return        :
*
*    note          :
*
*
************************************************************************************************************
*/
uint sunxi_sprite_part_rawdata_verify(uint base_start, long long base_bytes)
{
	uint checksum = 0;
	uint unaligned_bytes, last_time_bytes;
	uint rest_sectors;
	uint crt_start;
	char *tmp_buf = NULL;

	tmp_buf = (char *)malloc(VERIFY_ONCE_BYTES);
	if(!tmp_buf)
	{
		printf("sunxi sprite err: unable to malloc memory for verify\n");

		return 0;
	}
	crt_start       = base_start;
	rest_sectors    = (uint)((base_bytes + 511)>>9);
	unaligned_bytes = (uint)base_bytes & 0x1ff;

	debug("read total sectors %d\n", rest_sectors);
	debug("read part start %d\n", crt_start);
    while(rest_sectors >= VERIFY_ONCE_SECTORS)
    {
    	if(sunxi_sprite_read(crt_start, VERIFY_ONCE_SECTORS, tmp_buf) != VERIFY_ONCE_SECTORS)
    	{
    		printf("sunxi sprite: read flash error when verify\n");
			checksum = 0;

    		goto __rawdata_verify_err;
    	}
    	crt_start    += VERIFY_ONCE_SECTORS;
    	rest_sectors -= VERIFY_ONCE_SECTORS;
    	checksum     += add_sum(tmp_buf, VERIFY_ONCE_BYTES);
    	debug("check sum = 0x%x\n", checksum);
    }
    if(rest_sectors)
    {
    	if(sunxi_sprite_read(crt_start, rest_sectors, tmp_buf) != rest_sectors)
    	{
    		printf("sunxi sprite: read flash error when verify\n");
			checksum = 0;

    		goto __rawdata_verify_err;
    	}
    	if(unaligned_bytes)
    	{
    		last_time_bytes = (rest_sectors - 1) * 512 + unaligned_bytes;
    	}
    	else
    	{
    		last_time_bytes = rest_sectors * 512;
    	}
    	checksum += add_sum(tmp_buf, last_time_bytes);
		debug("check sum = 0x%x\n", checksum);
    }

__rawdata_verify_err:
	if(tmp_buf)
	{
		free(tmp_buf);
	}

	return checksum;

}