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
efi_zboot_decompress_init(unsigned long * alloc_size)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
efi_zboot_decompress(u8 * out,unsigned long outlen)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