@@ -7,12 +7,15 @@
#include <sys/types.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <errno.h>
#include "generated/autoconf.h"
#include "swupdate.h"
+#include "swupdate_dict.h"
#include "handler.h"
#include "util.h"
#include "bootloader.h"
@@ -25,7 +28,8 @@ static int install_boot_environment(struct img_type *img,
{
int ret;
int fdout;
-
+ FILE *fp;
+ char *buf;
char filename[64];
struct stat statbuf;
@@ -35,6 +39,11 @@ static int install_boot_environment(struct img_type *img,
img->fname);
return -1;
}
+
+ if (!img->bootloader) {
+ ERROR("Internal fault, please report !");
+ return -EFAULT;
+ }
ret = stat(filename, &statbuf);
if (ret) {
fdout = openfileoutput(filename);
@@ -42,14 +51,40 @@ static int install_boot_environment(struct img_type *img,
close(fdout);
}
- ret = bootloader_apply_list(filename);
- if (ret != 0) {
- ERROR("Error setting bootloader environment");
- } else {
- TRACE("Bootloader environment from %s updated", img->fname);
+ /*
+ * Do not set now the bootloader environment
+ * because this can cause a corrupted environment
+ * if a successive handler fails.
+ * Just put the environment in a the global list
+ * and let that the core will update it at the end
+ * of install
+ */
+ fp = fopen(filename, "r");
+ if (!fp)
+ return -EACCES;
+
+ buf = (char *)malloc(MAX_BOOT_SCRIPT_LINE_LENGTH);
+ if (!buf) {
+ ERROR("Out of memory, exiting !");
+ fclose(fp);
+ return -ENOMEM;
+ }
+
+ while (fgets(buf, MAX_BOOT_SCRIPT_LINE_LENGTH, fp)) {
+ char **pair = NULL;
+ unsigned int cnt;
+
+ pair = string_split(buf, '=');
+ cnt = count_string_array((const char **)pair);
+
+ if (cnt > 0 && strlen(pair[0]))
+ dict_set_value(img->bootloader, pair[0], pair[1]);
+ free(pair);
}
+ fclose(fp);
+ free(buf);
- return ret;
+ return 0;
}
__attribute__((constructor))
The bootloader handler sets the environment using an image (ASCII file) with the list of variables to be set and their values. This can under some circunstances brick the target because the environment is set in the middle of un update and not at the end, as it happens when the variables are listed in the "bootenv" section of sw-description. The environment is in fact set for the new release and in case of a power cut or if simply the update is cancelled, the device after a reboot will try to start with the new environment. In most cases, the new environment points to the new version of the software that is at least corrupted orabsent. This patch changes the behavior and chekcs the values read from the ASCII file, but not set the environment. It puts the variables in the global list exactly as the parser does, and the environment will be set just at the end of the installation. Signed-off-by: Stefano Babic <sbabic@denx.de> --- handlers/boot_handler.c | 49 +++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 7 deletions(-)