[Skiboot] [PATCH 04/10] core: Add generic XZ decoding function
Samuel Mendoza-Jonas
sam at mendozajonas.com
Tue Jun 13 13:39:09 AEST 2017
On Fri, 2017-06-09 at 16:55 +1000, Matt Brown wrote:
> This adds a simple function to decode any given XZ data area.
> The uncomp_len value is optional. Unfortunately we cannot calculate the
> uncompressed size of the XZ region before decompressing it.
> We can pass in the value if this is known, otherwise we allocate a region
> 10x the original size. Which may be significantly more than necessary.
>
> Signed-off-by: Matt Brown <matthew.brown.dev at gmail.com>
> ---
> core/Makefile.inc | 2 +-
> core/decode-xz.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> include/platform.h | 2 +
> 3 files changed, 115 insertions(+), 1 deletion(-)
> create mode 100644 core/decode-xz.c
>
> diff --git a/core/Makefile.inc b/core/Makefile.inc
> index b09c30c..7f376bd 100644
> --- a/core/Makefile.inc
> +++ b/core/Makefile.inc
> @@ -8,7 +8,7 @@ CORE_OBJS += pci-opal.o fast-reboot.o device.o exceptions.o trace.o affinity.o
> CORE_OBJS += vpd.o hostservices.o platform.o nvram.o nvram-format.o hmi.o
> CORE_OBJS += console-log.o ipmi.o time-utils.o pel.o pool.o errorlog.o
> CORE_OBJS += timer.o i2c.o rtc.o flash.o sensor.o ipmi-opal.o
> -CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o
> +CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o decode-xz.o
>
> ifeq ($(SKIBOOT_GCOV),1)
> CORE_OBJS += gcov-profiling.o
> diff --git a/core/decode-xz.c b/core/decode-xz.c
> new file mode 100644
> index 0000000..4855e9b
> --- /dev/null
> +++ b/core/decode-xz.c
> @@ -0,0 +1,112 @@
> +/* Copyright 2017 IBM Corp.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> + * implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +#include <skiboot.h>
> +#include <platform.h>
> +#include <libxz/xz.h>
> +
> +
> +#define HEADER_MAGIC "\3757zXZ"
> +#define HEADER_MAGIC_SIZE 6
> +/*
> + * decode_resource_xz
> + * Decodes any xz compressed memory region.
> + *
> + * @buf : pointer to memory region pointer
> + * @len : pointer to length of compressed region
> + * @uncomp_len: pointer to uncompressed length (optional)
> + *
> + * Returns 1 - successful or 0 - failed
> + */
> +int decode_resource_xz(void **buf, size_t *len, size_t *uncomp_len)
If decode_resource_xz is used in patch 1 ("Decode payload initrd on FSP
machines"), this patch should come before it.
> +{
> + struct xz_dec *file;
> + struct xz_buf bufs;
> + char *input_header;
> + uint64_t *out_len;
> + enum xz_ret rc;
> +
> + uint8_t *r_buf = (uint8_t *)(*buf);
> + size_t r_len = *len;
> +
> + /* Check if input header matched XZ encoding signature */
> + input_header = malloc(HEADER_MAGIC_SIZE);
> + if (!input_header)
> + return 0;
> +
> + memcpy(input_header, r_buf, HEADER_MAGIC_SIZE);
> + if (strcmp(input_header, HEADER_MAGIC)){
> + prlog(PR_PRINTF, "DECODE: resource header magic does not match\
> + xz format\n");
> + free(input_header);
> + return 0;
> + }
> +
> +
> + /* Set up decoder */
> + file = xz_dec_init(XZ_SINGLE, 0x100000);
> +
> + if (!file) {
> + /* Allocation failed */
> + prlog(PR_PRINTF, "DECODE: xz_dec_init allocation error\n ");
> + free(input_header);
> + return 0;
> + }
> +
> + out_len = (uint64_t *)malloc(sizeof(uint64_t));
I think you only use out_len within the function and don't pass the
pointer anywhere - would it be worth just having this instead? One less
thing to free :)
uint64_t out_len;
..
out_len = uncomp_len ? *uncomp_len : (r_len * 10);
> + if (!uncomp_len)
> + *out_len = (r_len) * 10;
> + else
> + *out_len = *uncomp_len;
> +
> + bufs.in = (const uint8_t *)r_buf;
> + bufs.in_pos = 0;
> + bufs.in_size = r_len;
> + bufs.out = (uint8_t *)local_alloc(0, *out_len, 0x10000);
> + bufs.out_pos = 0;
> + bufs.out_size = *(size_t *)out_len;
I don't think you need these casts (or for eg. r_buf, could declare it as
const to begin with).
> +
> + if (bufs.out == NULL) {
> + /* Buffer allocation failed */
> + prlog(PR_PRINTF, "DECODE: bufs.out allocation error\n ");
> + free(out_len);
> + free(input_header);
> + return 0;
> + }
> +
> + rc = xz_dec_run(file, &bufs);
> +
> + if (rc != XZ_STREAM_END) {
> + prlog(PR_ALERT, "DECODE: XZ decompression failed rc:%d\n", rc);
> + free(bufs.out);
> + free(out_len);
> + free(input_header);
> + return 0;
> + }
> +
> + /* Redefine resource base and size */
> + *buf = (void *)bufs.out;
> + *len = (size_t)*out_len;
> +
> + prlog(PR_PRINTF, "DECODE: decode_resource_xz base: %p, len: %llu \
> + remote: %p\n", bufs.out, *out_len, *buf);
> +
> + xz_dec_end(file);
> + free(out_len);
> + free(input_header);
> +
> + return 1;
> +}
> diff --git a/include/platform.h b/include/platform.h
> index e8848ca..0c41c35 100644
> --- a/include/platform.h
> +++ b/include/platform.h
> @@ -234,4 +234,6 @@ extern void set_bmc_platform(const struct bmc_platform *bmc);
>
> extern struct cpu_job* start_async_load(struct boot_resources *r);
>
> +/* XZ decoding*/
> +extern int decode_resource_xz(void **buf, size_t *len, size_t *uncomp_len);
> #endif /* __PLATFORM_H */
More information about the Skiboot
mailing list