412 lines
9.6 KiB
C
Executable File
412 lines
9.6 KiB
C
Executable File
/*
|
||
* (C) Copyright 2007-2013
|
||
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
||
* Jerry Wang <wangflord@allwinnertech.com>
|
||
*
|
||
* See file CREDITS for list of people who contributed to this
|
||
* project.
|
||
*
|
||
* This program is free software; you can redistribute it and/or
|
||
* modify it under the terms of the GNU General Public License as
|
||
* published by the Free Software Foundation; either version 2 of
|
||
* the License, or (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program; if not, write to the Free Software
|
||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||
* MA 02111-1307 USA
|
||
*/
|
||
#include <config.h>
|
||
#include <common.h>
|
||
#include <malloc.h>
|
||
#include "sparse/sparse.h"
|
||
#include <sunxi_mbr.h>
|
||
#include <sunxi_board.h>
|
||
|
||
#if defined (CONFIG_SUNXI_SPINOR)
|
||
#define VERIFY_ONCE_BYTES (2 * 1024 * 1024)
|
||
#else
|
||
#define VERIFY_ONCE_BYTES (16 * 1024 * 1024)
|
||
#endif
|
||
|
||
#define VERIFY_ONCE_SECTORS (VERIFY_ONCE_BYTES/512)
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
uint add_sum(void *buffer, uint length)
|
||
{
|
||
#ifndef CONFIG_USE_NEON_SIMD
|
||
unsigned int *buf;
|
||
unsigned int count;
|
||
unsigned int sum;
|
||
|
||
count = length >> 2; // 以 字(4bytes)为单位计数
|
||
sum = 0;
|
||
buf = (unsigned int *)buffer;
|
||
while(count--)
|
||
{
|
||
sum += *buf++; // 依次累加,求得校验和
|
||
};
|
||
|
||
switch(length & 0x03)
|
||
{
|
||
case 0:
|
||
return sum;
|
||
case 1:
|
||
sum += (*buf & 0x000000ff);
|
||
break;
|
||
case 2:
|
||
sum += (*buf & 0x0000ffff);
|
||
break;
|
||
case 3:
|
||
sum += (*buf & 0x00ffffff);
|
||
break;
|
||
}
|
||
#else
|
||
uint sum;
|
||
|
||
sum = add_sum_neon(buffer, length);
|
||
#endif
|
||
|
||
return sum;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* 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;
|
||
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
uint sunxi_sprite_part_sparsedata_verify(void)
|
||
{
|
||
return unsparse_checksum();
|
||
}
|
||
|
||
uint sunxi_sprite_generate_checksum(void *buffer, uint length, uint src_sum)
|
||
{
|
||
return sunxi_generate_checksum(buffer, length, src_sum);
|
||
}
|
||
|
||
int sunxi_sprite_verify_checksum(void *buffer, uint length, uint src_sum)
|
||
{
|
||
return sunxi_verify_checksum(buffer, length, src_sum);
|
||
}
|
||
/*
|
||
***************************************************************
|
||
* __mbr_map_dump
|
||
*
|
||
* Description:
|
||
* check the input para
|
||
* Parameters:
|
||
*
|
||
* Return value:
|
||
*
|
||
* History:
|
||
*
|
||
***************************************************************
|
||
*/
|
||
static void __mbr_map_dump(u8 *buf)
|
||
{
|
||
sunxi_mbr_t *mbr_info = (sunxi_mbr_t *)buf;
|
||
sunxi_partition *part_info;
|
||
u32 i;
|
||
char buffer[32];
|
||
|
||
printf("*************MBR DUMP***************\n");
|
||
printf("total mbr part %d\n", mbr_info->PartCount);
|
||
printf("\n");
|
||
for(part_info = mbr_info->array, i=0;i<mbr_info->PartCount;i++, part_info++)
|
||
{
|
||
memset(buffer, 0, 32);
|
||
memcpy(buffer, part_info->name, 16);
|
||
printf("part[%d] name :%s\n", i, buffer);
|
||
memset(buffer, 0, 32);
|
||
memcpy(buffer, part_info->classname, 16);
|
||
printf("part[%d] classname :%s\n", i, buffer);
|
||
printf("part[%d] addrlo :0x%x\n", i, part_info->addrlo);
|
||
printf("part[%d] lenlo :0x%x\n", i, part_info->lenlo);
|
||
printf("part[%d] user_type :%d\n", i, part_info->user_type);
|
||
printf("part[%d] keydata :%d\n", i, part_info->keydata);
|
||
printf("part[%d] ro :%d\n", i, part_info->ro);
|
||
printf("\n");
|
||
}
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_sprite_verify_mbr(void *buffer)
|
||
{
|
||
sunxi_mbr_t *local_mbr;
|
||
char *tmp_buf = (char *)buffer;
|
||
int i;
|
||
int mbr_num = SUNXI_MBR_COPY_NUM;
|
||
tmp_buf = buffer;
|
||
|
||
if (get_boot_storage_type() == STORAGE_NOR)
|
||
{
|
||
mbr_num = 1;
|
||
}
|
||
|
||
for(i=0;i<mbr_num;i++)
|
||
{
|
||
local_mbr = (sunxi_mbr_t *)tmp_buf;
|
||
if(crc32(0, (const unsigned char *)(tmp_buf + 4), SUNXI_MBR_SIZE - 4) != local_mbr->crc32)
|
||
{
|
||
printf("the %d mbr table is bad\n", i);
|
||
|
||
return -1;
|
||
}
|
||
else
|
||
{
|
||
printf("the %d mbr table is ok\n", i);
|
||
tmp_buf += SUNXI_MBR_SIZE;
|
||
}
|
||
}
|
||
#if 1
|
||
__mbr_map_dump(buffer);
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
|
||
int sunxi_sprite_get_one_valid_mbr(void *valid_mbr_buffer, void *source_mbr_buffer)
|
||
{
|
||
sunxi_mbr_t *local_mbr;
|
||
char *tmp_buf;
|
||
int i;
|
||
int mbr_num = SUNXI_MBR_COPY_NUM;
|
||
|
||
tmp_buf = source_mbr_buffer;
|
||
|
||
if (get_boot_storage_type() == STORAGE_NOR)
|
||
mbr_num = 1;
|
||
|
||
for (i = 0; i < mbr_num; i++) {
|
||
local_mbr = (sunxi_mbr_t *)tmp_buf;
|
||
if (crc32(0, (const unsigned char *)(tmp_buf + 4), SUNXI_MBR_SIZE - 4) != local_mbr->crc32) {
|
||
printf("the %d mbr table is bad\n", i);
|
||
tmp_buf += SUNXI_MBR_SIZE;
|
||
} else {
|
||
printf("the %d mbr table is ok\n", i);
|
||
memmove(valid_mbr_buffer, tmp_buf, SUNXI_MBR_SIZE);
|
||
#if 1
|
||
__mbr_map_dump(valid_mbr_buffer);
|
||
#endif
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
|
||
int sunxi_sprite_read_mbr(void *buffer, uint mbr_copy)
|
||
{
|
||
uint sectors;
|
||
|
||
sectors = mbr_copy*SUNXI_MBR_SIZE/512;
|
||
if (sectors != sunxi_sprite_read(0, sectors, buffer))
|
||
return -1;
|
||
|
||
#ifdef CONFIG_GPT_SUPPORT
|
||
char *p = buffer;
|
||
char *p_sunxi_mbr = p + 3*SUNXI_MBR_SIZE;
|
||
/* 00K~48K ->GPT entry */
|
||
/* 48K~64K ->sunxi mbr */
|
||
/* for sunxi_sprite_verify_mbr get success result */
|
||
memcpy(p + 0*SUNXI_MBR_SIZE, p_sunxi_mbr, SUNXI_MBR_SIZE);
|
||
memcpy(p + 1*SUNXI_MBR_SIZE, p_sunxi_mbr, SUNXI_MBR_SIZE);
|
||
memcpy(p + 2*SUNXI_MBR_SIZE, p_sunxi_mbr, SUNXI_MBR_SIZE);
|
||
#endif
|
||
return 0;
|
||
|
||
}
|
||
|
||
int sunxi_sprite_verify_mbr_from_flash(u32 blocks, u32 mbr_copy)
|
||
{
|
||
int ret;
|
||
u32 data_len;
|
||
char *data_buf = NULL;
|
||
|
||
printf("sunxi_sprite_verify_mbr_from_flash\n");
|
||
data_len = (blocks << 9);
|
||
data_buf = malloc(data_len);
|
||
if (data_buf == NULL) {
|
||
printf("%s: malloc fail\n", __func__);
|
||
return -1;
|
||
}
|
||
memset(data_buf, 0x0, data_len);
|
||
|
||
ret = sunxi_sprite_read_mbr(data_buf, mbr_copy);
|
||
if (ret < 0) {
|
||
printf("%s:sunxi_sprite_read_mbr fail\n", __func__);
|
||
free(data_buf);
|
||
return -1;
|
||
}
|
||
|
||
if (sunxi_sprite_verify_mbr(data_buf) < 0) {
|
||
printf("mbr_verify fail\n");
|
||
free(data_buf);
|
||
return -1;
|
||
}
|
||
|
||
free(data_buf);
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_sprite_verify_dlmap(void *buffer)
|
||
{
|
||
sunxi_download_info *local_dlmap;
|
||
char *tmp_buf = (char *)buffer;
|
||
|
||
tmp_buf = buffer;
|
||
local_dlmap = (sunxi_download_info *)tmp_buf;
|
||
if(crc32(0, (const unsigned char *)(tmp_buf + 4), SUNXI_MBR_SIZE - 4) != local_dlmap->crc32)
|
||
{
|
||
printf("downlaod map is bad\n");
|
||
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|