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);
 | |
| }
 |