271 lines
6.8 KiB
C
271 lines
6.8 KiB
C
|
/*
|
|||
|
* (C) Copyright 2007-2011
|
|||
|
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
|||
|
* Tom Cubie <tangliang@allwinnertech.com>
|
|||
|
*
|
|||
|
* (C) Copyright 2011
|
|||
|
* Texas Instruments, <www.ti.com>
|
|||
|
* Author: Vikram Pandita <vikram.pandita@ti.com>
|
|||
|
*
|
|||
|
* 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 "update_simg.h"
|
|||
|
#include "sparse.h"
|
|||
|
#include "sparse_format.h"
|
|||
|
|
|||
|
#define SPARSE_HEADER_MAJOR_VER 1
|
|||
|
|
|||
|
unsigned int sparse_format_type;
|
|||
|
unsigned int chunk_count;
|
|||
|
int last_rest_size;
|
|||
|
int chunk_length;
|
|||
|
sparse_header_t globl_header;
|
|||
|
|
|||
|
|
|||
|
static int wirte_to_0xff(FILE *file, unsigned int length)
|
|||
|
{
|
|||
|
char buffer[4 * 1024];
|
|||
|
unsigned int tmp_length;
|
|||
|
|
|||
|
tmp_length = length;
|
|||
|
memset(buffer, 0xff, 4 * 1024);
|
|||
|
while(tmp_length >= 4 * 1024)
|
|||
|
{
|
|||
|
fwrite(buffer, 4 * 1024, 1, file);
|
|||
|
tmp_length -= 4 * 1024;
|
|||
|
}
|
|||
|
if(tmp_length)
|
|||
|
{
|
|||
|
fwrite(buffer, tmp_length, 1, file);
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
/*
|
|||
|
************************************************************************************************************
|
|||
|
*
|
|||
|
* unsparse_probe
|
|||
|
*
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>
|
|||
|
*
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ <EFBFBD><EFBFBD>
|
|||
|
*
|
|||
|
* ˵<EFBFBD><EFBFBD> <EFBFBD><EFBFBD>
|
|||
|
*
|
|||
|
*
|
|||
|
************************************************************************************************************
|
|||
|
*/
|
|||
|
int unsparse_probe(char *source, unsigned int length)
|
|||
|
{
|
|||
|
sparse_header_t *header = (sparse_header_t*) source;
|
|||
|
|
|||
|
if (header->magic != SPARSE_HEADER_MAGIC)
|
|||
|
{
|
|||
|
printf("sparse: bad magic\n");
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
if ((header->major_version != SPARSE_HEADER_MAJOR_VER) ||
|
|||
|
(header->file_hdr_sz != sizeof(sparse_header_t)) ||
|
|||
|
(header->chunk_hdr_sz != sizeof(chunk_header_t)))
|
|||
|
{
|
|||
|
printf("sparse: incompatible format\n");
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
last_rest_size = 0;
|
|||
|
chunk_count = 0;
|
|||
|
chunk_length = 0;
|
|||
|
sparse_format_type = SPARSE_FORMAT_TYPE_TOTAL_HEAD;
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
/*
|
|||
|
************************************************************************************************************
|
|||
|
*
|
|||
|
* DRAM_Write
|
|||
|
*
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>
|
|||
|
*
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ <EFBFBD><EFBFBD>
|
|||
|
*
|
|||
|
* ˵<EFBFBD><EFBFBD> <EFBFBD><EFBFBD>
|
|||
|
*
|
|||
|
*
|
|||
|
************************************************************************************************************
|
|||
|
*/
|
|||
|
int unsparse_direct_write(void *pbuf, int length, FILE *dfile)
|
|||
|
{
|
|||
|
int unenough_length;
|
|||
|
int this_rest_size;
|
|||
|
int tmp_down_size;
|
|||
|
char *tmp_buf, *tmp_dest_buf;
|
|||
|
chunk_header_t *chunk;
|
|||
|
|
|||
|
this_rest_size = last_rest_size + length;
|
|||
|
tmp_buf = (char *)pbuf - last_rest_size;
|
|||
|
last_rest_size = 0;
|
|||
|
|
|||
|
while(this_rest_size > 0)
|
|||
|
{
|
|||
|
switch(sparse_format_type)
|
|||
|
{
|
|||
|
case SPARSE_FORMAT_TYPE_TOTAL_HEAD:
|
|||
|
{
|
|||
|
memcpy(&globl_header, tmp_buf, sizeof(sparse_header_t));
|
|||
|
this_rest_size -= sizeof(sparse_header_t);
|
|||
|
tmp_buf += sizeof(sparse_header_t);
|
|||
|
|
|||
|
sparse_format_type = SPARSE_FORMAT_TYPE_CHUNK_HEAD;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
case SPARSE_FORMAT_TYPE_CHUNK_HEAD:
|
|||
|
{
|
|||
|
if(this_rest_size < sizeof(chunk_header_t))
|
|||
|
{
|
|||
|
printf("sparse: chunk head data is not enough\n");
|
|||
|
last_rest_size = this_rest_size;
|
|||
|
tmp_dest_buf = (char *)pbuf - this_rest_size;
|
|||
|
memcpy(tmp_dest_buf, tmp_buf, this_rest_size);
|
|||
|
this_rest_size = 0;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
chunk = (chunk_header_t *)tmp_buf;
|
|||
|
/* move to next chunk */
|
|||
|
tmp_buf += sizeof(chunk_header_t); //<2F><>ʱtmp_buf<75>Ѿ<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>chunk<6E><6B><EFBFBD><EFBFBD>data<74><61>ʼ<EFBFBD><CABC>ַ
|
|||
|
this_rest_size -= sizeof(chunk_header_t); //ʣ<><CAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
|
|||
|
chunk_length = chunk->chunk_sz * globl_header.blk_sz; //<2F><>ǰ<EFBFBD><C7B0><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD>Ҫд<D2AA><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
|
|||
|
//printf("chunk index = %d\n", chunk_count ++);
|
|||
|
|
|||
|
switch (chunk->chunk_type)
|
|||
|
{
|
|||
|
case CHUNK_TYPE_RAW:
|
|||
|
|
|||
|
if (chunk->total_sz != (chunk_length + sizeof(chunk_header_t)))
|
|||
|
{
|
|||
|
printf("sparse: bad chunk size for chunk %d, type Raw\n", chunk_count);
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
//<2F><><EFBFBD>ﲻ<EFBFBD><EFB2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><DDB2>֣<EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>״̬
|
|||
|
sparse_format_type = SPARSE_FORMAT_TYPE_CHUNK_DATA;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case CHUNK_TYPE_DONT_CARE:
|
|||
|
if (chunk->total_sz != sizeof(chunk_header_t))
|
|||
|
{
|
|||
|
printf("sparse: bogus DONT CARE chunk\n");
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
wirte_to_0xff(dfile, chunk_length);
|
|||
|
sparse_format_type = SPARSE_FORMAT_TYPE_CHUNK_HEAD;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
printf("sparse: unknown chunk ID %x\n", chunk->chunk_type);
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
case SPARSE_FORMAT_TYPE_CHUNK_DATA:
|
|||
|
{
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>㹻<EFBFBD><E3B9BB>ǰchunk<6E><6B><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
|
|||
|
unenough_length = (chunk_length >= this_rest_size)? (chunk_length - this_rest_size):0;
|
|||
|
if(!unenough_length)
|
|||
|
{
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD>㹻<EFBFBD><E3B9BB>ֱ<EFBFBD><D6B1>д<EFBFBD><D0B4>
|
|||
|
fwrite(tmp_buf, chunk_length, 1, dfile);
|
|||
|
if(chunk_length & 511)
|
|||
|
{
|
|||
|
printf("data is not sector align 0\n");
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
tmp_buf += chunk_length;
|
|||
|
this_rest_size -= chunk_length;
|
|||
|
chunk_length = 0;
|
|||
|
|
|||
|
sparse_format_type = SPARSE_FORMAT_TYPE_CHUNK_HEAD;
|
|||
|
}
|
|||
|
else //<2F><><EFBFBD><EFBFBD>ȱʧ<C8B1><CAA7><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
{
|
|||
|
if(this_rest_size < 8 * 1024) //<2F>ȿ<EFBFBD><C8BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>8k
|
|||
|
{
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷŵ<DDB7><C5B5><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD>һ<EFBFBD>δ<EFBFBD><CEB4><EFBFBD>
|
|||
|
tmp_dest_buf = (char *)pbuf - this_rest_size;
|
|||
|
memcpy(tmp_dest_buf, tmp_buf, this_rest_size);
|
|||
|
last_rest_size = this_rest_size;
|
|||
|
this_rest_size = 0;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>16kʱ
|
|||
|
//<2F><>ȱʧ<C8B1><CAA7><EFBFBD>ݳ<EFBFBD><DDB3>Ȳ<EFBFBD><C8B2><EFBFBD>4kʱ,<2C><><EFBFBD><EFBFBD>ֻȱ<D6BB><C8B1>ʮ<EFBFBD><CAAE><EFBFBD>ֽ<EFBFBD>
|
|||
|
if(unenough_length < 4 * 1024)
|
|||
|
{
|
|||
|
//<2F><><EFBFBD><EFBFBD>ƴ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ΰ<EFBFBD>δ<EFBFBD><CEB4>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݺ<EFBFBD>ȱʧ<C8B1><CAA7><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>¼
|
|||
|
tmp_down_size = this_rest_size + unenough_length - 4 * 1024;
|
|||
|
}
|
|||
|
else //<2F><><EFBFBD>ﴦ<EFBFBD><EFB4A6>ȱʧ<C8B1><CAA7><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>8k(<28><><EFBFBD><EFBFBD>)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ͬʱ<CDAC><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>16k
|
|||
|
{
|
|||
|
//ֱ<><D6B1><EFBFBD><EFBFBD>¼<EFBFBD><C2BC>ǰȫ<C7B0><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
|
|||
|
tmp_down_size = this_rest_size & (~(512 -1)); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
fwrite(tmp_buf, tmp_down_size, 1, dfile);
|
|||
|
if(tmp_down_size & 511)
|
|||
|
{
|
|||
|
printf("data is not sector align 1\n");
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
tmp_buf += tmp_down_size;
|
|||
|
chunk_length -= tmp_down_size;
|
|||
|
this_rest_size -= tmp_down_size;
|
|||
|
tmp_dest_buf = (char *)pbuf - this_rest_size;
|
|||
|
memcpy(tmp_dest_buf, tmp_buf, this_rest_size);
|
|||
|
last_rest_size = this_rest_size;
|
|||
|
this_rest_size = 0;
|
|||
|
|
|||
|
sparse_format_type = SPARSE_FORMAT_TYPE_CHUNK_DATA;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
default:
|
|||
|
{
|
|||
|
printf("sparse: unknown status\n");
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|