[OpenBIOS] [PATCH 2/2] add Adler-32 checksum capability

Mark Cave-Ayland mark.cave-ayland at ilande.co.uk
Thu Apr 16 20:21:32 CEST 2015


On 09/04/15 02:35, Cormac O'Brien wrote:

> From: Cormac O'Brien <cormac at 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);
> +		bind_func("adler32", adler32);
>  		feval(bootscript);
>  	}
>  	else

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.




More information about the OpenBIOS mailing list