diff mbox series

[V3,1/2] Allow again bootloader scripts

Message ID 1515947062-7830-1-git-send-email-sbabic@denx.de
State Accepted
Headers show
Series [V3,1/2] Allow again bootloader scripts | expand

Commit Message

Stefano Babic Jan. 14, 2018, 4:24 p.m. UTC
commit ff12cd69445c0f49d44ad0b75dea6f6ec1b0e449 forbids to use a bootloader
script in the "images" section of sw-description. This avoids to set bootloader's
variables in the middle of an installation that can brick the device.
However, having a script is often much more comfortable as a list of couple
<name, value> inside sw-description. This allows again to have bootloader scripts,
but they must be inserted in the "bootenv" section of sw-description.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---

Changes since V2:
	- use ARRAY_SIZE() macro

Changes since V1:
	- replaces switch() with arrays

 core/parser.c              |  2 +
 corelib/installer.c        | 93 +++++++++++++++++++++++++++-------------------
 corelib/stream_interface.c | 25 +++++++------
 include/installer.h        |  1 -
 include/swupdate.h         |  1 +
 parser/parser.c            | 43 +++++++++++++++------
 6 files changed, 103 insertions(+), 62 deletions(-)
diff mbox series

Patch

diff --git a/core/parser.c b/core/parser.c
index a1232bd..cdfbea8 100644
--- a/core/parser.c
+++ b/core/parser.c
@@ -147,6 +147,8 @@  int parse(struct swupdate_cfg *sw, const char *descfile)
 					"images / files");
 	ret |= check_handler_list(&sw->partitions, PARTITION_HANDLER,
 					"partitions");
+	ret |= check_handler_list(&sw->bootscripts, BOOTLOADER_HANDLER,
+					"bootloader");
 	if (ret)
 		return -EINVAL;
 
diff --git a/corelib/installer.c b/corelib/installer.c
index fc3011e..f0b7720 100644
--- a/corelib/installer.c
+++ b/corelib/installer.c
@@ -233,6 +233,27 @@  static int prepare_boot_script(struct swupdate_cfg *cfg, const char *script)
 	return ret;
 }
 
