summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSantosh Sivaraj <santosh@fossix.org>2019-01-18 09:22:12 +0530
committerStewart Smith <stewart@linux.ibm.com>2019-02-25 21:59:03 -0600
commit3ac2db0a83e70bb7768c64b3fbf480e326c07d10 (patch)
tree49a3807f0fdd86aa595c8bc35555ab39ea277c16
parent647dc4aff7b6a9cbfe2338ae354246650e476bf1 (diff)
downloadblackbird-skiboot-3ac2db0a83e70bb7768c64b3fbf480e326c07d10.tar.gz
blackbird-skiboot-3ac2db0a83e70bb7768c64b3fbf480e326c07d10.zip
flash: Add support for async decompression
Implement a standard API for decompressing images using the existing method found in the IMC code. This patch also standardizes error codes and does the decompression asynchronously. The IMC decompress() function is refactored to decompress blobs/images as a separate CPU job. 'xz_decompress_start()' starts the decompression in a newly created CPU job; while 'wait_xz_decompress()' waits for the job to complete. The IMC code will be first user for the new APIs; whose implementation is provided as reference in the next patch. Signed-off-by: Santosh Sivaraj <santosh@fossix.org> Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
-rw-r--r--core/flash.c103
-rw-r--r--include/skiboot.h34
2 files changed, 137 insertions, 0 deletions
diff --git a/core/flash.c b/core/flash.c
index 5fae0f3f..90189dd6 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -27,6 +27,7 @@
#include <libflash/ecc.h>
#include <libstb/secureboot.h>
#include <libstb/trustedboot.h>
+#include <libxz/xz.h>
#include <elf.h>
struct flash {
@@ -834,3 +835,105 @@ int flash_start_preload_resource(enum resource_id id, uint32_t subid,
return OPAL_SUCCESS;
}
+
+/*
+ * The `libxz` decompression routines are blocking; the new decompression
+ * routines, wrapper around `libxz` functions, provide support for asynchronous
+ * decompression. There are two routines, which start the decompression, and one
+ * which waits for the decompression to complete.
+ *
+ * The decompressed image will be present in the `dst` parameter of
+ * `xz_decompress` structure.
+ *
+ * When the decompression is successful, the xz_decompress->status will be
+ * `OPAL_SUCCESS` else OPAL_PARAMETER, see definition of xz_decompress structure
+ * for details.
+ */
+static void xz_decompress(void *data)
+{
+ struct xz_decompress *xz = (struct xz_decompress *)data;
+ struct xz_dec *s;
+ struct xz_buf b;
+
+ /* Initialize the xz library first */
+ xz_crc32_init();
+ s = xz_dec_init(XZ_SINGLE, 0);
+ if (s == NULL) {
+ prerror("initialization error for xz\n");
+ xz->status = OPAL_NO_MEM;
+ return;
+ }
+
+ xz->xz_error = XZ_DATA_ERROR;
+ xz->status = OPAL_PARTIAL;
+
+ b.in = xz->src;
+ b.in_pos = 0;
+ b.in_size = xz->src_size;
+ b.out = xz->dst;
+ b.out_pos = 0;
+ b.out_size = xz->dst_size;
+
+ /* Start decompressing */
+ xz->xz_error = xz_dec_run(s, &b);
+ if (xz->xz_error != XZ_STREAM_END) {
+ prerror("failed to decompress subpartition\n");
+ xz->status = OPAL_PARAMETER;
+ } else
+ xz->status = OPAL_SUCCESS;
+
+ xz_dec_end(s);
+}
+
+/*
+ * xz_start_decompress: start the decompression job and return.
+ *
+ * struct xz_decompress *xz, should be populated by the caller with
+ * - the starting address of the compressed binary
+ * - the address where the decompressed image should be placed
+ * - the sizes of the source and the destination
+ *
+ * xz->src: Source address (The compressed binary)
+ * xz->src_size: Source size
+ * xz->dst: Destination address (The memory area where the `src` will be
+ * decompressed)
+ * xz->dst_size: Destination size
+ *
+ * The `status` value will be OPAL_PARTIAL till the job completes (successfully
+ * or not)
+ */
+void xz_start_decompress(struct xz_decompress *xz)
+{
+ struct cpu_job *job;
+
+ if (!xz)
+ return;
+
+ if (!xz->dst || !xz->dst_size || !xz->src || !xz->src_size) {
+ xz->status = OPAL_PARAMETER;
+ return;
+ }
+
+ job = cpu_queue_job(NULL, "xz_decompress", xz_decompress,
+ (void *) xz);
+ if (!job) {
+ xz->status = OPAL_NO_MEM;
+ return;
+ }
+
+ xz->job = job;
+}
+
+/*
+ * This function waits for the decompression job to complete. The `ret`
+ * structure member in `xz_decompress` will have the status code.
+ *
+ * status == OPAL_SUCCESS on success, else the corresponding error code.
+ */
+void wait_xz_decompress(struct xz_decompress *xz)
+{
+ if (!xz)
+ return;
+
+ cpu_wait_job(xz->job, true);
+}
diff --git a/include/skiboot.h b/include/skiboot.h
index 6da62233..e828b158 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -236,6 +236,40 @@ extern void flash_fw_version_preload(void);
extern void flash_dt_add_fw_version(void);
extern const char *flash_map_resource_name(enum resource_id id);
+/*
+ * Decompression routines
+ *
+ * The below structure members are needed for the xz library routines,
+ * src: Source address (The compressed binary)
+ * src_size: Source size
+ * dst: Destination address (The memory area where the `src` will be
+ * decompressed)
+ * dst_size: Destination size
+ */
+struct xz_decompress {
+ void *dst;
+ void *src;
+ size_t dst_size;
+ size_t src_size;
+ /* The status of the decompress process:
+ - OPAL_PARTIAL: if the job is in progress
+ - OPAL_SUCCESS: if the job is successful
+ - OPAL_NO_MEM: memory allocation failure
+ - OPAL_PARAMETER: If any of the above (src, dst..) are invalid or
+ if xz decompress fails. In which case the caller should check the
+ xz_error for failure reason.
+ */
+ int status;
+ int xz_error;
+ /* The decompression job, this will be freed if the caller uses
+ * `wait_xz_decompression` function, in any other case its the
+ * responsibility of caller to free the allocation job. */
+ struct cpu_job *job;
+};
+
+extern void xz_start_decompress(struct xz_decompress *);
+extern void wait_xz_decompress(struct xz_decompress *);
+
/* NVRAM support */
extern void nvram_init(void);
extern void nvram_read_complete(bool success);
OpenPOWER on IntegriCloud