From 15aa91bbd13ca17b6f992e40f9baec05c12a75c6 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Fri, 25 May 2018 12:09:20 +0100 Subject: [PATCH] dfu: Add dfu_element_get_contents_chunk() --- plugins/dfu/dfu-element.c | 59 +++++++++++++++++++++++++++++++++++++++ plugins/dfu/dfu-element.h | 4 +++ 2 files changed, 63 insertions(+) diff --git a/plugins/dfu/dfu-element.c b/plugins/dfu/dfu-element.c index 29aedaf74..ae595f13c 100644 --- a/plugins/dfu/dfu-element.c +++ b/plugins/dfu/dfu-element.c @@ -39,6 +39,8 @@ #include "dfu-common.h" #include "dfu-element.h" +#include "fwupd-error.h" + static void dfu_element_finalize (GObject *object); typedef struct { @@ -252,3 +254,60 @@ dfu_element_set_target_size (DfuElement *element, guint32 target_size) g_bytes_unref (priv->contents); priv->contents = g_bytes_new_take (buf, target_size); } + +/** + * dfu_element_get_contents_chunk: + * @element: a #DfuElement + * @address: an address greater than dfu_element_get_address() + * @chunk_sz_max: the size of the new chunk + * @error: a #GError, or %NULL + * + * Gets a block of data from the @element. If the contents of the element is + * smaller than the requested chunk size then the #GBytes will be smaller + * than @chunk_sz_max. Use dfu_utils_bytes_pad() if padding is required. + * + * If the @address is larger than the size of the @element then an error is returned. + * + * Return value: (transfer full): a #GBytes, or %NULL + **/ +GBytes * +dfu_element_get_contents_chunk (DfuElement *element, + guint32 address, + guint32 chunk_sz_max, + GError **error) +{ + GBytes *blob; + gsize chunk_left; + guint32 offset; + + /* check address requested is larger than base address */ + if (address < dfu_element_get_address (element)) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "requested address 0x%x less than base address 0x%x", + (guint) address, (guint) dfu_element_get_address (element)); + return NULL; + } + + /* offset into data */ + offset = address - dfu_element_get_address (element); + blob = dfu_element_get_contents (element); + if (offset > g_bytes_get_size (blob)) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_NOT_FOUND, + "offset 0x%x larger than data size 0x%x", + (guint) offset, + (guint) g_bytes_get_size (blob)); + return NULL; + } + + /* if we have less data than requested */ + chunk_left = g_bytes_get_size (blob) - offset; + if (chunk_sz_max > chunk_left) + return g_bytes_new_from_bytes (blob, offset, chunk_left); + + /* check chunk */ + return g_bytes_new_from_bytes (blob, offset, chunk_sz_max); +} diff --git a/plugins/dfu/dfu-element.h b/plugins/dfu/dfu-element.h index c04d544f2..46e047d5d 100644 --- a/plugins/dfu/dfu-element.h +++ b/plugins/dfu/dfu-element.h @@ -39,6 +39,10 @@ DfuElement *dfu_element_new (void); GBytes *dfu_element_get_contents (DfuElement *element); guint32 dfu_element_get_address (DfuElement *element); +GBytes *dfu_element_get_contents_chunk (DfuElement *element, + guint32 address, + guint32 chunk_sz_max, + GError **error); void dfu_element_set_contents (DfuElement *element, GBytes *contents);