/* * 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 #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); }