These patches provide a small increase in OpenBIOS OS 9 support by fixing an out-of-memory error and adding a necessary Adler-32 checksum function, respectively.
From: Cormac O'Brien cormac@c-obrien.org
This patch fixes an issue with boot script buffer allocation that causes trouble with Mac OS 9. The file containing the boot script also has a fair amount of machine code, so this patch causes the loader to only allocate enough for the boot script.
--- libopenbios/bootinfo_load.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/libopenbios/bootinfo_load.c b/libopenbios/bootinfo_load.c index fa9e36b..fcb23ea 100644 --- a/libopenbios/bootinfo_load.c +++ b/libopenbios/bootinfo_load.c @@ -134,12 +134,12 @@ bootinfo_init_program(void) char *base; int proplen; phandle_t chosen; - int tag, taglen, script, scriptlen, scriptvalid, entity, chrp; + int tag, taglen, script, scriptend, scriptlen, 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 */ @@ -161,15 +161,8 @@ bootinfo_init_program(void) 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; }
@@ -197,7 +190,13 @@ bootinfo_init_program(void) } else if (chrp == 1) { if (strncasecmp(tagbuf, "boot-script", 11) == 0) { script = 1; + + scriptend = current; + while (base[++scriptend + 1] != '<'); + scriptlen = scriptend - current; + bootscript = malloc(scriptlen); scriptlen = 0; + } else if (strncasecmp(tagbuf, "/boot-script", 12) == 0) {
script = 0;
On 09/04/15 02:35, Cormac O'Brien wrote:
From: Cormac O'Brien cormac@c-obrien.org
This patch fixes an issue with boot script buffer allocation that causes trouble with Mac OS 9. The file containing the boot script also has a fair amount of machine code, so this patch causes the loader to only allocate enough for the boot script.
libopenbios/bootinfo_load.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/libopenbios/bootinfo_load.c b/libopenbios/bootinfo_load.c index fa9e36b..fcb23ea 100644 --- a/libopenbios/bootinfo_load.c +++ b/libopenbios/bootinfo_load.c @@ -134,12 +134,12 @@ bootinfo_init_program(void) char *base; int proplen; phandle_t chosen;
- int tag, taglen, script, scriptlen, scriptvalid, entity, chrp;
- int tag, taglen, script, scriptend, scriptlen, 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 */
@@ -161,15 +161,8 @@ bootinfo_init_program(void) 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");
return; }free(bootscript);
@@ -197,7 +190,13 @@ bootinfo_init_program(void) } else if (chrp == 1) { if (strncasecmp(tagbuf, "boot-script", 11) == 0) { script = 1;
scriptend = current;
while (base[++scriptend + 1] != '<');
scriptlen = scriptend - current;
bootscript = malloc(scriptlen); scriptlen = 0;
} else if (strncasecmp(tagbuf, "/boot-script", 12) == 0) { script = 0;
While this is a great hack to fix up the memory allocation, I'm not convinced of its robustness, e.g. what happens if you have an entity in the XML?
I'd be more inclined to do an additional loop beforehand which terminates either if it reaches size or the EOT character, and then use that to work out the correct memory size to allocate before the main while() loop.
ATB,
Mark.
From: Cormac O'Brien cormac@c-obrien.org
This patch adds Adler-32 checksum functionality to the Forth interpreter as required by the Mac OS 9 boot script. This code might belong somewhere else, do let me know.
--- libopenbios/bootinfo_load.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
diff --git a/libopenbios/bootinfo_load.c b/libopenbios/bootinfo_load.c index fcb23ea..d0ccd89 100644 --- a/libopenbios/bootinfo_load.c +++ b/libopenbios/bootinfo_load.c @@ -30,6 +30,54 @@ do { } while (0) #endif
+/* adler32 -- Adapted from Mark Adler's zlib implementation */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +void +adler32( void ) { + unsigned int len = POP(); + char *buf = POP(); + unsigned long adler = POP(); + + if (buf == NULL) { + RET(-1); + } + + long base = 65521L; + int nmax = 5552; + + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + while (len > 0) { + k = (len < nmax ? len : nmax); + len -= k; + + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + + if (k != 0) { + do { + s1 += *buf++; + s2 += s1; + } while (--k); + } + + s1 %= base; + s2 %= base; + } + RET(s2 << 16 | s1); +} + static char * get_device( const char *path ) { @@ -255,6 +303,7 @@ bootinfo_init_program(void) /* If the payload is bootinfo then we execute it immediately */ if (scriptvalid) { DPRINTF("bootscript: %s\n", bootscript); + bind_func("adler32", adler32); feval(bootscript); } else
On 09/04/15 02:35, Cormac O'Brien wrote:
From: Cormac O'Brien cormac@c-obrien.org
This patch adds Adler-32 checksum functionality to the Forth interpreter as required by the Mac OS 9 boot script. This code might belong somewhere else, do let me know.
libopenbios/bootinfo_load.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
diff --git a/libopenbios/bootinfo_load.c b/libopenbios/bootinfo_load.c index fcb23ea..d0ccd89 100644 --- a/libopenbios/bootinfo_load.c +++ b/libopenbios/bootinfo_load.c @@ -30,6 +30,54 @@ do { } while (0) #endif
+/* adler32 -- Adapted from Mark Adler's zlib implementation */
Can we add a stack diagram?
+#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8);
+void +adler32( void ) {
- unsigned int len = POP();
- char *buf = POP();
- unsigned long adler = POP();
- if (buf == NULL) {
RET(-1);
- }
- long base = 65521L;
- int nmax = 5552;
- unsigned long s1 = adler & 0xffff;
- unsigned long s2 = (adler >> 16) & 0xffff;
- int k;
- while (len > 0) {
k = (len < nmax ? len : nmax);
len -= k;
while (k >= 16) {
DO16(buf);
buf += 16;
k -= 16;
}
if (k != 0) {
do {
s1 += *buf++;
s2 += s1;
} while (--k);
}
s1 %= base;
s2 %= base;
- }
- RET(s2 << 16 | s1);
+}
static char * get_device( const char *path ) { @@ -255,6 +303,7 @@ bootinfo_init_program(void) /* If the payload is bootinfo then we execute it immediately */ if (scriptvalid) { DPRINTF("bootscript: %s\n", bootscript);
feval(bootscript); } elsebind_func("adler32", adler32);
A couple of minor points here: firstly, can we switch to using the standard uint32_t/uint64_t instead of long? The reason for this is that if we decided to later move the function to the core then the sizes of int/long will change between 32-bit and 64-bit which may cause some unpredictable results.
Secondly the function should be moved somewhere outside of bootinfo_load.c - I'd go for arch/ppc/qemu/init.c, similar to ffilll() which was another Mac-only OpenFirmware word.
ATB,
Mark.
On Apr 8, 2015, at 9:35 PM, Cormac O'Brien wrote:
These patches provide a small increase in OpenBIOS OS 9 support by fixing an out-of-memory error and adding a necessary Adler-32 checksum function, respectively.
Cool, someone else is helping to add Mac OS 9 support to QEMU. Thank you so much.
What operating system do you use to build OpenBIOS?