1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/efi.h> 4 #include <linux/zlib.h> 5 6 #include <asm/efi.h> 7 8 #include "efistub.h" 9 10 #include "inftrees.c" 11 #include "inffast.c" 12 #include "inflate.c" 13 14 extern unsigned char _gzdata_start[], _gzdata_end[]; 15 extern u32 __aligned(1) payload_size; 16 17 static struct z_stream_s stream; 18 19 efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size) 20 { 21 efi_status_t status; 22 int rc; 23 24 /* skip the 10 byte header, assume no recorded filename */ 25 stream.next_in = _gzdata_start + 10; 26 stream.avail_in = _gzdata_end - stream.next_in; 27 28 status = efi_allocate_pages(zlib_inflate_workspacesize(), 29 (unsigned long *)&stream.workspace, 30 ULONG_MAX); 31 if (status != EFI_SUCCESS) 32 return status; 33 34 rc = zlib_inflateInit2(&stream, -MAX_WBITS); 35 if (rc != Z_OK) { 36 efi_err("failed to initialize GZIP decompressor: %d\n", rc); 37 status = EFI_LOAD_ERROR; 38 goto out; 39 } 40 41 *alloc_size = payload_size; 42 return EFI_SUCCESS; 43 out: 44 efi_free(zlib_inflate_workspacesize(), (unsigned long)stream.workspace); 45 return status; 46 } 47 48 efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen) 49 { 50 int rc; 51 52 stream.next_out = out; 53 stream.avail_out = outlen; 54 55 rc = zlib_inflate(&stream, 0); 56 zlib_inflateEnd(&stream); 57 58 efi_free(zlib_inflate_workspacesize(), (unsigned long)stream.workspace); 59 60 if (rc != Z_STREAM_END) { 61 efi_err("GZIP decompression failed with status %d\n", rc); 62 return EFI_LOAD_ERROR; 63 } 64 65 efi_cache_sync_image((unsigned long)out, outlen); 66 67 return EFI_SUCCESS; 68 } 69