[OpenBIOS] [PATCH] bootinfo_init_program: improve memory allocation efficiency

Cormac O'Brien i.am.cormac.obrien at gmail.com
Sun Apr 19 21:52:58 CEST 2015


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 at 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);
-- 
2.3.5




More information about the OpenBIOS mailing list