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