12e379d2fSMasahiro Yamada /* 22e379d2fSMasahiro Yamada * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 32e379d2fSMasahiro Yamada * 42e379d2fSMasahiro Yamada * SPDX-License-Identifier: BSD-3-Clause 52e379d2fSMasahiro Yamada */ 62e379d2fSMasahiro Yamada 72e379d2fSMasahiro Yamada #include <assert.h> 82e379d2fSMasahiro Yamada #include <stdint.h> 92e379d2fSMasahiro Yamada 10*09d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 11*09d40e0eSAntonio Nino Diaz #include <common/bl_common.h> 12*09d40e0eSAntonio Nino Diaz #include <common/debug.h> 13*09d40e0eSAntonio Nino Diaz #include <common/image_decompress.h> 14*09d40e0eSAntonio Nino Diaz 152e379d2fSMasahiro Yamada static uintptr_t decompressor_buf_base; 162e379d2fSMasahiro Yamada static uint32_t decompressor_buf_size; 172e379d2fSMasahiro Yamada static decompressor_t *decompressor; 182e379d2fSMasahiro Yamada static struct image_info saved_image_info; 192e379d2fSMasahiro Yamada 202e379d2fSMasahiro Yamada void image_decompress_init(uintptr_t buf_base, uint32_t buf_size, 212e379d2fSMasahiro Yamada decompressor_t *_decompressor) 222e379d2fSMasahiro Yamada { 232e379d2fSMasahiro Yamada decompressor_buf_base = buf_base; 242e379d2fSMasahiro Yamada decompressor_buf_size = buf_size; 252e379d2fSMasahiro Yamada decompressor = _decompressor; 262e379d2fSMasahiro Yamada } 272e379d2fSMasahiro Yamada 282e379d2fSMasahiro Yamada void image_decompress_prepare(struct image_info *info) 292e379d2fSMasahiro Yamada { 302e379d2fSMasahiro Yamada /* 312e379d2fSMasahiro Yamada * If the image is compressed, it should be loaded into the temporary 322e379d2fSMasahiro Yamada * buffer instead of its final destination. We save image_info, then 332e379d2fSMasahiro Yamada * override ->image_base and ->image_max_size so that load_image() will 342e379d2fSMasahiro Yamada * transfer the compressed data to the temporary buffer. 352e379d2fSMasahiro Yamada */ 362e379d2fSMasahiro Yamada saved_image_info = *info; 372e379d2fSMasahiro Yamada info->image_base = decompressor_buf_base; 382e379d2fSMasahiro Yamada info->image_max_size = decompressor_buf_size; 392e379d2fSMasahiro Yamada } 402e379d2fSMasahiro Yamada 412e379d2fSMasahiro Yamada int image_decompress(struct image_info *info) 422e379d2fSMasahiro Yamada { 432e379d2fSMasahiro Yamada uintptr_t compressed_image_base, image_base, work_base; 442e379d2fSMasahiro Yamada uint32_t compressed_image_size, work_size; 452e379d2fSMasahiro Yamada int ret; 462e379d2fSMasahiro Yamada 472e379d2fSMasahiro Yamada /* 482e379d2fSMasahiro Yamada * The size of compressed data has been filled by load_image(). 492e379d2fSMasahiro Yamada * Read it out before restoring image_info. 502e379d2fSMasahiro Yamada */ 512e379d2fSMasahiro Yamada compressed_image_size = info->image_size; 522e379d2fSMasahiro Yamada compressed_image_base = info->image_base; 532e379d2fSMasahiro Yamada *info = saved_image_info; 542e379d2fSMasahiro Yamada 552e379d2fSMasahiro Yamada assert(compressed_image_size <= decompressor_buf_size); 562e379d2fSMasahiro Yamada 572e379d2fSMasahiro Yamada image_base = info->image_base; 582e379d2fSMasahiro Yamada 592e379d2fSMasahiro Yamada /* 602e379d2fSMasahiro Yamada * Use the rest of the temporary buffer as workspace of the 612e379d2fSMasahiro Yamada * decompressor since the decompressor may need additional memory. 622e379d2fSMasahiro Yamada */ 632e379d2fSMasahiro Yamada work_base = compressed_image_base + compressed_image_size; 642e379d2fSMasahiro Yamada work_size = decompressor_buf_size - compressed_image_size; 652e379d2fSMasahiro Yamada 662e379d2fSMasahiro Yamada ret = decompressor(&compressed_image_base, compressed_image_size, 672e379d2fSMasahiro Yamada &image_base, info->image_max_size, 682e379d2fSMasahiro Yamada work_base, work_size); 692e379d2fSMasahiro Yamada if (ret) { 702e379d2fSMasahiro Yamada ERROR("Failed to decompress image (err=%d)\n", ret); 712e379d2fSMasahiro Yamada return ret; 722e379d2fSMasahiro Yamada } 732e379d2fSMasahiro Yamada 742e379d2fSMasahiro Yamada /* image_base is updated to the final pos when decompressor() exits. */ 752e379d2fSMasahiro Yamada info->image_size = image_base - info->image_base; 762e379d2fSMasahiro Yamada 772e379d2fSMasahiro Yamada flush_dcache_range(info->image_base, info->image_size); 782e379d2fSMasahiro Yamada 792e379d2fSMasahiro Yamada return 0; 802e379d2fSMasahiro Yamada } 81