+static int run_prepost_scripts(struct imglist *list, script_fn type)
+{
+	int ret;
+	struct img_type *img;
+	struct installer_handler *hnd;
+
+	/* Scripts must be run before installing images */
+	LIST_FOREACH(img, list, next) {
+		if (!img->is_script)
+			continue;
+		hnd = find_handler(img);
+		if (hnd) {
+			ret = hnd->installer(img, &type);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
 static int update_bootloader_env(void)
 {
 	int ret = 0;
@@ -291,13 +312,14 @@  int install_images(struct swupdate_cfg *sw, int fdsw, int fromfile)
 	/* Extract all scripts, preinstall scripts must be run now */
 	const char* tmpdir_scripts = get_tmpdirscripts();
 	ret = extract_scripts(fdsw, &sw->scripts, fromfile);
+	ret |= extract_scripts(fdsw, &sw->bootscripts, fromfile);
 	if (ret) {
 		ERROR("extracting script to %s failed", tmpdir_scripts);
 		return ret;
 	}
 
 	/* Scripts must be run before installing images */
-	ret = run_prepost_scripts(sw, PREINSTALL);
+	ret = run_prepost_scripts(&sw->scripts, PREINSTALL);
 	if (ret) {
 		ERROR("execute preinstall scripts failed");
 		return ret;
@@ -388,7 +410,7 @@  int install_images(struct swupdate_cfg *sw, int fdsw, int fromfile)
 
 	}
 
-	ret = run_prepost_scripts(sw, POSTINSTALL);
+	ret = run_prepost_scripts(&sw->scripts, POSTINSTALL);
 	if (ret) {
 		ERROR("execute postinstall scripts failed");
 		return ret;
@@ -397,31 +419,11 @@  int install_images(struct swupdate_cfg *sw, int fdsw, int fromfile)
 	if (!LIST_EMPTY(&sw->bootloader))
 		ret = update_bootloader_env();
 
-	return ret;
-}
+	ret |= run_prepost_scripts(&sw->bootscripts, POSTINSTALL);
 
-int run_prepost_scripts(struct swupdate_cfg *sw, script_fn type)
-{
-	int ret;
-	struct img_type *img;
-	struct installer_handler *hnd;
-
-	/* Scripts must be run before installing images */
-	LIST_FOREACH(img, &sw->scripts, next) {
-		if (!img->is_script)
-			continue;
-		hnd = find_handler(img);
-		if (hnd) {
-			ret = hnd->installer(img, &type);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
+	return ret;
 }
 
-
 static void remove_sw_file(char __attribute__ ((__unused__)) *fname)
 {
 #ifndef CONFIG_NOCLEANUP
@@ -430,11 +432,32 @@  static void remove_sw_file(char __attribute__ ((__unused__)) *fname)
 #endif
 }
 
+static void cleaup_img_entry(struct img_type *img)
+{
+	char *fn;
+	int i;
+	const char *tmp[] = { get_tmpdirscripts(), get_tmpdir() };
+
+	if (img->fname[0]) {
+		for (i = 0; i < ARRAY_SIZE(tmp); i++) {
+			if (asprintf(&fn, "%s%s", tmp[i], img->fname) == ENOMEM_ASPRINTF) {
+				ERROR("Path too long: %s%s", tmp[i], img->fname);
+			} else {
+				remove_sw_file(fn);
+				free(fn);
+			}
+		}
+	}
+	dict_drop_db(&img->properties);
+}
+
 void cleanup_files(struct swupdate_cfg *software) {
 	char fn[64];
 	struct img_type *img;
 	struct hw_type *hw;
 	const char* TMPDIR = get_tmpdir();
+	int count;
+	struct imglist *list[] = {&software->scripts, &software->bootscripts};
 
 	LIST_FOREACH(img, &software->images, next) {
 		if (img->fname[0]) {
@@ -447,22 +470,14 @@  void cleanup_files(struct swupdate_cfg *software) {
 		LIST_REMOVE(img, next);
 		free(img);
 	}
-	LIST_FOREACH(img, &software->scripts, next) {
-		if (img->fname[0]) {
-			if (snprintf(fn, sizeof(fn), "%s%s", get_tmpdirscripts(),
-				     img->fname) >= (int)sizeof(fn)) {
-				ERROR("Path too long: %s%s", get_tmpdirscripts(), img->fname);
-			}
-			remove_sw_file(fn);
-			if (snprintf(fn, sizeof(fn), "%s%s", get_tmpdir(),
-				     img->fname) >= (int)sizeof(fn)) {
-				ERROR("Path too long: %s%s", TMPDIR, img->fname);
-			}
-			remove_sw_file(fn);
+
+	for (count = 0; count < ARRAY_SIZE(list); count++) {
+		LIST_FOREACH(img, list[count], next) {
+			cleaup_img_entry(img);
+
+			LIST_REMOVE(img, next);
+			free(img);
 		}
-		dict_drop_db(&img->properties);
-		LIST_REMOVE(img, next);
-		free(img);
 	}
 
 	dict_drop_db(&software->bootloader);
diff --git a/corelib/stream_interface.c b/corelib/stream_interface.c
index a200d7e..35baf94 100644
--- a/corelib/stream_interface.c
+++ b/corelib/stream_interface.c
@@ -186,20 +186,23 @@  static int extract_files(int fd, struct swupdate_cfg *software)
 				break;
 			}
 
-			skip = check_if_required(&software->images, &fdh,
-						&software->installed_sw_list,
+			int i;
+
+			struct imglist *list[] = {&software->images,
+						  &software->scripts,
+						  &software->bootscripts};
+
+			for (i = 0; i < ARRAY_SIZE(list); i++) {
+				skip = check_if_required(list[i], &fdh,
+						(list[i] == &software->images) ?
+							&software->installed_sw_list : NULL,
 						get_tmpdir(),
 						&img);
-			if (skip == SKIP_FILE) {
-				/*
-				 *  Check for script, but scripts are not checked
-				 *  for version
-				 */
-				skip = check_if_required(&software->scripts, &fdh,
-							NULL,
-							get_tmpdir(),
-							&img);
+
+				if (skip != SKIP_FILE)
+					break;
 			}
+
 			TRACE("Found file:\n\tfilename %s\n\tsize %u %s",
 				fdh.filename,
 				(unsigned int)fdh.size,
diff --git a/include/installer.h b/include/installer.h
index 658b064..c0fe5e5 100644
--- a/include/installer.h
+++ b/include/installer.h
@@ -31,7 +31,6 @@  int check_if_required(struct imglist *list, struct filehdr *pfdh,
 				struct img_type **pimg);
 int install_images(struct swupdate_cfg *sw, int fdsw, int fromfile);
 int install_single_image(struct img_type *img);
-int run_prepost_scripts(struct swupdate_cfg *sw, script_fn type);
 int postupdate(struct swupdate_cfg *swcfg, const char *info);
 void cleanup_files(struct swupdate_cfg *software);
 
diff --git a/include/swupdate.h b/include/swupdate.h
index b065f7e..2cc824d 100644
--- a/include/swupdate.h
+++ b/include/swupdate.h
@@ -134,6 +134,7 @@  struct swupdate_cfg {
 	struct imglist images;
 	struct imglist partitions;
 	struct imglist scripts;
+	struct imglist bootscripts;
 	struct dictlist bootloader;
 	struct proclist extprocs;
 	void *dgst;	/* Structure for signed images */
diff --git a/parser/parser.c b/parser/parser.c
index 3a1d6a5..f0b3cb4 100644
--- a/parser/parser.c
+++ b/parser/parser.c
@@ -359,6 +359,7 @@  static int parse_bootloader(parsertype p, void *cfg, struct swupdate_cfg *swcfg)
 {
 	void *setting, *elem;
 	int count, i;
+	struct img_type *script;
 	char name[32];
 	char value[255];
 
@@ -380,24 +381,44 @@  static int parse_bootloader(parsertype p, void *cfg, struct swupdate_cfg *swcfg)
 		/*
 		 * Check for mandatory field
 		 */
-		if(!(exist_field_string(p, elem, "name"))) {
-			TRACE("bootloader entry without variable name field, skipping..");
+		if(exist_field_string(p, elem, "name")) {
+			/*
+			 * Call directly get_field_string with size 0
+			 * to let allocate the place for the strings
+			 */
+			GET_FIELD_STRING(p, elem, "name", name);
+			GET_FIELD_STRING(p, elem, "value", value);
+			dict_set_value(&swcfg->bootloader, name, value);
+			TRACE("Bootloader var: %s = %s\n",
+				name,
+				dict_get_value(&swcfg->bootloader, name));
 			continue;
 		}
 
-
 		/*
-		 * Call directly get_field_string with size 0
-		 * to let allocate the place for the strings
+		 * Check if it is a bootloader script
 		 */
-		GET_FIELD_STRING(p, elem, "name", name);
-		GET_FIELD_STRING(p, elem, "value", value);
-		dict_set_value(&swcfg->bootloader, name, value);
+		if(!(exist_field_string(p, elem, "filename"))) {
+			TRACE("bootloader entry is neither a script nor name/value.");
+			continue;
+		}
+		script = (struct img_type *)calloc(1, sizeof(struct img_type));
+		if (!script) {
+			ERROR( "No memory: malloc failed\n");
+			return -ENOMEM;
+		}
+		GET_FIELD_STRING(p, elem, "filename", script->fname);
+		GET_FIELD_STRING(p, elem, "type", script->type);
+		GET_FIELD_STRING(p, elem, "data", script->type_data);
+		get_hash_value(p, elem, script->sha256);
+		get_field(p, elem, "encrypted", &script->is_encrypted);
+		get_field(p, elem, "compressed", &script->compressed);
+		script->is_script = 1;
 
-		TRACE("Bootloader var: %s = %s\n",
-			name,
-			dict_get_value(&swcfg->bootloader, name));
+		LIST_INSERT_HEAD(&swcfg->bootscripts, script, next);
 
+		TRACE("Found U-Boot Script: %s\n",
+			script->fname);
 	}
 
 	return 0;