1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/efi.h>
4 #include <linux/zstd.h>
5 
6 #include <asm/efi.h>
7 
8 #include "decompress_sources.h"
9 #include "efistub.h"
10 
11 extern unsigned char _gzdata_start[], _gzdata_end[];
12 extern u32 __aligned(1) payload_size;
13 
14 static size_t wksp_size;
15 static void *wksp;
16 
efi_zboot_decompress_init(unsigned long * alloc_size)17 efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size)
18 {
19 	efi_status_t status;
20 
21 	wksp_size = zstd_dctx_workspace_bound();
22 	status = efi_allocate_pages(wksp_size, (unsigned long *)&wksp, ULONG_MAX);
23 	if (status != EFI_SUCCESS)
24 		return status;
25 
26 	*alloc_size = payload_size;
27 	return EFI_SUCCESS;
28 }
29 
efi_zboot_decompress(u8 * out,unsigned long outlen)30 efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen)
31 {
32 	zstd_dctx *dctx = zstd_init_dctx(wksp, wksp_size);
33 	size_t ret;
34 	int retval;
35 
36 	ret = zstd_decompress_dctx(dctx, out, outlen, _gzdata_start,
37 				   _gzdata_end - _gzdata_start - 4);
38 	efi_free(wksp_size, (unsigned long)wksp);
39 
40 	retval = zstd_get_error_code(ret);
41 	if (retval) {
42 		efi_err("ZSTD-decompression failed with status %d\n", retval);
43 		return EFI_LOAD_ERROR;
44 	}
45 
46 	efi_cache_sync_image((unsigned long)out, outlen);
47 
48 	return EFI_SUCCESS;
49 }
50