This patch provides a more memory-efficient method of allocating memory for the boot script by using the actual script length (including entity translations) instead of the file size.
Signed-off-by: Cormac O'Brien i.am.cormac.obrien@gmail.com
--- libopenbios/bootinfo_load.c | 102 +++++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 35 deletions(-)
diff --git a/libopenbios/bootinfo_load.c b/libopenbios/bootinfo_load.c index fa9e36b..bd282f4 100644 --- a/libopenbios/bootinfo_load.c +++ b/libopenbios/bootinfo_load.c @@ -20,7 +20,7 @@ #include "libopenbios/ofmem.h" #include "libc/vsprintf.h"
-//#define DEBUG_BOOTINFO +#define DEBUG_BOOTINFO
#ifdef DEBUG_BOOTINFO #define DPRINTF(fmt, args...) \ @@ -134,12 +134,13 @@ bootinfo_init_program(void) char *base; int proplen; phandle_t chosen; - int tag, taglen, script, scriptlen, scriptvalid, entity, chrp; + int tag, taglen, script, scriptind, scriptlen, scriptstart, scriptvalid, + entity, chrp; char tagbuf[128], c; char *device, *filename, *directory, *partition; int current, size; char *bootscript; - char *tmp; + char *tmp; char bootpath[1024];
/* Parse the boot script */ @@ -158,21 +159,14 @@ bootinfo_init_program(void) feval("load-base"); base = (char*)cell2pointer(POP());
- feval("load-size"); - size = POP(); - - bootscript = malloc(size); - if (bootscript == NULL) { - DPRINTF("Can't malloc %d bytes\n", size); - return; - } - if (!is_bootinfo(base)) { DPRINTF("Not a valid bootinfo memory image\n"); - free(bootscript); return; }
+ feval("load-size"); + size = POP(); + chrp = 0; tag = 0; taglen = 0; @@ -198,16 +192,10 @@ bootinfo_init_program(void) if (strncasecmp(tagbuf, "boot-script", 11) == 0) { script = 1; scriptlen = 0; + scriptstart = current; } else if (strncasecmp(tagbuf, "/boot-script", 12) == 0) { - script = 0; - bootscript[scriptlen] = '\0'; - - DPRINTF("got bootscript %s\n", - bootscript); - scriptvalid = -1; - break; } else if (strncasecmp(tagbuf, "/chrp-boot", 10) == 0) break; @@ -217,42 +205,86 @@ bootinfo_init_program(void) } else if (script && c == '&') { entity = 1; taglen = 0; - } else if (entity && c ==';') { + } else if (entity && c == ';') { entity = 0; tagbuf[taglen] = '\0'; if (strncasecmp(tagbuf, "lt", 2) == 0) { - bootscript[scriptlen++] = '<'; + scriptlen++; } else if (strncasecmp(tagbuf, "gt", 2) == 0) { - bootscript[scriptlen++] = '>'; + scriptlen++; } else if (strncasecmp(tagbuf, "device", 6) == 0) { - strcpy(bootscript + scriptlen, device); scriptlen += strlen(device); } else if (strncasecmp(tagbuf, "partition", 9) == 0) { - strcpy(bootscript + scriptlen, partition); scriptlen += strlen(partition); } else if (strncasecmp(tagbuf, "directory", 9) == 0) { - strcpy(bootscript + scriptlen, directory); scriptlen += strlen(directory); } else if (strncasecmp(tagbuf, "filename", 8) == 0) { - strcpy(bootscript + scriptlen, filename); scriptlen += strlen(filename); } else if (strncasecmp(tagbuf, "full-path", 9) == 0) { - strcpy(bootscript + scriptlen, bootpath); scriptlen += strlen(bootpath); - } else { /* unknown, keep it */ - bootscript[scriptlen] = '&'; - strcpy(bootscript + scriptlen + 1, tagbuf); - scriptlen += taglen + 1; - bootscript[scriptlen] = ';'; - scriptlen++; + } else { + scriptlen += taglen + 2; } } else if (entity && taglen < sizeof(tagbuf)) { tagbuf[taglen++] = c; } else if (script && scriptlen < size) { - bootscript[scriptlen++] = c; + scriptlen++; + } + } + + bootscript = malloc(scriptlen * sizeof *bootscript + 1); + if (bootscript == NULL) { + DPRINTF("Can't malloc %d bytes\n", size); + return; + } + + entity = 0; + scriptind = 0; + taglen = 0; + current = scriptstart; + while (current < scriptstart + scriptlen) { + c = base[current++]; + + if (c == '&') { + entity = 1; + taglen = 0; + } else if (entity && c == ';') { + entity = 0; + tagbuf[taglen] = '\0'; + if (strncasecmp(tagbuf, "lt", 2) == 0) { + bootscript[scriptind++] = '<'; + } else if (strncasecmp(tagbuf, "gt", 2) == 0) { + bootscript[scriptind++] = '>'; + } else if (strncasecmp(tagbuf, "device", 6) == 0) { + strcpy(bootscript + scriptind, device); + scriptind += strlen(device); + } else if (strncasecmp(tagbuf, "partition", 9) == 0) { + strcpy(bootscript + scriptind, partition); + scriptind += strlen(partition); + } else if (strncasecmp(tagbuf, "directory", 9) == 0) { + strcpy(bootscript + scriptind, directory); + scriptind += strlen(directory); + } else if (strncasecmp(tagbuf, "filename", 8) == 0) { + strcpy(bootscript + scriptind, filename); + scriptlen += strlen(filename); + } else if (strncasecmp(tagbuf, "full-path", 9) == 0) { + strcpy(bootscript + scriptind, bootpath); + scriptlen += strlen(bootscript); + } else { /* unknown, keep it */ + bootscript[scriptind++] = '&'; + strcpy(bootscript + scriptind, tagbuf); + scriptind += taglen; + bootscript[scriptind++] = ';'; + } + } else if (entity && taglen < sizeof(tagbuf)) { + tagbuf[taglen++] = c; + } else { + bootscript[scriptind++] = c; } }
+ bootscript[scriptlen] = '\0'; + /* If the payload is bootinfo then we execute it immediately */ if (scriptvalid) { DPRINTF("bootscript: %s\n", bootscript);