This new property allows the user to specify a specific offset from a
raw device and not rely only on the partition.
This is useful for example to update a kernel or a bootloader which is
not part of a partition
It handles the following multiplicative suffixes: K=1024 and M=1024*1024.
This commit has been tested:
* with and without signature
* with and without compression
Signed-off-by: Sid-Ali TEIR <
st...@witekio.us>
core/cpio_utils.c | 30 ++++++++++++++++++++++++++----
corelib/stream_interface.c | 6 +++---
doc/source/sw-description.rst | 14 ++++++++++++++
include/globals.h | 1 +
include/swupdate.h | 1 +
include/util.h | 1 +
parser/parse_external.c | 4 ++++
parser/parser.c | 1 +
8 files changed, 51 insertions(+), 7 deletions(-)
diff --git a/core/cpio_utils.c b/core/cpio_utils.c
index db5753e..025eddb 100644
--- a/core/cpio_utils.c
+++ b/core/cpio_utils.c
@@ -17,8 +17,10 @@
* Foundation, Inc.
*/
+#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
+#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
@@ -109,7 +111,7 @@ static int copy_write(void *out, const void *buf, int len)
return 0;
}
-int copyfile(int fdin, void *out, int nbytes, unsigned long *offs,
+int copyfile(int fdin, void *out, int nbytes, unsigned long *offs, const char *seek_str,
int skip_file, int __attribute__ ((__unused__)) compressed,
uint32_t *checksum, unsigned char *hash, int encrypted, writeimage callback)
{
@@ -130,6 +132,17 @@ int copyfile(int fdin, void *out, int nbytes, unsigned long *offs,
unsigned char *aes_key;
unsigned char *ivt;
int fdout = -1;
+ unsigned long seek = 0;
+ char *endp = NULL;
+
+ if (seek_str != NULL && strnlen(seek_str, MAX_SEEK_STRING_SIZE) != 0) {
+ errno = 0;
+ seek = ustrtoul(seek_str, &endp, 0);
+ if (seek_str == endp || (seek == ULONG_MAX && errno == ERANGE)) {
+ ERROR("offset argument: ustrtoul failed");
+ return -EFAULT;
+ }
+ }
if (!callback) {
callback = copy_write;
@@ -174,6 +187,14 @@ int copyfile(int fdin, void *out, int nbytes, unsigned long *offs,
}
}
+ if (seek) {
+ TRACE("offset has been defined: %lu bytes\n", seek);
+ if (lseek(fdout, seek, SEEK_SET) < 0) {
+ ERROR("offset argument: seek failed\n");
+ return -EFAULT;
+ }
+ }
+
#ifdef CONFIG_GUNZIP
if (compressed) {
ret = decompress_image(fdin, offs, nbytes, fdout, checksum, dgst);
@@ -288,6 +309,7 @@ int copyimage(void *out, struct img_type *img, writeimage callback)
out,
img->size,
(unsigned long *)&img->offset,
+ img->seek_str,
0, /* no skip */
img->compressed,
&img->checksum,
@@ -356,7 +378,7 @@ off_t extract_sw_description(int fd, const char *descfile, off_t start)
close(fdout);
return -1;
}
- if (copyfile(fd, &fdout, fdh.size, &offset, 0, 0, &checksum, NULL, 0, NULL) < 0) {
+ if (copyfile(fd, &fdout, fdh.size, &offset, NULL, 0, 0, &checksum, NULL, 0, NULL) < 0) {
ERROR("%s corrupted or not valid\n", descfile);
close(fdout);
return -1;
@@ -418,7 +440,7 @@ off_t extract_next_file(int fd, int fdout, off_t start, int compressed,
if (lseek(fd, offset, SEEK_SET) < 0)
ERROR("CPIO file corrupted : %s\n", strerror(errno));
- if (copyfile(fd, &fdout, fdh.size, &offset, 0, compressed, &checksum, hash, encrypted, NULL) < 0) {
+ if (copyfile(fd, &fdout, fdh.size, &offset, NULL, 0, compressed, &checksum, hash, encrypted, NULL) < 0) {
ERROR("Error copying extracted file\n");
}
@@ -467,7 +489,7 @@ int cpio_scan(int fd, struct swupdate_cfg *cfg, off_t start)
* use copyfile for checksum verification, as we skip file
* we do not have to provide fdout
*/
- if (copyfile(fd, NULL, fdh.size, &offset, 1, 0, &checksum, NULL, 0, NULL) != 0) {
+ if (copyfile(fd, NULL, fdh.size, &offset, NULL, 1, 0, &checksum, NULL, 0, NULL) != 0) {
ERROR("invalid archive\n");
return -1;
}
diff --git a/corelib/stream_interface.c b/corelib/stream_interface.c
index 429b046..d292d40 100644
--- a/corelib/stream_interface.c
+++ b/corelib/stream_interface.c
@@ -105,7 +105,7 @@ static int extract_file_to_tmp(int fd, const char *fname, unsigned long *poffs)
if (fdout < 0)
return -1;
- if (copyfile(fd, &fdout, fdh.size, poffs, 0, 0, &checksum, NULL, 0, NULL) < 0) {
+ if (copyfile(fd, &fdout, fdh.size, poffs, NULL, 0, 0, &checksum, NULL, 0, NULL) < 0) {
close(fdout);
return -1;
}
@@ -209,7 +209,7 @@ static int extract_files(int fd, struct swupdate_cfg *software)
fdout = openfileoutput(img->extract_file);
if (fdout < 0)
return -1;
- if (copyfile(fd, &fdout, fdh.size, &offset, 0, 0, &checksum, img->sha256, 0, NULL) < 0) {
+ if (copyfile(fd, &fdout, fdh.size, &offset, NULL, 0, 0, &checksum, img->sha256, 0, NULL) < 0) {
close(fdout);
return -1;
}
@@ -223,7 +223,7 @@ static int extract_files(int fd, struct swupdate_cfg *software)
break;
case SKIP_FILE:
- if (copyfile(fd, &fdout, fdh.size, &offset, skip, 0, &checksum, NULL, 0, NULL) < 0) {
+ if (copyfile(fd, &fdout, fdh.size, &offset, NULL, skip, 0, &checksum, NULL, 0, NULL) < 0) {
return -1;
}
if (checksum != (unsigned long)fdh.chksum) {
diff --git a/doc/source/sw-description.rst b/doc/source/sw-description.rst
index 6af71de..a360cf7 100644
--- a/doc/source/sw-description.rst
+++ b/doc/source/sw-description.rst
@@ -173,6 +173,8 @@ The syntax is:
device[optional] = <destination volume>;
mtdname[optional] = <destination mtd name>;
type[optional] = <handler>;
+ /* optionally, the image can be copied at a specific offset in raw mode */
+ offset[optional] = <offset>;
/* optionally, the image can be compressed if it is in raw mode */
compressed;
},
@@ -205,6 +207,18 @@ To update an image in raw mode, the syntax is:
device = "/dev/mmcblk0p1";
}
+To flash am image at a specific offset, the syntax is:
+
+
+::
+
+ {
+ filename = "u-boot.bin";
+ device = "/dev/mmcblk0p1";
+ offset = "16K";
+ }
+
+The offset handles the following multiplicative suffixes: K=1024 and M=1024*1024.
However, writing to flash in raw mode must be managed in a special
way. Flashes must be erased before copying, and writing into NAND
diff --git a/include/globals.h b/include/globals.h
index ddb42de..43b5d61 100644
--- a/include/globals.h
+++ b/include/globals.h
@@ -31,6 +31,7 @@
#define UBOOT_VAR_LENGTH 16
#define MAX_REVISION_LENGTH SWUPDATE_GENERAL_STRING_SIZE
#define MAX_UBOOT_SCRIPT_LINE_LENGTH 1024
+#define MAX_SEEK_STRING_SIZE 32
/* These are fixed path to temporary files */
#define SCRIPTS_DIR TMPDIR "scripts/"
diff --git a/include/swupdate.h b/include/swupdate.h
index bff757e..4d3246b 100644
--- a/include/swupdate.h
+++ b/include/swupdate.h
@@ -69,6 +69,7 @@ struct img_type {
char type_data[SWUPDATE_GENERAL_STRING_SIZE]; /* Data for handler */
char extract_file[MAX_IMAGE_FNAME];
char filesystem[MAX_IMAGE_FNAME];
+ char seek_str[MAX_SEEK_STRING_SIZE];
int required;
int provided;
int compressed;
diff --git a/include/util.h b/include/util.h
index ca3a5cf..6678b15 100644
--- a/include/util.h
+++ b/include/util.h
@@ -154,6 +154,7 @@ void unlock_uboot_env(int lock);
int openfile(const char *filename);
int copyfile(int fdin, void *out, int nbytes, unsigned long *offs,
+ const char *seek_str,
int skip_file, int compressed, uint32_t *checksum,
unsigned char *hash, int encrypted, writeimage callback);
int copyimage(void *out, struct img_type *img, writeimage callback);
diff --git a/parser/parse_external.c b/parser/parse_external.c
index 7c5cce2..0247552 100644
--- a/parser/parse_external.c
+++ b/parser/parse_external.c
@@ -43,6 +43,7 @@
static void sw_append_stream(struct img_type *img, const char *key,
const char *value)
{
+ const char offset[] = "offset";
if (!strcmp(key, "type"))
strncpy(img->type, value,
@@ -75,6 +76,9 @@ static void sw_append_stream(struct img_type *img, const char *key,
if (!strcmp(key, "device"))
strncpy(img->device, value,
sizeof(img->device));
+ if (!strncmp(key, offset, sizeof(offset)))
+ strncpy(img->seek_str, value,
+ sizeof(img->seek_str));
if (!strcmp(key, "script"))
img->is_script = 1;
if (!strcmp(key, "path"))
diff --git a/parser/parser.c b/parser/parser.c
index 33a4960..ec2c0fc 100644
--- a/parser/parser.c
+++ b/parser/parser.c
@@ -389,6 +389,7 @@ static void parse_images(parsertype p, void *cfg, struct swupdate_cfg *swcfg)
GET_FIELD_STRING(p, elem, "device", image->device);
GET_FIELD_STRING(p, elem, "mtdname", image->path);
GET_FIELD_STRING(p, elem, "type", image->type);
+ GET_FIELD_STRING(p, elem, "offset", image->seek_str);
GET_FIELD_STRING(p, elem, "data", image->type_data);
get_hash_value(p, elem, image->sha256);
--
2.11.1