238 lines
5.6 KiB
C
238 lines
5.6 KiB
C
|
/*
|
||
|
* Usefuls routines based on the LzmaTest.c file from LZMA SDK 4.65
|
||
|
*
|
||
|
* Copyright (C) 2007-2009 Industrie Dial Face S.p.A.
|
||
|
* Luigi 'Comio' Mantellini (luigi.mantellini@idf-hit.com)
|
||
|
*
|
||
|
* Copyright (C) 1999-2005 Igor Pavlov
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-2.0+
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* LZMA_Alone stream format:
|
||
|
*
|
||
|
* uchar Properties[5]
|
||
|
* uint64 Uncompressed size
|
||
|
* uchar data[*]
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#define LZMA_PROPERTIES_OFFSET 0
|
||
|
#define LZMA_SIZE_OFFSET LZMA_PROPS_SIZE
|
||
|
#define LZMA_DATA_OFFSET LZMA_SIZE_OFFSET+sizeof(uint64_t)
|
||
|
|
||
|
#include "os_types.h"
|
||
|
|
||
|
#include "LzmaTools.h"
|
||
|
#include "LzmaDec.h"
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "7zAlloc.h"
|
||
|
|
||
|
#include "flash.h"
|
||
|
#include "ahb.h"
|
||
|
#include "iot_mtd.h"
|
||
|
|
||
|
#include "ram.h"
|
||
|
|
||
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||
|
|
||
|
extern char ram_share_buf[];
|
||
|
|
||
|
static unsigned char *heap_buf = (unsigned char*)ram_share_buf;
|
||
|
|
||
|
static void *SzAlloc(void *p, size_t size) { return buffer_alloc_malloc(size); }
|
||
|
static void SzFree(void *p, void *address) { buffer_alloc_free(address); }
|
||
|
|
||
|
|
||
|
struct dataStream
|
||
|
{
|
||
|
const unsigned char * inData;
|
||
|
size_t inLen;
|
||
|
|
||
|
unsigned char * outData;
|
||
|
size_t outLen;
|
||
|
};
|
||
|
|
||
|
struct dataStream ds;
|
||
|
static uint32_t start_addr = 0, end_addr = 0;
|
||
|
|
||
|
static void flash_erase_blocks(uint32_t addr, uint32_t size)
|
||
|
{
|
||
|
flash_write_param_t param = {
|
||
|
.sw_mode = MOD_SW_MODE_DIS,
|
||
|
.erase_mode = MODE_ERASE_BLOCK64
|
||
|
};
|
||
|
|
||
|
start_addr = (addr + BLOCK_ERASE_64K_MASK) & (~BLOCK_ERASE_64K_MASK);
|
||
|
end_addr = (addr + size) & (~BLOCK_ERASE_64K_MASK);
|
||
|
|
||
|
/* disable cache space */
|
||
|
ahb_cache_space_dis_for_flash_write();
|
||
|
for (uint32_t erase_addr = start_addr; erase_addr < end_addr;
|
||
|
erase_addr += BLOCK_ERASE_64K_SIZE) {
|
||
|
flash_erase(erase_addr, ¶m);
|
||
|
}
|
||
|
/* enable cache space again */
|
||
|
ahb_cache_space_ena_for_flash_write();
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
inputCallback(void *ctx, void *buf, size_t * size)
|
||
|
{
|
||
|
size_t rd = 0;
|
||
|
|
||
|
rd = (ds.inLen < *size) ? ds.inLen : *size;
|
||
|
|
||
|
if (rd > 0) {
|
||
|
memcpy(buf, (void *) ds.inData, rd);
|
||
|
ds.inData += rd;
|
||
|
ds.inLen -= rd;
|
||
|
}
|
||
|
|
||
|
*size = rd;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static size_t
|
||
|
outputCallback(void *ctx, const void *buf, size_t size)
|
||
|
{
|
||
|
flash_write_param_t param = {0};
|
||
|
|
||
|
/*write to the FW addr in flash*/
|
||
|
param.read_mode = MOD_SFC_READ_QUAD_IO_FAST;
|
||
|
param.write_mode = MOD_SFC_PROG_STAND;
|
||
|
param.is_erase = 1;
|
||
|
param.sw_mode = MOD_SW_MODE_DIS;
|
||
|
/* disable cache space */
|
||
|
ahb_cache_space_dis();
|
||
|
if ((start_addr <= (uint32_t)(ds.outData + ds.outLen)) &&
|
||
|
((uint32_t)(ds.outData + ds.outLen + size) <= end_addr)) {
|
||
|
param.is_erase = 0;
|
||
|
}
|
||
|
flash_write(buf, (uint32_t)(ds.outData + ds.outLen), (uint32_t)size, ¶m);
|
||
|
/* enable cache space again */
|
||
|
ahb_cache_space_ena();
|
||
|
ds.outLen += (uint32_t)size;
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
#define IN_BUF_SIZE (1 << 14)
|
||
|
#define OUT_BUF_SIZE (1 << 14)
|
||
|
|
||
|
Byte inBuf[IN_BUF_SIZE];
|
||
|
Byte outBuf[OUT_BUF_SIZE];
|
||
|
|
||
|
static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
|
||
|
UInt64 unpackSize)
|
||
|
{
|
||
|
int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
|
||
|
size_t inPos = 0, inSize = 0, outPos = 0;
|
||
|
LzmaDec_Init(state);
|
||
|
for (;;)
|
||
|
{
|
||
|
if (inPos == inSize)
|
||
|
{
|
||
|
inSize = IN_BUF_SIZE;
|
||
|
RINOK(inStream->Read(inStream, inBuf, &inSize));
|
||
|
inPos = 0;
|
||
|
}
|
||
|
{
|
||
|
SRes res;
|
||
|
SizeT inProcessed = inSize - inPos;
|
||
|
SizeT outProcessed = OUT_BUF_SIZE - outPos;
|
||
|
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
|
||
|
ELzmaStatus status;
|
||
|
if (thereIsSize && outProcessed > unpackSize)
|
||
|
{
|
||
|
outProcessed = (SizeT)unpackSize;
|
||
|
finishMode = LZMA_FINISH_END;
|
||
|
}
|
||
|
|
||
|
res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
|
||
|
inBuf + inPos, &inProcessed, finishMode, &status);
|
||
|
inPos += inProcessed;
|
||
|
outPos += outProcessed;
|
||
|
unpackSize -= outProcessed;
|
||
|
|
||
|
if (outStream)
|
||
|
if (outStream->Write(outStream, outBuf, outPos) != outPos)
|
||
|
return SZ_ERROR_WRITE;
|
||
|
|
||
|
outPos = 0;
|
||
|
|
||
|
if (res != SZ_OK || (thereIsSize && unpackSize == 0))
|
||
|
return res;
|
||
|
|
||
|
if (inProcessed == 0 && outProcessed == 0)
|
||
|
{
|
||
|
if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
|
||
|
return SZ_ERROR_DATA;
|
||
|
return res;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
int BufferDecode(uint8_t *dst, uint32_t *dstLen, uint8_t *src, uint32_t srcLen )
|
||
|
{
|
||
|
ISeqOutStream outStream;
|
||
|
ISeqInStream inStream;
|
||
|
ISzAlloc g_Alloc;
|
||
|
UInt64 unpackSize;
|
||
|
int i;
|
||
|
size_t header_size;
|
||
|
SRes res = 0;
|
||
|
|
||
|
CLzmaDec state;
|
||
|
|
||
|
outStream.Write= outputCallback;
|
||
|
inStream.Read = inputCallback;
|
||
|
|
||
|
ds.inData = src;
|
||
|
ds.inLen = srcLen;
|
||
|
ds.outData = dst;
|
||
|
ds.outLen = 0;
|
||
|
|
||
|
/* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
|
||
|
unsigned char header[LZMA_PROPS_SIZE + 8];
|
||
|
|
||
|
/* Read and parse header */
|
||
|
header_size = sizeof(header);
|
||
|
inStream.Read(&inStream, header, &header_size);
|
||
|
|
||
|
unpackSize = 0;
|
||
|
for (i = 0; i < 8; i++)
|
||
|
unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
|
||
|
flash_erase_blocks((uint32_t)dst, (uint32_t)unpackSize);
|
||
|
|
||
|
memory_buffer_alloc_init(heap_buf, RAM_SHA_BUFFER_LEN);
|
||
|
|
||
|
g_Alloc.Alloc = SzAlloc;
|
||
|
g_Alloc.Free = SzFree;
|
||
|
|
||
|
LzmaDec_Construct(&state);
|
||
|
LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);
|
||
|
|
||
|
res = Decode2(&state, &outStream, &inStream, unpackSize);
|
||
|
LzmaDec_Free(&state, &g_Alloc);
|
||
|
|
||
|
*dstLen = ds.outLen;
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
int lzmaBuffToBuffDecompress (unsigned char *outStream, uint32_t *uncompressedSize,
|
||
|
unsigned char *inStream, uint32_t length)
|
||
|
{
|
||
|
return BufferDecode(outStream, uncompressedSize, inStream, length);
|
||
|
}
|