319 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			319 lines
		
	
	
		
			7.8 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 "iot_config.h"
 | ||
|  | #include "flash.h"
 | ||
|  | #include "ahb.h"
 | ||
|  | #include "iot_mtd.h"
 | ||
|  | 
 | ||
|  | #include "sbl_boot_hw.h"
 | ||
|  | 
 | ||
|  | #define min(a, b) (((a) < (b)) ? (a) : (b))
 | ||
|  | 
 | ||
|  | /* LZMA decoder need 1M size buffer */ | ||
|  | #define BUF_SZ LZMA_BUF_SIZE
 | ||
|  | #define BUF_ADDR LZMA_BUF_ADDR
 | ||
|  | 
 | ||
|  | static unsigned char *heap_buf = (unsigned char*)BUF_ADDR; | ||
|  | 
 | ||
|  | 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) | ||
|  | { | ||
|  | #if RUN_IN_PSRAM
 | ||
|  |     if (size > 0) { | ||
|  |         memcpy((void *) (ds.outData + ds.outLen), buf, size); | ||
|  |         ds.outLen += size; | ||
|  |     } | ||
|  | 
 | ||
|  | #else
 | ||
|  |     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_for_flash_write(); | ||
|  |     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_for_flash_write(); | ||
|  |     ds.outLen += (uint32_t)size; | ||
|  | #endif
 | ||
|  |     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, BUF_SZ); | ||
|  | 
 | ||
|  |     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) | ||
|  | { | ||
|  | #if RUN_IN_PSRAM
 | ||
|  |     int res = SZ_ERROR_DATA; | ||
|  |     int i; | ||
|  |     ISzAlloc g_Alloc; | ||
|  | 
 | ||
|  |     SizeT outSizeFull = 0xFFFFFFFF; /* 4GBytes limit */ | ||
|  |     SizeT outProcessed; | ||
|  |     SizeT outSize; | ||
|  |     SizeT outSizeHigh; | ||
|  |     ELzmaStatus state; | ||
|  |     SizeT compressedSize = (SizeT)(length - LZMA_PROPS_SIZE); | ||
|  | 
 | ||
|  |     memset(&state, 0, sizeof(state)); | ||
|  | 
 | ||
|  |     outSize = 0; | ||
|  |     outSizeHigh = 0; | ||
|  |     /* Read the uncompressed size */ | ||
|  |     for (i = 0; i < 8; i++) { | ||
|  |         unsigned char b = inStream[LZMA_SIZE_OFFSET + i]; | ||
|  |             if (i < 4) { | ||
|  |                 outSize     += (UInt32)(b) << (i * 8); | ||
|  |         } else { | ||
|  |                 outSizeHigh += (UInt32)(b) << ((i - 4) * 8); | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     outSizeFull = (SizeT)outSize; | ||
|  |     if (sizeof(SizeT) >= 8) { | ||
|  |         /*
 | ||
|  |          * SizeT is a 64 bit uint => We can manage files larger than 4GB! | ||
|  |          * | ||
|  |          */ | ||
|  |             outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); | ||
|  |     } else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) { | ||
|  |         /*
 | ||
|  |          * SizeT is a 32 bit uint => We cannot manage files larger than | ||
|  |          * 4GB!  Assume however that all 0xf values is "unknown size" and | ||
|  |          * not actually a file of 2^64 bits. | ||
|  |          * | ||
|  |          */ | ||
|  |         if (outSizeHigh != (SizeT)-1 || outSize != (SizeT)-1) { | ||
|  |             return SZ_ERROR_DATA; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     memory_buffer_alloc_init(heap_buf, BUF_SZ); | ||
|  | 
 | ||
|  |     g_Alloc.Alloc = SzAlloc; | ||
|  |     g_Alloc.Free = SzFree; | ||
|  | 
 | ||
|  |     /* Short-circuit early if we know the buffer can't hold the results. */ | ||
|  |     if (outSizeFull != (SizeT)-1 && *uncompressedSize < outSizeFull) | ||
|  |         return SZ_ERROR_OUTPUT_EOF; | ||
|  | 
 | ||
|  |     /* Decompress */ | ||
|  |     outProcessed = min(outSizeFull, *uncompressedSize); | ||
|  | 
 | ||
|  |     res = LzmaDecode( | ||
|  |         outStream, &outProcessed, | ||
|  |         inStream + LZMA_DATA_OFFSET, &compressedSize, | ||
|  |         inStream, LZMA_PROPS_SIZE, LZMA_FINISH_END, &state, &g_Alloc); | ||
|  |     *uncompressedSize = outProcessed; | ||
|  | 
 | ||
|  |     if (res != SZ_OK)  { | ||
|  |         return res; | ||
|  |     } | ||
|  | 
 | ||
|  |     return res; | ||
|  | #else
 | ||
|  |     return BufferDecode(outStream, uncompressedSize, inStream, length); | ||
|  | #endif
 | ||
|  | } |