diff options
Diffstat (limited to 'contrib/syslinux-4.02/core/rllpack.c')
-rw-r--r-- | contrib/syslinux-4.02/core/rllpack.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/core/rllpack.c b/contrib/syslinux-4.02/core/rllpack.c new file mode 100644 index 0000000..bb9f046 --- /dev/null +++ b/contrib/syslinux-4.02/core/rllpack.c @@ -0,0 +1,105 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * rllpack.inc + * + * Very simple RLL compressor/decompressor, used to pack binary structures + * together. + * + * Format of leading byte + * 1-128 = x verbatim bytes follow + * 129-223 = (x-126) times subsequent byte + * 224-255 = (x-224)*256+(next byte) times the following byte + * 0 = end of data + * + * These structures are stored *in reverse order* in high memory. + * High memory pointers point to one byte beyond the end. + */ + +#include <com32.h> +#include <stddef.h> +#include <string.h> + +void rllpack(com32sys_t * regs) +{ + uint8_t *i = (uint8_t *) (regs->esi.l); + uint8_t *o = (uint8_t *) (regs->edi.l); + size_t cnt = regs->ecx.l; + size_t run, vrun, tcnt; + uint8_t *hdr = NULL; + uint8_t c; + + vrun = (size_t)-1; + while (cnt) { + c = *i; + + run = 1; + tcnt = (cnt > 8191) ? 8191 : cnt; + while (run < tcnt && i[run] == c) + run++; + + if (run < 3) { + if (vrun >= 128) { + hdr = --o; + vrun = 0; + } + *--o = c; + *hdr = ++vrun; + i++; + cnt--; + } else { + if (run < 224 - 126) { + *--o = run + 126; + } else { + o -= 2; + *(uint16_t *) o = run + (224 << 8); + } + *--o = c; + vrun = (size_t)-1; + i += run; + cnt -= run; + } + } + *--o = 0; + + regs->esi.l = (size_t)i; + regs->edi.l = (size_t)o; +} + +void rllunpack(com32sys_t * regs) +{ + uint8_t *i = (uint8_t *) regs->esi.l; + uint8_t *o = (uint8_t *) regs->edi.l; + uint8_t c; + size_t n; + + while ((c = *--i)) { + if (c <= 128) { + while (c--) + *o++ = *--i; + } else { + if (c < 224) + n = c - 126; + else + n = ((c - 224) << 8) + *--i; + c = *--i; + while (n--) + *o++ = c; + } + } + + regs->esi.l = (size_t)i; + regs->ecx.l = (size_t)o - regs->edi.l; + regs->edi.l = (size_t)o; +} |