Message ID | 1515930315-9438-1-git-send-email-sbabic@denx.de |
---|---|
State | Changes Requested |
Headers | show |
Series | [V2,1/2] Allow again bootloader scripts | expand |
Hi Stefano, Am 14.01.2018 um 12:45 schrieb Stefano Babic: > 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 V1: > - replaces switch() with arrays > > core/parser.c | 2 + > corelib/installer.c | 93 +++++++++++++++++++++++++++------------------- > corelib/stream_interface.c | 24 ++++++------ > include/installer.h | 1 - > include/swupdate.h | 1 + > parser/parser.c | 44 ++++++++++++++++------ > 6 files changed, 103 insertions(+), 62 deletions(-) > [snip] > diff --git a/corelib/installer.c b/corelib/installer.c > index fc3011e..6dd5b43 100644 > --- a/corelib/installer.c > +++ b/corelib/installer.c [snip] > @@ -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 < 2; i++) { Maybe you could use ARRAY_SIZE instead of a fixed number to avoid mistakes in future changes. > + 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 < 2; count++) { ARRAY_SIZE ? > + 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..48308a5 100644 > --- a/corelib/stream_interface.c > +++ b/corelib/stream_interface.c > @@ -186,20 +186,22 @@ static int extract_files(int fd, struct swupdate_cfg *software) > break; > } > > - skip = check_if_required(&software->images, &fdh, > - &software->installed_sw_list, > + int i; > + > + for (i = 0; i < 3; i++) { ARRAY_SIZE ? > + struct imglist *list[] = {&software->images, > + &software->scripts, > + &software->bootscripts}; This could be defined outside the loop. > + > + skip = check_if_required(list[i], &fdh, > + (i == 0) ? &software->installed_sw_list : NULL, Maybe the check could replaced by (list[i] != &software->images) to make the intent clear and avoid future mistakes. > 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, [snip] > diff --git a/parser/parser.c b/parser/parser.c > index 3a1d6a5..ed9b762 100644 > --- a/parser/parser.c > +++ b/parser/parser.c > @@ -380,24 +381,45 @@ 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); > + get_field(p, elem, "encrypted", &script->is_encrypted); You already set this value two lines above. > + 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; Best regards Stefan
Hi Stefan, On 14/01/2018 14:18, Stefan Herbrechtsmeier wrote: > Hi Stefano, > > > Am 14.01.2018 um 12:45 schrieb Stefano Babic: >> 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 V1: >> - replaces switch() with arrays >> >> core/parser.c | 2 + >> corelib/installer.c | 93 >> +++++++++++++++++++++++++++------------------- >> corelib/stream_interface.c | 24 ++++++------ >> include/installer.h | 1 - >> include/swupdate.h | 1 + >> parser/parser.c | 44 ++++++++++++++++------ >> 6 files changed, 103 insertions(+), 62 deletions(-) >> > > [snip] > >> diff --git a/corelib/installer.c b/corelib/installer.c >> index fc3011e..6dd5b43 100644 >> --- a/corelib/installer.c >> +++ b/corelib/installer.c > > [snip] > >> @@ -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 < 2; i++) { > > Maybe you could use ARRAY_SIZE instead of a fixed number to avoid > mistakes in future changes. Sure, I fix it in V3. > >> + 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 < 2; count++) { > > ARRAY_SIZE ? > >> + 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..48308a5 100644 >> --- a/corelib/stream_interface.c >> +++ b/corelib/stream_interface.c >> @@ -186,20 +186,22 @@ static int extract_files(int fd, struct >> swupdate_cfg *software) >> break; >> } >> - skip = check_if_required(&software->images, &fdh, >> - &software->installed_sw_list, >> + int i; >> + >> + for (i = 0; i < 3; i++) { > > ARRAY_SIZE ? > >> + struct imglist *list[] = {&software->images, >> + &software->scripts, >> + &software->bootscripts}; > > This could be defined outside the loop. > Right. >> + >> + skip = check_if_required(list[i], &fdh, >> + (i == 0) ? &software->installed_sw_list : NULL, > > Maybe the check could replaced by (list[i] != &software->images) to make > the intent clear and avoid future mistakes. Agree, fix in V3. > >> 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, > > [snip] > >> diff --git a/parser/parser.c b/parser/parser.c >> index 3a1d6a5..ed9b762 100644 >> --- a/parser/parser.c >> +++ b/parser/parser.c >> @@ -380,24 +381,45 @@ 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); >> + get_field(p, elem, "encrypted", &script->is_encrypted); > > You already set this value two lines above. > >> + 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; > Best regards, Stefano -- ===================================================================== DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de =====================================================================
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..6dd5b43 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 < 2; 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 < 2; 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..48308a5 100644 --- a/corelib/stream_interface.c +++ b/corelib/stream_interface.c @@ -186,20 +186,22 @@ static int extract_files(int fd, struct swupdate_cfg *software) break; } - skip = check_if_required(&software->images, &fdh, - &software->installed_sw_list, + int i; + + for (i = 0; i < 3; i++) { + struct imglist *list[] = {&software->images, + &software->scripts, + &software->bootscripts}; + + skip = check_if_required(list[i], &fdh, + (i == 0) ? &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..ed9b762 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,45 @@ 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); + get_field(p, elem, "encrypted", &script->is_encrypted); + 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;
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 V1: - replaces switch() with arrays core/parser.c | 2 + corelib/installer.c | 93 +++++++++++++++++++++++++++------------------- corelib/stream_interface.c | 24 ++++++------ include/installer.h | 1 - include/swupdate.h | 1 + parser/parser.c | 44 ++++++++++++++++------ 6 files changed, 103 insertions(+), 62 deletions(-)