diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 69 | ||||
-rw-r--r-- | lib/Makefile | 13 | ||||
-rw-r--r-- | lib/abuf.c | 109 | ||||
-rw-r--r-- | lib/acpi/acpi_table.c | 19 | ||||
-rw-r--r-- | lib/crc32.c | 9 | ||||
-rw-r--r-- | lib/display_options.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/Kconfig | 12 | ||||
-rw-r--r-- | lib/efi_loader/efi_gop.c | 61 | ||||
-rw-r--r-- | lib/efi_loader/efi_tcg2.c | 7 | ||||
-rw-r--r-- | lib/fdtdec.c | 44 | ||||
-rw-r--r-- | lib/gunzip.c | 28 | ||||
-rw-r--r-- | lib/hang.c | 2 | ||||
-rw-r--r-- | lib/hash-checksum.c | 2 | ||||
-rw-r--r-- | lib/lmb.c | 37 | ||||
-rw-r--r-- | lib/lz4_wrapper.c | 2 | ||||
-rw-r--r-- | lib/md5.c | 6 | ||||
-rw-r--r-- | lib/optee/Kconfig | 40 | ||||
-rw-r--r-- | lib/optee/Makefile | 2 | ||||
-rw-r--r-- | lib/optee/optee.c | 23 | ||||
-rw-r--r-- | lib/rsa/Kconfig | 1 | ||||
-rw-r--r-- | lib/rsa/rsa-sign.c | 83 | ||||
-rw-r--r-- | lib/rsa/rsa-verify.c | 15 | ||||
-rw-r--r-- | lib/string.c | 13 | ||||
-rw-r--r-- | lib/tiny-printf.c | 6 | ||||
-rw-r--r-- | lib/zstd/Makefile | 2 | ||||
-rw-r--r-- | lib/zstd/zstd.c | 64 |
26 files changed, 437 insertions, 234 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 130fa0630ac..70bf8e7a464 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -92,7 +92,6 @@ config TPL_SPRINTF config SSCANF bool - default n config STRTO bool @@ -348,7 +347,6 @@ menu "Android Verified Boot" config LIBAVB bool "Android Verified Boot 2.0 support" depends on ANDROID_BOOT_IMAGE - default n help This enables support of Android Verified Boot 2.0 which can be used to assure the end user of the integrity of the software running on a @@ -375,7 +373,6 @@ config SHA256 The SHA256 algorithm produces a 256-bit (32-byte) hash value (digest). - config SHA512 bool "Enable SHA512 support" help @@ -401,6 +398,66 @@ config SHA_HW_ACCEL hashing algorithms. This affects the 'hash' command and also the hash_lookup_algo() function. +if SPL + +config SPL_SHA1 + bool "Enable SHA1 support in SPL" + default y if SHA1 + help + This option enables support of hashing using SHA1 algorithm. + The hash is calculated in software. + The SHA1 algorithm produces a 160-bit (20-byte) hash value + (digest). + +config SPL_SHA256 + bool "Enable SHA256 support in SPL" + default y if SHA256 + help + This option enables support of hashing using SHA256 algorithm. + The hash is calculated in software. + The SHA256 algorithm produces a 256-bit (32-byte) hash value + (digest). + +config SPL_SHA512 + bool "Enable SHA512 support in SPL" + default y if SHA512 + help + This option enables support of hashing using SHA512 algorithm. + The hash is calculated in software. + The SHA512 algorithm produces a 512-bit (64-byte) hash value + (digest). + +config SPL_SHA384 + bool "Enable SHA384 support in SPL" + default y if SHA384 + select SPL_SHA512 + help + This option enables support of hashing using SHA384 algorithm. + The hash is calculated in software. This is also selects SHA512, + because these implementations share the bulk of the code.. + The SHA384 algorithm produces a 384-bit (48-byte) hash value + (digest). + +config SPL_SHA_HW_ACCEL + bool "Enable hardware acceleration for SHA hash functions" + default y if SHA_HW_ACCEL + help + This option enables hardware acceleration for the SHA1 and SHA256 + hashing algorithms. This affects the 'hash' command and also the + hash_lookup_algo() function. + +config SPL_SHA_PROG_HW_ACCEL + bool "Enable Progressive hashing support using hardware in SPL" + depends on SHA_PROG_HW_ACCEL + default y + help + This option enables hardware-acceleration for SHA progressive + hashing. + Data can be streamed in a block at a time and the hashing is + performed in hardware. + +endif + if SHA_HW_ACCEL config SHA512_HW_ACCEL @@ -439,6 +496,11 @@ config SPL_MD5 security applications, but it can be useful for providing a quick checksum of a block of data. +config CRC32 + def_bool y + help + Enables CRC32 support in U-Boot. This is normally required. + config CRC32C bool @@ -769,7 +831,6 @@ endmenu config PHANDLE_CHECK_SEQ bool "Enable phandle check while getting sequence number" - default n help When there are multiple device tree nodes with same name, enable this config option to distinguish them using diff --git a/lib/Makefile b/lib/Makefile index 93be86c34a0..5ddbc77ed6d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_FIT) += libfdt/ obj-$(CONFIG_OF_LIVE) += of_live.o obj-$(CONFIG_CMD_DHRYSTONE) += dhry/ obj-$(CONFIG_ARCH_AT91) += at91/ -obj-$(CONFIG_OPTEE) += optee/ +obj-$(CONFIG_OPTEE_LIB) += optee/ obj-$(CONFIG_ASN1_DECODER) += asn1_decoder.o obj-y += crypto/ @@ -80,14 +80,12 @@ obj-$(CONFIG_$(SPL_)LIB_RATIONAL) += rational.o obj-$(CONFIG_LIBAVB) += libavb/ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ -ifneq ($(CONFIG_$(SPL_TPL_)BUILD)$(CONFIG_$(SPL_TPL_)OF_PLATDATA),yy) -obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += fdtdec_common.o -obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += fdtdec.o -endif +obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o obj-$(CONFIG_$(SPL_TPL_)HASH) += crc16.o +obj-$(CONFIG_MMC_SPI_CRC_ON) += crc16.o obj-y += net_utils.o endif obj-$(CONFIG_ADDR_MAP) += addr_map.o @@ -98,9 +96,7 @@ obj-y += display_options.o CFLAGS_display_options.o := $(if $(BUILD_TAG),-DBUILD_TAG='"$(BUILD_TAG)"') obj-$(CONFIG_BCH) += bch.o obj-$(CONFIG_MMC_SPI) += crc7.o -#ifndef CONFIG_TPL_BUILD -obj-y += crc32.o -#endif +obj-$(CONFIG_$(SPL_TPL_)CRC32) += crc32.o obj-$(CONFIG_CRC32C) += crc32c.o obj-y += ctype.o obj-y += div64.o @@ -136,6 +132,7 @@ obj-$(CONFIG_OID_REGISTRY) += oid_registry.o obj-$(CONFIG_SSCANF) += sscanf.o endif +obj-y += abuf.o obj-y += date.o obj-y += rtc-lib.o obj-$(CONFIG_LIB_ELF) += elf.o diff --git a/lib/abuf.c b/lib/abuf.c new file mode 100644 index 00000000000..4b17e0b8c0d --- /dev/null +++ b/lib/abuf.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Handles a buffer that can be allocated and freed + * + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <abuf.h> +#include <malloc.h> +#include <mapmem.h> +#include <string.h> + +void abuf_set(struct abuf *abuf, void *data, size_t size) +{ + abuf_uninit(abuf); + abuf->data = data; + abuf->size = size; +} + +void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size) +{ + abuf_set(abuf, map_sysmem(addr, size), size); +} + +bool abuf_realloc(struct abuf *abuf, size_t new_size) +{ + void *ptr; + + if (!new_size) { + /* easy case, just need to uninit, freeing any allocation */ + abuf_uninit(abuf); + return true; + } else if (abuf->alloced) { + /* currently allocated, so need to reallocate */ + ptr = realloc(abuf->data, new_size); + if (!ptr) + return false; + abuf->data = ptr; + abuf->size = new_size; + return true; + } else if (new_size <= abuf->size) { + /* + * not currently alloced and new size is no larger. Just update + * it. Data is lost off the end if new_size < abuf->size + */ + abuf->size = new_size; + return true; + } else { + /* not currently allocated and new size is larger. Alloc and + * copy in data. The new space is not inited. + */ + ptr = memdup(abuf->data, new_size); + if (!ptr) + return false; + abuf->data = ptr; + abuf->size = new_size; + abuf->alloced = true; + return true; + } +} + +void *abuf_uninit_move(struct abuf *abuf, size_t *sizep) +{ + void *ptr; + + if (sizep) + *sizep = abuf->size; + if (!abuf->size) + return NULL; + if (abuf->alloced) { + ptr = abuf->data; + } else { + ptr = memdup(abuf->data, abuf->size); + if (!ptr) + return NULL; + } + /* Clear everything out so there is no record of the data */ + abuf_init(abuf); + + return ptr; +} + +void abuf_init_set(struct abuf *abuf, void *data, size_t size) +{ + abuf_init(abuf); + abuf_set(abuf, data, size); +} + +void abuf_init_move(struct abuf *abuf, void *data, size_t size) +{ + abuf_init_set(abuf, data, size); + abuf->alloced = true; +} + +void abuf_uninit(struct abuf *abuf) +{ + if (abuf->alloced) + free(abuf->data); + abuf_init(abuf); +} + +void abuf_init(struct abuf *abuf) +{ + abuf->data = NULL; + abuf->size = 0; + abuf->alloced = false; +} diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 2f077417841..d1685404c21 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -11,11 +11,28 @@ #include <log.h> #include <mapmem.h> #include <tables_csum.h> +#include <timestamp.h> #include <version.h> #include <acpi/acpi_table.h> #include <asm/global_data.h> #include <dm/acpi.h> +/* + * OEM_REVISION is 32-bit unsigned number. It should be increased only when + * changing software version. Therefore it should not depend on build time. + * U-Boot calculates it from U-Boot version and represent it in hexadecimal + * notation. As U-Boot version is in form year.month set low 8 bits to 0x01 + * to have valid date. So for U-Boot version 2021.04 OEM_REVISION is set to + * value 0x20210401. + */ +#define OEM_REVISION ((((U_BOOT_VERSION_NUM / 1000) % 10) << 28) | \ + (((U_BOOT_VERSION_NUM / 100) % 10) << 24) | \ + (((U_BOOT_VERSION_NUM / 10) % 10) << 20) | \ + ((U_BOOT_VERSION_NUM % 10) << 16) | \ + (((U_BOOT_VERSION_NUM_PATCH / 10) % 10) << 12) | \ + ((U_BOOT_VERSION_NUM_PATCH % 10) << 8) | \ + 0x01) + int acpi_create_dmar(struct acpi_dmar *dmar, enum dmar_flags flags) { struct acpi_table_header *header = &dmar->header; @@ -100,7 +117,7 @@ void acpi_fill_header(struct acpi_table_header *header, char *signature) memcpy(header->signature, signature, 4); memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, OEM_TABLE_ID, 8); - header->oem_revision = U_BOOT_BUILD_DATE; + header->oem_revision = OEM_REVISION; memcpy(header->aslc_id, ASLC_ID, 4); } diff --git a/lib/crc32.c b/lib/crc32.c index f2acc107fe4..5a3127e03ad 100644 --- a/lib/crc32.c +++ b/lib/crc32.c @@ -84,7 +84,7 @@ static void __efi_runtime make_crc_table(void) } crc_table_empty = 0; } -#else +#elif !defined(CONFIG_ARM64_CRC32) /* ======================================================================== * Table of CRC-32's of all single-byte values (made by make_crc_table) */ @@ -184,6 +184,12 @@ const uint32_t * ZEXPORT get_crc_table() */ uint32_t __efi_runtime crc32_no_comp(uint32_t crc, const Bytef *buf, uInt len) { +#ifdef CONFIG_ARM64_CRC32 + crc = cpu_to_le32(crc); + while (len--) + crc = __builtin_aarch64_crc32b(crc, *buf++); + return le32_to_cpu(crc); +#else const uint32_t *tab = crc_table; const uint32_t *b =(const uint32_t *)buf; size_t rem_len; @@ -221,6 +227,7 @@ uint32_t __efi_runtime crc32_no_comp(uint32_t crc, const Bytef *buf, uInt len) } return le32_to_cpu(crc); +#endif } #undef DO_CRC diff --git a/lib/display_options.c b/lib/display_options.c index 4da1f5244f3..360b01bcf5f 100644 --- a/lib/display_options.c +++ b/lib/display_options.c @@ -8,7 +8,7 @@ #include <compiler.h> #include <console.h> #include <div64.h> -#include <version.h> +#include <version_string.h> #include <linux/ctype.h> #include <asm/io.h> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index f48d9e8b513..83d584a60e5 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -39,7 +39,6 @@ config CMD_BOOTEFI_BOOTMGR config EFI_SETUP_EARLY bool - default n choice prompt "Store for non-volatile UEFI variables" @@ -113,7 +112,6 @@ config EFI_SET_TIME bool "SetTime() runtime service" depends on EFI_GET_TIME default y if ARCH_QEMU || SANDBOX - default n help Provide the SetTime() runtime service at boottime. This service can be used by an EFI application to adjust the real time clock. @@ -123,7 +121,6 @@ config EFI_HAVE_CAPSULE_SUPPORT config EFI_RUNTIME_UPDATE_CAPSULE bool "UpdateCapsule() runtime service" - default n select EFI_HAVE_CAPSULE_SUPPORT help Select this option if you want to use UpdateCapsule and @@ -132,7 +129,6 @@ config EFI_RUNTIME_UPDATE_CAPSULE config EFI_CAPSULE_ON_DISK bool "Enable capsule-on-disk support" select EFI_HAVE_CAPSULE_SUPPORT - default n help Select this option if you want to use capsule-on-disk feature, that is, capsules can be fetched and executed from files @@ -142,7 +138,6 @@ config EFI_CAPSULE_ON_DISK config EFI_IGNORE_OSINDICATIONS bool "Ignore OsIndications for CapsuleUpdate on-disk" depends on EFI_CAPSULE_ON_DISK - default n help There are boards where U-Boot does not support SetVariable at runtime. Select this option if you want to use the capsule-on-disk feature @@ -152,7 +147,6 @@ config EFI_IGNORE_OSINDICATIONS config EFI_CAPSULE_ON_DISK_EARLY bool "Initiate capsule-on-disk at U-Boot boottime" depends on EFI_CAPSULE_ON_DISK - default n select EFI_SETUP_EARLY help Normally, without this option enabled, capsules will be @@ -163,7 +157,6 @@ config EFI_CAPSULE_ON_DISK_EARLY config EFI_CAPSULE_FIRMWARE bool - default n config EFI_CAPSULE_FIRMWARE_MANAGEMENT bool "Capsule: Firmware Management Protocol" @@ -210,7 +203,6 @@ config EFI_CAPSULE_AUTHENTICATE select PKCS7_VERIFY select IMAGE_SIGN_INFO select EFI_SIGNATURE_SUPPORT - default n help Select this option if you want to enable capsule authentication @@ -271,7 +263,6 @@ endif config EFI_LOADER_BOUNCE_BUFFER bool "EFI Applications use bounce buffers for DMA operations" depends on ARM64 - default n help Some hardware does not support DMA to full 64bit addresses. For this hardware we can create a bounce buffer so that payloads don't have to @@ -345,7 +336,7 @@ config EFI_LOAD_FILE2_INITRD config EFI_SECURE_BOOT bool "Enable EFI secure boot support" - depends on EFI_LOADER + depends on EFI_LOADER && FIT_SIGNATURE select HASH select SHA256 select RSA @@ -357,7 +348,6 @@ config EFI_SECURE_BOOT select PKCS7_MESSAGE_PARSER select PKCS7_VERIFY select EFI_SIGNATURE_SUPPORT - default n help Select this option to enable EFI secure boot support. Once SecureBoot mode is enforced, any EFI binary can run only if diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index 1206b2d7a2c..7683a34a965 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -64,6 +64,27 @@ out: return EFI_EXIT(ret); } +static __always_inline struct efi_gop_pixel efi_vid30_to_blt_col(u32 vid) +{ + struct efi_gop_pixel blt = { + .reserved = 0, + }; + + blt.blue = (vid & 0x3ff) >> 2; + vid >>= 10; + blt.green = (vid & 0x3ff) >> 2; + vid >>= 10; + blt.red = (vid & 0x3ff) >> 2; + return blt; +} + +static __always_inline u32 efi_blt_col_to_vid30(struct efi_gop_pixel *blt) +{ + return (u32)(blt->red << 2) << 20 | + (u32)(blt->green << 2) << 10 | + (u32)(blt->blue << 2); +} + static __always_inline struct efi_gop_pixel efi_vid16_to_blt_col(u16 vid) { struct efi_gop_pixel blt = { @@ -191,6 +212,9 @@ static __always_inline efi_status_t gop_blt_int(struct efi_gop *this, if (vid_bpp == 32) pix = *(struct efi_gop_pixel *)&fb32[ slineoff + j + sx]; + else if (vid_bpp == 30) + pix = efi_vid30_to_blt_col(fb32[ + slineoff + j + sx]); else pix = efi_vid16_to_blt_col(fb16[ slineoff + j + sx]); @@ -207,6 +231,9 @@ static __always_inline efi_status_t gop_blt_int(struct efi_gop *this, case EFI_BLT_VIDEO_TO_VIDEO: if (vid_bpp == 32) fb32[dlineoff + j + dx] = *(u32 *)&pix; + else if (vid_bpp == 30) + fb32[dlineoff + j + dx] = + efi_blt_col_to_vid30(&pix); else fb16[dlineoff + j + dx] = efi_blt_col_to_vid16(&pix); @@ -231,7 +258,10 @@ static efi_uintn_t gop_get_bpp(struct efi_gop *this) #else case LCD_COLOR32: #endif - vid_bpp = 32; + if (gopobj->info.pixel_format == EFI_GOT_BGRA8) + vid_bpp = 32; + else + vid_bpp = 30; break; #ifdef CONFIG_DM_VIDEO case VIDEO_BPP16: @@ -277,6 +307,17 @@ static efi_status_t gop_blt_buf_to_vid16(struct efi_gop *this, dy, width, height, delta, 16); } +static efi_status_t gop_blt_buf_to_vid30(struct efi_gop *this, + struct efi_gop_pixel *buffer, + u32 foo, efi_uintn_t sx, + efi_uintn_t sy, efi_uintn_t dx, + efi_uintn_t dy, efi_uintn_t width, + efi_uintn_t height, efi_uintn_t delta) +{ + return gop_blt_int(this, buffer, EFI_BLT_BUFFER_TO_VIDEO, sx, sy, dx, + dy, width, height, delta, 30); +} + static efi_status_t gop_blt_buf_to_vid32(struct efi_gop *this, struct efi_gop_pixel *buffer, u32 foo, efi_uintn_t sx, @@ -394,6 +435,10 @@ efi_status_t EFIAPI gop_blt(struct efi_gop *this, struct efi_gop_pixel *buffer, ret = gop_blt_buf_to_vid32(this, buffer, operation, sx, sy, dx, dy, width, height, delta); + else if (vid_bpp == 30) + ret = gop_blt_buf_to_vid30(this, buffer, operation, sx, + sy, dx, dy, width, height, + delta); else ret = gop_blt_buf_to_vid16(this, buffer, operation, sx, sy, dx, dy, width, height, @@ -432,7 +477,7 @@ efi_status_t EFIAPI gop_blt(struct efi_gop *this, struct efi_gop_pixel *buffer, efi_status_t efi_gop_register(void) { struct efi_gop_obj *gopobj; - u32 bpix, col, row; + u32 bpix, format, col, row; u64 fb_base, fb_size; void *fb; efi_status_t ret; @@ -449,6 +494,7 @@ efi_status_t efi_gop_register(void) priv = dev_get_uclass_priv(vdev); bpix = priv->bpix; + format = priv->format; col = video_get_xsize(vdev); row = video_get_ysize(vdev); fb_base = (uintptr_t)priv->fb; @@ -458,6 +504,7 @@ efi_status_t efi_gop_register(void) int line_len; bpix = panel_info.vl_bpix; + format = VIDEO_UNKNOWN; col = panel_info.vl_col; row = panel_info.vl_row; fb_base = gd->fb_base; @@ -517,7 +564,15 @@ efi_status_t efi_gop_register(void) if (bpix == LCD_COLOR32) #endif { - gopobj->info.pixel_format = EFI_GOT_BGRA8; + if (format == VIDEO_X2R10G10B10) { + gopobj->info.pixel_format = EFI_GOT_BITMASK; + gopobj->info.pixel_bitmask[0] = 0x3ff00000; /* red */ + gopobj->info.pixel_bitmask[1] = 0x000ffc00; /* green */ + gopobj->info.pixel_bitmask[2] = 0x000003ff; /* blue */ + gopobj->info.pixel_bitmask[3] = 0xc0000000; /* reserved */ + } else { + gopobj->info.pixel_format = EFI_GOT_BGRA8; + } } else { gopobj->info.pixel_format = EFI_GOT_BITMASK; gopobj->info.pixel_bitmask[0] = 0xf800; /* red */ diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index d3b8f93f148..74f0bef2396 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -14,7 +14,7 @@ #include <efi_tcg2.h> #include <log.h> #include <malloc.h> -#include <version.h> +#include <version_string.h> #include <tpm-v2.h> #include <u-boot/hash-checksum.h> #include <u-boot/sha1.h> @@ -1343,10 +1343,11 @@ out: */ static efi_status_t efi_append_scrtm_version(struct udevice *dev) { - u8 ver[] = U_BOOT_VERSION_STRING; efi_status_t ret; - ret = tcg2_measure_event(dev, 0, EV_S_CRTM_VERSION, sizeof(ver), ver); + ret = tcg2_measure_event(dev, 0, EV_S_CRTM_VERSION, + strlen(version_string) + 1, + (u8 *)version_string); return ret; } diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 7358cb6dd16..af92e65bde6 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -870,50 +870,6 @@ const u8 *fdtdec_locate_byte_array(const void *blob, int node, return cell; } -int fdtdec_get_config_int(const void *blob, const char *prop_name, - int default_val) -{ - int config_node; - - debug("%s: %s\n", __func__, prop_name); - config_node = fdt_path_offset(blob, "/config"); - if (config_node < 0) - return default_val; - return fdtdec_get_int(blob, config_node, prop_name, default_val); -} - -int fdtdec_get_config_bool(const void *blob, const char *prop_name) -{ - int config_node; - const void *prop; - - debug("%s: %s\n", __func__, prop_name); - config_node = fdt_path_offset(blob, "/config"); - if (config_node < 0) - return 0; - prop = fdt_get_property(blob, config_node, prop_name, NULL); - - return prop != NULL; -} - -char *fdtdec_get_config_string(const void *blob, const char *prop_name) -{ - const char *nodep; - int nodeoffset; - int len; - - debug("%s: %s\n", __func__, prop_name); - nodeoffset = fdt_path_offset(blob, "/config"); - if (nodeoffset < 0) - return NULL; - - nodep = fdt_getprop(blob, nodeoffset, prop_name, &len); - if (!nodep) - return NULL; - - return (char *)nodep; -} - u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells) { u64 number = 0; diff --git a/lib/gunzip.c b/lib/gunzip.c index bee3b9261f3..a8e498d98d8 100644 --- a/lib/gunzip.c +++ b/lib/gunzip.c @@ -84,32 +84,32 @@ int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) #ifdef CONFIG_CMD_UNZIP __weak -void gzwrite_progress_init(u64 expectedsize) +void gzwrite_progress_init(ulong expectedsize) { putc('\n'); } __weak void gzwrite_progress(int iteration, - u64 bytes_written, - u64 total_bytes) + ulong bytes_written, + ulong total_bytes) { if (0 == (iteration & 3)) - printf("%llu/%llu\r", bytes_written, total_bytes); + printf("%lu/%lu\r", bytes_written, total_bytes); } __weak void gzwrite_progress_finish(int returnval, - u64 bytes_written, - u64 total_bytes, + ulong bytes_written, + ulong total_bytes, u32 expected_crc, u32 calculated_crc) { if (0 == returnval) { - printf("\n\t%llu bytes, crc 0x%08x\n", + printf("\n\t%lu bytes, crc 0x%08x\n", total_bytes, calculated_crc); } else { - printf("\n\tuncompressed %llu of %llu\n" + printf("\n\tuncompressed %lu of %lu\n" "\tcrcs == 0x%08x/0x%08x\n", bytes_written, total_bytes, expected_crc, calculated_crc); @@ -119,15 +119,15 @@ void gzwrite_progress_finish(int returnval, int gzwrite(unsigned char *src, int len, struct blk_desc *dev, unsigned long szwritebuf, - u64 startoffs, - u64 szexpected) + ulong startoffs, + ulong szexpected) { int i, flags; z_stream s; int r = 0; unsigned char *writebuf; unsigned crc = 0; - u64 totalfilled = 0; + ulong totalfilled = 0; lbaint_t blksperbuf, outblock; u32 expected_crc; u32 payload_size; @@ -142,7 +142,7 @@ int gzwrite(unsigned char *src, int len, } if (startoffs & (dev->blksz-1)) { - printf("%s: start offset %llu not a multiple of %lu\n", + printf("%s: start offset %lu not a multiple of %lu\n", __func__, startoffs, dev->blksz); return -1; } @@ -182,12 +182,12 @@ int gzwrite(unsigned char *src, int len, if (szexpected == 0) { szexpected = le32_to_cpu(szuncompressed); } else if (szuncompressed != (u32)szexpected) { - printf("size of %llx doesn't match trailer low bits %x\n", + printf("size of %lx doesn't match trailer low bits %x\n", szexpected, szuncompressed); return -1; } if (lldiv(szexpected, dev->blksz) > (dev->lba - outblock)) { - printf("%s: uncompressed size %llu exceeds device size\n", + printf("%s: uncompressed size %lu exceeds device size\n", __func__, szexpected); return -1; } diff --git a/lib/hang.c b/lib/hang.c index 578ac78d453..2735774f9a4 100644 --- a/lib/hang.c +++ b/lib/hang.c @@ -24,7 +24,7 @@ void hang(void) { #if !defined(CONFIG_SPL_BUILD) || \ (CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) && \ - CONFIG_IS_ENABLED(SERIAL_SUPPORT)) + CONFIG_IS_ENABLED(SERIAL)) puts("### ERROR ### Please RESET the board ###\n"); #endif bootstage_error(BOOTSTAGE_ID_NEED_RESET); diff --git a/lib/hash-checksum.c b/lib/hash-checksum.c index d732ecc38fd..8f2a42f9a08 100644 --- a/lib/hash-checksum.c +++ b/lib/hash-checksum.c @@ -17,7 +17,7 @@ #include <image.h> int hash_calculate(const char *name, - const struct image_region region[], + const struct image_region *region, int region_count, uint8_t *checksum) { struct hash_algo *algo; diff --git a/lib/lmb.c b/lib/lmb.c index 7bd1255f7a4..676b3a0bda6 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -12,6 +12,10 @@ #include <log.h> #include <malloc.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + #define LMB_ALLOC_ANYWHERE 0 static void lmb_dump_region(struct lmb_region *rgn, char *name) @@ -113,12 +117,43 @@ void lmb_init(struct lmb *lmb) lmb->reserved.cnt = 0; } +void arch_lmb_reserve_generic(struct lmb *lmb, ulong sp, ulong end, ulong align) +{ + ulong bank_end; + int bank; + + /* + * Reserve memory from aligned address below the bottom of U-Boot stack + * until end of U-Boot area using LMB to prevent U-Boot from overwriting + * that memory. + */ + debug("## Current stack ends at 0x%08lx ", sp); + + /* adjust sp by 4K to be safe */ + sp -= align; + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + if (!gd->bd->bi_dram[bank].size || + sp < gd->bd->bi_dram[bank].start) + continue; + /* Watch out for RAM at end of address space! */ + bank_end = gd->bd->bi_dram[bank].start + + gd->bd->bi_dram[bank].size - 1; + if (sp > bank_end) + continue; + if (bank_end > end) + bank_end = end - 1; + + lmb_reserve(lmb, sp, bank_end - sp + 1); + break; + } +} + static void lmb_reserve_common(struct lmb *lmb, void *fdt_blob) { arch_lmb_reserve(lmb); board_lmb_reserve(lmb); - if (IMAGE_ENABLE_OF_LIBFDT && fdt_blob) + if (CONFIG_IS_ENABLED(OF_LIBFDT) && fdt_blob) boot_fdt_add_mem_rsv_regions(lmb, fdt_blob); } diff --git a/lib/lz4_wrapper.c b/lib/lz4_wrapper.c index cdbcd05bd43..ebcb5c09a22 100644 --- a/lib/lz4_wrapper.c +++ b/lib/lz4_wrapper.c @@ -6,10 +6,10 @@ #include <common.h> #include <compiler.h> #include <image.h> -#include <lz4.h> #include <linux/kernel.h> #include <linux/types.h> #include <asm/unaligned.h> +#include <u-boot/lz4.h> static u16 LZ4_readLE16(const void *src) { diff --git a/lib/md5.c b/lib/md5.c index e2ba622ea4e..9d34465564e 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -55,7 +55,7 @@ byteReverse(unsigned char *buf, unsigned longs) * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ -static void +void MD5Init(struct MD5Context *ctx) { ctx->buf[0] = 0x67452301; @@ -71,7 +71,7 @@ MD5Init(struct MD5Context *ctx) * Update context to reflect the concatenation of another buffer full * of bytes. */ -static void +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) { register __u32 t; @@ -120,7 +120,7 @@ MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ -static void +void MD5Final(unsigned char digest[16], struct MD5Context *ctx) { unsigned int count; diff --git a/lib/optee/Kconfig b/lib/optee/Kconfig index c398f9b9535..517136a4485 100644 --- a/lib/optee/Kconfig +++ b/lib/optee/Kconfig @@ -1,40 +1,20 @@ -config OPTEE - bool "Support OPTEE images" - help - U-Boot can be configured to boot OPTEE images. - Selecting this option will enable shared OPTEE library code and - enable an OPTEE specific bootm command that will perform additional - OPTEE specific checks before booting an OPTEE image created with - mkimage. - -config OPTEE_LOAD_ADDR - hex "OPTEE load address" - default 0x00000000 - depends on OPTEE +config OPTEE_LIB + bool "Support OPTEE library" + default y if OPTEE || OPTEE_IMAGE help - The load address of the bootable OPTEE binary. + Selecting this option will enable the shared OPTEE library code. -config OPTEE_TZDRAM_SIZE - hex "Amount of Trust-Zone RAM for the OPTEE image" - default 0x0000000 - depends on OPTEE - help - The size of pre-allocated Trust Zone DRAM to allocate for the OPTEE - runtime. - -config OPTEE_TZDRAM_BASE - hex "Base address of Trust-Zone RAM for the OPTEE image" - default 0x00000000 - depends on OPTEE +config OPTEE_IMAGE + bool "Support OPTEE images" help - The base address of pre-allocated Trust Zone DRAM for - the OPTEE runtime. + Selecting this option to boot OPTEE images. + This option enable the OPTEE specific checks done before booting + an OPTEE image created with mkimage config BOOTM_OPTEE bool "Support OPTEE bootm command" select BOOTM_LINUX - depends on OPTEE - default n + select OPTEE_IMAGE help Select this command to enable chain-loading of a Linux kernel via an OPTEE firmware. diff --git a/lib/optee/Makefile b/lib/optee/Makefile index b6923118642..9befe606d88 100644 --- a/lib/optee/Makefile +++ b/lib/optee/Makefile @@ -2,4 +2,4 @@ # # (C) Copyright 2017 Linaro -obj-$(CONFIG_OPTEE) += optee.o +obj-y += optee.o diff --git a/lib/optee/optee.c b/lib/optee/optee.c index 672690dc538..766d0d9e3fa 100644 --- a/lib/optee/optee.c +++ b/lib/optee/optee.c @@ -16,14 +16,13 @@ #define optee_hdr_err_msg \ "OPTEE verification error:" \ - "\n\thdr=%p image=0x%08lx magic=0x%08x tzdram 0x%08lx-0x%08lx " \ + "\n\thdr=%p image=0x%08lx magic=0x%08x" \ "\n\theader lo=0x%08x hi=0x%08x size=0x%08lx arch=0x%08x" \ "\n\tuimage params 0x%08lx-0x%08lx\n" -int optee_verify_image(struct optee_header *hdr, unsigned long tzdram_start, - unsigned long tzdram_len, unsigned long image_len) +#if defined(CONFIG_OPTEE_IMAGE) +static int optee_verify_image(struct optee_header *hdr, unsigned long image_len) { - unsigned long tzdram_end = tzdram_start + tzdram_len; uint32_t tee_file_size; tee_file_size = hdr->init_size + hdr->paged_size + @@ -31,11 +30,7 @@ int optee_verify_image(struct optee_header *hdr, unsigned long tzdram_start, if (hdr->magic != OPTEE_MAGIC || hdr->version != OPTEE_VERSION || - hdr->init_load_addr_hi > tzdram_end || - hdr->init_load_addr_lo < tzdram_start || - tee_file_size > tzdram_len || - tee_file_size != image_len || - (hdr->init_load_addr_lo + tee_file_size) > tzdram_end) { + tee_file_size != image_len) { return -EINVAL; } @@ -47,12 +42,9 @@ int optee_verify_bootm_image(unsigned long image_addr, unsigned long image_len) { struct optee_header *hdr = (struct optee_header *)image_addr; - unsigned long tzdram_start = CONFIG_OPTEE_TZDRAM_BASE; - unsigned long tzdram_len = CONFIG_OPTEE_TZDRAM_SIZE; - int ret; - ret = optee_verify_image(hdr, tzdram_start, tzdram_len, image_len); + ret = optee_verify_image(hdr, image_len); if (ret) goto error; @@ -63,13 +55,14 @@ int optee_verify_bootm_image(unsigned long image_addr, return ret; error: - printf(optee_hdr_err_msg, hdr, image_addr, hdr->magic, tzdram_start, - tzdram_start + tzdram_len, hdr->init_load_addr_lo, + printf(optee_hdr_err_msg, hdr, image_addr, hdr->magic, + hdr->init_load_addr_lo, hdr->init_load_addr_hi, image_len, hdr->arch, image_load_addr, image_load_addr + image_len); return ret; } +#endif #if defined(CONFIG_OF_LIBFDT) static int optee_copy_firmware_node(ofnode node, void *fdt_blob) diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig index a90d67e5a87..cf802a6d40a 100644 --- a/lib/rsa/Kconfig +++ b/lib/rsa/Kconfig @@ -20,6 +20,7 @@ config SPL_RSA config SPL_RSA_VERIFY bool + depends on SPL_RSA help Add RSA signature verification support in SPL. diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index 0e0a890fd15..0579e5294ee 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -19,24 +19,6 @@ #include <openssl/evp.h> #include <openssl/engine.h> -#if OPENSSL_VERSION_NUMBER >= 0x10000000L -#define HAVE_ERR_REMOVE_THREAD_STATE -#endif - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ - (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) -static void RSA_get0_key(const RSA *r, - const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) -{ - if (n != NULL) - *n = r->n; - if (e != NULL) - *e = r->e; - if (d != NULL) - *d = r->d; -} -#endif - static int rsa_err(const char *msg) { unsigned long sslErr = ERR_get_error(); @@ -272,7 +254,7 @@ static int rsa_engine_get_priv_key(const char *keydir, const char *name, else if (name) snprintf(key_id, sizeof(key_id), "%s", - name); + name ? name : ""); else if (keyfile) snprintf(key_id, sizeof(key_id), "%s", keyfile); else @@ -314,24 +296,11 @@ static int rsa_init(void) { int ret; -#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ - (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) - ret = SSL_library_init(); -#else ret = OPENSSL_init_ssl(0, NULL); -#endif if (!ret) { fprintf(stderr, "Failure to init SSL library\n"); return -1; } -#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ - (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) - SSL_load_error_strings(); - - OpenSSL_add_all_algorithms(); - OpenSSL_add_all_digests(); - OpenSSL_add_all_ciphers(); -#endif return 0; } @@ -347,8 +316,7 @@ static int rsa_engine_init(const char *engine_id, ENGINE **pe) e = ENGINE_by_id(engine_id); if (!e) { fprintf(stderr, "Engine isn't available\n"); - ret = -1; - goto err_engine_by_id; + return -1; } if (!ENGINE_init(e)) { @@ -381,29 +349,9 @@ err_set_rsa: ENGINE_finish(e); err_engine_init: ENGINE_free(e); -err_engine_by_id: -#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ - (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) - ENGINE_cleanup(); -#endif return ret; } -static void rsa_remove(void) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ - (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) - CRYPTO_cleanup_all_ex_data(); - ERR_free_strings(); -#ifdef HAVE_ERR_REMOVE_THREAD_STATE - ERR_remove_thread_state(NULL); -#else - ERR_remove_state(0); -#endif - EVP_cleanup(); -#endif -} - static void rsa_engine_remove(ENGINE *e) { if (e) { @@ -453,15 +401,14 @@ static int rsa_sign_with_key(EVP_PKEY *pkey, struct padding_algo *padding_algo, goto err_sign; } -#ifdef CONFIG_FIT_RSASSA_PSS - if (padding_algo && !strcmp(padding_algo->name, "pss")) { + if (CONFIG_IS_ENABLED(FIT_RSASSA_PSS) && padding_algo && + !strcmp(padding_algo->name, "pss")) { if (EVP_PKEY_CTX_set_rsa_padding(ckey, RSA_PKCS1_PSS_PADDING) <= 0) { ret = rsa_err("Signer padding setup failed"); goto err_sign; } } -#endif /* CONFIG_FIT_RSASSA_PSS */ for (i = 0; i < region_count; i++) { if (!EVP_DigestSignUpdate(context, region[i].data, @@ -476,12 +423,7 @@ static int rsa_sign_with_key(EVP_PKEY *pkey, struct padding_algo *padding_algo, goto err_sign; } - #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ - (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) - EVP_MD_CTX_cleanup(context); - #else - EVP_MD_CTX_reset(context); - #endif + EVP_MD_CTX_reset(context); EVP_MD_CTX_destroy(context); debug("Got signature: %zu bytes, expected %d\n", size, EVP_PKEY_size(pkey)); @@ -513,7 +455,7 @@ int rsa_sign(struct image_sign_info *info, if (info->engine_id) { ret = rsa_engine_init(info->engine_id, &e); if (ret) - goto err_engine; + return ret; } ret = rsa_get_priv_key(info->keydir, info->keyname, info->keyfile, @@ -528,7 +470,6 @@ int rsa_sign(struct image_sign_info *info, EVP_PKEY_free(pkey); if (info->engine_id) rsa_engine_remove(e); - rsa_remove(); return ret; @@ -537,8 +478,6 @@ err_sign: err_priv: if (info->engine_id) rsa_engine_remove(e); -err_engine: - rsa_remove(); return ret; } @@ -686,12 +625,8 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest) ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey); if (ret) goto err_get_pub_key; -#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ - (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) - rsa = EVP_PKEY_get1_RSA(pkey); -#else + rsa = EVP_PKEY_get0_RSA(pkey); -#endif ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared); if (ret) goto err_get_params; @@ -761,10 +696,6 @@ done: if (ret) ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; err_get_params: -#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ - (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) - RSA_free(rsa); -#endif EVP_PKEY_free(pkey); err_get_pub_key: if (info->engine_id) diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index ad6d33d043a..600c93ab810 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -102,7 +102,7 @@ U_BOOT_PADDING_ALGO(pkcs_15) = { }; #endif -#ifdef CONFIG_FIT_RSASSA_PSS +#if CONFIG_IS_ENABLED(FIT_RSASSA_PSS) static void u32_i2osp(uint32_t val, uint8_t *buf) { buf[0] = (uint8_t)((val >> 24) & 0xff); @@ -313,7 +313,6 @@ U_BOOT_PADDING_ALGO(pss) = { #endif -#if CONFIG_IS_ENABLED(FIT_SIGNATURE) || CONFIG_IS_ENABLED(RSA_VERIFY_WITH_PKEY) /** * rsa_verify_key() - Verify a signature against some data using RSA Key * @@ -385,9 +384,7 @@ static int rsa_verify_key(struct image_sign_info *info, return 0; } -#endif -#if CONFIG_IS_ENABLED(RSA_VERIFY_WITH_PKEY) /** * rsa_verify_with_pkey() - Verify a signature against some data using * only modulus and exponent as RSA key properties. @@ -408,6 +405,9 @@ int rsa_verify_with_pkey(struct image_sign_info *info, struct key_prop *prop; int ret; + if (!CONFIG_IS_ENABLED(RSA_VERIFY_WITH_PKEY)) + return -EACCES; + /* Public key is self-described to fill key_prop */ ret = rsa_gen_key_prop(info->key, info->keylen, &prop); if (ret) { @@ -422,13 +422,6 @@ int rsa_verify_with_pkey(struct image_sign_info *info, return ret; } -#else -int rsa_verify_with_pkey(struct image_sign_info *info, - const void *hash, uint8_t *sig, uint sig_len) -{ - return -EACCES; -} -#endif #if CONFIG_IS_ENABLED(FIT_SIGNATURE) /** diff --git a/lib/string.c b/lib/string.c index ba176fb08f7..78bd65c4136 100644 --- a/lib/string.c +++ b/lib/string.c @@ -659,6 +659,19 @@ void * memscan(void * addr, int c, size_t size) } #endif +char *memdup(const void *src, size_t len) +{ + char *p; + + p = malloc(len); + if (!p) + return NULL; + + memcpy(p, src, len); + + return p; +} + #ifndef __HAVE_ARCH_STRSTR /** * strstr - Find the first substring in a %NUL terminated string diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c index 89aaa854771..f661fc65054 100644 --- a/lib/tiny-printf.c +++ b/lib/tiny-printf.c @@ -48,7 +48,7 @@ static void div_out(struct printf_info *info, unsigned long *num, out_dgt(info, dgt); } -#ifdef CONFIG_SPL_NET_SUPPORT +#ifdef CONFIG_SPL_NET static void string(struct printf_info *info, char *s) { char ch; @@ -178,7 +178,7 @@ static void __maybe_unused pointer(struct printf_info *info, const char *fmt, } break; #endif -#ifdef CONFIG_SPL_NET_SUPPORT +#ifdef CONFIG_SPL_NET case 'm': return mac_address_string(info, ptr, false); case 'M': @@ -270,7 +270,7 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) } break; case 'p': - if (CONFIG_IS_ENABLED(NET_SUPPORT) || _DEBUG) { + if (CONFIG_IS_ENABLED(NET) || _DEBUG) { pointer(info, fmt, va_arg(va, void *)); /* * Skip this because it pulls in _ctype which is diff --git a/lib/zstd/Makefile b/lib/zstd/Makefile index 33c1df48ec8..12170892923 100644 --- a/lib/zstd/Makefile +++ b/lib/zstd/Makefile @@ -1,4 +1,4 @@ obj-y += zstd_decompress.o zstd_decompress-y := huf_decompress.o decompress.o \ - entropy_common.o fse_decompress.o zstd_common.o + entropy_common.o fse_decompress.o zstd_common.o zstd.o diff --git a/lib/zstd/zstd.c b/lib/zstd/zstd.c new file mode 100644 index 00000000000..bf9cd19cfa3 --- /dev/null +++ b/lib/zstd/zstd.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 Google LLC + */ + +#define LOG_CATEGORY LOGC_BOOT + +#include <common.h> +#include <abuf.h> +#include <log.h> +#include <malloc.h> +#include <linux/zstd.h> + +int zstd_decompress(struct abuf *in, struct abuf *out) +{ + ZSTD_DStream *dstream; + ZSTD_inBuffer in_buf; + ZSTD_outBuffer out_buf; + void *workspace; + size_t wsize; + int ret; + + wsize = ZSTD_DStreamWorkspaceBound(abuf_size(in)); + workspace = malloc(wsize); + if (!workspace) { + debug("%s: cannot allocate workspace of size %zu\n", __func__, + wsize); + return -ENOMEM; + } + + dstream = ZSTD_initDStream(abuf_size(in), workspace, wsize); + if (!dstream) { + log_err("%s: ZSTD_initDStream failed\n", __func__); + ret = -EPERM; + goto do_free; + } + + in_buf.src = abuf_data(in); + in_buf.pos = 0; + in_buf.size = abuf_size(in); + + out_buf.dst = abuf_data(out); + out_buf.pos = 0; + out_buf.size = abuf_size(out); + + while (1) { + size_t res; + + res = ZSTD_decompressStream(dstream, &out_buf, &in_buf); + if (ZSTD_isError(res)) { + ret = ZSTD_getErrorCode(res); + log_err("ZSTD_decompressStream error %d\n", ret); + goto do_free; + } + + if (in_buf.pos >= abuf_size(in) || !res) + break; + } + + ret = out_buf.pos; +do_free: + free(workspace); + return ret; +} |