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