1*2e379d2fSMasahiro Yamada /* 2*2e379d2fSMasahiro Yamada * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3*2e379d2fSMasahiro Yamada * 4*2e379d2fSMasahiro Yamada * SPDX-License-Identifier: BSD-3-Clause 5*2e379d2fSMasahiro Yamada */ 6*2e379d2fSMasahiro Yamada 7*2e379d2fSMasahiro Yamada #include <arch_helpers.h> 8*2e379d2fSMasahiro Yamada #include <assert.h> 9*2e379d2fSMasahiro Yamada #include <bl_common.h> 10*2e379d2fSMasahiro Yamada #include <debug.h> 11*2e379d2fSMasahiro Yamada #include <image_decompress.h> 12*2e379d2fSMasahiro Yamada #include <stdint.h> 13*2e379d2fSMasahiro Yamada 14*2e379d2fSMasahiro Yamada static uintptr_t decompressor_buf_base; 15*2e379d2fSMasahiro Yamada static uint32_t decompressor_buf_size; 16*2e379d2fSMasahiro Yamada static decompressor_t *decompressor; 17*2e379d2fSMasahiro Yamada static struct image_info saved_image_info; 18*2e379d2fSMasahiro Yamada 19*2e379d2fSMasahiro Yamada void image_decompress_init(uintptr_t buf_base, uint32_t buf_size, 20*2e379d2fSMasahiro Yamada decompressor_t *_decompressor) 21*2e379d2fSMasahiro Yamada { 22*2e379d2fSMasahiro Yamada decompressor_buf_base = buf_base; 23*2e379d2fSMasahiro Yamada decompressor_buf_size = buf_size; 24*2e379d2fSMasahiro Yamada decompressor = _decompressor; 25*2e379d2fSMasahiro Yamada } 26*2e379d2fSMasahiro Yamada 27*2e379d2fSMasahiro Yamada void image_decompress_prepare(struct image_info *info) 28*2e379d2fSMasahiro Yamada { 29*2e379d2fSMasahiro Yamada /* 30*2e379d2fSMasahiro Yamada * If the image is compressed, it should be loaded into the temporary 31*2e379d2fSMasahiro Yamada * buffer instead of its final destination. We save image_info, then 32*2e379d2fSMasahiro Yamada * override ->image_base and ->image_max_size so that load_image() will 33*2e379d2fSMasahiro Yamada * transfer the compressed data to the temporary buffer. 34*2e379d2fSMasahiro Yamada */ 35*2e379d2fSMasahiro Yamada saved_image_info = *info; 36*2e379d2fSMasahiro Yamada info->image_base = decompressor_buf_base; 37*2e379d2fSMasahiro Yamada info->image_max_size = decompressor_buf_size; 38*2e379d2fSMasahiro Yamada } 39*2e379d2fSMasahiro Yamada 40*2e379d2fSMasahiro Yamada int image_decompress(struct image_info *info) 41*2e379d2fSMasahiro Yamada { 42*2e379d2fSMasahiro Yamada uintptr_t compressed_image_base, image_base, work_base; 43*2e379d2fSMasahiro Yamada uint32_t compressed_image_size, work_size; 44*2e379d2fSMasahiro Yamada int ret; 45*2e379d2fSMasahiro Yamada 46*2e379d2fSMasahiro Yamada /* 47*2e379d2fSMasahiro Yamada * The size of compressed data has been filled by load_image(). 48*2e379d2fSMasahiro Yamada * Read it out before restoring image_info. 49*2e379d2fSMasahiro Yamada */ 50*2e379d2fSMasahiro Yamada compressed_image_size = info->image_size; 51*2e379d2fSMasahiro Yamada compressed_image_base = info->image_base; 52*2e379d2fSMasahiro Yamada *info = saved_image_info; 53*2e379d2fSMasahiro Yamada 54*2e379d2fSMasahiro Yamada assert(compressed_image_size <= decompressor_buf_size); 55*2e379d2fSMasahiro Yamada 56*2e379d2fSMasahiro Yamada image_base = info->image_base; 57*2e379d2fSMasahiro Yamada 58*2e379d2fSMasahiro Yamada /* 59*2e379d2fSMasahiro Yamada * Use the rest of the temporary buffer as workspace of the 60*2e379d2fSMasahiro Yamada * decompressor since the decompressor may need additional memory. 61*2e379d2fSMasahiro Yamada */ 62*2e379d2fSMasahiro Yamada work_base = compressed_image_base + compressed_image_size; 63*2e379d2fSMasahiro Yamada work_size = decompressor_buf_size - compressed_image_size; 64*2e379d2fSMasahiro Yamada 65*2e379d2fSMasahiro Yamada ret = decompressor(&compressed_image_base, compressed_image_size, 66*2e379d2fSMasahiro Yamada &image_base, info->image_max_size, 67*2e379d2fSMasahiro Yamada work_base, work_size); 68*2e379d2fSMasahiro Yamada if (ret) { 69*2e379d2fSMasahiro Yamada ERROR("Failed to decompress image (err=%d)\n", ret); 70*2e379d2fSMasahiro Yamada return ret; 71*2e379d2fSMasahiro Yamada } 72*2e379d2fSMasahiro Yamada 73*2e379d2fSMasahiro Yamada /* image_base is updated to the final pos when decompressor() exits. */ 74*2e379d2fSMasahiro Yamada info->image_size = image_base - info->image_base; 75*2e379d2fSMasahiro Yamada 76*2e379d2fSMasahiro Yamada flush_dcache_range(info->image_base, info->image_size); 77*2e379d2fSMasahiro Yamada 78*2e379d2fSMasahiro Yamada return 0; 79*2e379d2fSMasahiro Yamada } 80