diff mbox series

[1/2] flash: Add support for async decompression

Message ID 20190118035213.18902-1-santosh@fossix.org
State Accepted
Headers show
Series [1/2] flash: Add support for async decompression | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success master/apply_patch Successfully applied
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot success Test snowpatch/job/snowpatch-skiboot on branch master

Commit Message

Santosh Sivaraj Jan. 18, 2019, 3:52 a.m. UTC
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>
---
 core/flash.c      | 103 ++++++++++++++++++++++++++++++++++++++++++++++
 include/skiboot.h |  34 +++++++++++++++
 2 files changed, 137 insertions(+)
diff mbox series

Patch

diff --git a/core/flash.c b/core/flash.c
index 08d69edc..4fb7a170 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 {
@@ -981,3 +982,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 8b53c768..7c796c30 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -235,6 +235,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);