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