summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--BUGS4
-rw-r--r--MCONFIG6
-rw-r--r--MCONFIG.build33
-rw-r--r--MCONFIG.embedded21
-rw-r--r--Makefile2
-rw-r--r--TODO22
-rwxr-xr-xcodepage/cptable.pl40
-rw-r--r--com32/MCONFIG29
-rw-r--r--com32/Makefile2
-rw-r--r--com32/include/dev.h1
-rw-r--r--com32/include/dirent.h18
-rw-r--r--com32/include/netinet/in.h48
-rw-r--r--com32/include/string.h1
-rw-r--r--com32/include/sys/cpu.h21
-rw-r--r--com32/include/sys/dirent.h30
-rw-r--r--com32/include/syslinux/pxe.h487
-rw-r--r--com32/include/syslinux/pxe_api.h566
-rw-r--r--com32/lib/MCONFIG17
-rw-r--r--com32/lib/Makefile3
-rw-r--r--com32/lib/closedir.c16
-rw-r--r--com32/lib/com32.ld68
-rw-r--r--com32/lib/opendir.c19
-rw-r--r--com32/lib/readdir.c42
-rw-r--r--com32/lib/strpcpy.c20
-rw-r--r--com32/lib/sys/entry.S58
-rw-r--r--com32/lib/sys/file.h12
-rw-r--r--com32/lib/sys/open.c6
-rw-r--r--com32/lib/sys/openmem.c61
-rw-r--r--com32/mboot/mboot.c2
-rw-r--r--com32/modules/Makefile3
-rw-r--r--com32/modules/dir.c35
-rw-r--r--com32/modules/host.c42
-rw-r--r--com32/rosh/rosh.c18
-rw-r--r--com32/rosh/rosh.h2
-rw-r--r--com32/tools/.gitignore1
-rw-r--r--com32/tools/Makefile30
-rw-r--r--com32/tools/relocs.c693
-rw-r--r--core/Makefile72
-rw-r--r--core/abort.inc6
-rw-r--r--core/adv.inc22
-rw-r--r--core/bcopy32.inc297
-rw-r--r--core/bcopyxx.inc18
-rw-r--r--core/bios.inc8
-rw-r--r--core/bootsect.inc8
-rw-r--r--core/cache.c134
-rw-r--r--core/cache.inc4
-rw-r--r--core/call16.c27
-rw-r--r--core/callback.inc208
-rwxr-xr-xcore/checksumiso.pl51
-rw-r--r--core/cleanup.inc7
-rw-r--r--core/cmdline.inc4
-rw-r--r--core/codepage.S5
-rw-r--r--core/com32.inc414
-rw-r--r--core/comboot.inc108
-rw-r--r--core/common.inc25
-rw-r--r--core/config.inc6
-rw-r--r--core/configinit.inc2
-rw-r--r--core/conio.inc15
-rw-r--r--core/cpuinit.inc52
-rw-r--r--core/dir.c45
-rw-r--r--core/diskfs.inc182
-rw-r--r--core/diskio.c318
-rw-r--r--core/diskstart.inc109
-rw-r--r--core/dnsresolv.inc389
-rw-r--r--core/ext2_fs.inc183
-rw-r--r--core/extern.inc26
-rw-r--r--core/extlinux.asm913
-rw-r--r--core/font.inc6
-rw-r--r--core/fs.c300
-rw-r--r--core/fs/btrfs/btrfs.c655
-rw-r--r--core/fs/btrfs/btrfs.h275
-rw-r--r--core/fs/btrfs/crc32c.h50
-rw-r--r--core/fs/ext2/bmap.c185
-rw-r--r--core/fs/ext2/ext2.c476
-rw-r--r--core/fs/ext2/ext2_fs.h299
-rw-r--r--core/fs/fat/fat.c860
-rw-r--r--core/fs/fat/fat_fs.h156
-rw-r--r--core/fs/iso9660/iso9660.c452
-rw-r--r--core/fs/iso9660/iso9660_fs.h27
-rw-r--r--core/fs/lib/mangle.c47
-rw-r--r--core/fs/pxe/dhcp_option.c270
-rw-r--r--core/fs/pxe/dnsresolv.c341
-rw-r--r--core/fs/pxe/idle.c110
-rw-r--r--core/fs/pxe/pxe.c1661
-rw-r--r--core/fs/pxe/pxe.h224
-rw-r--r--core/getc.inc19
-rw-r--r--core/graphics.inc6
-rw-r--r--core/head.inc6
-rw-r--r--core/hello.c30
-rw-r--r--core/highmem.inc6
-rw-r--r--core/idle.inc38
-rw-r--r--core/include/cache.h25
-rw-r--r--core/include/codepage.h27
-rw-r--r--core/include/core.h61
-rw-r--r--core/include/disk.h36
-rw-r--r--core/include/fs.h172
-rw-r--r--core/init.inc110
-rw-r--r--core/isolinux.asm584
-rw-r--r--core/kaboom.c16
-rw-r--r--core/layout.inc56
-rw-r--r--core/ldlinux.asm1410
-rw-r--r--core/loadhigh.inc10
-rw-r--r--core/localboot.inc6
-rw-r--r--core/lzo/enter.ash89
-rw-r--r--core/lzo/leave.ash114
-rw-r--r--core/lzo/lzo1c_d.ash184
-rw-r--r--core/lzo/lzo1f_d.ash176
-rw-r--r--core/lzo/lzo1x_d.ash401
-rw-r--r--core/lzo/lzo1x_f1.S63
-rw-r--r--core/lzo/lzo_asm.h287
-rw-r--r--core/macros.inc2
-rw-r--r--core/malloc.c224
-rw-r--r--core/parsecmd.inc9
-rw-r--r--core/parseconfig.inc26
-rw-r--r--core/plaincon.inc2
-rw-r--r--core/pm.inc450
-rw-r--r--core/pmcall.inc70
-rw-r--r--core/prefix.inc17
-rw-r--r--core/printf.c20
-rw-r--r--core/pxeidle.inc122
-rw-r--r--core/pxelinux.asm2618
-rw-r--r--core/rllpack.c105
-rw-r--r--core/rllpack.inc164
-rw-r--r--core/runkernel.inc26
-rw-r--r--core/serirq.inc24
-rw-r--r--core/stack.inc12
-rw-r--r--core/strcpy.inc2
-rw-r--r--core/strecpy.inc2
-rw-r--r--core/syslinux.ld280
-rw-r--r--core/timer.inc46
-rw-r--r--core/ui.inc35
-rw-r--r--core/writedec.inc2
-rw-r--r--core/writehex.inc1
-rw-r--r--core/writestr.inc1
-rw-r--r--doc/comboot.txt19
-rw-r--r--dos/Makefile16
-rw-r--r--dos/argv.c4
-rw-r--r--dos/com16.ld130
-rw-r--r--dos/crt0.S29
-rw-r--r--dos/dosexe.ld131
-rw-r--r--dos/header.S46
-rw-r--r--dos/malloc.c32
-rw-r--r--dos/stdlib.h1
-rw-r--r--dos/syslinux.c72
-rw-r--r--extlinux/btrfs.h22
-rw-r--r--extlinux/main.c403
-rwxr-xr-xlibinstaller/bin2c.pl4
-rw-r--r--libinstaller/setadv.c13
-rw-r--r--libinstaller/syslinux.h16
-rw-r--r--libinstaller/syslxint.h115
-rw-r--r--libinstaller/syslxmod.c335
-rw-r--r--linux/syslinux.c26
-rw-r--r--lzo/.gitignore1
-rw-r--r--lzo/LZO.TXT291
-rw-r--r--lzo/Makefile39
-rw-r--r--lzo/include/lzo/lzo1.h96
-rw-r--r--lzo/include/lzo/lzo1a.h96
-rw-r--r--lzo/include/lzo/lzo1b.h160
-rw-r--r--lzo/include/lzo/lzo1c.h160
-rw-r--r--lzo/include/lzo/lzo1f.h108
-rw-r--r--lzo/include/lzo/lzo1x.h177
-rw-r--r--lzo/include/lzo/lzo1y.h145
-rw-r--r--lzo/include/lzo/lzo1z.h150
-rw-r--r--lzo/include/lzo/lzo2a.h92
-rw-r--r--lzo/include/lzo/lzo_asm.h139
-rw-r--r--lzo/include/lzo/lzoconf.h417
-rw-r--r--lzo/include/lzo/lzodefs.h1807
-rw-r--r--lzo/include/lzo/lzoutil.h73
-rw-r--r--lzo/prepcore.c385
-rw-r--r--lzo/src/compr1b.h81
-rw-r--r--lzo/src/compr1c.h81
-rw-r--r--lzo/src/config1x.h118
-rw-r--r--lzo/src/lzo1_d.ch155
-rw-r--r--lzo/src/lzo1x_1.c50
-rw-r--r--lzo/src/lzo1x_1k.c50
-rw-r--r--lzo/src/lzo1x_1l.c50
-rw-r--r--lzo/src/lzo1x_1o.c50
-rw-r--r--lzo/src/lzo1x_9x.c881
-rw-r--r--lzo/src/lzo1x_c.ch351
-rw-r--r--lzo/src/lzo1x_d.ch466
-rw-r--r--lzo/src/lzo1x_d1.c46
-rw-r--r--lzo/src/lzo1x_d2.c46
-rw-r--r--lzo/src/lzo1x_d3.c108
-rw-r--r--lzo/src/lzo1x_o.c45
-rw-r--r--lzo/src/lzo1x_oo.ch366
-rw-r--r--lzo/src/lzo_conf.h323
-rw-r--r--lzo/src/lzo_crc.c167
-rw-r--r--lzo/src/lzo_dict.h316
-rw-r--r--lzo/src/lzo_dll.ch64
-rw-r--r--lzo/src/lzo_init.c176
-rw-r--r--lzo/src/lzo_mchw.ch242
-rw-r--r--lzo/src/lzo_ptr.c92
-rw-r--r--lzo/src/lzo_ptr.h154
-rw-r--r--lzo/src/lzo_str.c71
-rw-r--r--lzo/src/lzo_swd.ch707
-rw-r--r--lzo/src/lzo_util.c165
-rw-r--r--lzo/src/miniacc.h6553
-rw-r--r--lzo/src/stats1a.h137
-rw-r--r--lzo/src/stats1b.h142
-rw-r--r--lzo/src/stats1c.h61
-rw-r--r--mtools/syslinux.c28
-rw-r--r--version2
-rw-r--r--win32/syslinux.c21
204 files changed, 30256 insertions, 8583 deletions
diff --git a/.gitignore b/.gitignore
index 7657c3d0..c7866759 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,7 @@
*.map
*.o
*.orig
+*.raw
*.rej
*.s
*.sec
diff --git a/BUGS b/BUGS
deleted file mode 100644
index 9639da80..00000000
--- a/BUGS
+++ /dev/null
@@ -1,4 +0,0 @@
-Known bugs that have not yet been fixed:
-
-- PXELINUX: Some PXE stacks fail with routing enabled, some with
- routing disabled. Try both?
diff --git a/MCONFIG b/MCONFIG
index e9c16d38..72f7f525 100644
--- a/MCONFIG
+++ b/MCONFIG
@@ -32,15 +32,17 @@ BOOTDIR = /boot
EXTLINUXDIR = $(BOOTDIR)/extlinux
NASM = nasm
-NASMOPT = -O9999
+NASMOPT = -Ox
PERL = perl
+UPX = upx
CHMOD = chmod
CC = gcc
gcc_ok = $(shell tmpf=gcc_ok.$$$$.tmp; \
- if $(CC) $(1) -c $(topdir)/dummy.c -o $$tmpf 2>/dev/null ; \
+ if $(CC) $(GCCOPT) $(1) -c $(topdir)/dummy.c \
+ -o $$tmpf 2>/dev/null ; \
then echo '$(1)'; else echo '$(2)'; fi; \
rm -f $$tmpf)
diff --git a/MCONFIG.build b/MCONFIG.build
new file mode 100644
index 00000000..d1abff2a
--- /dev/null
+++ b/MCONFIG.build
@@ -0,0 +1,33 @@
+## -*- makefile -*- ------------------------------------------------------
+##
+## Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
+##
+## 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., 53 Temple Place Ste 330,
+## Boston MA 02111-1307, USA; either version 2 of the License, or
+## (at your option) any later version; incorporated herein by reference.
+##
+## -----------------------------------------------------------------------
+
+##
+## Right now we don't distinguish between "build" system and the "host"
+## system, although we really should...
+##
+include $(topdir)/MCONFIG
+
+OPTFLAGS = -g -Os
+INCLUDES =
+CFLAGS = -W -Wall -Wno-sign-compare -D_FILE_OFFSET_BITS=64 \
+ $(OPTFLAGS) $(INCLUDES)
+LDFLAGS =
+LIBS =
+
+.SUFFIXES: .c .o .S .s .i .elf .com .bin .asm .lst .c32 .lss
+
+%.o: %.c
+ $(CC) $(UMAKEDEPS) $(CFLAGS) -c -o $@ $<
+%.i: %.c
+ $(CC) $(UMAKEDEPS) $(CFLAGS) -E -o $@ $<
+%.s: %.c
+ $(CC) $(UMAKEDEPS) $(CFLAGS) -S -o $@ $<
diff --git a/MCONFIG.embedded b/MCONFIG.embedded
index 37abe917..e8879fc5 100644
--- a/MCONFIG.embedded
+++ b/MCONFIG.embedded
@@ -16,14 +16,21 @@
include $(topdir)/MCONFIG
-GCCOPT := $(call gcc_ok,-m32,) \
- $(call gcc_ok,-ffreestanding,) \
- $(call gcc_ok,-fno-stack-protector,) \
- $(call gcc_ok,-falign-functions=0,-malign-functions=0) \
- $(call gcc_ok,-falign-jumps=0,-malign-jumps=0) \
- $(call gcc_ok,-falign-loops=0,-malign-loops=0) \
- -march=i386 -Os -fomit-frame-pointer -mregparm=3 -DREGPARM=3 \
+GCCOPT := $(call gcc_ok,-m32,)
+GCCOPT += $(call gcc_ok,-ffreestanding,)
+GCCOPT += $(call gcc_ok,-fno-stack-protector,)
+GCCOPT += $(call gcc_ok,-fwrapv,)
+GCCOPT += $(call gcc_ok,-freg-struct-return,)
+GCCOPT += -march=i386 -Os -fomit-frame-pointer -mregparm=3 -DREGPARM=3 \
-msoft-float
+GCCOPT += $(call gcc_ok,-fno-exceptions,)
+GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,)
+GCCOPT += $(call gcc_ok,-fno-strict-aliasing,)
+GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0)
+GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0)
+GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0)
+GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0)
+GCCOPT += $(call gcc_ok,-mpreferred-stack-boundary=2,)
LIBGCC := $(shell $(CC) $(GCCOPT) --print-libgcc)
diff --git a/Makefile b/Makefile
index d0f5e71d..6fbec336 100644
--- a/Makefile
+++ b/Makefile
@@ -52,7 +52,7 @@ BOBJECTS = $(BTARGET) \
# Note: libinstaller is both a BSUBDIR and an ISUBDIR. It contains
# files that depend only on the B phase, but may have to be regenerated
# for "make installer".
-BSUBDIRS = codepage core memdisk modules com32 mbr memdump gpxe sample \
+BSUBDIRS = codepage com32 lzo core memdisk modules mbr memdump gpxe sample \
libinstaller dos win32 dosutil
ITARGET =
IOBJECTS = $(ITARGET) dos/copybs.com \
diff --git a/TODO b/TODO
deleted file mode 100644
index 530b4bfb..00000000
--- a/TODO
+++ /dev/null
@@ -1,22 +0,0 @@
-*** To do in the short term:
-
-- PXELINUX: Figure out localboot/idle problems.
-
-- PXELINUX: Support changing the default server and boot file prefix?
-
-- Library support for all the comboot system calls.
-
-- Deal with non-512-byte sectors (if I can get media which does...)
-
-
-*** Future projects:
-
-- Clean up the command-line parsing.
-
-- Cleaned up documentation, with a real man page.
-
-- API call to get directory listing.
-
-- COM32-based CLI.
-
-- Rewrite the filesystems to run in protected mode C code.
diff --git a/codepage/cptable.pl b/codepage/cptable.pl
index 05cfc3eb..e29cf006 100755
--- a/codepage/cptable.pl
+++ b/codepage/cptable.pl
@@ -82,7 +82,7 @@ open(CPOUT, '>', $cpout)
# Magic number, in anticipation of being able to load these
# files dynamically...
#
-print CPOUT pack("VV", 0x8fad232b, 0x9c295319);
+print CPOUT pack("VV", 0x58a8b3d4, 0x51d21eb1);
# Header fields available for future use...
print CPOUT pack("VVVVVV", 0, 0, 0, 0, 0, 0);
@@ -97,6 +97,7 @@ print CPOUT pack("VVVVVV", 0, 0, 0, 0, 0, 0);
# ... where @ytab is console codepage -> Unicode and
# %tabx is Unicode -> filesystem codepage.
#
+@uctab = (undef) x 256;
for ($i = 0; $i < 256; $i++) {
$uuc = $ucase{$ytab[$i]}; # Unicode upper case
if (defined($tabx{$uuc})) {
@@ -106,15 +107,44 @@ for ($i = 0; $i < 256; $i++) {
# Upper case equivalent stripped of accents
$u = $tabx{${$decomp{$uuc}}[0]};
} else {
- # No equivalent at all found. Set this to zero, which should
- # prevent shortname matching altogether (still making longname
- # matching possible, of course.)
- $u = 0;
+ # No equivalent at all found. Assume it is a lower-case-only
+ # character, like greek alpha in CP437.
+ $u = $i;
}
+ $uctab[$i] = $u;
print CPOUT pack("C", $u);
}
#
+# Self (shortname) lowercase table.
+# This depends both on the console codepage and the filesystem codepage;
+# the logical transcoding operation is:
+#
+# $taby{$lcase{$xtab[$i]}}
+#
+# ... where @ytab is console codepage -> Unicode and
+# %tabx is Unicode -> filesystem codepage.
+#
+@lctab = (undef) x 256;
+for ($i = 0; $i < 256; $i++) {
+ $llc = $lcase{$xtab[$i]}; # Unicode lower case
+ if (defined($l = $taby{$llc}) && $uctab[$l] == $i) {
+ # Straight-forward conversion
+ } elsif (defined($l = $tabx{${$decomp{$llc}}[0]}) && $uctab[$l] == $i) {
+ # Lower case equivalent stripped of accents
+ } else {
+ # No equivalent at all found. Find *anything* that matches the
+ # bijection criterion...
+ for ($l = 0; $l < 256; $l++) {
+ last if ($uctab[$l] == $i);
+ }
+ $l = $i if ($l == 256); # If nothing, we're screwed anyway...
+ }
+ $lctab[$i] = $l;
+ print CPOUT pack("C", $l);
+}
+
+#
# Unicode (longname) matching table.
# This only depends on the console codepage.
#
diff --git a/com32/MCONFIG b/com32/MCONFIG
index 578e2832..80f92f6c 100644
--- a/com32/MCONFIG
+++ b/com32/MCONFIG
@@ -1,5 +1,5 @@
## -*- makefile -*- -------------------------------------------------------
-##
+##
## Copyright 2008-2009 H. Peter Anvin - All Rights Reserved
## Copyright 2009 Intel Corporation; author: H. Peter Anvin
##
@@ -17,12 +17,24 @@
include $(topdir)/MCONFIG
-GCCOPT := $(call gcc_ok,-std=gnu99,) \
- $(call gcc_ok,-m32,) \
- $(call gcc_ok,-fno-stack-protector,) \
- -mregparm=3 -DREGPARM=3 -march=i386 -Os
-
-com32 = $(topdir)/com32
+GCCOPT := $(call gcc_ok,-std=gnu99,)
+GCCOPT += $(call gcc_ok,-m32,)
+GCCOPT += $(call gcc_ok,-fno-stack-protector,)
+GCCOPT += $(call gcc_ok,-fwrapv,)
+GCCOPT += $(call gcc_ok,-freg-struct-return,)
+GCCOPT += -mregparm=3 -DREGPARM=3 -march=i386 -Os
+GCCOPT += $(call gcc_ok,-fPIE,-fPIC)
+GCCOPT += $(call gcc_ok,-fno-exceptions,)
+GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,)
+GCCOPT += $(call gcc_ok,-fno-strict-aliasing,)
+GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0)
+GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0)
+GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0)
+GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0)
+GCCOPT += $(call gcc_ok,-mpreferred-stack-boundary=2,)
+
+com32 := $(topdir)/com32
+RELOCS := $(com32)/tools/relocs
ifneq ($(NOGPL),1)
GPLLIB = $(com32)/gpllib/libcom32gpl.a
@@ -42,7 +54,7 @@ SFLAGS = $(GCCOPT) $(GCCWARN) -march=i386 \
-I$(com32)/libutil/include -I$(com32)/include $(GPLINCLUDE)
COM32LD = $(com32)/lib/com32.ld
-LDFLAGS = -m elf_i386 -T $(COM32LD)
+LDFLAGS = -m elf_i386 --emit-relocs -T $(COM32LD)
LIBGCC := $(shell $(CC) $(GCCOPT) --print-libgcc)
LNXCFLAGS = -I$(com32)/libutil/include $(GCCWARN) -O -g -D_GNU_SOURCE
@@ -81,3 +93,4 @@ C_LNXLIBS = $(com32)/libutil/libutil_lnx.a
%.c32: %.elf
$(OBJCOPY) -O binary $< $@
+ $(RELOCS) $< >> $@ || ( rm -f $@ ; false )
diff --git a/com32/Makefile b/com32/Makefile
index 69a125e6..89d0694e 100644
--- a/com32/Makefile
+++ b/com32/Makefile
@@ -1,3 +1,3 @@
-SUBDIRS = lib gpllib libutil modules mboot menu samples rosh cmenu hdt gfxboot
+SUBDIRS = tools lib gpllib libutil modules mboot menu samples rosh cmenu hdt gfxboot
all tidy dist clean spotless install:
set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done
diff --git a/com32/include/dev.h b/com32/include/dev.h
index 7809fb56..70b3165c 100644
--- a/com32/include/dev.h
+++ b/com32/include/dev.h
@@ -41,6 +41,7 @@ struct input_dev;
struct output_dev;
__extern int opendev(const struct input_dev *, const struct output_dev *, int);
+__extern int openmem(const void *, size_t, int);
/* Common generic devices */
diff --git a/com32/include/dirent.h b/com32/include/dirent.h
index d99b21fb..c4aca4f0 100644
--- a/com32/include/dirent.h
+++ b/com32/include/dirent.h
@@ -10,23 +10,7 @@
#include <stddef.h>
#include <sys/types.h>
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-struct dirent {
- long d_ino; /* Inode/File number */
- off_t d_size; /* Size of file */
- mode_t d_mode; /* Type of file */
- char d_name[NAME_MAX + 1];
-};
-
-typedef struct {
- short dd_stat; /* status return from last lookup */
- uint16_t dd_fd;
- size_t dd_sect;
- char dd_name[NAME_MAX + 1]; /* directory */
-} DIR;
+#include <sys/dirent.h>
__extern DIR *opendir(const char *);
__extern struct dirent *readdir(DIR *);
diff --git a/com32/include/netinet/in.h b/com32/include/netinet/in.h
index 051cc08f..ccf04750 100644
--- a/com32/include/netinet/in.h
+++ b/com32/include/netinet/in.h
@@ -4,37 +4,47 @@
/* COM32 will be running on an i386 platform */
#include <stdint.h>
+#include <klibc/compiler.h>
-static inline uint16_t __htons(uint16_t v)
+#define __htons_macro(v) ((uint16_t) \
+ (((uint16_t)(v) << 8) | \
+ ((uint16_t)(v) >> 8)))
+
+static inline __constfunc uint16_t __htons(uint16_t v)
{
- return ((v) << 8) | ((v) >> 8);
+ return __htons_macro(v);
}
-#define htons(x) __htons(x)
-#define ntohs(x) __htons(x)
+#define htons(x) (__builtin_constant_p(x) ? __htons_macro(x) : __htons(x))
+#define ntohs(x) htons(x)
+
+#define __htonl_macro(v) ((uint32_t) \
+ ((((uint32_t)(v) & 0x000000ff) << 24) | \
+ (((uint32_t)(v) & 0x0000ff00) << 8) | \
+ (((uint32_t)(v) & 0x00ff0000) >> 8) | \
+ (((uint32_t)(v) & 0xff000000) >> 24)))
-static inline uint32_t __htonl(uint32_t v)
+static inline __constfunc uint32_t __htonl(uint32_t v)
{
- if (__builtin_constant_p(v)) {
- return (((v) & 0x000000ff) << 24) |
- (((v) & 0x0000ff00) << 8) |
- (((v) & 0x00ff0000) >> 8) | (((v) & 0xff000000) >> 24);
- } else {
-asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0":"+abcd"(v));
- return v;
- }
+ asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0"
+ : "+q" (v));
+ return v;
}
-#define htonl(x) __htonl(x)
-#define ntohl(x) __htonl(x)
+#define htonl(x) (__builtin_constant_p(x) ? __htonl_macro(x) : __htonl(x))
+#define ntohl(x) htonl(x)
+
+#define __htonq_macro(v) ((uint64_t) \
+ (((uint64_t)__htonl_macro((uint32_t)(v)) << 32) | \
+ (__htonl_macro((uint32_t)((uint64_t)(v) >> 32)))))
-static inline uint64_t __htonq(uint64_t v)
+static inline __constfunc uint64_t __htonq(uint64_t v)
{
- return ((uint64_t) __htonl(v) << 32) | __htonl(v >> 32);
+ return ((uint64_t)__htonl(v) << 32) | __htonl(v >> 32);
}
-#define htonq(x) __htonq(x)
-#define ntohq(x) __htonq(x)
+#define htonq(x) (__builtin_constant_p(x) ? __htonq_macro(x) : __htonq(x))
+#define ntohq(x) htonq(x)
typedef uint32_t in_addr_t;
typedef uint16_t in_port_t;
diff --git a/com32/include/string.h b/com32/include/string.h
index c964ee3b..af9792b6 100644
--- a/com32/include/string.h
+++ b/com32/include/string.h
@@ -23,7 +23,6 @@ __extern char *strcat(char *, const char *);
__extern char *strchr(const char *, int);
__extern int strcmp(const char *, const char *);
__extern char *strcpy(char *, const char *);
-__extern char *strpcpy(char *, const char *);
__extern size_t strcspn(const char *, const char *);
__extern char *strdup(const char *);
__extern char *strndup(const char *, size_t);
diff --git a/com32/include/sys/cpu.h b/com32/include/sys/cpu.h
index dfba02e7..d96ec665 100644
--- a/com32/include/sys/cpu.h
+++ b/com32/include/sys/cpu.h
@@ -23,21 +23,26 @@ static inline void cpuid_count(uint32_t op, uint32_t cnt,
uint32_t * eax, uint32_t * ebx,
uint32_t * ecx, uint32_t * edx)
{
-asm("cpuid":"=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
+asm("pushl %%ebx ; cpuid ; movl %%ebx,%0 ; popl %%ebx":"=a"(*eax), "=SD"(*ebx), "=c"(*ecx),
+ "=d"(*edx)
: "a"(op), "c"(cnt));
}
static inline void cpuid(uint32_t op, uint32_t * eax, uint32_t * ebx,
uint32_t * ecx, uint32_t * edx)
{
- cpuid_count(op, 0, eax, ebx, ecx, edx);
+asm("pushl %%ebx ; cpuid ; movl %%ebx,%0 ; popl %%ebx":"=a"(*eax), "=SD"(*ebx), "=c"(*ecx),
+ "=d"(*edx)
+: "a"(op));
}
static inline __constfunc uint32_t cpuid_eax(uint32_t level)
{
uint32_t v;
-asm("cpuid": "=a"(v): "a"(level):"ebx", "ecx", "edx");
+asm("pushl %%ebx ; cpuid ; popl %%ebx":"=a"(v)
+: "a"(level)
+: "ecx", "edx");
return v;
}
@@ -45,7 +50,9 @@ static inline __constfunc uint32_t cpuid_ebx(uint32_t level)
{
uint32_t v;
-asm("cpuid": "=b"(v), "+a"(level): :"ecx", "edx");
+asm("pushl %%ebx ; cpuid ; movl %%ebx,%0 ; popl %%ebx":"=a"(v)
+: "a"(level)
+: "ecx", "edx");
return v;
}
@@ -53,7 +60,8 @@ static inline __constfunc uint32_t cpuid_ecx(uint32_t level)
{
uint32_t v;
-asm("cpuid": "=c"(v), "+a"(level): :"ebx", "edx");
+asm("pushl %%ebx ; cpuid ; popl %%ebx":"=c"(v), "+a"(level)
+: : "edx");
return v;
}
@@ -61,7 +69,8 @@ static inline __constfunc uint32_t cpuid_edx(uint32_t level)
{
uint32_t v;
-asm("cpuid": "=d"(v), "+a"(level): :"ebx", "ecx");
+asm("pushl %%ebx ; cpuid ; popl %%ebx":"=d"(v), "+a"(level)
+: : "ecx");
return v;
}
diff --git a/com32/include/sys/dirent.h b/com32/include/sys/dirent.h
new file mode 100644
index 00000000..cc2916e1
--- /dev/null
+++ b/com32/include/sys/dirent.h
@@ -0,0 +1,30 @@
+/*
+ * sys/dirent.h
+ */
+
+#ifndef DIRENT_H
+#define DIRENT_H
+
+#include <stdint.h>
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+struct dirent {
+ uint32_t d_ino;
+ uint32_t d_off;
+ uint16_t d_reclen;
+ uint16_t d_type;
+ char d_name[NAME_MAX + 1];
+};
+
+struct file;
+
+typedef struct {
+ struct file *dd_dir;
+} DIR;
+
+#define DIR_REC_LEN(name) (12 + strlen(name) + 1 + 3) & ~3
+
+#endif /* sys/dirent.h */
diff --git a/com32/include/syslinux/pxe.h b/com32/include/syslinux/pxe.h
index 037642bc..041e0ae1 100644
--- a/com32/include/syslinux/pxe.h
+++ b/com32/include/syslinux/pxe.h
@@ -34,493 +34,10 @@
#ifndef _SYSLINUX_PXE_H
#define _SYSLINUX_PXE_H
-#include <stdint.h>
-#include <netinet/in.h>
-#include <klibc/compiler.h>
-
-/* PXE spec structures and definitions. These mostly follow the PXE
- spec, except when the PXE spec is unnecessarily stupid. Of course,
- that is most of the time. */
-
-/* Basic types; use Unix-like _t convention instead of SCREAMING; also
- re-use types we already have, like in_addr_t. */
-
-typedef uint16_t pxenv_status_t;
-
-#define MAC_ADDR_LEN 16
-typedef uint8_t mac_addr_t[MAC_ADDR_LEN];
-
-/* "Protected mode segment descriptor" according to PXE... */
-typedef struct {
- uint16_t segaddr;
- uint32_t physaddr;
- uint16_t segsize;
-} __packed pxe_segdesc_t;
-
-typedef struct {
- uint16_t offs;
- uint16_t seg;
-} segoff16_t;
-
-typedef struct {
- uint8_t opcode;
-#define BOOTP_REQ 1
-#define BOOTP_REP 2
- uint8_t Hardware;
- uint8_t Hardlen;
- uint8_t Gatehops;
- uint32_t ident;
- uint16_t seconds;
- uint16_t Flags;
-#define BOOTP_BCAST 0x8000
- in_addr_t cip; /* Client IP address */
- in_addr_t yip; /* You IP address */
- in_addr_t sip; /* next server IP address */
- in_addr_t gip; /*relay agent IP address */
- mac_addr_t CAddr;
- uint8_t Sname[64];
- uint8_t bootfile[128];
- union {
-#define BOOTP_DHCPVEND 1024
- uint8_t d[BOOTP_DHCPVEND];
- struct {
- uint8_t magic[4];
-#define VM_RFC1048 0x63825363L
- uint32_t flags;
- uint8_t pad[56];
- } v;
- } vendor;
-} __packed pxe_bootp_t;
-
-/* Function calling structures and constants */
-
-typedef struct s_PXENV_GET_CACHED_INFO {
- pxenv_status_t Status;
- uint16_t PacketType;
-#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1
-#define PXENV_PACKET_TYPE_DHCP_ACK 2
-#define PXENV_PACKET_TYPE_CACHED_REPLY 3
- uint16_t BufferSize;
- segoff16_t Buffer;
- uint16_t BufferLimit;
-} __packed t_PXENV_GET_CACHED_INFO;
-
-typedef struct s_PXENV_START_UNDI {
- pxenv_status_t Status;
- uint16_t AX;
- uint16_t BX;
- uint16_t DX;
- uint16_t DI;
- uint16_t ES;
-} __packed t_PXENV_START_UNDI;
-
-typedef struct s_PXENV_STOP_UNDI {
- pxenv_status_t Status;
-} __packed t_PXENV_STOP_UNDI;
-
-typedef struct s_PXENV_START_BASE {
- pxenv_status_t Status;
-} __packed t_PXENV_START_BASE;
-
-typedef struct s_PXENV_STOP_BASE {
- pxenv_status_t Status;
-} __packed t_PXENV_STOP_BASE;
-
-typedef struct s_PXENV_TFTP_OPEN {
- pxenv_status_t Status;
- in_addr_t ServerIPAddress;
- in_addr_t GatewayIPAddress;
- uint8_t FileName[128];
- in_port_t TFTPPort;
- uint16_t PacketSize;
-} __packed t_PXENV_TFTP_OPEN;
-
-typedef struct s_PXENV_TFTP_CLOSE {
- pxenv_status_t Status;
-} __packed t_PXENV_TFTP_CLOSE;
-
-typedef struct s_PXENV_TFTP_READ {
- pxenv_status_t Status;
- uint16_t PacketNumber;
- uint16_t BufferSize;
- segoff16_t Buffer;
-} __packed t_PXENV_TFTP_READ;
-
-typedef struct s_PXENV_TFTP_READ_FILE {
- pxenv_status_t Status;
- uint8_t FileName[128];
- uint32_t BufferSize;
- void *Buffer;
- in_addr_t ServerIPAddress;
- in_addr_t GatewayIPAddress;
- in_addr_t McastIPAddress;
- in_port_t TFTPClntPort;
- in_port_t TFTPSrvPort;
- uint16_t TFTPOpenTimeOut;
- uint16_t TFTPReopenDelay;
-} __packed t_PXENV_TFTP_READ_FILE;
-
-typedef struct s_PXENV_TFTP_GET_FSIZE {
- pxenv_status_t Status;
- in_addr_t ServerIPAddress;
- in_addr_t GatewayIPAddress;
- uint8_t FileName[128];
- uint32_t FileSize;
-} __packed t_PXENV_TFTP_GET_FSIZE;
-
-typedef struct s_PXENV_UDP_OPEN {
- pxenv_status_t status;
- in_addr_t src_ip;
-} __packed t_PXENV_UDP_OPEN;
-
-typedef struct s_PXENV_UDP_CLOSE {
- pxenv_status_t status;
-} __packed t_PXENV_UDP_CLOSE;
-
-typedef struct s_PXENV_UDP_WRITE {
- pxenv_status_t status;
- in_addr_t ip;
- in_addr_t gw;
- in_port_t src_port;
- in_port_t dst_port;
- uint16_t buffer_size;
- segoff16_t buffer;
-} __packed t_PXENV_UDP_WRITE;
-
-typedef struct s_PXENV_UDP_READ {
- pxenv_status_t status;
- in_addr_t src_ip;
- in_addr_t dest_ip;
- in_port_t s_port;
- in_port_t d_port;
- uint16_t buffer_size;
- segoff16_t buffer;
-} __packed t_PXENV_UDP_READ;
-
-typedef struct s_PXENV_UNDI_STARTUP {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_STARTUP;
-
-typedef struct s_PXENV_UNDI_CLEANUP {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_CLEANUP;
-
-typedef struct s_PXENV_UNDI_INITIALIZE {
- pxenv_status_t Status;
- void *ProtocolIni;
- uint8_t reserved[8];
-} __packed t_PXENV_UNDI_INITIALIZE;
-
-#define MAXNUM_MCADDR 8
-typedef struct s_PXENV_UNDI_MCAST_ADDRESS {
- uint16_t MCastAddrCount;
- mac_addr_t McastAddr[MAXNUM_MCADDR];
-} __packed t_PXENV_UNDI_MCAST_ADDRESS;
-
-typedef struct s_PXENV_UNDI_RESET {
- pxenv_status_t Status;
- t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
-} __packed t_PXENV_UNDI_RESET;
-
-typedef struct s_PXENV_UNDI_SHUTDOWN {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_SHUTDOWN;
-
-typedef struct s_PXENV_UNDI_OPEN {
- pxenv_status_t Status;
- uint16_t OpenFlag;
- uint16_t PktFilter;
-#define FLTR_DIRECTED 0x0001
-#define FLTR_BRDCST 0x0002
-#define FLTR_PRMSCS 0x0004
-#define FLTR_SRC_RTG 0x0008
- t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
-} __packed t_PXENV_UNDI_OPEN;
-
-typedef struct s_PXENV_UNDI_CLOSE {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_CLOSE;
-
-typedef struct s_PXENV_UNDI_TRANSMIT {
- pxenv_status_t Status;
- uint8_t Protocol;
-#define P_UNKNOWN 0
-#define P_IP 1
-#define P_ARP 2
-#define P_RARP 3
- uint8_t XmitFlag;
-#define XMT_DESTADDR 0x0000
-#define XMT_BROADCAST 0x0001
- segoff16_t DestAddr;
- segoff16_t TBD;
- uint32_t Reserved[2];
-} __packed t_PXENV_UNDI_TRANSMIT;
-#define MAX_DATA_BLKS 8
-typedef struct s_PXENV_UNDI_TBD {
- uint16_t ImmedLength;
- segoff16_t Xmit;
- uint16_t DataBlkCount;
- struct DataBlk {
- uint8_t TDPtrType;
- uint8_t TDRsvdByte;
- uint16_t TDDataLen;
- segoff16_t TDDataPtr;
- } DataBlock[MAX_DATA_BLKS];
-} __packed t_PXENV_UNDI_TBD;
-
-typedef struct s_PXENV_UNDI_SET_MCAST_ADDRESS {
- pxenv_status_t Status;
- t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
-} __packed t_PXENV_UNDI_SET_MCAST_ADDR;
-
-typedef struct s_PXENV_UNDI_SET_STATION_ADDRESS {
- pxenv_status_t Status;
- mac_addr_t StationAddress;
-} __packed t_PXENV_UNDI_SET_STATION_ADDR;
-
-typedef struct s_PXENV_UNDI_SET_PACKET_FILTER {
- pxenv_status_t Status;
- uint8_t filter;
-} __packed t_PXENV_UNDI_SET_PACKET_FILTER;
-
-typedef struct s_PXENV_UNDI_GET_INFORMATION {
- pxenv_status_t Status;
- uint16_t BaseIo;
- uint16_t IntNumber;
- uint16_t MaxTranUnit;
- uint16_t HwType;
-#define ETHER_TYPE 1
-#define EXP_ETHER_TYPE 2
-#define IEEE_TYPE 6
-#define ARCNET_TYPE 7
- uint16_t HwAddrLen;
- mac_addr_t CurrentNodeAddress;
- mac_addr_t PermNodeAddress;
- uint16_t ROMAddress;
- uint16_t RxBufCt;
- uint16_t TxBufCt;
-} __packed t_PXENV_UNDI_GET_INFORMATION;
-
-typedef struct s_PXENV_UNDI_GET_STATISTICS {
- pxenv_status_t Status;
- uint32_t XmtGoodFrames;
- uint32_t RcvGoodFrames;
- uint32_t RcvCRCErrors;
- uint32_t RcvResourceErrors;
-} __packed t_PXENV_UNDI_GET_STATISTICS;
-
-typedef struct s_PXENV_UNDI_CLEAR_STATISTICS {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_CLEAR_STATISTICS;
-
-typedef struct s_PXENV_UNDI_INITIATE_DIAGS {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_INITIATE_DIAGS;
-
-typedef struct s_PXENV_UNDI_FORCE_INTERRUPT {
- pxenv_status_t Status;
-} __packed t_PXENV_UNDI_FORCE_INTERRUPT;
-
-typedef struct s_PXENV_UNDI_GET_MCAST_ADDRESS {
- pxenv_status_t Status;
- in_addr_t InetAddr;
- mac_addr_t MediaAddr;
-} __packed t_PXENV_UNDI_GET_MCAST_ADDR;
-
-typedef struct s_PXENV_UNDI_GET_NIC_TYPE {
- pxenv_status_t Status;
- uint8_t NicType;
-#define PCI_NIC 2
-#define PnP_NIC 3
-#define CardBus_NIC 4
- union {
- struct {
- uint16_t Vendor_ID;
- uint16_t Dev_ID;
- uint8_t Base_Class;
- uint8_t Sub_Class;
- uint8_t Prog_Intf;
- uint8_t Rev;
- uint16_t BusDevFunc;
- uint16_t SubVendor_ID;
- uint16_t SubDevice_ID;
- } pci, cardbus;
- struct {
- uint32_t EISA_Dev_ID;
- uint8_t Base_Class;
- uint8_t Sub_Class;
- uint8_t Prog_Intf;
- uint16_t CardSelNum;
- } __packed pnp;
- } __packed info;
-} __packed t_PXENV_UNDI_GET_NIC_TYPE;
-
-typedef struct s_PXENV_UNDI_GET_IFACE_INFO {
- pxenv_status_t Status;
- uint8_t IfaceType[16];
- uint32_t LinkSpeed;
- uint32_t ServiceFlags;
- uint32_t Reserved[4];
-} __packed t_PXENV_UNDI_GET_NDIS_INFO;
-
-typedef struct s_PXENV_UNDI_GET_STATE {
-#define PXE_UNDI_GET_STATE_STARTED 1
-#define PXE_UNDI_GET_STATE_INITIALIZED 2
-#define PXE_UNDI_GET_STATE_OPENED 3
- pxenv_status_t Status;
- uint8_t UNDIstate;
-} __packed t_PXENV_UNDI_GET_STATE;
-
-typedef struct s_PXENV_UNDI_ISR {
- pxenv_status_t Status;
- uint16_t FuncFlag;
- uint16_t BufferLength;
- uint16_t FrameLength;
- uint16_t FrameHeaderLength;
- segoff16_t Frame;
- uint8_t ProtType;
- uint8_t PktType;
-} __packed t_PXENV_UNDI_ISR;
-#define PXENV_UNDI_ISR_IN_START 1
-#define PXENV_UNDI_ISR_IN_PROCESS 2
-#define PXENV_UNDI_ISR_IN_GET_NEXT 3
-/* One of these will be returned for
- PXENV_UNDI_ISR_IN_START */
-#define PXENV_UNDI_ISR_OUT_OURS 0
-#define PXENV_UNDI_USR_OUT_NOT_OURS 1
-/* One of these will be returned for
- PXENV_UNDI_ISR_IN_PROCESS and
- PXENV_UNDI_ISR_IN_GET_NEXT */
-#define PXENV_UNDI_ISR_OUT_DONE 0
-#define PXENV_UNDI_ISR_OUT_TRANSMIT 2
-#define PXENV_UNDI_ISR_OUT_RECEIVE 3
-#define PXENV_UNDI_ISR_OUT_BUSY 4
-
-/* Function numbers and error codes */
-
-#define PXENV_TFTP_OPEN 0x0020
-#define PXENV_TFTP_CLOSE 0x0021
-#define PXENV_TFTP_READ 0x0022
-#define PXENV_TFTP_READ_FILE 0x0023
-#define PXENV_TFTP_READ_FILE_PMODE 0x0024
-#define PXENV_TFTP_GET_FSIZE 0x0025
-
-#define PXENV_UDP_OPEN 0x0030
-#define PXENV_UDP_CLOSE 0x0031
-#define PXENV_UDP_READ 0x0032
-#define PXENV_UDP_WRITE 0x0033
-
-#define PXENV_START_UNDI 0x0000
-#define PXENV_UNDI_STARTUP 0x0001
-#define PXENV_UNDI_CLEANUP 0x0002
-#define PXENV_UNDI_INITIALIZE 0x0003
-#define PXENV_UNDI_RESET_NIC 0x0004
-#define PXENV_UNDI_SHUTDOWN 0x0005
-#define PXENV_UNDI_OPEN 0x0006
-#define PXENV_UNDI_CLOSE 0x0007
-#define PXENV_UNDI_TRANSMIT 0x0008
-#define PXENV_UNDI_SET_MCAST_ADDR 0x0009
-#define PXENV_UNDI_SET_STATION_ADDR 0x000A
-#define PXENV_UNDI_SET_PACKET_FILTER 0x000B
-#define PXENV_UNDI_GET_INFORMATION 0x000C
-#define PXENV_UNDI_GET_STATISTICS 0x000D
-#define PXENV_UNDI_CLEAR_STATISTICS 0x000E
-#define PXENV_UNDI_INITIATE_DIAGS 0x000F
-#define PXENV_UNDI_FORCE_INTERRUPT 0x0010
-#define PXENV_UNDI_GET_MCAST_ADDR 0x0011
-#define PXENV_UNDI_GET_NIC_TYPE 0x0012
-#define PXENV_UNDI_GET_IFACE_INFO 0x0013
-#define PXENV_UNDI_ISR 0x0014
-#define PXENV_STOP_UNDI 0x0015 /* Overlap...? */
-#define PXENV_UNDI_GET_STATE 0x0015 /* Overlap...? */
-
-#define PXENV_UNLOAD_STACK 0x0070
-#define PXENV_GET_CACHED_INFO 0x0071
-#define PXENV_RESTART_DHCP 0x0072
-#define PXENV_RESTART_TFTP 0x0073
-#define PXENV_MODE_SWITCH 0x0074
-#define PXENV_START_BASE 0x0075
-#define PXENV_STOP_BASE 0x0076
-
-#define PXENV_EXIT_SUCCESS 0x0000
-#define PXENV_EXIT_FAILURE 0x0001
-
-#define PXENV_STATUS_SUCCESS 0x00
-#define PXENV_STATUS_FAILURE 0x01
-#define PXENV_STATUS_BAD_FUNC 0x02
-#define PXENV_STATUS_UNSUPPORTED 0x03
-#define PXENV_STATUS_KEEP_UNDI 0x04
-#define PXENV_STATUS_KEEP_ALL 0x05
-#define PXENV_STATUS_OUT_OF_RESOURCES 0x06
-#define PXENV_STATUS_ARP_TIMEOUT 0x11
-#define PXENV_STATUS_UDP_CLOSED 0x18
-#define PXENV_STATUS_UDP_OPEN 0x19
-#define PXENV_STATUS_TFTP_CLOSED 0x1A
-#define PXENV_STATUS_TFTP_OPEN 0x1B
-#define PXENV_STATUS_MCOPY_PROBLEM 0x20
-#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21
-#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22
-#define PXENV_STATUS_BIS_INIT_FAILURE 0x23
-#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24
-#define PXENV_STATUS_BIS_GBOA_FAILURE 0x25
-#define PXENV_STATUS_BIS_FREE_FAILURE 0x26
-#define PXENV_STATUS_BIS_GSI_FAILURE 0x27
-#define PXENV_STATUS_BIS_BAD_CKSUM 0x28
-#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30
-#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32
-
-#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33
-#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35
-#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36
-#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38
-#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39
-#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3A
-#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3B
-#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3C
-#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3D
-#define PXENV_STATUS_TFTP_NO_FILESIZE 0x3E
-#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3F
-#define PXENV_STATUS_DHCP_TIMEOUT 0x51
-#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52
-#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53
-#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54
-#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60
-#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61
-#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62
-#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63
-#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64
-#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65
-#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66
-#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67
-#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68
-#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69
-#define PXENV_STATUS_UNDI_INVALID_STATE 0x6A
-#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6B
-#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6C
-#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74
-#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76
-#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77
-#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78
-#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79
-#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xA0
-#define PXENV_STATUS_BINL_NO_PXE_SERVER 0xA1
-#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xA2
-#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xA3
-#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xB0
-#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xC0
-#define PXENV_STATUS_LOADER_NO_BC_ROMID 0xC1
-#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xC2
-#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xC3
-#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xC4
-#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xC5
-#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xC6
-#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xC8
-#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xC9
-#define PXENV_STATUS_LOADER_UNDI_START 0xCA
-#define PXENV_STATUS_LOADER_BC_START 0xCB
+#include <syslinux/pxe_api.h>
/* SYSLINUX-defined PXE utility functions */
-int pxe_get_cached_info(int level, void **buf, size_t * len);
+int pxe_get_cached_info(int level, void **buf, size_t *len);
int pxe_get_nic_type(t_PXENV_UNDI_GET_NIC_TYPE * gnt);
#endif /* _SYSLINUX_PXE_H */
diff --git a/com32/include/syslinux/pxe_api.h b/com32/include/syslinux/pxe_api.h
new file mode 100644
index 00000000..fcc4f873
--- /dev/null
+++ b/com32/include/syslinux/pxe_api.h
@@ -0,0 +1,566 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * syslinux/pxe_api.h
+ *
+ * PXE type and constant definitions for SYSLINUX
+ */
+
+#ifndef _SYSLINUX_PXE_API_H
+#define _SYSLINUX_PXE_API_H
+
+#include <stdint.h>
+#include <netinet/in.h>
+#include <klibc/compiler.h>
+#include <com32.h>
+
+/* PXE spec structures and definitions. These mostly follow the PXE
+ spec, except when the PXE spec is unnecessarily stupid. Of course,
+ that is most of the time. */
+
+/* Basic types; use Unix-like _t convention instead of SCREAMING; also
+ re-use types we already have, like in_addr_t. */
+
+typedef uint16_t pxenv_status_t;
+
+#define MAC_ADDR_LEN 16
+typedef uint8_t mac_addr_t[MAC_ADDR_LEN];
+
+/* "Protected mode segment descriptor" according to PXE... */
+typedef struct {
+ uint16_t sel;
+ uint32_t base;
+ uint16_t size;
+} __packed pxe_segdesc_t;
+
+typedef far_ptr_t segoff16_t;
+
+typedef struct {
+ uint8_t opcode;
+#define BOOTP_REQ 1
+#define BOOTP_REP 2
+ uint8_t Hardware;
+ uint8_t Hardlen;
+ uint8_t Gatehops;
+ uint32_t ident;
+ uint16_t seconds;
+ uint16_t Flags;
+#define BOOTP_BCAST 0x8000
+ in_addr_t cip; /* Client IP address */
+ in_addr_t yip; /* You IP address */
+ in_addr_t sip; /* next server IP address */
+ in_addr_t gip; /*relay agent IP address */
+ mac_addr_t CAddr;
+ uint8_t Sname[64];
+ uint8_t bootfile[128];
+ union {
+#define BOOTP_DHCPVEND 1024
+ uint8_t d[BOOTP_DHCPVEND];
+ struct {
+ uint8_t magic[4];
+#define VM_RFC1048 0x63825363L
+ uint32_t flags;
+ uint8_t pad[56];
+ } v;
+ } vendor;
+} __packed pxe_bootp_t;
+
+/* Function calling structures and constants */
+
+typedef struct s_PXENV_GET_CACHED_INFO {
+ pxenv_status_t Status;
+ uint16_t PacketType;
+#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1
+#define PXENV_PACKET_TYPE_DHCP_ACK 2
+#define PXENV_PACKET_TYPE_CACHED_REPLY 3
+ uint16_t BufferSize;
+ segoff16_t Buffer;
+ uint16_t BufferLimit;
+} __packed t_PXENV_GET_CACHED_INFO;
+
+typedef struct s_PXENV_START_UNDI {
+ pxenv_status_t Status;
+ uint16_t AX;
+ uint16_t BX;
+ uint16_t DX;
+ uint16_t DI;
+ uint16_t ES;
+} __packed t_PXENV_START_UNDI;
+
+typedef struct s_PXENV_STOP_UNDI {
+ pxenv_status_t Status;
+} __packed t_PXENV_STOP_UNDI;
+
+typedef struct s_PXENV_START_BASE {
+ pxenv_status_t Status;
+} __packed t_PXENV_START_BASE;
+
+typedef struct s_PXENV_STOP_BASE {
+ pxenv_status_t Status;
+} __packed t_PXENV_STOP_BASE;
+
+typedef struct s_PXENV_TFTP_OPEN {
+ pxenv_status_t Status;
+ in_addr_t ServerIPAddress;
+ in_addr_t GatewayIPAddress;
+ uint8_t FileName[128];
+ in_port_t TFTPPort;
+ uint16_t PacketSize;
+} __packed t_PXENV_TFTP_OPEN;
+
+typedef struct s_PXENV_TFTP_CLOSE {
+ pxenv_status_t Status;
+} __packed t_PXENV_TFTP_CLOSE;
+
+typedef struct s_PXENV_TFTP_READ {
+ pxenv_status_t Status;
+ uint16_t PacketNumber;
+ uint16_t BufferSize;
+ segoff16_t Buffer;
+} __packed t_PXENV_TFTP_READ;
+
+typedef struct s_PXENV_TFTP_READ_FILE {
+ pxenv_status_t Status;
+ uint8_t FileName[128];
+ uint32_t BufferSize;
+ void *Buffer;
+ in_addr_t ServerIPAddress;
+ in_addr_t GatewayIPAddress;
+ in_addr_t McastIPAddress;
+ in_port_t TFTPClntPort;
+ in_port_t TFTPSrvPort;
+ uint16_t TFTPOpenTimeOut;
+ uint16_t TFTPReopenDelay;
+} __packed t_PXENV_TFTP_READ_FILE;
+
+typedef struct s_PXENV_TFTP_GET_FSIZE {
+ pxenv_status_t Status;
+ in_addr_t ServerIPAddress;
+ in_addr_t GatewayIPAddress;
+ uint8_t FileName[128];
+ uint32_t FileSize;
+} __packed t_PXENV_TFTP_GET_FSIZE;
+
+typedef struct s_PXENV_UDP_OPEN {
+ pxenv_status_t status;
+ in_addr_t src_ip;
+} __packed t_PXENV_UDP_OPEN;
+
+typedef struct s_PXENV_UDP_CLOSE {
+ pxenv_status_t status;
+} __packed t_PXENV_UDP_CLOSE;
+
+typedef struct s_PXENV_UDP_WRITE {
+ pxenv_status_t status;
+ in_addr_t ip;
+ in_addr_t gw;
+ in_port_t src_port;
+ in_port_t dst_port;
+ uint16_t buffer_size;
+ segoff16_t buffer;
+} __packed t_PXENV_UDP_WRITE;
+
+typedef struct s_PXENV_UDP_READ {
+ pxenv_status_t status;
+ in_addr_t src_ip;
+ in_addr_t dest_ip;
+ in_port_t s_port;
+ in_port_t d_port;
+ uint16_t buffer_size;
+ segoff16_t buffer;
+} __packed t_PXENV_UDP_READ;
+
+typedef struct s_PXENV_UNDI_STARTUP {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_STARTUP;
+
+typedef struct s_PXENV_UNDI_CLEANUP {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_CLEANUP;
+
+typedef struct s_PXENV_UNDI_INITIALIZE {
+ pxenv_status_t Status;
+ void *ProtocolIni;
+ uint8_t reserved[8];
+} __packed t_PXENV_UNDI_INITIALIZE;
+
+#define MAXNUM_MCADDR 8
+typedef struct s_PXENV_UNDI_MCAST_ADDRESS {
+ uint16_t MCastAddrCount;
+ mac_addr_t McastAddr[MAXNUM_MCADDR];
+} __packed t_PXENV_UNDI_MCAST_ADDRESS;
+
+typedef struct s_PXENV_UNDI_RESET {
+ pxenv_status_t Status;
+ t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} __packed t_PXENV_UNDI_RESET;
+
+typedef struct s_PXENV_UNDI_SHUTDOWN {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_SHUTDOWN;
+
+typedef struct s_PXENV_UNDI_OPEN {
+ pxenv_status_t Status;
+ uint16_t OpenFlag;
+ uint16_t PktFilter;
+#define FLTR_DIRECTED 0x0001
+#define FLTR_BRDCST 0x0002
+#define FLTR_PRMSCS 0x0004
+#define FLTR_SRC_RTG 0x0008
+ t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} __packed t_PXENV_UNDI_OPEN;
+
+typedef struct s_PXENV_UNDI_CLOSE {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_CLOSE;
+
+typedef struct s_PXENV_UNDI_TRANSMIT {
+ pxenv_status_t Status;
+ uint8_t Protocol;
+#define P_UNKNOWN 0
+#define P_IP 1
+#define P_ARP 2
+#define P_RARP 3
+ uint8_t XmitFlag;
+#define XMT_DESTADDR 0x0000
+#define XMT_BROADCAST 0x0001
+ segoff16_t DestAddr;
+ segoff16_t TBD;
+ uint32_t Reserved[2];
+} __packed t_PXENV_UNDI_TRANSMIT;
+#define MAX_DATA_BLKS 8
+typedef struct s_PXENV_UNDI_TBD {
+ uint16_t ImmedLength;
+ segoff16_t Xmit;
+ uint16_t DataBlkCount;
+ struct DataBlk {
+ uint8_t TDPtrType;
+ uint8_t TDRsvdByte;
+ uint16_t TDDataLen;
+ segoff16_t TDDataPtr;
+ } DataBlock[MAX_DATA_BLKS];
+} __packed t_PXENV_UNDI_TBD;
+
+typedef struct s_PXENV_UNDI_SET_MCAST_ADDRESS {
+ pxenv_status_t Status;
+ t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} __packed t_PXENV_UNDI_SET_MCAST_ADDR;
+
+typedef struct s_PXENV_UNDI_SET_STATION_ADDRESS {
+ pxenv_status_t Status;
+ mac_addr_t StationAddress;
+} __packed t_PXENV_UNDI_SET_STATION_ADDR;
+
+typedef struct s_PXENV_UNDI_SET_PACKET_FILTER {
+ pxenv_status_t Status;
+ uint8_t filter;
+} __packed t_PXENV_UNDI_SET_PACKET_FILTER;
+
+typedef struct s_PXENV_UNDI_GET_INFORMATION {
+ pxenv_status_t Status;
+ uint16_t BaseIo;
+ uint16_t IntNumber;
+ uint16_t MaxTranUnit;
+ uint16_t HwType;
+#define ETHER_TYPE 1
+#define EXP_ETHER_TYPE 2
+#define IEEE_TYPE 6
+#define ARCNET_TYPE 7
+ uint16_t HwAddrLen;
+ mac_addr_t CurrentNodeAddress;
+ mac_addr_t PermNodeAddress;
+ uint16_t ROMAddress;
+ uint16_t RxBufCt;
+ uint16_t TxBufCt;
+} __packed t_PXENV_UNDI_GET_INFORMATION;
+
+typedef struct s_PXENV_UNDI_GET_STATISTICS {
+ pxenv_status_t Status;
+ uint32_t XmtGoodFrames;
+ uint32_t RcvGoodFrames;
+ uint32_t RcvCRCErrors;
+ uint32_t RcvResourceErrors;
+} __packed t_PXENV_UNDI_GET_STATISTICS;
+
+typedef struct s_PXENV_UNDI_CLEAR_STATISTICS {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_CLEAR_STATISTICS;
+
+typedef struct s_PXENV_UNDI_INITIATE_DIAGS {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_INITIATE_DIAGS;
+
+typedef struct s_PXENV_UNDI_FORCE_INTERRUPT {
+ pxenv_status_t Status;
+} __packed t_PXENV_UNDI_FORCE_INTERRUPT;
+
+typedef struct s_PXENV_UNDI_GET_MCAST_ADDRESS {
+ pxenv_status_t Status;
+ in_addr_t InetAddr;
+ mac_addr_t MediaAddr;
+} __packed t_PXENV_UNDI_GET_MCAST_ADDR;
+
+typedef struct s_PXENV_UNDI_GET_NIC_TYPE {
+ pxenv_status_t Status;
+ uint8_t NicType;
+#define PCI_NIC 2
+#define PnP_NIC 3
+#define CardBus_NIC 4
+ union {
+ struct {
+ uint16_t Vendor_ID;
+ uint16_t Dev_ID;
+ uint8_t Base_Class;
+ uint8_t Sub_Class;
+ uint8_t Prog_Intf;
+ uint8_t Rev;
+ uint16_t BusDevFunc;
+ uint16_t SubVendor_ID;
+ uint16_t SubDevice_ID;
+ } pci, cardbus;
+ struct {
+ uint32_t EISA_Dev_ID;
+ uint8_t Base_Class;
+ uint8_t Sub_Class;
+ uint8_t Prog_Intf;
+ uint16_t CardSelNum;
+ } __packed pnp;
+ } __packed info;
+} __packed t_PXENV_UNDI_GET_NIC_TYPE;
+
+typedef struct s_PXENV_UNDI_GET_IFACE_INFO {
+ pxenv_status_t Status;
+ uint8_t IfaceType[16];
+ uint32_t LinkSpeed;
+ uint32_t ServiceFlags;
+ uint32_t Reserved[4];
+} __packed t_PXENV_UNDI_GET_NDIS_INFO;
+
+typedef struct s_PXENV_UNDI_GET_STATE {
+#define PXE_UNDI_GET_STATE_STARTED 1
+#define PXE_UNDI_GET_STATE_INITIALIZED 2
+#define PXE_UNDI_GET_STATE_OPENED 3
+ pxenv_status_t Status;
+ uint8_t UNDIstate;
+} __packed t_PXENV_UNDI_GET_STATE;
+
+typedef struct s_PXENV_UNDI_ISR {
+ pxenv_status_t Status;
+ uint16_t FuncFlag;
+ uint16_t BufferLength;
+ uint16_t FrameLength;
+ uint16_t FrameHeaderLength;
+ segoff16_t Frame;
+ uint8_t ProtType;
+ uint8_t PktType;
+} __packed t_PXENV_UNDI_ISR;
+
+typedef struct s_PXENV_FILE_API_CHECK {
+ pxenv_status_t Status;
+ uint16_t Size;
+ uint32_t Magic;
+ uint32_t Provider;
+ uint32_t APIMask;
+ uint32_t Flags;
+} __packed t_PXENV_FILE_API_CHECK;
+
+typedef struct s_PXENV_FILE_READ {
+ pxenv_status_t Status;
+ uint16_t FileHandle;
+ uint16_t BufferSize;
+ segoff16_t Buffer;
+} __packed t_PXENV_FILE_READ;
+
+typedef struct s_PXENV_FILE_OPEN {
+ pxenv_status_t Status;
+ uint16_t FileHandle;
+ segoff16_t FileName;
+ uint32_t Reserved;
+} __packed t_PXENV_FILE_OPEN;
+
+typedef struct s_PXENV_GET_FILE_SIZE {
+ pxenv_status_t Status;
+ uint16_t FileHandle;
+ uint32_t FileSize;
+} __packed t_PXENV_GET_FILE_SIZE;
+
+typedef struct s_PXENV_UNLOAD_STACK {
+ pxenv_status_t Status;
+ uint8_t reserved[10];
+} __packed t_PXENV_UNLOAD_STACK;
+
+#define PXENV_UNDI_ISR_IN_START 1
+#define PXENV_UNDI_ISR_IN_PROCESS 2
+#define PXENV_UNDI_ISR_IN_GET_NEXT 3
+/* One of these will be returned for
+ PXENV_UNDI_ISR_IN_START */
+#define PXENV_UNDI_ISR_OUT_OURS 0
+#define PXENV_UNDI_USR_OUT_NOT_OURS 1
+/* One of these will be returned for
+ PXENV_UNDI_ISR_IN_PROCESS and
+ PXENV_UNDI_ISR_IN_GET_NEXT */
+#define PXENV_UNDI_ISR_OUT_DONE 0
+#define PXENV_UNDI_ISR_OUT_TRANSMIT 2
+#define PXENV_UNDI_ISR_OUT_RECEIVE 3
+#define PXENV_UNDI_ISR_OUT_BUSY 4
+
+/* Function numbers and error codes */
+
+#define PXENV_TFTP_OPEN 0x0020
+#define PXENV_TFTP_CLOSE 0x0021
+#define PXENV_TFTP_READ 0x0022
+#define PXENV_TFTP_READ_FILE 0x0023
+#define PXENV_TFTP_READ_FILE_PMODE 0x0024
+#define PXENV_TFTP_GET_FSIZE 0x0025
+
+#define PXENV_UDP_OPEN 0x0030
+#define PXENV_UDP_CLOSE 0x0031
+#define PXENV_UDP_READ 0x0032
+#define PXENV_UDP_WRITE 0x0033
+
+#define PXENV_START_UNDI 0x0000
+#define PXENV_UNDI_STARTUP 0x0001
+#define PXENV_UNDI_CLEANUP 0x0002
+#define PXENV_UNDI_INITIALIZE 0x0003
+#define PXENV_UNDI_RESET_NIC 0x0004
+#define PXENV_UNDI_SHUTDOWN 0x0005
+#define PXENV_UNDI_OPEN 0x0006
+#define PXENV_UNDI_CLOSE 0x0007
+#define PXENV_UNDI_TRANSMIT 0x0008
+#define PXENV_UNDI_SET_MCAST_ADDR 0x0009
+#define PXENV_UNDI_SET_STATION_ADDR 0x000A
+#define PXENV_UNDI_SET_PACKET_FILTER 0x000B
+#define PXENV_UNDI_GET_INFORMATION 0x000C
+#define PXENV_UNDI_GET_STATISTICS 0x000D
+#define PXENV_UNDI_CLEAR_STATISTICS 0x000E
+#define PXENV_UNDI_INITIATE_DIAGS 0x000F
+#define PXENV_UNDI_FORCE_INTERRUPT 0x0010
+#define PXENV_UNDI_GET_MCAST_ADDR 0x0011
+#define PXENV_UNDI_GET_NIC_TYPE 0x0012
+#define PXENV_UNDI_GET_IFACE_INFO 0x0013
+#define PXENV_UNDI_ISR 0x0014
+#define PXENV_STOP_UNDI 0x0015 /* Overlap...? */
+#define PXENV_UNDI_GET_STATE 0x0015 /* Overlap...? */
+
+#define PXENV_UNLOAD_STACK 0x0070
+#define PXENV_GET_CACHED_INFO 0x0071
+#define PXENV_RESTART_DHCP 0x0072
+#define PXENV_RESTART_TFTP 0x0073
+#define PXENV_MODE_SWITCH 0x0074
+#define PXENV_START_BASE 0x0075
+#define PXENV_STOP_BASE 0x0076
+
+/* gPXE extensions... */
+#define PXENV_FILE_OPEN 0x00e0
+#define PXENV_FILE_CLOSE 0x00e1
+#define PXENV_FILE_SELECT 0x00e2
+#define PXENV_FILE_READ 0x00e3
+#define PXENV_GET_FILE_SIZE 0x00e4
+#define PXENV_FILE_EXEC 0x00e5
+#define PXENV_FILE_API_CHECK 0x00e6
+
+/* Exit codes */
+#define PXENV_EXIT_SUCCESS 0x0000
+#define PXENV_EXIT_FAILURE 0x0001
+
+/* Status codes */
+#define PXENV_STATUS_SUCCESS 0x00
+#define PXENV_STATUS_FAILURE 0x01
+#define PXENV_STATUS_BAD_FUNC 0x02
+#define PXENV_STATUS_UNSUPPORTED 0x03
+#define PXENV_STATUS_KEEP_UNDI 0x04
+#define PXENV_STATUS_KEEP_ALL 0x05
+#define PXENV_STATUS_OUT_OF_RESOURCES 0x06
+#define PXENV_STATUS_ARP_TIMEOUT 0x11
+#define PXENV_STATUS_UDP_CLOSED 0x18
+#define PXENV_STATUS_UDP_OPEN 0x19
+#define PXENV_STATUS_TFTP_CLOSED 0x1a
+#define PXENV_STATUS_TFTP_OPEN 0x1b
+#define PXENV_STATUS_MCOPY_PROBLEM 0x20
+#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21
+#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22
+#define PXENV_STATUS_BIS_INIT_FAILURE 0x23
+#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24
+#define PXENV_STATUS_BIS_GBOA_FAILURE 0x25
+#define PXENV_STATUS_BIS_FREE_FAILURE 0x26
+#define PXENV_STATUS_BIS_GSI_FAILURE 0x27
+#define PXENV_STATUS_BIS_BAD_CKSUM 0x28
+#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30
+#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32
+
+#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33
+#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35
+#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36
+#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38
+#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39
+#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3a
+#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3b
+#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3c
+#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3d
+#define PXENV_STATUS_TFTP_NO_FILESIZE 0x3e
+#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3f
+#define PXENV_STATUS_DHCP_TIMEOUT 0x51
+#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52
+#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53
+#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54
+#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60
+#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61
+#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64
+#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65
+#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66
+#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67
+#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68
+#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69
+#define PXENV_STATUS_UNDI_INVALID_STATE 0x6a
+#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6b
+#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6c
+#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74
+#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76
+#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77
+#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78
+#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79
+#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xa0
+#define PXENV_STATUS_BINL_NO_PXE_SERVER 0xa1
+#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xa2
+#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xa3
+#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xb0
+#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xc0
+#define PXENV_STATUS_LOADER_NO_BC_ROMID 0xc1
+#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xc2
+#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xc3
+#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xc4
+#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xc5
+#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xc6
+#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xc8
+#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xc9
+#define PXENV_STATUS_LOADER_UNDI_START 0xca
+#define PXENV_STATUS_LOADER_BC_START 0xcb
+
+#endif /* _SYSLINUX_PXE_API_H */
diff --git a/com32/lib/MCONFIG b/com32/lib/MCONFIG
index 1ae83bc7..44278bd1 100644
--- a/com32/lib/MCONFIG
+++ b/com32/lib/MCONFIG
@@ -2,9 +2,20 @@
include $(topdir)/MCONFIG
-GCCOPT := $(call gcc_ok,-std=gnu99,) \
- $(call gcc_ok,-m32,) \
- $(call gcc_ok,-fno-stack-protector,) \
+GCCOPT := $(call gcc_ok,-std=gnu99,)
+GCCOPT += $(call gcc_ok,-m32,)
+GCCOPT += $(call gcc_ok,-fno-stack-protector,)
+GCCOPT += $(call gcc_ok,-fwrapv,)
+GCCOPT += $(call gcc_ok,-freg-struct-return,)
+GCCOPT += $(call gcc_ok,-fPIE,-fPIC)
+GCCOPT += $(call gcc_ok,-fno-exceptions,)
+GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,)
+GCCOPT += $(call gcc_ok,-fno-strict-aliasing,)
+GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0)
+GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0)
+GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0)
+GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0)
+GCCOPT += $(call gcc_ok,-mpreferred-stack-boundary=2,)
INCLUDE = -I.
STRIP = strip --strip-all -R .comment -R .note
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index ff5887b0..e66b6560 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -17,7 +17,7 @@ LIBOBJS = \
exit.o onexit.o \
perror.o printf.o puts.o qsort.o realloc.o seed48.o snprintf.o \
sprintf.o srand48.o sscanf.o stack.o strcasecmp.o strcat.o \
- strchr.o strcmp.o strcpy.o strpcpy.o strdup.o strlen.o \
+ strchr.o strcmp.o strcpy.o strdup.o strlen.o \
strerror.o strnlen.o \
strncasecmp.o strncat.o strncmp.o strncpy.o strndup.o \
stpcpy.o stpncpy.o \
@@ -40,6 +40,7 @@ LIBOBJS = \
sys/entry.o sys/exit.o sys/argv.o sys/times.o \
sys/fileinfo.o sys/opendev.o sys/read.o sys/write.o sys/ftell.o \
sys/close.o sys/open.o sys/fileread.o sys/fileclose.o \
+ sys/openmem.o \
sys/isatty.o sys/fstat.o \
\
sys/zfile.o sys/zfopen.o \
diff --git a/com32/lib/closedir.c b/com32/lib/closedir.c
index a2d11105..f4de67ae 100644
--- a/com32/lib/closedir.c
+++ b/com32/lib/closedir.c
@@ -14,17 +14,17 @@
int closedir(DIR * dir)
{
- int rv;
- com32sys_t regs;
- if (dir == NULL) {
- rv = 0;
- } else {
- memset(&regs, 0, sizeof regs); /* ?Needed? */
+ int rv = -1;
+
+ if (dir) {
+ com32sys_t regs;
+ memset(&regs, 0, sizeof regs);
regs.eax.w[0] = 0x0022;
- regs.esi.w[0] = dir->dd_fd;
+ regs.esi.l = (uint32_t)dir;
__com32.cs_intcall(0x22, &regs, &regs);
- free(dir); /* garbage collection? */
+ free(dir);
rv = 0;
}
+
return rv;
}
diff --git a/com32/lib/com32.ld b/com32/lib/com32.ld
index 36d5b6ed..37ee46cf 100644
--- a/com32/lib/com32.ld
+++ b/com32/lib/com32.ld
@@ -11,8 +11,9 @@ ENTRY(_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
- . = 0x101000;
+ . = 0;
PROVIDE (__executable_start = .);
+ PROVIDE (_stext = .);
.init :
{
@@ -28,40 +29,52 @@ SECTIONS
{
KEEP (*(.fini))
} =0x90909090
- PROVIDE (__etext = .);
PROVIDE (_etext = .);
- PROVIDE (etext = .);
+
+ __rodata_start = .;
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
+ __rodata_end = .;
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
the linker would then create the section even if it turns out to
be empty, which isn't pretty. */
. = ALIGN(4);
- PROVIDE (__preinit_array_start = .);
- .preinit_array : { *(.preinit_array) }
- PROVIDE (__preinit_array_end = .);
- PROVIDE (__init_array_start = .);
- .init_array : { *(.init_array) }
- PROVIDE (__init_array_end = .);
- PROVIDE (__fini_array_start = .);
- .fini_array : { *(.fini_array) }
- PROVIDE (__fini_array_end = .);
- PROVIDE (__ctors_start = .);
- .ctors :
- {
+ .preinit_array : {
+ PROVIDE (__preinit_array_start = .);
+ *(.preinit_array)
+ PROVIDE (__preinit_array_end = .);
+ }
+ .init_array : {
+ PROVIDE (__init_array_start = .);
+ *(.init_array)
+ PROVIDE (__init_array_end = .);
+ }
+ .fini_array : {
+ PROVIDE (__fini_array_start = .);
+ *(.fini_array)
+ PROVIDE (__fini_array_end = .);
+ }
+ .ctors : {
+ PROVIDE (__ctors_start = .);
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
+ PROVIDE (__ctors_end = .);
}
- PROVIDE (__ctors_end = .);
- PROVIDE (__dtors_start = .);
- .dtors :
- {
+ .dtors : {
+ PROVIDE (__dtors_start = .);
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
+ PROVIDE (__dtors_end = .);
+ }
+
+ .got : {
+ PROVIDE (__got_start = .);
+ KEEP (*(.got.plt))
+ KEEP (*(.got))
+ PROVIDE (__got_end = .);
}
- PROVIDE (__dtors_end = .);
/* Adjust the address for the data segment. Avoid mixing code and
data within same 128-byte chunk. */
@@ -69,12 +82,14 @@ SECTIONS
.data :
{
- *(.data .data.* .gnu.linkonce.d.*)
+ _sdata = .;
+ KEEP(*(.data .data.* .gnu.linkonce.d.*))
SORT(CONSTRUCTORS)
+ *(.data1)
+ . = ALIGN(4);
+ _edata = .;
}
- .data1 : { *(.data1) }
- _edata = .;
- PROVIDE (edata = .);
+
__bss_start = .;
.bss :
{
@@ -84,11 +99,10 @@ SECTIONS
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
- . = ALIGN(32 / 8);
+ . = ALIGN(4);
}
- . = ALIGN(32 / 8);
+ . = ALIGN(4);
_end = .;
- PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
diff --git a/com32/lib/opendir.c b/com32/lib/opendir.c
index 21fe91d4..c5e9aa05 100644
--- a/com32/lib/opendir.c
+++ b/com32/lib/opendir.c
@@ -14,11 +14,9 @@
DIR *opendir(const char *pathname)
{
- DIR *newdir;
+ DIR *newdir = NULL;
com32sys_t regs;
-
- newdir = NULL;
-
+
strlcpy(__com32.cs_bounce, pathname, __com32.cs_bounce_size);
regs.eax.w[0] = 0x0020;
@@ -26,16 +24,13 @@ DIR *opendir(const char *pathname)
regs.es = SEG(__com32.cs_bounce);
__com32.cs_intcall(0x22, &regs, &regs);
-
+
if (!(regs.eflags.l & EFLAGS_CF)) {
- /* Initialization: malloc() then zero */
- newdir = calloc(1, sizeof(DIR));
- strcpy(newdir->dd_name, pathname);
- newdir->dd_fd = regs.esi.w[0];
- newdir->dd_sect = regs.eax.l;
- newdir->dd_stat = 0;
+ /* Initialization: malloc() then zero */
+ newdir = calloc(1, sizeof(DIR));
+ newdir->dd_dir = (struct file *)regs.eax.l;
}
-
+
/* We're done */
return newdir;
}
diff --git a/com32/lib/readdir.c b/com32/lib/readdir.c
index 3737d1ad..d59ad3a2 100644
--- a/com32/lib/readdir.c
+++ b/com32/lib/readdir.c
@@ -16,42 +16,12 @@ struct dirent *readdir(DIR * dir)
{
struct dirent *newde;
com32sys_t regs;
-
- newde = NULL;
- if ((dir != NULL) && (dir->dd_fd != 0) && (dir->dd_stat >= 0)) {
- memset(__com32.cs_bounce, 0, 32);
- memset(&regs, 0, sizeof(regs));
-
- regs.eax.w[0] = 0x0021;
- regs.esi.w[0] = dir->dd_fd;
- regs.edi.w[0] = OFFS(__com32.cs_bounce);
- regs.es = SEG(__com32.cs_bounce);
-
- __com32.cs_intcall(0x22, &regs, &regs);
-
-#if 0
- /* Don't do this as we won't be able to rewind. */
- dir->dd_fd = regs.esi.w[0]; /* Shouldn't be needed? */
-#endif
- if ((!(regs.eflags.l & EFLAGS_CF)) && (regs.esi.w[0] != 0)) {
- newde = calloc(1, sizeof(newde));
- if (newde != NULL) {
- strcpy(newde->d_name, __com32.cs_bounce);
- newde->d_mode = regs.edx.b[0];
- newde->d_size = regs.eax.l;
- newde->d_ino = regs.ebx.l;
- dir->dd_stat = 1;
- } else {
- dir->dd_stat = -2;
- errno = ENOMEM;
- }
- } else {
- dir->dd_stat = -1;
- errno = EIO; /* Is this the right nmber? */
- }
- } else {
- errno = EBADF;
- }
+
+ memset(&regs, 0, sizeof(regs));
+ regs.eax.w[0] = 0x0021;
+ regs.esi.l = (uint32_t)dir;
+ __com32.cs_intcall(0x22, &regs, &regs);
+ newde = (struct dirent *)(regs.eax.l);
return newde;
}
diff --git a/com32/lib/strpcpy.c b/com32/lib/strpcpy.c
deleted file mode 100644
index a4fd2a06..00000000
--- a/com32/lib/strpcpy.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * strpcpy.c
- *
- * strpcpy() - strcpy() which returns a pointer to the final null
- */
-
-#include <string.h>
-
-char *strpcpy(char *dst, const char *src)
-{
- char *q = dst;
- const char *p = src;
- char ch;
-
- do {
- *q++ = ch = *p++;
- } while (ch);
-
- return q - 1;
-}
diff --git a/com32/lib/sys/entry.S b/com32/lib/sys/entry.S
index 53bf2ecb..a3a1eaa8 100644
--- a/com32/lib/sys/entry.S
+++ b/com32/lib/sys/entry.S
@@ -36,54 +36,78 @@
.globl _start
.type _start, @function
_start:
- /* This first instruction acts as COM32 magic number */
- movl $0x21cd4cff,%eax
+ /* This first instruction acts as COM32R magic number */
+ movl $0x21cd4cfe,%eax
/* Upwards string operations */
cld
+ /* Find our own location */
+ call 1f
+1: popl %ebx
+ addl $_GLOBAL_OFFSET_TABLE_ + (. - 1b), %ebx
+
+ /* Process relocations (which overlay the .bss segment) */
+ leal _edata@GOTOFF(%ebx),%esi
+ leal _start@GOTOFF(%ebx),%edx
+2: lodsl
+ andl %eax,%eax
+ jz 3f
+ addl %edx,(%eax,%edx)
+ jmp 2b
+3:
+ /* Relocate the GOT (is this right?) */
+ leal __got_start@GOTOFF(%ebx),%esi
+ leal __got_end@GOTOFF(%ebx),%edi
+4:
+ addl %edx,(%esi)
+ addl $4,%esi
+ cmpl %edi,%esi
+ jb 4b
+
/* Zero the .bss segment */
xorl %eax,%eax
- movl $__bss_start,%edi # Symbol provided by linker
- movl $_end+3,%ecx # Symbol provided by linker
+ leal __bss_start@GOTOFF(%ebx),%edi
+ leal _end+3@GOTOFF(%ebx),%ecx
subl %edi,%ecx
shrl $2,%ecx
rep ; stosl
/* Copy COM32 invocation parameters */
leal 4(%esp),%esi # Argument list
- movl $__com32,%edi
+ leal __com32@GOTOFF(%ebx),%edi
movl $(COM32_ARGS),%ecx
movl %esp,-4(%edi) # Save the initial stack ptr
cmpl (%esi),%ecx
- jbe 1f
+ jbe 5f
movl (%esi),%ecx
-1: inc %ecx # Copy the argument count, too
+5: inc %ecx # Copy the argument count, too
rep ; movsl
/* Parse the command line (assumes REGPARM) */
- movl __com32+4,%edx # Command line
- pushl %edx # Make space for argv
+ movl __com32+4@GOTOFF(%ebx),%edx # Command line
+ pushl %edx # Make space for argv
movl %esp,%eax
call __parse_argv
- pushl %eax # Save argc
+ pushl %eax # Save argc
/* Look for library initialization functions */
- movl $__ctors_start, %esi
-2:
- cmpl $__ctors_end, %esi
- jae 3f
+ leal __ctors_start@GOTOFF(%ebx),%esi
+ leal __ctors_end@GOTOFF(%ebx),%edi
+6:
+ cmpl %edi,%esi
+ jae 7f
call *(%esi)
addl $4,%esi
- jmp 2b
+ jmp 6b
/*
* Actually run main. This assumes REGPARM is used!!!!
*/
-3:
+7:
popl %eax # argc
popl %edx # argv
call main
- call *(__exit_handler)
+ call *__exit_handler@GOTOFF(%ebx)
hlt
.size _start, .-_start
diff --git a/com32/lib/sys/file.h b/com32/lib/sys/file.h
index fff91b19..66192fbf 100644
--- a/com32/lib/sys/file.h
+++ b/com32/lib/sys/file.h
@@ -56,18 +56,18 @@ struct input_dev {
uint16_t dev_magic; /* Magic number */
uint16_t flags; /* Flags */
int fileflags; /* Permitted file flags */
- ssize_t(*read) (struct file_info *, void *, size_t);
- int (*close) (struct file_info *);
- int (*open) (struct file_info *);
+ ssize_t (*read)(struct file_info *, void *, size_t);
+ int (*close)(struct file_info *);
+ int (*open)(struct file_info *);
};
struct output_dev {
uint16_t dev_magic; /* Magic number */
uint16_t flags; /* Flags */
int fileflags;
- ssize_t(*write) (struct file_info *, const void *, size_t);
- int (*close) (struct file_info *);
- int (*open) (struct file_info *);
+ ssize_t (*write)(struct file_info *, const void *, size_t);
+ int (*close)(struct file_info *);
+ int (*open)(struct file_info *);
const struct output_dev *fallback; /* Fallback option for certain consoles */
};
diff --git a/com32/lib/sys/open.c b/com32/lib/sys/open.c
index aac5e6f4..0bd490c7 100644
--- a/com32/lib/sys/open.c
+++ b/com32/lib/sys/open.c
@@ -41,7 +41,7 @@
extern ssize_t __file_read(struct file_info *, void *, size_t);
extern int __file_close(struct file_info *);
-static const struct input_dev file_dev = {
+const struct input_dev __file_dev = {
.dev_magic = __DEV_MAGIC,
.flags = __DEV_FILE | __DEV_INPUT,
.fileflags = O_RDONLY,
@@ -56,7 +56,7 @@ int open(const char *pathname, int flags, ...)
int fd;
struct file_info *fp;
- fd = opendev(&file_dev, NULL, flags);
+ fd = opendev(&__file_dev, NULL, flags);
if (fd < 0)
return -1;
@@ -79,7 +79,7 @@ int open(const char *pathname, int flags, ...)
{
uint16_t blklg2;
- asm("bsrw %1,%0" : "=r" (blklg2) : "rm" (regs.ecx.w[0]));
+ asm("bsrw %1,%0" : "=r" (blklg2) : "rm" (regs.ecx.w[0]));
fp->i.blocklg2 = blklg2;
}
fp->i.length = regs.eax.l;
diff --git a/com32/lib/sys/openmem.c b/com32/lib/sys/openmem.c
new file mode 100644
index 00000000..33b8de0d
--- /dev/null
+++ b/com32/lib/sys/openmem.c
@@ -0,0 +1,61 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <errno.h>
+#include <com32.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "file.h"
+
+/*
+ * openmem.c
+ *
+ * Open a chunk of memory as if it was a file
+ */
+
+const struct input_dev __file_dev;
+
+int openmem(const void *base, size_t len, int flags)
+{
+ int fd;
+ struct file_info *fp;
+
+ fd = opendev(&__file_dev, NULL, flags);
+
+ if (fd < 0)
+ return -1;
+
+ fp = &__file_info[fd];
+
+ fp->i.length = fp->i.nbytes = len;
+ fp->i.datap = (void *)base;
+ fp->i.filedes = 0; /* No actual file */
+ fp->i.offset = 0;
+
+ return fd;
+}
diff --git a/com32/mboot/mboot.c b/com32/mboot/mboot.c
index 8425e068..a0b55628 100644
--- a/com32/mboot/mboot.c
+++ b/com32/mboot/mboot.c
@@ -135,7 +135,7 @@ static int get_modules(char **argv, struct module_data **mdp)
char *p;
mp->cmdline = p = malloc(arglen);
for (; *argp && strcmp(*argp, module_separator); argp++) {
- p = strpcpy(p, *argp);
+ p = stpcpy(p, *argp);
*p++ = ' ';
}
*--p = '\0';
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index 35906587..b7d6212e 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -21,7 +21,8 @@ include ../MCONFIG
MODULES = chain.c32 config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \
disk.c32 pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 \
meminfo.c32 sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 \
- kbdmap.c32 cmd.c32 vpdtest.c32 gpxecmd.c32 ifcpu.c32
+ kbdmap.c32 cmd.c32 vpdtest.c32 host.c32 dir.c32 gpxecmd.c32 \
+ ifcpu.c32
TESTFILES =
diff --git a/com32/modules/dir.c b/com32/modules/dir.c
new file mode 100644
index 00000000..913c2ca7
--- /dev/null
+++ b/com32/modules/dir.c
@@ -0,0 +1,35 @@
+/*
+ * A dir test module
+ */
+#include <stdio.h>
+#include <console.h>
+#include <string.h>
+#include <com32.h>
+#include <dirent.h>
+
+int main(int argc, char *argv[])
+{
+ DIR *dir;
+ struct dirent *de;
+
+ openconsole(&dev_null_r, &dev_stdcon_w);
+
+ if (argc != 2) {
+ printf("Usage: dir direcotry\n");
+ return 0;
+ }
+
+ dir = opendir(argv[1]);
+ if (dir == NULL) {
+ printf("Unable to read dir: %s\n", argv[1]);
+ return 0;
+ }
+
+ while ((de = readdir(dir)) != NULL)
+ printf("%s\n", de->d_name);
+
+ closedir(dir);
+
+ return 0;
+}
+
diff --git a/com32/modules/host.c b/com32/modules/host.c
new file mode 100644
index 00000000..94ca876d
--- /dev/null
+++ b/com32/modules/host.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include <console.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <com32.h>
+
+static struct in_addr dnsresolve(const char *hostname)
+{
+ com32sys_t regs;
+ struct in_addr addr;
+
+ strcpy(__com32.cs_bounce, hostname);
+
+ regs.eax.w[0] = 0x0010;
+ regs.es = SEG(__com32.cs_bounce);
+ regs.ebx.w[0] = OFFS(__com32.cs_bounce);
+ __intcall(0x22, &regs, &regs);
+
+ addr.s_addr = regs.eax.l;
+ return addr;
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ struct in_addr addr;
+
+ openconsole(&dev_null_r, &dev_stdcon_w);
+
+ for (i = 1; i < argc; i++) {
+ addr = dnsresolve(argv[i]);
+
+ printf("%-39s %08X %d.%d.%d.%d\n",
+ argv[i], ntohl(addr.s_addr),
+ ((uint8_t *)&addr.s_addr)[0],
+ ((uint8_t *)&addr.s_addr)[1],
+ ((uint8_t *)&addr.s_addr)[2],
+ ((uint8_t *)&addr.s_addr)[3]);
+ }
+
+ return 0;
+}
diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c
index 720d8644..13e8ffbd 100644
--- a/com32/rosh/rosh.c
+++ b/com32/rosh/rosh.c
@@ -389,12 +389,12 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr)
ROSH_DEBUG("--'%s'\n", filestr);
}
fd = open(filestr, O_RDONLY);
- if (fd != -1) {
+ if (fd == -1) {
status = fstat(fd, &fdstat);
- if (S_ISDIR(fdstat.st_mode)) {
+ if (S_ISDIR(fdstat.st_mode)) {
ROSH_DEBUG("PATH '%s' is a directory\n", ifilstr);
d = fdopendir(fd);
- de = readdir(d);
+ de = readdir(d);
while (de != NULL) {
#ifdef DO_DEBUG
filestr2[0] = 0;
@@ -423,19 +423,18 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr)
}
} else {
#ifdef __COM32__
- if (filestr[strlen(filestr) - 1] == SEP) {
+ if (filestr[strlen(filestr) - 1] == SEP) {
/* Directory */
filepos = 0;
- d = opendir(filestr);
+ d = opendir(filestr);
if (d != NULL) {
- printf("DIR:'%s' %8d %8d\n", d->dd_name, d->dd_fd,
- d->dd_sect);
+ //printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect, d->dd_offset);
de = readdir(d);
while (de != NULL) {
filepos++;
#ifdef DO_DEBUG
// if (strlen(de->d_name) > 25) de->d_name[25] = 0;
- switch (de->d_mode) {
+ switch (de->d_type) {
case 16:
ty = 'D';
break;
@@ -445,8 +444,6 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr)
default:
ty = '*';
}
- printf("@%8d:%8d:%4d ", (int)de->d_ino, (int)de->d_size,
- de->d_mode);
#endif /* DO_DEBUG */
// printf("%s\n", de->d_name);
printf("'%s'\n", de->d_name);
@@ -458,7 +455,6 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr)
de = readdir(d);
// if(filepos>15){ de = NULL; printf("Force Break\n");}
}
- printf("Dir.dd_fd: '%8d'\n", d->dd_fd);
closedir(d);
} else {
rosh_error(0, "dir:NULL", filestr);
diff --git a/com32/rosh/rosh.h b/com32/rosh/rosh.h
index 64b0564c..0c41bac9 100644
--- a/com32/rosh/rosh.h
+++ b/com32/rosh/rosh.h
@@ -47,6 +47,8 @@
#error SYSLINUX (I believe) requires __GNUC__
#endif /* __GNUC__ */
+#define DO_DEBUG 1
+
#ifdef DO_DEBUG
#define ROSH_DEBUG(f, ...) printf (f, ## __VA_ARGS__)
#ifdef DO_DEBUG2
diff --git a/com32/tools/.gitignore b/com32/tools/.gitignore
new file mode 100644
index 00000000..b5397de4
--- /dev/null
+++ b/com32/tools/.gitignore
@@ -0,0 +1 @@
+/relocs
diff --git a/com32/tools/Makefile b/com32/tools/Makefile
new file mode 100644
index 00000000..3665f84b
--- /dev/null
+++ b/com32/tools/Makefile
@@ -0,0 +1,30 @@
+## -*- makefile -*- ------------------------------------------------------
+##
+## Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
+##
+## 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., 53 Temple Place Ste 330,
+## Boston MA 02111-1307, USA; either version 2 of the License, or
+## (at your option) any later version; incorporated herein by reference.
+##
+## -----------------------------------------------------------------------
+
+topdir = ../..
+include $(topdir)/MCONFIG.build
+
+BINS = relocs
+
+all : $(BINS)
+
+relocs : relocs.o
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+tidy dist clean spotless:
+ rm -f $(BINS)
+ rm -f *.o *.a .*.d
+ rm -f */*.o */*.a */.*.d
+
+installer:
+
+-include .*.d */.*.d
diff --git a/com32/tools/relocs.c b/com32/tools/relocs.c
new file mode 100644
index 00000000..be57bf7e
--- /dev/null
+++ b/com32/tools/relocs.c
@@ -0,0 +1,693 @@
+/*
+ * This file is taken from the Linux kernel and is distributed under GPL v2.
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <elf.h>
+#include <byteswap.h>
+#define USE_BSD
+#include <endian.h>
+#include <regex.h>
+#include <sys/types.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+static Elf32_Ehdr ehdr;
+static unsigned long reloc_count, reloc_idx;
+static unsigned long *relocs;
+
+struct section {
+ Elf32_Shdr shdr;
+ struct section *link;
+ Elf32_Sym *symtab;
+ Elf32_Rel *reltab;
+ char *strtab;
+};
+static struct section *secs;
+
+static void die(char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(1);
+}
+
+/*
+ * Following symbols have been audited. Don't warn user about
+ * absolute relocations present w.r.t these symbols.
+ */
+
+/* True absolute relocations */
+
+static const char safe_abs_regex[] =
+"^(__.*_len|__.*_dwords)$";
+static regex_t safe_abs_regex_c;
+
+static int is_safe_abs_reloc(const char *sym_name)
+{
+ return !regexec(&safe_abs_regex_c, sym_name, 0, NULL, 0);
+}
+
+/* These are relative even though the linker marks them absolute */
+
+static const char safe_rel_regex[] =
+"^(__.*_start|__.*_end|_end|_[se](text|data))$";
+static regex_t safe_rel_regex_c;
+
+static int is_safe_rel_reloc(const char *sym_name)
+{
+ return !regexec(&safe_rel_regex_c, sym_name, 0, NULL, 0);
+}
+
+static void regex_init(void)
+{
+ char errbuf[128];
+ int err;
+
+ err = regcomp(&safe_abs_regex_c, safe_abs_regex,
+ REG_EXTENDED|REG_NOSUB);
+ if (err) {
+ regerror(err, &safe_abs_regex_c, errbuf, sizeof errbuf);
+ die("%s", errbuf);
+ }
+
+ err = regcomp(&safe_rel_regex_c, safe_rel_regex,
+ REG_EXTENDED|REG_NOSUB);
+ if (err) {
+ regerror(err, &safe_rel_regex_c, errbuf, sizeof errbuf);
+ die("%s", errbuf);
+ }
+}
+
+static const char *sym_type(unsigned type)
+{
+ static const char *type_name[] = {
+#define SYM_TYPE(X) [X] = #X
+ SYM_TYPE(STT_NOTYPE),
+ SYM_TYPE(STT_OBJECT),
+ SYM_TYPE(STT_FUNC),
+ SYM_TYPE(STT_SECTION),
+ SYM_TYPE(STT_FILE),
+ SYM_TYPE(STT_COMMON),
+ SYM_TYPE(STT_TLS),
+#undef SYM_TYPE
+ };
+ const char *name = "unknown sym type name";
+ if (type < ARRAY_SIZE(type_name)) {
+ name = type_name[type];
+ }
+ return name;
+}
+
+static const char *sym_bind(unsigned bind)
+{
+ static const char *bind_name[] = {
+#define SYM_BIND(X) [X] = #X
+ SYM_BIND(STB_LOCAL),
+ SYM_BIND(STB_GLOBAL),
+ SYM_BIND(STB_WEAK),
+#undef SYM_BIND
+ };
+ const char *name = "unknown sym bind name";
+ if (bind < ARRAY_SIZE(bind_name)) {
+ name = bind_name[bind];
+ }
+ return name;
+}
+
+static const char *sym_visibility(unsigned visibility)
+{
+ static const char *visibility_name[] = {
+#define SYM_VISIBILITY(X) [X] = #X
+ SYM_VISIBILITY(STV_DEFAULT),
+ SYM_VISIBILITY(STV_INTERNAL),
+ SYM_VISIBILITY(STV_HIDDEN),
+ SYM_VISIBILITY(STV_PROTECTED),
+#undef SYM_VISIBILITY
+ };
+ const char *name = "unknown sym visibility name";
+ if (visibility < ARRAY_SIZE(visibility_name)) {
+ name = visibility_name[visibility];
+ }
+ return name;
+}
+
+static const char *rel_type(unsigned type)
+{
+ static const char *type_name[] = {
+#define REL_TYPE(X) [X] = #X
+ REL_TYPE(R_386_NONE),
+ REL_TYPE(R_386_32),
+ REL_TYPE(R_386_PC32),
+ REL_TYPE(R_386_GOT32),
+ REL_TYPE(R_386_PLT32),
+ REL_TYPE(R_386_COPY),
+ REL_TYPE(R_386_GLOB_DAT),
+ REL_TYPE(R_386_JMP_SLOT),
+ REL_TYPE(R_386_RELATIVE),
+ REL_TYPE(R_386_GOTOFF),
+ REL_TYPE(R_386_GOTPC),
+#undef REL_TYPE
+ };
+ const char *name = NULL;
+ if (type < ARRAY_SIZE(type_name))
+ name = type_name[type];
+ if (!name)
+ name = "unknown";
+ return name;
+}
+
+static const char *sec_name(unsigned shndx)
+{
+ const char *sec_strtab;
+ const char *name;
+ sec_strtab = secs[ehdr.e_shstrndx].strtab;
+ name = "<noname>";
+ if (shndx < ehdr.e_shnum) {
+ name = sec_strtab + secs[shndx].shdr.sh_name;
+ }
+ else if (shndx == SHN_ABS) {
+ name = "ABSOLUTE";
+ }
+ else if (shndx == SHN_COMMON) {
+ name = "COMMON";
+ }
+ return name;
+}
+
+static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym)
+{
+ const char *name;
+ name = "<noname>";
+ if (sym->st_name) {
+ name = sym_strtab + sym->st_name;
+ }
+ else {
+ name = sec_name(secs[sym->st_shndx].shdr.sh_name);
+ }
+ return name;
+}
+
+
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define le16_to_cpu(val) (val)
+#define le32_to_cpu(val) (val)
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+#define le16_to_cpu(val) bswap_16(val)
+#define le32_to_cpu(val) bswap_32(val)
+#endif
+
+static uint16_t elf16_to_cpu(uint16_t val)
+{
+ return le16_to_cpu(val);
+}
+
+static uint32_t elf32_to_cpu(uint32_t val)
+{
+ return le32_to_cpu(val);
+}
+
+static void read_ehdr(FILE *fp)
+{
+ if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) {
+ die("Cannot read ELF header: %s\n",
+ strerror(errno));
+ }
+ if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) {
+ die("No ELF magic\n");
+ }
+ if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) {
+ die("Not a 32 bit executable\n");
+ }
+ if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) {
+ die("Not a LSB ELF executable\n");
+ }
+ if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
+ die("Unknown ELF version\n");
+ }
+ /* Convert the fields to native endian */
+ ehdr.e_type = elf16_to_cpu(ehdr.e_type);
+ ehdr.e_machine = elf16_to_cpu(ehdr.e_machine);
+ ehdr.e_version = elf32_to_cpu(ehdr.e_version);
+ ehdr.e_entry = elf32_to_cpu(ehdr.e_entry);
+ ehdr.e_phoff = elf32_to_cpu(ehdr.e_phoff);
+ ehdr.e_shoff = elf32_to_cpu(ehdr.e_shoff);
+ ehdr.e_flags = elf32_to_cpu(ehdr.e_flags);
+ ehdr.e_ehsize = elf16_to_cpu(ehdr.e_ehsize);
+ ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize);
+ ehdr.e_phnum = elf16_to_cpu(ehdr.e_phnum);
+ ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize);
+ ehdr.e_shnum = elf16_to_cpu(ehdr.e_shnum);
+ ehdr.e_shstrndx = elf16_to_cpu(ehdr.e_shstrndx);
+
+ if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) {
+ die("Unsupported ELF header type\n");
+ }
+ if (ehdr.e_machine != EM_386) {
+ die("Not for x86\n");
+ }
+ if (ehdr.e_version != EV_CURRENT) {
+ die("Unknown ELF version\n");
+ }
+ if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) {
+ die("Bad Elf header size\n");
+ }
+ if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) {
+ die("Bad program header entry\n");
+ }
+ if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) {
+ die("Bad section header entry\n");
+ }
+ if (ehdr.e_shstrndx >= ehdr.e_shnum) {
+ die("String table index out of bounds\n");
+ }
+}
+
+static void read_shdrs(FILE *fp)
+{
+ int i;
+ Elf32_Shdr shdr;
+
+ secs = calloc(ehdr.e_shnum, sizeof(struct section));
+ if (!secs) {
+ die("Unable to allocate %d section headers\n",
+ ehdr.e_shnum);
+ }
+ if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) {
+ die("Seek to %d failed: %s\n",
+ ehdr.e_shoff, strerror(errno));
+ }
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ if (fread(&shdr, sizeof shdr, 1, fp) != 1)
+ die("Cannot read ELF section headers %d/%d: %s\n",
+ i, ehdr.e_shnum, strerror(errno));
+ sec->shdr.sh_name = elf32_to_cpu(shdr.sh_name);
+ sec->shdr.sh_type = elf32_to_cpu(shdr.sh_type);
+ sec->shdr.sh_flags = elf32_to_cpu(shdr.sh_flags);
+ sec->shdr.sh_addr = elf32_to_cpu(shdr.sh_addr);
+ sec->shdr.sh_offset = elf32_to_cpu(shdr.sh_offset);
+ sec->shdr.sh_size = elf32_to_cpu(shdr.sh_size);
+ sec->shdr.sh_link = elf32_to_cpu(shdr.sh_link);
+ sec->shdr.sh_info = elf32_to_cpu(shdr.sh_info);
+ sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign);
+ sec->shdr.sh_entsize = elf32_to_cpu(shdr.sh_entsize);
+ if (sec->shdr.sh_link < ehdr.e_shnum)
+ sec->link = &secs[sec->shdr.sh_link];
+ }
+
+}
+
+static void read_strtabs(FILE *fp)
+{
+ int i;
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ if (sec->shdr.sh_type != SHT_STRTAB) {
+ continue;
+ }
+ sec->strtab = malloc(sec->shdr.sh_size);
+ if (!sec->strtab) {
+ die("malloc of %d bytes for strtab failed\n",
+ sec->shdr.sh_size);
+ }
+ if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
+ die("Seek to %d failed: %s\n",
+ sec->shdr.sh_offset, strerror(errno));
+ }
+ if (fread(sec->strtab, 1, sec->shdr.sh_size, fp)
+ != sec->shdr.sh_size) {
+ die("Cannot read symbol table: %s\n",
+ strerror(errno));
+ }
+ }
+}
+
+static void read_symtabs(FILE *fp)
+{
+ int i,j;
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ if (sec->shdr.sh_type != SHT_SYMTAB) {
+ continue;
+ }
+ sec->symtab = malloc(sec->shdr.sh_size);
+ if (!sec->symtab) {
+ die("malloc of %d bytes for symtab failed\n",
+ sec->shdr.sh_size);
+ }
+ if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
+ die("Seek to %d failed: %s\n",
+ sec->shdr.sh_offset, strerror(errno));
+ }
+ if (fread(sec->symtab, 1, sec->shdr.sh_size, fp)
+ != sec->shdr.sh_size) {
+ die("Cannot read symbol table: %s\n",
+ strerror(errno));
+ }
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
+ Elf32_Sym *sym = &sec->symtab[j];
+ sym->st_name = elf32_to_cpu(sym->st_name);
+ sym->st_value = elf32_to_cpu(sym->st_value);
+ sym->st_size = elf32_to_cpu(sym->st_size);
+ sym->st_shndx = elf16_to_cpu(sym->st_shndx);
+ }
+ }
+}
+
+
+static void read_relocs(FILE *fp)
+{
+ int i,j;
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ if (sec->shdr.sh_type != SHT_REL) {
+ continue;
+ }
+ sec->reltab = malloc(sec->shdr.sh_size);
+ if (!sec->reltab) {
+ die("malloc of %d bytes for relocs failed\n",
+ sec->shdr.sh_size);
+ }
+ if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
+ die("Seek to %d failed: %s\n",
+ sec->shdr.sh_offset, strerror(errno));
+ }
+ if (fread(sec->reltab, 1, sec->shdr.sh_size, fp)
+ != sec->shdr.sh_size) {
+ die("Cannot read symbol table: %s\n",
+ strerror(errno));
+ }
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
+ Elf32_Rel *rel = &sec->reltab[j];
+ rel->r_offset = elf32_to_cpu(rel->r_offset);
+ rel->r_info = elf32_to_cpu(rel->r_info);
+ }
+ }
+}
+
+
+static void print_absolute_symbols(void)
+{
+ int i;
+ printf("Absolute symbols\n");
+ printf(" Num: Value Size Type Bind Visibility Name\n");
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ char *sym_strtab;
+ Elf32_Sym *sh_symtab;
+ int j;
+
+ if (sec->shdr.sh_type != SHT_SYMTAB) {
+ continue;
+ }
+ sh_symtab = sec->symtab;
+ sym_strtab = sec->link->strtab;
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
+ Elf32_Sym *sym;
+ const char *name;
+ sym = &sec->symtab[j];
+ name = sym_name(sym_strtab, sym);
+ if (sym->st_shndx != SHN_ABS) {
+ continue;
+ }
+ printf("%5d %08x %5d %10s %10s %12s %s\n",
+ j, sym->st_value, sym->st_size,
+ sym_type(ELF32_ST_TYPE(sym->st_info)),
+ sym_bind(ELF32_ST_BIND(sym->st_info)),
+ sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)),
+ name);
+ }
+ }
+ printf("\n");
+}
+
+static int print_absolute_relocs(FILE *f)
+{
+ int i, printed = 0;
+
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ struct section *sec_applies, *sec_symtab;
+ char *sym_strtab;
+ Elf32_Sym *sh_symtab;
+ int j;
+ if (sec->shdr.sh_type != SHT_REL) {
+ continue;
+ }
+ sec_symtab = sec->link;
+ sec_applies = &secs[sec->shdr.sh_info];
+ if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
+ continue;
+ }
+ sh_symtab = sec_symtab->symtab;
+ sym_strtab = sec_symtab->link->strtab;
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
+ Elf32_Rel *rel;
+ Elf32_Sym *sym;
+ const char *name;
+ rel = &sec->reltab[j];
+ sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
+ name = sym_name(sym_strtab, sym);
+ if (sym->st_shndx != SHN_ABS) {
+ continue;
+ }
+
+ /* Absolute symbols are not relocated if bzImage is
+ * loaded at a non-compiled address. Display a warning
+ * to user at compile time about the absolute
+ * relocations present.
+ *
+ * User need to audit the code to make sure
+ * some symbols which should have been section
+ * relative have not become absolute because of some
+ * linker optimization or wrong programming usage.
+ *
+ * Before warning check if this absolute symbol
+ * relocation is harmless.
+ */
+ if (is_safe_abs_reloc(name) ||
+ is_safe_rel_reloc(name))
+ continue;
+
+ if (!printed) {
+ fprintf(f, "Unknown absolute relocations present\n");
+ fprintf(f, "Offset Info Type Sym.Value Sym.Name\n");
+ printed = 1;
+ }
+
+ fprintf(f, "%08x %08x %10s %08x %s\n",
+ rel->r_offset,
+ rel->r_info,
+ rel_type(ELF32_R_TYPE(rel->r_info)),
+ sym->st_value,
+ name);
+ }
+ }
+
+ if (printed)
+ fputc('\n', f);
+
+ return printed;
+}
+
+static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
+{
+ int i;
+ /* Walk through the relocations */
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ char *sym_strtab;
+ Elf32_Sym *sh_symtab;
+ struct section *sec_applies, *sec_symtab;
+ int j;
+ struct section *sec = &secs[i];
+
+ if (sec->shdr.sh_type != SHT_REL) {
+ continue;
+ }
+ sec_symtab = sec->link;
+ sec_applies = &secs[sec->shdr.sh_info];
+ if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
+ continue;
+ }
+ sh_symtab = sec_symtab->symtab;
+ sym_strtab = sec_symtab->link->strtab;
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
+ Elf32_Rel *rel;
+ Elf32_Sym *sym;
+ unsigned r_type;
+ rel = &sec->reltab[j];
+ sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
+ r_type = ELF32_R_TYPE(rel->r_info);
+ /* Don't visit relocations to absolute symbols */
+ if (sym->st_shndx == SHN_ABS &&
+ !is_safe_rel_reloc(sym_name(sym_strtab, sym)))
+ continue;
+
+ switch (r_type) {
+ case R_386_NONE:
+ case R_386_PC32:
+ case R_386_GOTPC:
+ case R_386_GOTOFF:
+ case R_386_GOT32:
+ case R_386_PLT32:
+ /* Relative relocations don't need to
+ be adjusted */
+ break;
+ case R_386_32:
+ /* Visit relocations that need adjustment */
+ visit(rel, sym);
+ break;
+ default:
+ die("Unsupported relocation type: %s (%d)\n",
+ rel_type(r_type), r_type);
+ }
+ }
+ }
+}
+
+static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
+{
+ (void)rel; (void)sym;
+ reloc_count += 1;
+}
+
+static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
+{
+ (void)sym;
+
+ /* Remember the address that needs to be adjusted. */
+ relocs[reloc_idx++] = rel->r_offset;
+}
+
+static int cmp_relocs(const void *va, const void *vb)
+{
+ const unsigned long *a, *b;
+ a = va; b = vb;
+ return (*a == *b)? 0 : (*a > *b)? 1 : -1;
+}
+
+static void emit_relocs(int as_text)
+{
+ int i;
+ /* Count how many relocations I have and allocate space for them. */
+ reloc_count = 0;
+ walk_relocs(count_reloc);
+ relocs = malloc(reloc_count * sizeof(relocs[0]));
+ if (!relocs) {
+ die("malloc of %d entries for relocs failed\n",
+ reloc_count);
+ }
+ /* Collect up the relocations */
+ reloc_idx = 0;
+ walk_relocs(collect_reloc);
+
+ /* Order the relocations for more efficient processing */
+ qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs);
+
+ /* Print the relocations */
+ if (as_text) {
+ /* Print the relocations in a form suitable that
+ * gas will like.
+ */
+ printf(".section \".data.reloc\",\"a\"\n");
+ printf(".balign 4\n");
+ for (i = 0; i < reloc_count; i++) {
+ printf("\t .long 0x%08lx\n", relocs[i]);
+ }
+ printf("\n");
+ }
+ else {
+ unsigned char buf[4];
+ /* Now print each relocation */
+ for (i = 0; i < reloc_count; i++) {
+ buf[0] = (relocs[i] >> 0) & 0xff;
+ buf[1] = (relocs[i] >> 8) & 0xff;
+ buf[2] = (relocs[i] >> 16) & 0xff;
+ buf[3] = (relocs[i] >> 24) & 0xff;
+ fwrite(buf, 4, 1, stdout);
+ }
+ /* Print a stop */
+ memset(buf, 0, sizeof buf);
+ fwrite(buf, 4, 1, stdout);
+ }
+}
+
+static void usage(void)
+{
+ die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n");
+}
+
+int main(int argc, char **argv)
+{
+ int show_absolute_syms, show_absolute_relocs;
+ int as_text;
+ const char *fname;
+ FILE *fp;
+ int i;
+ int err = 0;
+
+ show_absolute_syms = 0;
+ show_absolute_relocs = 0;
+ as_text = 0;
+ fname = NULL;
+ for (i = 1; i < argc; i++) {
+ char *arg = argv[i];
+ if (*arg == '-') {
+ if (strcmp(argv[1], "--abs-syms") == 0) {
+ show_absolute_syms = 1;
+ continue;
+ }
+
+ if (strcmp(argv[1], "--abs-relocs") == 0) {
+ show_absolute_relocs = 1;
+ continue;
+ }
+ else if (strcmp(argv[1], "--text") == 0) {
+ as_text = 1;
+ continue;
+ }
+ }
+ else if (!fname) {
+ fname = arg;
+ continue;
+ }
+ usage();
+ }
+ if (!fname) {
+ usage();
+ }
+
+
+ regex_init();
+
+ fp = fopen(fname, "r");
+ if (!fp) {
+ die("Cannot open %s: %s\n",
+ fname, strerror(errno));
+ }
+ read_ehdr(fp);
+ read_shdrs(fp);
+ read_strtabs(fp);
+ read_symtabs(fp);
+ read_relocs(fp);
+ if (show_absolute_syms) {
+ print_absolute_symbols();
+ return 0;
+ }
+ if (show_absolute_relocs) {
+ print_absolute_relocs(stdout);
+ return 0;
+ }
+ err = print_absolute_relocs(stderr);
+ emit_relocs(as_text);
+ return err;
+}
diff --git a/core/Makefile b/core/Makefile
index 65418c48..707aad79 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -23,8 +23,8 @@ topdir = ..
include $(topdir)/MCONFIG.embedded
-include $(topdir)/version.mk
-OPTFLAGS =
-INCLUDES =
+OPTFLAGS =
+INCLUDES = -I./include -I$(com32)/include
# This is very similar to cp437; technically it's for Norway and Denmark,
# but it's unlikely the characters that are different will be used in
@@ -33,17 +33,30 @@ CODEPAGE = cp865
# The targets to build in this directory...
BTARGET = kwdhash.gen \
+ extlinux.bin extlinux.bss extlinux.sys \
ldlinux.bss ldlinux.sys ldlinux.bin \
- pxelinux.0 isolinux.bin isolinux-debug.bin \
- extlinux.bin extlinux.bss extlinux.sys
+ isolinux.bin isolinux-debug.bin pxelinux.0
# All primary source files for the main syslinux files
-NASMSRC = $(wildcard *.asm)
-NASMHDR = $(wildcard *.inc)
-CSRC = $(wildcard *.c)
-CHDR = $(wildcard *.h)
-OTHERSRC = keywords
-ALLSRC = $(NASMSRC) $(NASMHDR) $(CSRC) $(CHDR) $(OTHERSRC)
+NASMSRC := $(wildcard *.asm)
+NASMHDR := $(wildcard *.inc)
+CSRC := $(wildcard *.c */*.c */*/*.c)
+SSRC := $(wildcard *.S */*.S */*/*.S)
+CHDR := $(wildcard *.h)
+OTHERSRC := keywords
+ALLSRC = $(NASMSRC) $(NASMHDR) $(CSRC) $(SSRC) $(CHDR) $(OTHERSRC)
+
+COBJ := $(patsubst %.c,%.o,$(CSRC))
+SOBJ := $(patsubst %.S,%.o,$(SSRC))
+
+LIB = libcore.a
+LIBS = $(LIB) $(com32)/lib/libcom32.a $(LIBGCC)
+LIBOBJS = $(COBJ) $(SOBJ)
+
+NASMDEBUG = -g -F dwarf
+NASMOPT += $(NASMDEBUG)
+
+PREPCORE = ../lzo/prepcore
# The DATE is set on the make command line when building binaries for
# official release. Otherwise, substitute a hex string that is pretty much
@@ -62,26 +75,28 @@ kwdhash.gen: keywords genhash.pl
.PRECIOUS: %.elf
-# Standard rule for {isolinux,isolinux-debug}.bin
-iso%.bin: iso%.elf checksumiso.pl
- $(OBJCOPY) -O binary $< $@
- $(PERL) checksumiso.pl $@
+%.raw: %.elf
+ $(OBJCOPY) -O binary $< $(@:.bin=.raw)
-# Standard rule for {ldlinux,pxelinux,extlinux}.bin
-%.bin: %.elf
- $(OBJCOPY) -O binary $< $@
+%.bin: %.raw $(PREPCORE)
+ $(PREPCORE) $< $@
%.o: %.asm kwdhash.gen ../version.gen
- ( $(NASM) -M -DDEPEND $(NINCLUDE) -o $@ $< ; echo '' ) > .$@.d; true
- $(NASM) $(NASMOPT) -f elf -g -F stabs -DDATE_STR="'$(DATE)'" \
+ $(NASM) -f elf $(NASMOPT) -DDATE_STR="'$(DATE)'" \
-DHEXDATE="$(HEXDATE)" \
- -l $(@:.o=.lsr) -o $@ $<
+ -l $(@:.o=.lsr) -o $@ -MP -MD .$@.d $<
-%.elf: %.o syslinux.ld
- $(LD) $(LDFLAGS) -T syslinux.ld -M -o $@ $< > $(@:.elf=.map)
+%.elf: %.o $(LIBS) syslinux.ld
+ $(LD) $(LDFLAGS) -T syslinux.ld -M -o $@ $< $(LIBS) \
+ > $(@:.elf=.map)
$(OBJDUMP) -h $@ > $(@:.elf=.sec)
$(PERL) lstadjust.pl $(@:.elf=.lsr) $(@:.elf=.sec) $(@:.elf=.lst)
+$(LIB): $(LIBOBJS)
+ rm -f $@
+ $(AR) cq $@ $^
+ $(RANLIB) $@
+
pxelinux.0: pxelinux.bin
cp -f $< $@
@@ -97,12 +112,11 @@ extlinux.bss: extlinux.bin
extlinux.sys: extlinux.bin
dd if=$< of=$@ bs=512 skip=1
-# NASM prior to 2.03 wouldn't auto-generate this dependency...
-ldlinux.o: codepage.cp
-
codepage.cp: ../codepage/$(CODEPAGE).cp
cp -f $< $@
+codepage.o: codepage.S codepage.cp
+
install: installer
install-lib: installer
@@ -112,8 +126,10 @@ install-all: install install-lib
netinstall: installer
tidy dist:
- rm -f codepage.cp *.o *.elf stupid.* patch.offset .depend .*.d
- rm -f *.lsr *.lst *.map *.sec
+ rm -f codepage.cp *.o *.elf *.a stupid.* patch.offset .depend .*.d
+ rm -f *.elf.tmp *.sym
+ rm -f *.lsr *.lst *.map *.sec *.raw
+ rm -f */*.o */*/*.o */*.lst */*/*.lst */.*.d */*/.*.d
rm -f $(OBSOLETE)
clean: tidy
@@ -122,4 +138,4 @@ spotless: clean
rm -f $(BTARGET) *.bin *_bin.c
# Include dependencies file
--include .*.d
+-include .*.d */.*.d
diff --git a/core/abort.inc b/core/abort.inc
index 5b16b9d9..9b181363 100644
--- a/core/abort.inc
+++ b/core/abort.inc
@@ -17,7 +17,7 @@
; Code to terminate a kernel load
;
- section .text
+ section .text16
;
; dot_pause: same as abort_check, except prints a dot, too
@@ -78,7 +78,7 @@ error_or_command:
jnz on_error
jmp enter_command
- section .data
+ section .data16
aborted_msg db ' aborted.', CR, LF, 0
- section .text
+ section .text16
diff --git a/core/adv.inc b/core/adv.inc
index d856a1a2..2dc16339 100644
--- a/core/adv.inc
+++ b/core/adv.inc
@@ -57,7 +57,7 @@ adv1:
.data resb ADV_LEN
.tail resd 1
.end equ $
- section .text
+ section .text16
;
; This is called after config file parsing, so we know
@@ -67,24 +67,26 @@ adv_init:
cmp byte [ADVDrive],-1
jne adv_read
-;%if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
-%if IS_EXTLINUX ; Not yet implemented for the other derivatives
+%if IS_SYSLINUX || IS_EXTLINUX
+ cmp word [ADVSectors],2 ; Not present?
+ jb adv_verify
+
;
; Update pointers to default ADVs...
;
- mov bx,[LDLSectors]
+ mov bx,[DataSectors]
shl bx,2
mov ecx,[bsHidden]
- mov eax,[bx+SectorPtrs-8]
- mov edx,[bx+SectorPtrs-4]
+ mov eax,[bx+SectorPtrs] ; First ADV sector
+ mov edx,[bx+SectorPtrs+4] ; Second ADV sector
add eax,ecx
add edx,ecx
mov [ADVSec0],eax
mov [ADVSec1],edx
mov al,[DriveNumber]
mov [ADVDrive],al
+ jmp adv_read
%endif
- ; ** fall through to adv_verify **
;
; Initialize the ADV data structure in memory
@@ -492,12 +494,14 @@ adv_read_write:
stc
jmp .cb_done
- section .data
+ section .data16
alignz 4
ADVSec0 dd 0 ; Not specified
ADVSec1 dd 0 ; Not specified
ADVDrive db -1 ; No ADV defined
ADVCHSInfo db -1 ; We have CHS info for this drive
- section .bss
+ section .bss16
ADVOp resb 1
+
+ section .text16
diff --git a/core/bcopy32.inc b/core/bcopy32.inc
index c363373a..6537546b 100644
--- a/core/bcopy32.inc
+++ b/core/bcopy32.inc
@@ -29,7 +29,7 @@
;
bits 16
- section .text
+ section .text16
;
; bcopy:
@@ -39,17 +39,13 @@
; ESI - source pointer (-1 means do bzero rather than bcopy)
; EDI - target pointer
; ECX - byte count
-; DF - zero
;
; Outputs:
; ESI - first byte after source (garbage if ESI == -1 on entry)
; EDI - first byte after target
;
bcopy: jecxz .ret
- pushad
- push word pm_bcopy
- call simple_pm_call
- popad
+ pm_call pm_bcopy
add edi,ecx
add esi,ecx
.ret: ret
@@ -70,293 +66,8 @@ bcopy: jecxz .ret
; the entry point and src the mode (0 = pm, 1 = rm)
;
shuffle_and_boot_raw:
- push word pm_shuffle
- call simple_pm_call
- ; Never returns...
- jmp kaboom
-
-;
-; This routine is used to invoke a simple routine in 32-bit protected
-; mode (with 32-bit zero-based CS, DS, ES, and SS, with ESP pointing to the
-; real-mode stack even if the real-mode stack was in a nonzero SS.)
-;
-; No interrupt thunking services are provided; interrupts are disabled
-; for the duration of the routine. Don't run for too long at a time
-; unless you really mean it.
-;
-; Inputs:
-; On stack - pm entrypoint (IP only)
-; EAX, EBP preserved until real-mode exit
-; EBX, ECX, EDX, ESI and EDI passed to the called routine
-;
-; Outputs:
-; EAX, EBP restored from real-mode entry
-; All other registers as returned from called function
-; PM entrypoint cleaned off stack
-;
-simple_pm_call:
- push eax
- push ebp
- movzx ebp,sp ; BP is used as frame pointer
- pushfd ; Saves, among others, the IF flag
- push ds
- push es
- push fs
- push gs
-
- cli
- call enable_a20
-
- mov byte [cs:bcopy_gdt.TSS+5],89h ; Mark TSS unbusy
-
- ; Convert the stack segment to a base
- xor eax,eax
- mov ax,ss
- shl eax,4
- add ebp,eax ; EBP is now an absolute frame ptr
-
- ; Save the old segmented stack pointer
- mov [cs:.rm_esp],esp
- mov [cs:.rm_ss],ss
-
- o32 lgdt [cs:bcopy_gdt]
- mov eax,cr0
- or al,1
- mov cr0,eax ; Enter protected mode
- jmp PM_CS32:.in_pm
-
- bits 32
-.in_pm:
- mov ax,PM_DS32
- mov ss,eax
- lea esp,[ebp-8*4-2*4] ; Flat mode stack
- mov es,eax
- mov ds,eax
-
- ; Set fs, gs, tr, and ldtr in case we're on a virtual
- ; machine running on Intel VT hardware -- it can't
- ; deal with a partial transition, for no good reason.
-
- mov al,PM_DS16 ; Real-mode-like segment
- mov fs,eax
- mov gs,eax
- mov al,PM_TSS ; Intel VT really doesn't want
- ltr ax ; an invalid TR and LDTR, so give
- xor eax,eax ; it something that it can use...
- lldt ax ; (sigh)
-
- movzx eax,word [ebp+2*4+2]
- call eax ; Call actual routine
-
- jmp PM_CS16:.exit
- bits 16
-.exit:
- mov ax,PM_DS16 ; "Real-mode-like" data segment
- mov es,eax
- mov ds,eax
- mov ss,eax
-
- mov eax,cr0
- and al,~1
- mov cr0,eax ; Disable protected mode
- jmp 0:.in_rm
-
-.in_rm: ; Back in real mode
- lss esp,[cs:.rm_esp] ; Restore the stack
- pop gs
- pop fs
- pop es
- pop ds
-
- popfd ; Re-enables interrupts
- pop ebp
- pop eax
- ret 2 ; Drops the pm entry
-
- section .bss
- alignb 4
-.rm_esp resd 1
-.rm_ss resw 1
-
-
- section .text
-;
-; Routines to enable and disable (yuck) A20. These routines are gathered
-; from tips from a couple of sources, including the Linux kernel and
-; http://www.x86.org/. The need for the delay to be as large as given here
-; is indicated by Donnie Barnes of RedHat, the problematic system being an
-; IBM ThinkPad 760EL.
-;
-
- section .data
- alignz 2
-A20Ptr dw a20_dunno
-
- section .bss
- alignb 4
-A20Test resd 1 ; Counter for testing A20 status
-A20Tries resb 1 ; Times until giving up on A20
-
- section .text
-enable_a20:
- pushad
- mov byte [cs:A20Tries],255 ; Times to try to make this work
-
-try_enable_a20:
-
-;
-; First, see if we are on a system with no A20 gate, or the A20 gate
-; is already enabled for us...
-;
-a20_none:
- call a20_test
- jnz a20_done
- ; Otherwise, see if we had something memorized...
- jmp word [cs:A20Ptr]
-
-;
-; Next, try the BIOS (INT 15h AX=2401h)
-;
-a20_dunno:
-a20_bios:
- mov word [cs:A20Ptr], a20_bios
- mov ax,2401h
- pushf ; Some BIOSes muck with IF
- int 15h
- popf
-
- call a20_test
- jnz a20_done
-
-;
-; Enable the keyboard controller A20 gate
-;
-a20_kbc:
- mov dl, 1 ; Allow early exit
- call empty_8042
- jnz a20_done ; A20 live, no need to use KBC
-
- mov word [cs:A20Ptr], a20_kbc ; Starting KBC command sequence
-
- mov al,0D1h ; Write output port
- out 064h, al
- call empty_8042_uncond
-
- mov al,0DFh ; A20 on
- out 060h, al
- call empty_8042_uncond
-
- ; Apparently the UHCI spec assumes that A20 toggle
- ; ends with a null command (assumed to be for sychronization?)
- ; Put it here to see if it helps anything...
- mov al,0FFh ; Null command
- out 064h, al
- call empty_8042_uncond
-
- ; Verify that A20 actually is enabled. Do that by
- ; observing a word in low memory and the same word in
- ; the HMA until they are no longer coherent. Note that
- ; we don't do the same check in the disable case, because
- ; we don't want to *require* A20 masking (SYSLINUX should
- ; work fine without it, if the BIOS does.)
-.kbc_wait: push cx
- xor cx,cx
-.kbc_wait_loop:
- call a20_test
- jnz a20_done_pop
- loop .kbc_wait_loop
-
- pop cx
-;
-; Running out of options here. Final attempt: enable the "fast A20 gate"
-;
-a20_fast:
- mov word [cs:A20Ptr], a20_fast
- in al, 092h
- or al,02h
- and al,~01h ; Don't accidentally reset the machine!
- out 092h, al
-
-.fast_wait: push cx
- xor cx,cx
-.fast_wait_loop:
- call a20_test
- jnz a20_done_pop
- loop .fast_wait_loop
-
- pop cx
-
-;
-; Oh bugger. A20 is not responding. Try frobbing it again; eventually give up
-; and report failure to the user.
-;
- dec byte [cs:A20Tries]
- jnz a20_dunno ; Did we get the wrong type?
-
- mov si, err_a20
- jmp abort_load
-
- section .data
-err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0
- section .text
-
-;
-; A20 unmasked, proceed...
-;
-a20_done_pop: pop cx
-a20_done: popad
- ret
-
-;
-; This routine tests if A20 is enabled (ZF = 0). This routine
-; must not destroy any register contents.
-;
-; The no-write early out avoids the io_delay in the (presumably common)
-; case of A20 already enabled (e.g. from a previous call.)
-;
-a20_test:
- push es
- push cx
- push eax
- mov cx,0FFFFh ; HMA = segment 0FFFFh
- mov es,cx
- mov eax,[cs:A20Test]
- mov cx,32 ; Loop count
- jmp .test ; First iteration = early out
-.wait: add eax,0x430aea41 ; A large prime number
- mov [cs:A20Test],eax
- io_delay ; Serialize, and fix delay
-.test: cmp eax,[es:A20Test+10h]
- loopz .wait
-.done: pop eax
- pop cx
- pop es
- ret
-
-;
-; Routine to empty the 8042 KBC controller. If dl != 0
-; then we will test A20 in the loop and exit if A20 is
-; suddenly enabled.
-;
-empty_8042_uncond:
- xor dl,dl
-empty_8042:
- call a20_test
- jz .a20_on
- and dl,dl
- jnz .done
-.a20_on: io_delay
- in al, 064h ; Status port
- test al,1
- jz .no_output
- io_delay
- in al, 060h ; Read input
- jmp short empty_8042
-.no_output:
- test al,2
- jnz empty_8042
- io_delay
-.done: ret
+ mov bx,pm_shuffle
+ jmp enter_pm
;
; The 32-bit copy and shuffle code is "special", so it is in its own file
diff --git a/core/bcopyxx.inc b/core/bcopyxx.inc
index 89ae4f40..823662b4 100644
--- a/core/bcopyxx.inc
+++ b/core/bcopyxx.inc
@@ -204,6 +204,7 @@ pm_bcopy:
; the entry point and src the mode (0 = pm, 1 = rm)
;
pm_shuffle:
+ cli ; End interrupt service (for good)
mov ebx,edi ; EBX <- descriptor list
lea edx,[edi+ecx+15] ; EDX <- where to relocate our code to
and edx,~15 ; Align 16 to benefit the GDT
@@ -232,15 +233,16 @@ pm_shuffle:
call pm_bcopy
jmp .loop
.done:
+ lidt [edx+RM_IDT_ptr-bcopy_gdt] ; RM-like IDT
push ecx ; == 0, for cleaning the flags register
and esi,esi
- jz pm_shuffle_real_mode
+ jz pm_shuffle_16
popfd ; Clean the flags
jmp edi ; Protected mode entry
- ; We have a real-mode entry point, so we need to return
- ; to real mode. Note: EDX already points to the GDT.
-pm_shuffle_real_mode:
+ ; We have a 16-bit entry point, so we need to return
+ ; to 16-bit mode. Note: EDX already points to the GDT.
+pm_shuffle_16:
mov eax,edi
mov [edx+PM_CS16+2],ax
mov [edx+PM_DS16+2],ax
@@ -261,7 +263,11 @@ pm_shuffle_real_mode:
mov ss,edx
jmp PM_CS16:0
- align 16
+ align 4
+RM_IDT_ptr: dw 0FFFFh ; Length (nonsense, but matches CPU)
+ dd 0 ; Offset
+
+ alignz 16
; GDT descriptor entry
%macro desc 1
bcopy_gdt.%1:
@@ -312,4 +318,4 @@ bcopyxx_safe equ bcopyxx_len + bcopyxx_stack + 15
DummyTSS equ 0x580
bits 16
- section .text
+ section .text16
diff --git a/core/bios.inc b/core/bios.inc
index 987a2166..33a3cd4c 100644
--- a/core/bios.inc
+++ b/core/bios.inc
@@ -18,11 +18,17 @@
%ifndef _BIOS_INC
%define _BIOS_INC
+ global BIOS_fbm, BIOS_timer
- absolute 4*1Eh ; In the interrupt table
+ ; Interrupt vectors
+ absolute 4*1Ch
+BIOS_timer_hook resd 1
+
+ absolute 4*1Eh
fdctab equ $
fdctab1 resw 1
fdctab2 resw 1
+
absolute 0400h
serial_base resw 4 ; Base addresses for 4 serial ports
absolute 0413h
diff --git a/core/bootsect.inc b/core/bootsect.inc
index 0cf0c460..b8102cd5 100644
--- a/core/bootsect.inc
+++ b/core/bootsect.inc
@@ -80,7 +80,7 @@ load_bootsec:
xor bx,bx
%elif IS_PXELINUX
mov byte [KeepPXE],03h ; Chainloading + keep PXE
- call reset_pxe
+ pm_call reset_pxe
lfs si,[InitStack]
; Put restore DS, EDX and ESI to the true initial values
mov bx,[fs:si+6]
@@ -143,7 +143,9 @@ replace_bootstrap_noclearmode:
jmp .stackok
%endif
.stdstack:
- mov di,7C00h-44
+ ; StackBuf is guaranteed to have 44 bytes free immediately
+ ; above it, and it will not interfere with our existing stack.
+ mov di,StackBuf
push di
mov cx,22 ; 44 bytes
rep stosw
@@ -232,4 +234,4 @@ replace_stub:
jmp 0:0
.csip equ $-4
- section .text
+ section .text16
diff --git a/core/cache.c b/core/cache.c
new file mode 100644
index 00000000..415becff
--- /dev/null
+++ b/core/cache.c
@@ -0,0 +1,134 @@
+/*
+ * core/cache.c: A simple LRU-based cache implementation.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "core.h"
+#include "cache.h"
+
+
+/*
+ * Initialize the cache data structres. the _block_size_shift_ specify
+ * the block size, which is 512 byte for FAT fs of the current
+ * implementation since the block(cluster) size in FAT is a bit big.
+ *
+ */
+void cache_init(struct device *dev, int block_size_shift)
+{
+ struct cache_struct *prev, *cur;
+ char *data = dev->cache_data;
+ static __lowmem struct cache_struct cache_head, cache[MAX_CACHE_ENTRIES];
+ int i;
+
+ dev->cache_head = &cache_head;
+ dev->cache_block_size = 1 << block_size_shift;
+ dev->cache_entries = dev->cache_size >> block_size_shift;
+ if (dev->cache_entries > MAX_CACHE_ENTRIES)
+ dev->cache_entries = MAX_CACHE_ENTRIES;
+
+ cache_head.prev = &cache[dev->cache_entries-1];
+ cache_head.prev->next = &cache_head;
+ prev = &cache_head;
+
+ for (i = 0; i < dev->cache_entries; i++) {
+ cur = &cache[i];
+ cur->block = 0;
+ cur->prev = prev;
+ prev->next = cur;
+ cur->data = data;
+ data += dev->cache_block_size;
+ prev = cur++;
+ }
+}
+
+
+/*
+ * Check for a particular BLOCK in the block cache,
+ * and if it is already there, just do nothing and return;
+ * otherwise load it from disk and updata the LRU link.
+ *
+ */
+struct cache_struct* get_cache_block(struct device *dev, block_t block)
+{
+ struct cache_struct *head = (struct cache_struct *)dev->cache_head;
+ struct cache_struct *last = head->prev;
+ /* let's find it from the end, 'cause the endest is the freshest */
+ struct cache_struct *cs = head->prev;
+ int i;
+ static int total_read;
+ static int missed;
+
+#if 0
+ printf("we are looking for cache of %d\n", block);
+#endif
+
+ if (!block) {
+ printf("ERROR: we got a ZERO block number that's not we want!\n");
+ return NULL;
+ }
+
+ /* it's aleardy the freshest, so nothing we need do , just return it */
+ if (cs->block == block)
+ goto out;
+
+ for (i = 0; i < dev->cache_entries; i ++) {
+ if (cs->block == block)
+ break;
+ else
+ cs = cs->prev;
+ }
+
+ /* missed, so we need to load it */
+ if (i == dev->cache_entries) {
+ /* store it at the head of real cache */
+ cs = head->next;
+ cs->block = block;
+ getoneblk(dev->disk, cs->data, block, dev->cache_block_size);
+
+ missed ++;
+ }
+
+ /* remove cs from current position in list */
+ cs->prev->next = cs->next;
+ cs->next->prev = cs->prev;
+
+ /* add to just before head node */
+ last->next = cs;
+ cs->prev = last;
+ head->prev = cs;
+ cs->next = head;
+
+ out:
+ total_read ++;
+#if 0 /* testing how efficiency the cache is */
+ if (total_read % 5 == 0)
+ printf("total_read %d\tmissed %d\n", total_read, missed);
+#endif
+
+ /* in fact, that would never be happened */
+ if ((char *)(cs->data) > (char*)0x100000)
+ printf("the buffer addres higher than 1M limit\n");
+
+ return cs;
+}
+
+
+/*
+ * Just print the sector, and according the LRU algorithm,
+ * Left most value is the most least secotr, and Right most
+ * value is the most Recent sector. I see it's a Left Right Used
+ * (LRU) algorithm; Just kidding:)
+ */
+void print_cache(struct device *dev)
+{
+ int i = 0;
+ struct cache_struct *cs = dev->cache_head;
+ for (; i < dev->cache_entries; i++) {
+ cs = cs->next;
+ printf("%d(%p)\n", cs->block, cs->data);
+ }
+
+ printf("\n");
+}
diff --git a/core/cache.inc b/core/cache.inc
index 59755576..3b24cf04 100644
--- a/core/cache.inc
+++ b/core/cache.inc
@@ -10,7 +10,7 @@
;
; -----------------------------------------------------------------------
- section .text
+ section .text16
struc cptr
.sector: resd 1 ; Sector number
@@ -103,7 +103,7 @@ getcachesector:
pop cx
ret
- section .bss
+ section .bss16
; Each CachePtr contains:
; - Block pointer
diff --git a/core/call16.c b/core/call16.c
new file mode 100644
index 00000000..86d70461
--- /dev/null
+++ b/core/call16.c
@@ -0,0 +1,27 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * call16.c
+ *
+ * Simple wrapper to call 16-bit core functions from 32-bit code
+ */
+
+#include <stddef.h>
+#include "core.h"
+
+const com32sys_t zero_regs; /* Common all-zero register set */
+
+void call16(void (*func)(void), const com32sys_t *ireg, com32sys_t *oreg)
+{
+ core_farcall((size_t)func, ireg, oreg);
+}
diff --git a/core/callback.inc b/core/callback.inc
new file mode 100644
index 00000000..a33b5825
--- /dev/null
+++ b/core/callback.inc
@@ -0,0 +1,208 @@
+;; -----------------------------------------------------------------------
+;;
+;; Copyright 1994-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., 53 Temple Place Ste 330,
+;; Boston MA 02111-1307, USA; either version 2 of the License, or
+;; (at your option) any later version; incorporated herein by reference.
+;;
+;; -----------------------------------------------------------------------
+
+;;
+;; callback.inc
+;;
+;; Callbacks from 32-bit mode to 16-bit mode
+;;
+
+;
+; 16-bit intcall/farcall handling code
+;
+
+;
+; 32-bit support code
+;
+ bits 32
+ section .text
+
+;
+; Intcall/farcall invocation. We manifest a structure on the real-mode stack,
+; containing the com32sys_t structure from <com32.h> as well as
+; the following entries (from low to high address):
+; - Target offset
+; - Target segment
+; - Return offset
+; - Return segment (== real mode cs == 0)
+; - Return flags
+;
+ global core_farcall
+core_farcall:
+ mov eax,[esp+1*4] ; CS:IP
+ jmp core_syscall
+
+ global core_intcall
+core_intcall:
+ movzx eax,byte [esp+1*4] ; INT number
+ mov eax,[eax*4] ; Get CS:IP from low memory
+
+core_syscall:
+ pushfd ; Save IF among other things...
+ push ebx
+ push ebp
+ push esi
+ push edi
+ push dword [CallbackSP]
+
+ cld
+
+ movzx edi,word [word RealModeSSSP]
+ movzx ebx,word [word RealModeSSSP+2]
+ sub edi,54 ; Allocate 54 bytes
+ mov [word RealModeSSSP],di
+ shl ebx,4
+ add edi,ebx ; Create linear address
+
+ mov esi,[esp+8*4] ; Source regs
+ xor ecx,ecx
+ mov cl,11 ; 44 bytes to copy
+ rep movsd
+
+ ; EAX is already set up to be CS:IP
+ stosd ; Save in stack frame
+ mov eax,.rm_return ; Return seg:offs
+ stosd ; Save in stack frame
+ mov eax,[edi-12] ; Return flags
+ and eax,0x200cd7 ; Mask (potentially) unsafe flags
+ mov [edi-12],eax ; Primary flags entry
+ stosw ; Return flags
+
+ mov bx,.rm
+ jmp enter_rm ; Go to real mode
+
+ bits 16
+ section .text16
+.rm:
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ popad
+ popfd
+ mov [cs:CallbackSP],sp
+ retf ; Invoke routine
+
+.rm_return:
+ ; We clean up SP here because we don't know if the
+ ; routine returned with RET, RETF or IRET
+ mov sp,[cs:CallbackSP]
+ pushfd
+ pushad
+ push ds
+ push es
+ push fs
+ push gs
+ mov ebx,.pm_return
+ jmp enter_pm
+
+ ; On return, the 44-byte return structure is on the
+ ; real-mode stack, plus the 10 additional bytes used
+ ; by the target address (see above.)
+ bits 32
+ section .text
+.pm_return:
+ movzx esi,word [word RealModeSSSP]
+ movzx eax,word [word RealModeSSSP+2]
+ mov edi,[esp+9*4] ; Dest regs
+ shl eax,4
+ add esi,eax ; Create linear address
+ and edi,edi ; NULL pointer?
+ jnz .do_copy
+.no_copy: mov edi,esi ; Do a dummy copy-to-self
+.do_copy: xor ecx,ecx
+ mov cl,11 ; 44 bytes
+ rep movsd ; Copy register block
+
+ add dword [word RealModeSSSP],54
+ ; Remove from stack
+
+ pop dword [CallbackSP]
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ popfd
+ ret ; Return to 32-bit program
+
+;
+; Cfarcall invocation. We copy the stack frame to the real-mode stack,
+; followed by the return CS:IP and the CS:IP of the target function.
+;
+ global core_cfarcall
+core_cfarcall:
+ pushfd ; Save IF among other things...
+ push ebx
+ push ebp
+ push esi
+ push edi
+ push dword [CallbackSP]
+
+ cld
+ mov ecx,[esp+9*4] ; Size of stack frame
+
+ movzx edi,word [word RealModeSSSP]
+ movzx ebx,word [word RealModeSSSP+2]
+ mov [word CallbackSP],di
+ sub edi,ecx ; Allocate space for stack frame
+ and edi,~3 ; Round
+ sub edi,4*2 ; Return pointer, return value
+ mov [word RealModeSSSP],di
+ shl ebx,4
+ add edi,ebx ; Create linear address
+
+ mov eax,[esp+7*4] ; CS:IP
+ stosd ; Save to stack frame
+ mov eax,.rm_return ; Return seg:off
+ stosd
+ mov esi,[esp+8*4] ; Stack frame
+ mov eax,ecx ; Copy the stack frame
+ shr ecx,2
+ rep movsd
+ mov ecx,eax
+ and ecx,3
+ rep movsb
+
+ mov bx,.rm
+ jmp enter_rm
+
+ bits 16
+ section .text16
+.rm:
+ retf
+.rm_return:
+ mov sp,[cs:CallbackSP]
+ mov esi,eax
+ mov ebx,.pm_return
+ jmp enter_pm
+
+ bits 32
+ section .text
+.pm_return:
+ mov eax,esi
+ ; EDX already set up to be the RM return value
+ pop dword [CallbackSP]
+ pop ebx
+ pop ebp
+ pop esi
+ pop edi
+ popfd
+ ret
+
+ bits 16
+ section .bss16
+ alignb 4
+CallbackSP resd 1 ; SP saved during callback
+
+ bits 16
+ section .text16
diff --git a/core/checksumiso.pl b/core/checksumiso.pl
deleted file mode 100755
index 9b8c3ee5..00000000
--- a/core/checksumiso.pl
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/perl
-#
-# Construct a checksum for isolinux*.bin, compatible
-# with an mkisofs boot-info-table
-#
-
-use bytes;
-use integer;
-
-($file) = @ARGV;
-
-open(FILE, '+<', $file) or die "$0: cannot open $file: $!\n";
-binmode FILE;
-
-@fstat = stat(FILE) or die "$0: stat $file: $!\n";
-if (!$fstat[7]) {
- die "$0: $file: cannot query length\n";
-}
-
-# Pad file to a multiple of 2048 bytes
-$frac = $fstat[7] % 2048;
-if ($frac) {
- seek(FILE,$fstat[7],0)
- or die "$0: $file: cannot seek to end\n";
- print FILE "\0" x (2048-$frac);
-}
-
-# Checksum the file post header
-if ( !seek(FILE,64,0) ) {
- die "$0: $file: cannot seek past header\n";
-}
-
-$csum = 0;
-$bytes = 64;
-while ( ($n = read(FILE, $dw, 4)) > 0 ) {
- $dw .= "\0\0\0\0"; # Pad to at least 32 bits
- ($v) = unpack("V", $dw);
- $csum = ($csum + $v) & 0xffffffff;
- $bytes += $n;
-}
-
-# Update header
-if ( !seek(FILE,16,0) ) {
- die "$0: $file: cannot seek to header\n";
-}
-
-print FILE pack("VV", $bytes, $csum);
-
-close(FILE);
-
-exit 0;
diff --git a/core/cleanup.inc b/core/cleanup.inc
index 063ed73e..300584c7 100644
--- a/core/cleanup.inc
+++ b/core/cleanup.inc
@@ -16,7 +16,7 @@
;; Some final tidying before jumping to a kernel or bootsector
;;
- section .text
+ section .text16
;
; cleanup_hardware:
;
@@ -49,6 +49,11 @@ cleanup_hardware:
int 10h
.no_vmware:
%endif
+
+ call comboot_cleanup_api
+
+ call timer_cleanup
+
popad
; If we enabled serial port interrupts, clean them up now
diff --git a/core/cmdline.inc b/core/cmdline.inc
index 642e5e14..8b84f48d 100644
--- a/core/cmdline.inc
+++ b/core/cmdline.inc
@@ -45,7 +45,7 @@ make_plain_cmdline:
; Actual IPAppend strings...
;
%if IS_PXELINUX
- section .data
+ section .data16
alignz 2
IPAppends dw IPOption
dw BOOTIFStr
@@ -60,7 +60,7 @@ numIPAppends equ 0
;
; Assumes DS == CS; pushes output to ES:DI
;
- section .text
+ section .text16
do_ip_append:
%ifndef DEPEND
diff --git a/core/codepage.S b/core/codepage.S
new file mode 100644
index 00000000..4f1d4836
--- /dev/null
+++ b/core/codepage.S
@@ -0,0 +1,5 @@
+ .section ".rodata","a"
+ .globl codepage
+codepage:
+ .incbin "codepage.cp"
+ .size codepage, .-codepage
diff --git a/core/com32.inc b/core/com32.inc
index 72327929..3fa2d31e 100644
--- a/core/com32.inc
+++ b/core/com32.inc
@@ -1,6 +1,7 @@
;; -----------------------------------------------------------------------
;;
-;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
+;; Copyright 1994-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
@@ -26,30 +27,9 @@
; "mov ax,0x4cff; int 0x21" in 16-bit mode. This will abort the
; program with an error if run in 16-bit mode.
;
+com32_entry equ free_high_memory
- ; We need to make this a proper section rather
- ; than using absolute numbers, in order to work
- ; around a bug in GNU ld 2.17, which is still in
- ; use as of this writing in the form of Debian
- ; 4.0 (etch).
- bits 32
- section .com32 exec write nobits align=16
-pm_idt equ 0x100000 ; Needs to be absolute...
- resb 4096
-pm_entry: ; Needs to not be...
-
- bits 16
- section .data
- alignz 2
-com32_pmidt:
- dw 8*256 ; Limit
- dd pm_idt ; Address
-
-com32_rmidt:
- dw 0ffffh ; Limit
- dd 0 ; Address
-
- section .text
+ section .text16
is_com32_image:
push si ; Save file handle
push eax ; Save file length
@@ -67,362 +47,84 @@ is_com32_image:
call comboot_setup_api ; Set up the COMBOOT-style API
- mov edi,pm_entry ; Load address
+ mov edi,com32_entry ; Load address
pop eax ; File length
pop si ; File handle
xor dx,dx ; No padding
mov bx,abort_check ; Don't print dots, but allow abort
call load_high
-com32_start:
- mov ebx,com32_call_start ; Where to go in PM
-
-com32_enter_pm:
- cli
- mov ax,cs
- mov ds,ax
- mov [RealModeSSSP],sp
- mov [RealModeSSSP+2],ss
- cld
- call a20_test
- jnz .a20ok
- call enable_a20
-
-.a20ok:
- mov byte [bcopy_gdt.TSS+5],89h ; Mark TSS unbusy
-
- lgdt [bcopy_gdt] ; We can use the same GDT just fine
- lidt [com32_pmidt] ; Set up the IDT
- mov eax,cr0
- or al,1
- mov cr0,eax ; Enter protected mode
- jmp PM_CS32:.in_pm
-
- bits 32
-.in_pm:
- xor eax,eax ; Available for future use...
- mov fs,eax
- mov gs,eax
- lldt ax
+ mov esi,com32_entry
+ mov edi,trackbuf
+ mov ecx,5
+ call bcopy
+ cmp dword [trackbuf],0xcd4cfeb8
+ jne not_com32r
+ cmp byte [trackbuf+4],0x21
+ jne not_com32r
- mov al,PM_DS32 ; Set up data segments
- mov es,eax
- mov ds,eax
- mov ss,eax
-
- mov al,PM_TSS ; Be nice to Intel's VT by
- ltr ax ; giving it a valid TR
-
- mov esp,[PMESP] ; Load protmode %esp if available
- jmp ebx ; Go to where we need to go
+com32_start:
+ ;
+ ; Point the stack to the end of (permitted) high memory
+ ;
+ mov eax,[HighMemRsvd]
+ xor ax,ax ; Align to a 64K boundary
+ mov [PMESP],eax
+ mov ebx,.pm ; Where to go in PM
+ jmp enter_pm
;
; This is invoked right before the actually starting the COM32
; progam, in 32-bit mode...
;
-com32_call_start:
- ;
- ; Point the stack to the end of (permitted) high memory
- ;
- mov esp,[word HighMemRsvd]
- xor sp,sp ; Align to a 64K boundary
-
- ;
- ; Set up the protmode IDT and the interrupt jump buffers
- ; We set these up in the system area at 0x100000,
- ; but we could also put them beyond the stack.
- ;
- mov edi,pm_idt
-
- ; Form an interrupt gate descriptor
- mov eax,0x00200000+((pm_idt+8*256)&0x0000ffff)
- mov ebx,0x0000ee00+((pm_idt+8*256)&0xffff0000)
- xor ecx,ecx
- inc ch ; ecx <- 256
-
- push ecx
-.make_idt:
- stosd
- add eax,8
- xchg eax,ebx
- stosd
- xchg eax,ebx
- loop .make_idt
-
- pop ecx
-
- ; Each entry in the interrupt jump buffer contains
- ; the following instructions:
- ;
- ; 00000000 60 pushad
- ; 00000001 B0xx mov al,<interrupt#>
- ; 00000003 E9xxxxxxxx jmp com32_handle_interrupt
-
- mov eax,0e900b060h
- mov ebx,com32_handle_interrupt-(pm_idt+8*256+8)
-
-.make_ijb:
- stosd
- sub [edi-2],cl ; Interrupt #
- xchg eax,ebx
- stosd
- sub eax,8
- xchg eax,ebx
- loop .make_ijb
-
- ; Now everything is set up for interrupts...
+ bits 32
+ section .text
+.pm:
+ ; Set up the calling stack frame
push dword [HighMemSize] ; Memory managed by Syslinux
- push dword com32_cfarcall ; Cfarcall entry point
- push dword com32_farcall ; Farcall entry point
+ push dword core_cfarcall ; Cfarcall entry point
+ push dword core_farcall ; Farcall entry point
push dword (1 << 16) ; 64K bounce buffer
push dword (xfer_buf_seg << 4) ; Bounce buffer address
- push dword com32_intcall ; Intcall entry point
+ push dword core_intcall ; Intcall entry point
push dword command_line ; Command line pointer
push dword 7 ; Argument count
sti ; Interrupts OK now
- call pm_entry ; Run the program...
+ call com32_entry ; Run the program...
; ... on return, fall through to com32_exit ...
-
com32_exit:
- mov bx,com32_done ; Return to command loop
-
-com32_enter_rm:
- cli
- cld
- mov [PMESP],esp ; Save exit %esp
- xor esp,esp ; Make sure the high bits are zero
- jmp PM_CS16:.in_pm16 ; Return to 16-bit mode first
+ mov bx,.rm
+ jmp enter_rm
bits 16
-.in_pm16:
- mov ax,PM_DS16 ; Real-mode-like segment
- mov es,ax
- mov ds,ax
- mov ss,ax
- mov fs,ax
- mov gs,ax
-
- lidt [com32_rmidt] ; Real-mode IDT (rm needs no GDT)
- mov eax,cr0
- and al,~1
- mov cr0,eax
- jmp 0:.in_rm
-
-.in_rm: ; Back in real mode
- mov ax,cs ; Set up sane segments
- mov ds,ax
- mov es,ax
- mov fs,ax
- mov gs,ax
- lss sp,[RealModeSSSP] ; Restore stack
- jmp bx ; Go to whereever we need to go...
-
-com32_done:
+ section .text16
+.rm:
+ mov dword [PMESP],__stack_end ; Stop use of COM32 stack
sti
jmp enter_command
-;
-; 16-bit support code
-;
- bits 16
-
-;
-; 16-bit interrupt-handling code
-;
-com32_int_rm:
- pushf ; Flags on stack
- push cs ; Return segment
- push word .cont ; Return address
- push dword edx ; Segment:offset of IVT entry
- retf ; Invoke IVT routine
-.cont: ; ... on resume ...
- mov ebx,com32_int_resume
- jmp com32_enter_pm ; Go back to PM
-
-;
-; 16-bit intcall/farcall handling code
-;
-com32_sys_rm:
- pop gs
- pop fs
- pop es
- pop ds
- popad
- popfd
- mov [cs:Com32SysSP],sp
- retf ; Invoke routine
-.return:
- ; We clean up SP here because we don't know if the
- ; routine returned with RET, RETF or IRET
- mov sp,[cs:Com32SysSP]
- pushfd
- pushad
- push ds
- push es
- push fs
- push gs
- mov ebx,com32_syscall.resume
- jmp com32_enter_pm
-
-;
-; 16-bit cfarcall handing code
-;
-com32_cfar_rm:
- retf
-.return:
- mov sp,[cs:Com32SysSP]
- mov [cs:RealModeEAX],eax
- mov ebx,com32_cfarcall.resume
- jmp com32_enter_pm
-
-;
-; 32-bit support code
-;
- bits 32
-
-;
-; This is invoked on getting an interrupt in protected mode. At
-; this point, we need to context-switch to real mode and invoke
-; the interrupt routine.
-;
-; When this gets invoked, the registers are saved on the stack and
-; AL contains the register number.
-;
-com32_handle_interrupt:
- movzx eax,al
- xor ebx,ebx ; Actually makes the code smaller
- mov edx,[ebx+eax*4] ; Get the segment:offset of the routine
- mov bx,com32_int_rm
- jmp com32_enter_rm ; Go to real mode
-
-com32_int_resume:
- popad
- iret
-
-;
-; Intcall/farcall invocation. We manifest a structure on the real-mode stack,
-; containing the com32sys_t structure from <com32.h> as well as
-; the following entries (from low to high address):
-; - Target offset
-; - Target segment
-; - Return offset
-; - Return segment (== real mode cs == 0)
-; - Return flags
-;
-com32_farcall:
- pushfd ; Save IF among other things...
- pushad ; We only need to save some, but...
-
- mov eax,[esp+10*4] ; CS:IP
- jmp com32_syscall
-
-
-com32_intcall:
- pushfd ; Save IF among other things...
- pushad ; We only need to save some, but...
-
- movzx eax,byte [esp+10*4] ; INT number
- mov eax,[eax*4] ; Get CS:IP from low memory
-
-com32_syscall:
- cld
-
- movzx edi,word [word RealModeSSSP]
- movzx ebx,word [word RealModeSSSP+2]
- sub edi,54 ; Allocate 54 bytes
- mov [word RealModeSSSP],di
- shl ebx,4
- add edi,ebx ; Create linear address
-
- mov esi,[esp+11*4] ; Source regs
- xor ecx,ecx
- mov cl,11 ; 44 bytes to copy
- rep movsd
-
- ; EAX is already set up to be CS:IP
- stosd ; Save in stack frame
- mov eax,com32_sys_rm.return ; Return seg:offs
- stosd ; Save in stack frame
- mov eax,[edi-12] ; Return flags
- and eax,0x200cd7 ; Mask (potentially) unsafe flags
- mov [edi-12],eax ; Primary flags entry
- stosw ; Return flags
-
- mov bx,com32_sys_rm
- jmp com32_enter_rm ; Go to real mode
-
- ; On return, the 44-byte return structure is on the
- ; real-mode stack, plus the 10 additional bytes used
- ; by the target address (see above.)
-.resume:
- movzx esi,word [word RealModeSSSP]
- movzx eax,word [word RealModeSSSP+2]
- mov edi,[esp+12*4] ; Dest regs
- shl eax,4
- add esi,eax ; Create linear address
- and edi,edi ; NULL pointer?
- jnz .do_copy
-.no_copy: mov edi,esi ; Do a dummy copy-to-self
-.do_copy: xor ecx,ecx
- mov cl,11 ; 44 bytes
- rep movsd ; Copy register block
-
- add dword [word RealModeSSSP],54 ; Remove from stack
-
- popad
- popfd
- ret ; Return to 32-bit program
-
-;
-; Cfarcall invocation. We copy the stack frame to the real-mode stack,
-; followed by the return CS:IP and the CS:IP of the target function.
-;
-com32_cfarcall:
- pushfd
- pushad
-
- cld
- mov ecx,[esp+12*4] ; Size of stack frame
-
- movzx edi,word [word RealModeSSSP]
- movzx ebx,word [word RealModeSSSP+2]
- mov [word Com32SysSP],di
- sub edi,ecx ; Allocate space for stack frame
- and edi,~3 ; Round
- sub edi,4*2 ; Return pointer, return value
- mov [word RealModeSSSP],di
- shl ebx,4
- add edi,ebx ; Create linear address
-
- mov eax,[esp+10*4] ; CS:IP
- stosd ; Save to stack frame
- mov eax,com32_cfar_rm.return ; Return seg:off
- stosd
- mov esi,[esp+11*4] ; Stack frame
- mov eax,ecx ; Copy the stack frame
- shr ecx,2
- rep movsd
- mov ecx,eax
- and ecx,3
- rep movsb
-
- mov bx,com32_cfar_rm
- jmp com32_enter_rm
-
-.resume:
- popad
- mov eax,[word RealModeEAX]
- popfd
- ret
-
- bits 16
-
- section .bss1
- alignb 4
-RealModeSSSP resd 1 ; Real-mode SS:SP
-RealModeEAX resd 1 ; Real mode EAX
-PMESP resd 1 ; Protected-mode ESP
-Com32SysSP resw 1 ; SP saved during COM32 syscall
+not_com32r:
+ mov si,KernelCName
+ call writestr
+ mov si,not_com32r_msg
+ call writestr
+ jmp enter_command
- section .text
+ section .data16
+not_com32r_msg db ': not a COM32R image', CR, LF, 0
+
+ ; Ersatz com32 invocation structure, to make libcom32
+ ; code run the same if linked to the core. This is in
+ ; the .data16 segment so HighMemSize can live here.
+ global __com32
+ alignz 4
+__com32:
+ dd 7 ; Argument count
+ dd 0 ; No command line
+ dd core_intcall ; Intcall entry point
+ dd core_xfer_buf ; Bounce buffer address
+ dd 1 << 16 ; 64K bounce buffer
+ dd core_farcall ; Farcall entry point
+ dd core_cfarcall ; Cfarcall entry point
+HighMemSize dd 0 ; End of memory pointer (bytes)
diff --git a/core/comboot.inc b/core/comboot.inc
index cdba16d5..25409595 100644
--- a/core/comboot.inc
+++ b/core/comboot.inc
@@ -17,7 +17,7 @@
;; Common code for running a COMBOOT image
;;
- section .text
+ section .text16
; Parameter registers definition; this is the definition
; of the stack frame used by INT 21h and INT 22h.
@@ -63,7 +63,7 @@
; Looks like a COMBOOT image but too large
comboot_too_large:
- call close_file
+ pm_call close_file
mov si,err_comlarge
call writestr
jmp enter_command
@@ -126,7 +126,7 @@ is_comboot_image:
mov bx,100h ; Load at <seg>:0100h
mov cx,10000h >> SECTOR_SHIFT
; Absolute maximum # of sectors
- call getfssec
+ pm_call getfssec
cmp ecx,65536-256-2 ; Maximum size
ja comboot_too_large
@@ -148,8 +148,8 @@ comboot_return: cli ; May not have a safe stack
jmp comboot_exit
;
-; Set up the COMBOOT API interrupt vectors. This is also used
-; by the COM32 code.
+; Set up the COMBOOT API interrupt vectors. This is now done at
+; initialization time.
;
comboot_setup_api:
mov di,DOSErrTramp ; Error trampolines
@@ -178,11 +178,23 @@ comboot_setup_api:
loop .loop2
ret
- section .bss
+;
+; Restore the original state of the COMBOOT API vectors
+;
+comboot_cleanup_api:
+ pusha
+ mov si,DOSSaveVectors
+ mov di,4*20h
+ mov cx,20h
+ rep movsd ; Restore DOS-range vectors
+ popa
+ ret
+
+ section .bss16
alignb 4
DOSSaveVectors resd 32
- section .data
+ section .data16
%define comboot_err(x) (DOSErrTramp+4*((x)-20h))
comboot_vectors:
@@ -219,7 +231,7 @@ comboot_vectors:
dw comboot_err(3Eh) ; INT 3E = DOS FPU emulation
dw comboot_err(3Fh) ; INT 3F = DOS overlay manager
- section .text
+ section .text16
; INT 21h: generic DOS system call
comboot_int21: sti
@@ -295,12 +307,6 @@ comboot_exit_msg:
pop bx ; Return address
RESET_STACK_AND_SEGS SI ; Contains sti, cld
call adjust_screen ; The COMBOOT program might have changed the screen
- pusha
- mov si,DOSSaveVectors
- mov di,4*20h
- mov cx,20h
- rep movsd ; Restore DOS-range vectors
- popa
jcxz .nomsg
mov si,KernelCName
call writestr
@@ -511,9 +517,9 @@ comapi_open:
mov ds,P_ES
mov si,P_SI
mov di,InitRD
- call mangle_name
+ pm_call mangle_name
pop ds
- call searchdir
+ pm_call searchdir
jz comapi_err
mov P_EAX,eax
mov P_CX,SECTOR_SIZE
@@ -529,7 +535,7 @@ comapi_read:
mov bx,P_BX
mov si,P_SI
mov cx,P_CX
- call getfssec
+ pm_call getfssec
jnc .noteof
xor si,si ; SI <- 0 on EOF, CF <- 0
.noteof: mov P_SI,si
@@ -541,7 +547,7 @@ comapi_read:
;
comapi_close:
mov si,P_SI
- call close_file
+ pm_call close_file
clc
ret
@@ -629,7 +635,7 @@ comapi_cleanup:
test dl,3
setnz [KeepPXE]
sub bp,sp ; unload_pxe may move the stack around
- call unload_pxe
+ pm_call unload_pxe
add bp,sp ; restore frame pointer...
%elif IS_SYSLINUX || IS_EXTLINUX
; Restore original FDC table
@@ -680,10 +686,11 @@ comapi_ipappend:
; INT 22h AX=0010h Resolve hostname
;
%if IS_PXELINUX
+ extern pxe_dns_resolv
comapi_dnsresolv:
mov ds,P_ES
mov si,P_BX
- call dns_resolv
+ pm_call pxe_dns_resolv
mov P_EAX,eax
clc
ret
@@ -691,7 +698,7 @@ comapi_dnsresolv:
comapi_dnsresolv equ comapi_err
%endif
- section .text
+ section .text16
;
; INT 22h AX=0011h Obsolete
@@ -742,9 +749,9 @@ comapi_runkernel:
mov ds,P_DS
mov si,P_SI
mov di,KernelName
- call mangle_name
+ pm_call mangle_name
pop ds
- call searchdir
+ pm_call searchdir
jz comapi_err
; The kernel image was found, so we can load it...
@@ -892,59 +899,44 @@ comapi_getcwd:
;
; INT 22h AX=0020h Open directory
;
-%if IS_SYSLINUX
+%if IS_PXELINUX
+comapi_opendir equ comapi_err
+
+%else
comapi_opendir:
- push ds
- mov ds,P_ES
+ mov es,P_ES
mov si,P_SI
mov di,InitRD
- call mangle_name
- pop ds
- call searchdir
- jnz comapi_err ; Didn't find a directory
+ pm_call opendir
+ jz comapi_err ; Didn't find a directory
cmp eax,0
jz comapi_err ; Found nothing
- ;ZF is unset
- call alloc_fill_dir
- mov P_EAX,eax
- mov P_CX,SECTOR_SIZE
- mov P_SI,si
+ mov P_EAX,eax
clc
ret
-%else
-comapi_opendir equ comapi_err
%endif
;
; INT 22h AX=0021h Read directory
;
-%if IS_SYSLINUX
+%if IS_PXELINUX
+comapi_readdir equ comapi_err
+
+%else
comapi_readdir:
- mov es,P_ES
- mov di,P_DI
- mov si,P_SI
- call readdir
- mov P_EAX,eax
- mov P_DL,dl
- mov P_EBX,ebx
- mov P_SI,si
+ mov esi,P_ESI ; The address of DIR structure
+ pm_call readdir
+ mov P_EAX,eax ; The address of newly read dirent structure
ret
-%else
-comapi_readdir equ comapi_err
%endif
;
; INT 22h AX=0022h Close directory
;
-%if IS_SYSLINUX
comapi_closedir:
- mov si,P_SI
- call close_dir
- clc
+ mov esi,P_ESI ; The address of DIR structure
+ pm_call closedir
ret
-%else
-comapi_closedir equ comapi_err
-%endif
;
; INT 22h AX=0023h Query shuffler size
@@ -963,7 +955,7 @@ comapi_shufraw:
mov ecx,P_ECX
jmp shuffle_and_boot_raw
- section .data
+ section .data16
%macro int21 2
db %1
@@ -1042,8 +1034,10 @@ feature_flags_len equ ($-feature_flags)
err_notdos db ': attempted DOS system call INT ',0
err_comlarge db 'COMBOOT image too large.', CR, LF, 0
- section .bss1
+ section .bss16
alignb 4
DOSErrTramp resd 33 ; Error trampolines
+
+ global ConfigName, CurrentDirName
ConfigName resb FILENAME_MAX
CurrentDirName resb FILENAME_MAX
diff --git a/core/common.inc b/core/common.inc
new file mode 100644
index 00000000..7078011e
--- /dev/null
+++ b/core/common.inc
@@ -0,0 +1,25 @@
+;
+; Modules common to all derivatives. Do not include modules in this list
+; which have special section requirements (i.e. need to be in .init for
+; some derivatives.)
+;
+
+%include "getc.inc" ; getc et al
+%include "conio.inc" ; Console I/O
+%include "configinit.inc" ; Initialize configuration
+%include "parseconfig.inc" ; High-level config file handling
+%include "parsecmd.inc" ; Low-level config file handling
+%include "pm.inc" ; Protected mode
+%include "bcopy32.inc" ; 32-bit bcopy
+%include "loadhigh.inc" ; Load a file into high memory
+%include "font.inc" ; VGA font stuff
+%include "graphics.inc" ; VGA graphics
+%include "highmem.inc" ; High memory sizing
+%include "strcpy.inc" ; strcpy()
+%include "idle.inc" ; Idle handling
+%include "adv.inc" ; Auxillary Data Vector
+%include "timer.inc" ; Timer handling
+
+; Note: the prefix section is included late, to avoid problems with some
+; versions of NASM that had issues with forward references to EQU symbols.
+%include "prefix.inc" ; Prefix section for prepcore
diff --git a/core/config.inc b/core/config.inc
index 5a3d1c5a..269e13ec 100644
--- a/core/config.inc
+++ b/core/config.inc
@@ -32,6 +32,12 @@ MAX_FKEYS equ 12 ; Number of F-key help files
%assign HAS_LOCALBOOT 1
;
+; log2(Max filename size Including final null)
+;
+FILENAME_MAX_LG2 equ 8
+FILENAME_MAX equ (1 << FILENAME_MAX_LG2) ; Max mangled filename size
+
+;
; Version number definitinons
;
%include "../version.gen"
diff --git a/core/configinit.inc b/core/configinit.inc
index c6fdaf76..915e77f7 100644
--- a/core/configinit.inc
+++ b/core/configinit.inc
@@ -17,7 +17,7 @@
;; Initialize the configuration section
;;
- section .text
+ section .text16
reset_config:
call highmemsize
diff --git a/core/conio.inc b/core/conio.inc
index 16c39c65..835359fb 100644
--- a/core/conio.inc
+++ b/core/conio.inc
@@ -24,7 +24,7 @@
; loadkeys: Load a LILO-style keymap; file is open on the top of the
; getc stack.
;
- section .text
+ section .text16
loadkeys:
mov cx,256
@@ -207,8 +207,8 @@ msg_viewimage:
mov byte [si],0 ; Zero-terminate filename
mov si,VGAFileBuf
mov di,VGAFileMBuf
- call mangle_name
- call open
+ pm_call mangle_name
+ call core_open
jz msg_putcharnext ; Not there
call vgadisplayfile
; Fall through
@@ -389,7 +389,7 @@ debug_tracer: pushad
ret
%endif ; DEBUG_TRACERS
- section .data
+ section .data16
%if IS_ISOLINUX == 0 ; Defined elsewhere for ISOLINUX
crlf_msg db CR, LF
null_msg db 0
@@ -402,7 +402,7 @@ DisplayCon dw 01h ; Console display enabled
ScrollAttribute db 07h ; Grey on white (normal text color)
- section .bss
+ section .bss16
alignb 2
NextCharJump resw 1 ; Routine to interpret next print char
CursorDX equ $
@@ -414,7 +414,7 @@ VidRows resb 1 ; Rows on screen-1
; Serial console stuff; don't put this in .config becasue we don't want
; loading a new config file to undo this setting.
- section .data
+ section .data16
alignz 4
SerialPort dw 0 ; Serial port base (or 0 for no serial port)
BaudDivisor dw 115200/9600 ; Baud rate divisor
@@ -424,8 +424,9 @@ FlowInput db 0 ; Input bits for serial flow
FlowIgnore db 0 ; Ignore input unless these bits set
FlowDummy db 0 ; Unused
- section .bss
+ section .bss16
TextAttribute resb 1 ; Text attribute for message file
DisplayMask resb 1 ; Display modes mask
+ section .text16
%include "serirq.inc"
diff --git a/core/cpuinit.inc b/core/cpuinit.inc
deleted file mode 100644
index 4d8cc2e7..00000000
--- a/core/cpuinit.inc
+++ /dev/null
@@ -1,52 +0,0 @@
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
-;;
-;; 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., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; cpuinit.inc
-;;
-;; CPU-dependent initialization and related checks.
-;;
-
-check_escapes:
- mov ah,02h ; Check keyboard flags
- int 16h
- mov [KbdFlags],al ; Save for boot prompt check
- test al,04h ; Ctrl->skip 386 check
- jnz skip_checks
-
-;
-; Now check that there is sufficient low (DOS) memory
-;
-; NOTE: Linux doesn't use all of real_mode_seg, but we use the same
-; segment for COMBOOT images, which can use all 64K
-;
-dosram_k equ (real_mode_seg+0x1000) >> 6 ; Minimum DOS memory (K)
- int 12h
- cmp ax,dosram_k
- jae enough_ram
- mov si,err_noram
- call writestr_early
- jmp kaboom
-enough_ram:
-skip_checks:
-
- section .data
-err_noram db 'It appears your computer has less than '
- asciidec dosram_k
- db 'K of low ("DOS")'
- db CR, LF
- db 'RAM. Linux needs at least this amount to boot. If you get'
- db CR, LF
- db 'this message in error, hold down the Ctrl key while'
- db CR, LF
- db 'booting, and I will take your word for it.', CR, LF, 0
- section .text
diff --git a/core/dir.c b/core/dir.c
new file mode 100644
index 00000000..4013280a
--- /dev/null
+++ b/core/dir.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/dirent.h>
+#include "fs.h"
+#include "core.h"
+
+/*
+ * open dir, return the file structure pointer in _eax_, or NULL if failed
+ */
+void opendir(com32sys_t *regs)
+{
+ char *src = MK_PTR(regs->es, regs->esi.w[0]);
+ char *dst = MK_PTR(regs->ds, regs->edi.w[0]);
+ strcpy(dst, src);
+ searchdir(regs);
+ regs->eax.l = (uint32_t)handle_to_file(regs->esi.w[0]);
+}
+
+/*
+ * Read one dirent at one time.
+ *
+ * @input: _esi_ register stores the address of DIR structure
+ * @output: _eax_ register stores the address of newly read dirent structure
+ */
+void readdir(com32sys_t *regs)
+{
+ DIR *dir = (DIR *)regs->esi.l;
+ struct dirent *de = NULL;
+
+ if (dir->dd_dir)
+ de = this_fs->fs_ops->readdir(dir->dd_dir);
+ else
+ de = NULL;
+
+ /* Return the newly read de in _eax_ register */
+ regs->eax.l = (uint32_t)de;
+}
+
+void closedir(com32sys_t *regs)
+{
+ DIR *dir = (DIR *)regs->esi.l;
+ _close_file(dir->dd_dir);
+}
+
+
diff --git a/core/diskfs.inc b/core/diskfs.inc
new file mode 100644
index 00000000..b8d03762
--- /dev/null
+++ b/core/diskfs.inc
@@ -0,0 +1,182 @@
+; -*- fundamental -*- (asm-mode sucks)
+; -----------------------------------------------------------------------
+;
+; Copyright 1994-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.
+;
+; -----------------------------------------------------------------------
+
+;
+; diskfs.inc
+;
+; Common code for conventional disk-based filesystems
+;
+
+;
+; Some semi-configurable constants... change on your own risk.
+;
+NULLFILE equ 0 ; Null character == empty filename
+NULLOFFSET equ 0 ; Position in which to look
+retry_count equ 16 ; How patient are we with the disk?
+%assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top
+LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with
+
+SECTOR_SHIFT equ 9
+SECTOR_SIZE equ (1 << SECTOR_SHIFT)
+
+;
+; The following structure is used for "virtual kernels"; i.e. LILO-style
+; option labels. The options we permit here are `kernel' and `append
+; Since there is no room in the bottom 64K for all of these, we
+; stick them in high memory and copy them down before we need them.
+;
+ struc vkernel
+vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!**
+vk_rname: resb FILENAME_MAX ; Real name
+vk_appendlen: resw 1
+vk_type: resb 1 ; Type of file
+ alignb 4
+vk_append: resb max_cmd_len+1 ; Command line
+ alignb 4
+vk_end: equ $ ; Should be <= vk_size
+ endstruc
+
+
+
+; ---------------------------------------------------------------------------
+; BEGIN CODE
+; ---------------------------------------------------------------------------
+
+;
+; Memory below this point is reserved for the BIOS and the MBR
+;
+ section .earlybss
+ global trackbuf
+trackbufsize equ 8192
+trackbuf resb trackbufsize ; Track buffer goes here
+ ; ends at 2800h
+
+;
+; Common bootstrap code for disk-based derivatives
+;
+%include "diskstart.inc"
+
+
+;
+; Now, everything is "up and running"... patch kaboom for more
+; verbosity and using the full screen system
+;
+ ; E9 = JMP NEAR
+ mov di,kaboom.patch
+ mov al,0e9h
+ stosb
+ mov ax,kaboom2-2
+ sub ax,di
+ stosw
+
+;
+; Now we're all set to start with our *real* business. First load the
+; configuration file (if any) and parse it.
+;
+; In previous versions I avoided using 32-bit registers because of a
+; rumour some BIOSes clobbered the upper half of 32-bit registers at
+; random. I figure, though, that if there are any of those still left
+; they probably won't be trying to install Linux on them...
+;
+; The code is still ripe with 16-bitisms, though. Not worth the hassle
+; to take'm out. In fact, we may want to put them back if we're going
+; to boot ELKS at some point.
+;
+
+;
+; Load configuration file
+;
+ pm_call load_config
+ jz no_config_file
+
+;
+; Now we have the config file open. Parse the config file and
+; run the user interface.
+;
+%include "ui.inc"
+
+;
+;
+; kaboom2: once everything is loaded, replace the part of kaboom
+; starting with "kaboom.patch" with this part
+
+kaboom2:
+ mov si,err_bootfailed
+ call writestr
+ cmp byte [kaboom.again+1],18h ; INT 18h version?
+ je .int18
+ call getchar
+ call vgaclearmode
+ int 19h ; And try once more to boot...
+.norge: jmp short .norge ; If int 19h returned; this is the end
+.int18:
+ call vgaclearmode
+ int 18h
+.noreg: jmp short .noreg ; Nynorsk
+
+; -----------------------------------------------------------------------------
+; Common modules
+; -----------------------------------------------------------------------------
+
+%include "common.inc" ; Universal modules
+%include "plaincon.inc" ; writechr
+%include "writestr.inc" ; String output
+%include "writehex.inc" ; Hexadecimal output
+%include "localboot.inc" ; Disk-based local boot
+
+; -----------------------------------------------------------------------------
+; Begin data section
+; -----------------------------------------------------------------------------
+
+ section .data16
+copyright_str db ' Copyright (C) 1994-'
+ asciidec YEAR
+ db ' H. Peter Anvin et al', CR, LF, 0
+err_bootfailed db CR, LF, 'Boot failed: please change disks and press '
+ db 'a key to continue.', CR, LF, 0
+
+;
+; Config file keyword table
+;
+%include "keywords.inc"
+
+;
+; Extensions to search for (in *forward* order).
+;
+ alignz 4
+exten_table: db '.cbt' ; COMBOOT (specific)
+%if IS_SYSLINUX
+ db '.bss' ; Boot sector (add superblock)
+%endif
+ db '.bs', 0 ; Boot sector
+ db '.com' ; COMBOOT (same as DOS)
+ db '.c32' ; COM32
+exten_table_end:
+ dd 0, 0 ; Need 8 null bytes here
+
+;
+; Misc initialized (data) variables
+;
+%ifdef debug ; This code for debugging only
+debug_magic dw 0D00Dh ; Debug code sentinel
+%endif
+
+ alignz 4
+BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf
+BufSafeBytes dw trackbufsize ; = how many bytes?
+%ifndef DEPEND
+%if ( trackbufsize % SECTOR_SIZE ) != 0
+%error trackbufsize must be a multiple of SECTOR_SIZE
+%endif
+%endif
diff --git a/core/diskio.c b/core/diskio.c
new file mode 100644
index 00000000..eddcd8d8
--- /dev/null
+++ b/core/diskio.c
@@ -0,0 +1,318 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <klibc/compiler.h>
+#include <core.h>
+#include <fs.h>
+#include <disk.h>
+
+#define RETRY_COUNT 6
+
+static uint16_t MaxTransfer = 1 << (16 - 9);
+
+static int chs_rdwr_sectors(struct disk *disk, void *buf,
+ sector_t lba, size_t count, bool is_write)
+{
+ char *ptr = buf;
+ char *tptr;
+ size_t chunk, freeseg;
+ int sector_shift = disk->sector_shift;
+ uint32_t xlba = lba + disk->part_start; /* Truncated LBA (CHS is << 2 TB) */
+ uint32_t t;
+ uint16_t c, h, s;
+ com32sys_t ireg, oreg;
+ size_t done = 0;
+ size_t bytes;
+ int retry;
+
+ memset(&ireg, 0, sizeof ireg);
+
+ ireg.eax.b[1] = 0x02 + is_write;
+ ireg.edx.b[0] = disk->disk_number;
+
+ while (count) {
+ chunk = count;
+ if (chunk > MaxTransfer)
+ chunk = MaxTransfer;
+
+ freeseg = (0x10000 - ((size_t)ptr & 0xffff)) >> sector_shift;
+
+ if ((size_t)buf <= 0xf0000 && freeseg) {
+ /* Can do a direct load */
+ tptr = ptr;
+ } else {
+ /* Either accessing high memory or we're crossing a 64K line */
+ tptr = core_xfer_buf;
+ freeseg = (0x10000 - ((size_t)tptr & 0xffff)) >> sector_shift;
+ }
+ if (chunk > freeseg)
+ chunk = freeseg;
+
+ bytes = chunk << sector_shift;
+
+ if (tptr != ptr && is_write)
+ memcpy(tptr, ptr, bytes);
+
+ s = xlba % disk->s;
+ t = xlba / disk->s;
+ h = t % disk->h;
+ c = t / disk->h;
+
+ ireg.eax.b[0] = chunk;
+ ireg.ecx.b[1] = c;
+ ireg.ecx.b[0] = ((c & 0x300) >> 2) | (s+1);
+ ireg.edx.b[1] = h;
+ ireg.ebx.w[0] = OFFS(tptr);
+ ireg.es = SEG(tptr);
+
+ retry = RETRY_COUNT;
+
+ for (;;) {
+ __intcall(0x13, &ireg, &oreg);
+ if (!(oreg.eflags.l & EFLAGS_CF))
+ break;
+ if (retry--)
+ continue;
+
+ /* if we are reading ONE sector and go here, just make it _faile_ */
+ chunk = chunk == 1 ? 0 : ((chunk+1) >> 1);
+ if (chunk) {
+ MaxTransfer = chunk;
+ retry = RETRY_COUNT;
+ ireg.eax.b[0] = chunk;
+ continue;
+ }
+ return done; /* Failure */
+ }
+
+ bytes = chunk << sector_shift;
+
+ if (tptr != ptr && !is_write)
+ memcpy(ptr, tptr, bytes);
+
+ ptr += bytes;
+ xlba += chunk;
+ count -= chunk;
+ done += chunk;
+ }
+
+ return done;
+}
+
+struct edd_rdwr_packet {
+ uint16_t size;
+ uint16_t blocks;
+ far_ptr_t buf;
+ uint64_t lba;
+};
+
+static int edd_rdwr_sectors(struct disk *disk, void *buf,
+ sector_t lba, size_t count, bool is_write)
+{
+ static __lowmem struct edd_rdwr_packet pkt;
+ char *ptr = buf;
+ char *tptr;
+ size_t chunk, freeseg;
+ int sector_shift = disk->sector_shift;
+ com32sys_t ireg, oreg;
+ size_t done = 0;
+ size_t bytes;
+ int retry;
+
+ memset(&ireg, 0, sizeof ireg);
+
+ ireg.eax.b[1] = 0x42 + is_write;
+ ireg.edx.b[0] = disk->disk_number;
+ ireg.ds = SEG(&pkt);
+ ireg.esi.w[0] = OFFS(&pkt);
+
+ lba += disk->part_start;
+ while (count) {
+ chunk = count;
+ if (chunk > MaxTransfer)
+ chunk = MaxTransfer;
+
+ freeseg = (0x10000 - ((size_t)ptr & 0xffff)) >> sector_shift;
+
+ if ((size_t)buf <= 0xf0000 && freeseg) {
+ /* Can do a direct load */
+ tptr = ptr;
+ } else {
+ /* Either accessing high memory or we're crossing a 64K line */
+ tptr = core_xfer_buf;
+ freeseg = (0x10000 - ((size_t)tptr & 0xffff)) >> sector_shift;
+ }
+ if (chunk > freeseg)
+ chunk = freeseg;
+
+ bytes = chunk << sector_shift;
+
+ if (tptr != ptr && is_write)
+ memcpy(tptr, ptr, bytes);
+
+ pkt.size = sizeof pkt;
+ pkt.blocks = chunk;
+ pkt.buf = FAR_PTR(tptr);
+ pkt.lba = lba;
+
+ retry = RETRY_COUNT;
+
+ for (;;) {
+ __intcall(0x13, &ireg, &oreg);
+ if (!(oreg.eflags.l & EFLAGS_CF))
+ break;
+ if (retry--)
+ continue;
+ chunk = chunk == 1 ? 0 : ((chunk+1) >> 1);
+ if (chunk) {
+ MaxTransfer = chunk;
+ retry = RETRY_COUNT;
+ pkt.blocks = chunk;
+ continue;
+ }
+ /*** XXX: Consider falling back to CHS here?! ***/
+ printf("reading sectors error(EDD)\n");
+ return done; /* Failure */
+ }
+
+ bytes = chunk << sector_shift;
+
+ if (tptr != ptr && !is_write)
+ memcpy(ptr, tptr, bytes);
+
+ ptr += bytes;
+ lba += chunk;
+ count -= chunk;
+ done += chunk;
+ }
+ return done;
+}
+struct edd_disk_params {
+ uint16_t len;
+ uint16_t flags;
+ uint32_t phys_c;
+ uint32_t phys_h;
+ uint32_t phys_s;
+ uint64_t sectors;
+ uint16_t sector_size;
+ far_ptr_t dpte;
+ uint16_t devpath_key;
+ uint8_t devpath_len;
+ uint8_t _pad1[3];
+ char bus_type[4];
+ char if_type[8];
+ uint8_t if_path[8];
+ uint8_t dev_path[8];
+ uint8_t _pad2;
+ uint8_t devpath_csum;
+} __attribute__((packed));
+
+static inline bool is_power_of_2(uint32_t x)
+{
+ return !(x & (x-1));
+}
+
+static int ilog2(uint32_t num)
+{
+ int i = 0;
+
+ if (!is_power_of_2(num)) {
+ printf("ERROR: the num must be power of 2 when conveting to log2\n");
+ return 0;
+ }
+ while (num >>= 1)
+ i++;
+ return i;
+}
+
+void getoneblk(struct disk *disk, char *buf, block_t block, int block_size)
+{
+ int sec_per_block = block_size / disk->sector_size;
+
+ disk->rdwr_sectors(disk, buf, block * sec_per_block, sec_per_block, 0);
+}
+
+
+struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start,
+ uint16_t bsHeads, uint16_t bsSecPerTrack)
+{
+ static struct disk disk;
+ static __lowmem struct edd_disk_params edd_params;
+ com32sys_t ireg, oreg;
+ bool ebios = cdrom;
+ int sector_size = cdrom ? 2048 : 512;
+
+ memset(&ireg, 0, sizeof ireg);
+
+ /* Get EBIOS support */
+ ireg.eax.b[1] = 0x41;
+ ireg.ebx.w[0] = 0x55aa;
+ ireg.edx.b[0] = devno;
+ ireg.eflags.b[0] = 0x3; /* CF set */
+
+ __intcall(0x13, &ireg, &oreg);
+
+ if (cdrom || (!(oreg.eflags.l & EFLAGS_CF) &&
+ oreg.ebx.w[0] == 0xaa55 && (oreg.ecx.b[0] & 1))) {
+ ebios = true;
+
+ /* Query EBIOS parameters */
+ edd_params.len = sizeof edd_params;
+
+ ireg.eax.b[1] = 0x48;
+ ireg.ds = SEG(&edd_params);
+ ireg.esi.w[0] = OFFS(&edd_params);
+ __intcall(0x13, &ireg, &oreg);
+
+ if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.b[1] == 0) {
+ if (edd_params.len < sizeof edd_params)
+ memset((char *)&edd_params + edd_params.len, 0,
+ sizeof edd_params - edd_params.len);
+ if (edd_params.sector_size >= 512 &&
+ is_power_of_2(edd_params.sector_size))
+ sector_size = edd_params.sector_size;
+ }
+ }
+
+ /* CBIOS parameters */
+ disk.h = bsHeads;
+ disk.s = bsSecPerTrack;
+
+ if ((int8_t)devno < 0) {
+ /* Get hard disk geometry from BIOS */
+
+ ireg.eax.b[1] = 0x08;
+ __intcall(0x13, &ireg, &oreg);
+
+ if (!(oreg.eflags.l & EFLAGS_CF)) {
+ disk.h = oreg.edx.b[1] + 1;
+ disk.s = oreg.ecx.b[0] & 63;
+ }
+ }
+
+ disk.disk_number = devno;
+ disk.type = ebios;
+ disk.sector_size = sector_size;
+ disk.sector_shift = ilog2(sector_size);
+ disk.part_start = part_start;
+ disk.rdwr_sectors = ebios ? edd_rdwr_sectors : chs_rdwr_sectors;
+
+ return &disk;
+}
+
+
+/*
+ * initialize the device structure
+ */
+struct device * device_init(uint8_t devno, bool cdrom, sector_t part_start,
+ uint16_t bsHeads, uint16_t bsSecPerTrack)
+{
+ static struct device dev;
+
+ dev.disk = disk_init(devno, cdrom, part_start, bsHeads, bsSecPerTrack);
+
+ dev.cache_data = core_cache_buf;
+ dev.cache_size = sizeof core_cache_buf;
+
+ return &dev;
+}
diff --git a/core/diskstart.inc b/core/diskstart.inc
index 53229223..dfc7f8cb 100644
--- a/core/diskstart.inc
+++ b/core/diskstart.inc
@@ -18,11 +18,12 @@
;
; Expanded superblock
- section .bss
+ section .earlybss
alignb 8
SuperInfo resq 16 ; The first 16 bytes expanded 8 times
+DriveNumber resb 1
- section .text
+ section .init
;
; Some of the things that have to be saved very early are saved
; "close" to the initial stack pointer offset, in order to
@@ -33,6 +34,7 @@ PartInfo equ StackBuf ; Saved partition table entry
FloppyTable equ PartInfo+16 ; Floppy info table (must follow PartInfo)
OrigFDCTabPtr equ StackBuf-8 ; The 2nd high dword on the stack
OrigESDI equ StackBuf-4 ; The high dword on the stack
+StackTop equ OrigFDCTabPtr ; The start of the canonical stack
;
; Primary entry point. Tempting as though it may be, we can't put the
@@ -94,6 +96,7 @@ superblock_len_fat32 equ $-superblock+54
zb 54 ; Maximum needed size
superblock_max equ $-superblock
+ global SecPerClust
SecPerClust equ bxSecPerClust
;
; Note we don't check the constraints above now; we did that at install
@@ -250,6 +253,7 @@ getonesec:
; that is dead from that point; this saves space. However, please keep
; the order to dst,src to keep things sane.
;
+ global getlinsec
getlinsec:
add eax,[bsHidden] ; Add partition offset
xor edx,edx ; Zero-extend LBA (eventually allow 64 bits)
@@ -407,11 +411,12 @@ getlinsec_cbios:
;
; kaboom: write a message and bail out.
;
+ global kaboom
disk_error:
kaboom:
xor si,si
mov ss,si
- mov sp,StackBuf-4 ; Reset stack
+ mov sp,OrigFDCTabPtr ; Reset stack
mov ds,si ; Reset data segment
pop dword [fdctab] ; Restore FDC table
.patch: ; When we have full code, intercept here
@@ -451,6 +456,7 @@ bailmsg: db 'Boot error', 0Dh, 0Ah, 0
zb 1F8h-($-$$)
FirstSector dd 0xDEADBEEF ; Location of sector 1
+ global MaxTransfer
MaxTransfer dw 0x007F ; Max transfer size
; This field will be filled in 0xAA55 by the installer, but we abuse it
@@ -480,18 +486,15 @@ ldlinux_magic dd LDLINUX_MAGIC
; LDLINUX_MAGIC, plus 8 bytes.
;
patch_area:
-LDLDwords dw 0 ; Total dwords starting at ldlinux_sys,
- ; not including ADVs
-LDLSectors dw 0 ; Number of sectors - (bootsec+this sec)
- ; but including any ADVs
+DataSectors dw 0 ; Number of sectors (not including bootsec)
+ADVSectors dw 0 ; Additional sectors for ADVs
+LDLDwords dd 0 ; Total dwords starting at ldlinux_sys,
CheckSum dd 0 ; Checksum starting at ldlinux_sys
; value = LDLINUX_MAGIC - [sum of dwords]
-%if IS_EXTLINUX
-CurrentDir dd 2 ; "Current" directory inode number
-%endif
-
-; Space for up to 64 sectors, the theoretical maximum
-SectorPtrs times 64 dd 0
+ global CurrentDir
+CurrentDir dd 2 ; "Current" directory inode number (EXTLINUX)
+SecPtrOffset dw SectorPtrs - ldlinux_sys
+SecPtrCnt dw (SectorPtrsEnd - SectorPtrs) >> 2
ldlinux_ent:
;
@@ -523,23 +526,25 @@ print_bios:
mov [BIOSName],si
call writestr_early
- section .bss
+ section .earlybss
%define HAVE_BIOSNAME 1
BIOSName resw 1
- section .text
+ section .init
;
; Now we read the rest of LDLINUX.SYS. Don't bother loading the first
; sector again, though.
;
load_rest:
- mov si,SectorPtrs
- mov bx,7C00h+2*SECTOR_SIZE ; Where we start loading
- mov cx,[LDLSectors]
+ lea esi,[SectorPtrs]
+ mov ebx,7C00h+2*SECTOR_SIZE ; Where we start loading
+ mov cx,[DataSectors]
+ dec cx ; Minus this sector
.get_chunk:
jcxz .done
- xor bp,bp
+ xor ebp,ebp
+ mov di,bx ; Low 64K of target address
lodsd ; First sector of this chunk
mov edx,eax
@@ -548,16 +553,27 @@ load_rest:
inc bp
dec cx
jz .chunk_ready
+ cmp ebx,esi ; Pointer we don't have yet?
+ jae .chunk_ready
inc edx ; Next linear sector
cmp [si],edx ; Does it match
jnz .chunk_ready ; If not, this is it
add si,4 ; If so, add sector to chunk
- jmp short .make_chunk
+ add di,SECTOR_SIZE ; Check for 64K segment wrap
+ jnz .make_chunk
.chunk_ready:
+ push ebx
+ push es
+ shr ebx,4 ; Convert to a segment
+ mov es,bx
+ xor bx,bx
+ xor edx,edx ; Zero-extend LBA
call getlinsecsr
- shl bp,SECTOR_SHIFT
- add bx,bp
+ pop es
+ pop ebx
+ shl ebp,SECTOR_SHIFT
+ add ebx,ebp
jmp .get_chunk
.done:
@@ -569,14 +585,23 @@ load_rest:
;
verify_checksum:
mov si,ldlinux_sys
- mov cx,[LDLDwords]
- mov edx,-LDLINUX_MAGIC
+ mov ecx,[LDLDwords]
+ mov eax,-LDLINUX_MAGIC
+ push ds
.checksum:
- lodsd
- add edx,eax
- loop .checksum
+ add eax,[si]
+ add si,4
+ jnz .nowrap
+ ; Handle segment wrap
+ mov dx,ds
+ add dx,1000h
+ mov ds,dx
+.nowrap:
+ dec ecx
+ jnz .checksum
+ pop ds
- and edx,edx ; Should be zero
+ and eax,eax ; Should be zero
jz all_read ; We're cool, go for it!
;
@@ -647,15 +672,23 @@ rl_checkpt equ $ ; Must be <= 8000h
rl_checkpt_off equ ($-$$)
%ifndef DEPEND
-%if rl_checkpt_off > 400h
+%if rl_checkpt_off > 3FCh ; Need one pointer in here
%error "Sector 1 overflow"
%endif
%endif
+; Sector pointers
+ alignz 4
+MaxInitDataSize equ 96 << 10
+MaxLMA equ 0x7c00+SECTOR_SIZE+MaxInitDataSize
+SectorPtrs times MaxInitDataSize >> SECTOR_SHIFT dd 0
+SectorPtrsEnd equ $
+
; ----------------------------------------------------------------------------
; End of code and data that have to be in the first sector
; ----------------------------------------------------------------------------
+ section .text16
all_read:
;
; Let the user (and programmer!) know we got this far. This used to be
@@ -681,7 +714,21 @@ expand_super:
stosd ; Store expanded byte
loop .loop
+
;
-; Fall through to the mainline code...
+; Common initialization code
;
- section .text
+%include "init.inc"
+
+ pushad
+ mov eax,ROOT_FS_OPS
+ movzx dx,byte [DriveNumber]
+ ; DH = 0: we are boot from disk not CDROM
+ mov ecx,[bsHidden]
+ ; Reserved for upper 32 bits of partition offset...
+ ; mov ebx,[bsHidden+4]
+ xor ebx,ebx
+ mov si,[bsHeads]
+ mov di,[bsSecPerTrack]
+ pm_call fs_init
+ popad
diff --git a/core/dnsresolv.inc b/core/dnsresolv.inc
deleted file mode 100644
index c2c429cb..00000000
--- a/core/dnsresolv.inc
+++ /dev/null
@@ -1,389 +0,0 @@
-; -*- fundamental -*-
-; -----------------------------------------------------------------------
-;
-; Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
-;
-; 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., 53 Temple Place Ste 330,
-; Bostom MA 02111-1307, USA; either version 2 of the License, or
-; (at your option) any later version; incorporated herein by reference.
-;
-; -----------------------------------------------------------------------
-
-;
-; dnsresolv.inc
-;
-; Very simple DNS resolver (assumes recursion-enabled DNS server;
-; this should be the normal thing for client-serving DNS servers.)
-;
-
-DNS_PORT equ htons(53) ; Default DNS port
-DNS_MAX_PACKET equ 512 ; Defined by protocol
-; TFTP uses the range 49152-57343
-DNS_LOCAL_PORT equ htons(60053) ; All local DNS queries come from this port #
-DNS_MAX_SERVERS equ 4 ; Max no of DNS servers
-
- section .text
-
-;
-; Turn a string in DS:SI into a DNS "label set" in ES:DI.
-; On return, DI points to the first byte after the label set,
-; and SI to the terminating byte.
-;
-; On return, DX contains the number of dots encountered.
-;
-dns_mangle:
- push ax
- push bx
- xor dx,dx
-.isdot:
- inc dx
- xor al,al
- mov bx,di
- stosb
-.getbyte:
- lodsb
- and al,al
- jz .endstring
- cmp al,':'
- jz .endstring
- cmp al,'.'
- je .isdot
- inc byte [es:bx]
- stosb
- jmp .getbyte
-.endstring:
- dec si
- dec dx ; We always counted one high
- cmp byte [es:bx],0
- jz .done
- xor al,al
- stosb
-.done:
- pop bx
- pop ax
- ret
-
-;
-; Compare two sets of DNS labels, in DS:SI and ES:DI; the one in SI
-; is allowed pointers relative to a packet in DNSRecvBuf.
-;
-; Assumes DS == ES. ZF = 1 if same; no registers changed.
-; (Note: change reference to [di] to [es:di] to remove DS == ES assumption)
-;
-dns_compare:
- pusha
-%if 0
-
-.label:
- lodsb
- cmp al,0C0h
- jb .noptr
- and al,03Fh ; Get pointer value
- mov ah,al ; ... in network byte order!
- lodsb
- mov si,DNSRecvBuf
- add si,ax
- jmp .label
-.noptr:
- cmp al,[di]
- jne .done ; Mismatch
- inc di
- movzx cx,al ; End label?
- and cx,cx ; ZF = 1 if match
- jz .done
-
- ; We have a string of bytes that need to match now
- repe cmpsb
- je .label
-
-.done:
-%else
- xor ax,ax
-%endif
- popa
- ret
-
-;
-; Skip past a DNS label set in DS:SI.
-;
-dns_skiplabel:
- push ax
- xor ax,ax ; AH == 0
-.loop:
- lodsb
- cmp al,0C0h ; Pointer?
- jae .ptr
- and al,al
- jz .done
- add si,ax
- jmp .loop
-.ptr:
- inc si ; Pointer is two bytes
-.done:
- pop ax
- ret
-
- ; DNS header format
- struc dnshdr
-.id: resw 1
-.flags: resw 1
-.qdcount: resw 1
-.ancount: resw 1
-.nscount: resw 1
-.arcount: resw 1
- endstruc
-
- ; DNS query
- struc dnsquery
-.qtype: resw 1
-.qclass: resw 1
- endstruc
-
- ; DNS RR
- struc dnsrr
-.type: resw 1
-.class: resw 1
-.ttl: resd 1
-.rdlength: resw 1
-.rdata: equ $
- endstruc
-
- section .bss2
- alignb 2
-DNSSendBuf resb DNS_MAX_PACKET
-DNSRecvBuf resb DNS_MAX_PACKET
-LocalDomain resb 256 ; Max possible length
-DNSServers resd DNS_MAX_SERVERS
-
- section .data
-pxe_udp_write_pkt_dns:
-.status: dw 0 ; Status
-.sip: dd 0 ; Server IP
-.gip: dd 0 ; Gateway IP
-.lport: dw DNS_LOCAL_PORT ; Local port
-.rport: dw DNS_PORT ; Remote port
-.buffersize: dw 0 ; Size of packet
-.buffer: dw DNSSendBuf, 0 ; off, seg of buffer
-
-pxe_udp_read_pkt_dns:
-.status: dw 0 ; Status
-.sip: dd 0 ; Source IP
-.dip: dd 0 ; Destination (our) IP
-.rport: dw DNS_PORT ; Remote port
-.lport: dw DNS_LOCAL_PORT ; Local port
-.buffersize: dw DNS_MAX_PACKET ; Max packet size
-.buffer: dw DNSRecvBuf, 0 ; off, seg of buffer
-
-LastDNSServer dw DNSServers
-
-; Actual resolver function
-; Points to a null-terminated or :-terminated string in DS:SI
-; and returns the name in EAX if it exists and can be found.
-; If EAX = 0 on exit, the lookup failed.
-;
-; No segment assumptions permitted.
-;
- section .text
-dns_resolv:
- push ds
- push es
- push di
- push bx
- push cx
- push dx
-
- push cs
- pop es ; ES <- CS
-
- ; First, build query packet
- mov di,DNSSendBuf+dnshdr.flags
- inc word [es:di-2] ; New query ID
- mov ax,htons(0100h) ; Recursion requested
- stosw
- mov ax,htons(1) ; One question
- stosw
- xor ax,ax ; No answers, NS or ARs
- stosw
- stosw
- stosw
-
- call dns_mangle ; Convert name to DNS labels
-
- push cs ; DS <- CS
- pop ds
-
- push si ; Save pointer to after DNS string
-
- ; Initialize...
- mov eax,[MyIP]
- mov [pxe_udp_read_pkt_dns.dip],eax
-
- and dx,dx
- jnz .fqdn ; If we have dots, assume it's FQDN
- dec di ; Remove final null
- mov si,LocalDomain
- call strcpy ; Uncompressed DNS label set so it ends in null
-.fqdn:
-
- mov ax,htons(1)
- stosw ; QTYPE = 1 = A
- stosw ; QCLASS = 1 = IN
-
- sub di,DNSSendBuf
- mov [pxe_udp_write_pkt_dns.buffersize],di
-
- ; Now, send it to the nameserver(s)
- ; Outer loop: exponential backoff
- ; Inner loop: scan the various DNS servers
-
- mov bx,TimeoutTable
-.backoff:
- movzx dx,byte [bx]
- mov si,DNSServers
-.servers:
- cmp si,[LastDNSServer]
- jb .moreservers
-
-.nomoreservers:
- inc bx
- cmp bx,TimeoutTableEnd
- jb .backoff
-
- xor eax,eax ; Nothing...
-.done:
- pop si
- pop dx
- pop cx
- pop bx
- pop di
- pop es
- pop ds
- ret
-
-.moreservers:
- lodsd ; EAX <- next server
- push si
- push bx
- push cx
- push dx
-
- mov word [pxe_udp_write_pkt_dns.status],0
-
- mov [pxe_udp_write_pkt_dns.sip],eax
- mov [pxe_udp_read_pkt_dns.sip],eax
- xor eax,[MyIP]
- and eax,[Netmask]
- jz .nogw
- mov eax,[Gateway]
-.nogw:
- mov [pxe_udp_write_pkt_dns.gip],eax
-
- mov di,pxe_udp_write_pkt_dns
- mov bx,PXENV_UDP_WRITE
- call pxenv
- jc .timeout ; Treat failed transmit as timeout
- cmp word [pxe_udp_write_pkt_dns.status],0
- jne .timeout
-
- mov cx,[BIOS_timer]
-.waitrecv:
- mov ax,[BIOS_timer]
- sub ax,cx
- cmp ax,dx
- jae .timeout
-
- mov word [pxe_udp_read_pkt_dns.status],0
- mov word [pxe_udp_read_pkt_dns.buffersize],DNS_MAX_PACKET
- mov di,pxe_udp_read_pkt_dns
- mov bx,PXENV_UDP_READ
- call pxenv
- and ax,ax
- jnz .waitrecv
- cmp [pxe_udp_read_pkt_dns.status],ax
- jnz .waitrecv
-
- ; Got a packet, deal with it...
- mov si,DNSRecvBuf
- lodsw
- cmp ax,[DNSSendBuf] ; ID
- jne .waitrecv ; Not ours
-
- lodsw ; flags
- xor al,80h ; Query#/Answer bit
- test ax,htons(0F80Fh)
- jnz .badness
-
- lodsw
- xchg ah,al ; ntohs
- mov cx,ax ; Questions echoed
- lodsw
- xchg ah,al ; ntohs
- push ax ; Replies
- lodsw ; NS records
- lodsw ; Authority records
-
- jcxz .qskipped
-.skipq:
- call dns_skiplabel ; Skip name
- add si,4 ; Skip question trailer
- loop .skipq
-
-.qskipped:
- pop cx ; Number of replies
- jcxz .badness
-
-.parseanswer:
- mov di,DNSSendBuf+dnshdr_size
- call dns_compare
- pushf
- call dns_skiplabel
- mov ax,[si+8] ; RDLENGTH
- xchg ah,al ; ntohs
- popf
- jnz .notsame
- cmp dword [si],htons(1)*0x10001 ; TYPE = A, CLASS = IN?
- jne .notsame
- cmp ax,4 ; RDLENGTH = 4?
- jne .notsame
- ;
- ; We hit paydirt here...
- ;
- mov eax,[si+10]
-.gotresult:
- add sp,8 ; Drop timeout information
- jmp .done
-
-.notsame:
- add si,10
- add si,ax
- loop .parseanswer
-
-.badness:
- ; We got back no data from this server.
- ; Unfortunately, for a recursive, non-authoritative
- ; query there is no such thing as an NXDOMAIN reply,
- ; which technically means we can't draw any
- ; conclusions. However, in practice that means the
- ; domain doesn't exist. If this turns out to be a
- ; problem, we may want to add code to go through all
- ; the servers before giving up.
-
- ; If the DNS server wasn't capable of recursion, and
- ; isn't capable of giving us an authoritative reply
- ; (i.e. neither AA or RA set), then at least try a
- ; different setver...
-
- test word [DNSRecvBuf+dnshdr.flags],htons(0480h)
- jz .timeout
-
- xor eax,eax
- jmp .gotresult
-
-.timeout:
- pop dx
- pop cx
- pop bx
- pop si
- jmp .servers
diff --git a/core/ext2_fs.inc b/core/ext2_fs.inc
deleted file mode 100644
index e84efb14..00000000
--- a/core/ext2_fs.inc
+++ /dev/null
@@ -1,183 +0,0 @@
-; -----------------------------------------------------------------------
-;
-; Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
-;
-; 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., 675 Mass Ave, Cambridge MA 02139,
-; USA; either version 2 of the License, or (at your option) any later
-; version; incorporated herein by reference.
-;
-; -----------------------------------------------------------------------
-
-;
-; ext2_fs.inc
-;
-; NASM include file for ext2fs data structures
-;
-
-%define EXT2_SUPER_MAGIC 0xEF53
-
-%define EXT2_GOOD_OLD_REV 0 ; The good old (original) format
-%define EXT2_DYNAMIC_REV 1 ; V2 format w/ dynamic inode sizes
-%define EXT2_GOOD_OLD_INODE_SIZE 128
-
-; Special inode numbers
-%define EXT2_BAD_INO 1 ; Bad blocks inode
-%define EXT2_ROOT_INO 2 ; Root inode
-%define EXT2_BOOT_LOADER_INO 5 ; Boot loader inode
-%define EXT2_UNDEL_DIR_INO 6 ; Undelete directory inode
-%define EXT3_RESIZE_INO 7 ; Reserved group descriptors inode
-%define EXT3_JOURNAL_INO 8 ; Journal inode
-
-; We're readonly, so we only care about incompat features.
-%define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
-%define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
-%define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004
-%define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
-%define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
-%define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
-
-%define EXT2_NDIR_BLOCKS 12
-%define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
-%define EXT2_DIND_BLOCK (EXT2_IND_BLOCK+1)
-%define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK+1)
-%define EXT2_N_BLOCKS (EXT2_TIND_BLOCK+1)
-
-;
-; File types and file modes
-;
-%define S_IFDIR 0040000o ; Directory
-%define S_IFCHR 0020000o ; Character device
-%define S_IFBLK 0060000o ; Block device
-%define S_IFREG 0100000o ; Regular file
-%define S_IFIFO 0010000o ; FIFO
-%define S_IFLNK 0120000o ; Symbolic link
-%define S_IFSOCK 0140000o ; Socket
-
-%define S_IFSHIFT 12
-
-%define T_IFDIR (S_IFDIR >> S_IFSHIFT)
-%define T_IFCHR (S_IFCHR >> S_IFSHIFT)
-%define T_IFBLK (S_IFBLK >> S_IFSHIFT)
-%define T_IFREG (S_IFREG >> S_IFSHIFT)
-%define T_IFIFO (S_IFIFO >> S_IFSHIFT)
-%define T_IFLNK (S_IFLNK >> S_IFSHIFT)
-%define T_IFSOCK (S_IFSOCK >> S_IFSHIFT)
-
-;
-; Structure definition for the ext2 superblock
-;
- struc ext2_super_block
-s_inodes_count resd 1 ; Inodes count
-s_blocks_count resd 1 ; Blocks count
-s_r_blocks_count resd 1 ; Reserved blocks count
-s_free_blocks_count resd 1 ; Free blocks count
-s_free_inodes_count resd 1 ; Free inodes count
-s_first_data_block resd 1 ; First Data Block
-s_log_block_size resd 1 ; Block size
-s_log_frag_size resd 1 ; Fragment size
-s_blocks_per_group resd 1 ; # Blocks per group
-s_frags_per_group resd 1 ; # Fragments per group
-s_inodes_per_group resd 1 ; # Inodes per group
-s_mtime resd 1 ; Mount time
-s_wtime resd 1 ; Write time
-s_mnt_count resw 1 ; Mount count
-s_max_mnt_count resw 1 ; Maximal mount count
-s_magic resw 1 ; Magic signature
-s_state resw 1 ; File system state
-s_errors resw 1 ; Behaviour when detecting errors
-s_minor_rev_level resw 1 ; minor revision level
-s_lastcheck resd 1 ; time of last check
-s_checkinterval resd 1 ; max. time between checks
-s_creator_os resd 1 ; OS
-s_rev_level resd 1 ; Revision level
-s_def_resuid resw 1 ; Default uid for reserved blocks
-s_def_resgid resw 1 ; Default gid for reserved blocks
-s_first_ino resd 1 ; First non-reserved inode
-s_inode_size resw 1 ; size of inode structure
-s_block_group_nr resw 1 ; block group # of this superblock
-s_feature_compat resd 1 ; compatible feature set
-s_feature_incompat resd 1 ; incompatible feature set
-s_feature_ro_compat resd 1 ; readonly-compatible feature set
-s_uuid resb 16 ; 128-bit uuid for volume
-s_volume_name resb 16 ; volume name
-s_last_mounted resb 64 ; directory where last mounted
-s_algorithm_usage_bitmap resd 1 ; For compression
-s_prealloc_blocks resb 1 ; Nr of blocks to try to preallocate
-s_prealloc_dir_blocks resb 1 ; Nr to preallocate for dirs
-s_padding1 resw 1
-s_reserved resd 204 ; Padding to the end of the block
- endstruc
-
-%ifndef DEPEND
-%if ext2_super_block_size != 1024
-%error "ext2_super_block definition bogus"
-%endif
-%endif
-
-;
-; Structure definition for the ext2 inode
-;
- struc ext2_inode
-i_mode resw 1 ; File mode
-i_uid resw 1 ; Owner Uid
-i_size resd 1 ; Size in bytes
-i_atime resd 1 ; Access time
-i_ctime resd 1 ; Creation time
-i_mtime resd 1 ; Modification time
-i_dtime resd 1 ; Deletion Time
-i_gid resw 1 ; Group Id
-i_links_count resw 1 ; Links count
-i_blocks resd 1 ; Blocks count
-i_flags resd 1 ; File flags
-l_i_reserved1 resd 1
-i_block resd EXT2_N_BLOCKS ; Pointer to blocks
-i_version resd 1 ; File version (for NFS)
-i_file_acl resd 1 ; File ACL
-i_dir_acl resd 1 ; Directory ACL
-i_faddr resd 1 ; Fragment address
-l_i_frag resb 1 ; Fragment number
-l_i_fsize resb 1 ; Fragment size
-i_pad1 resw 1
-l_i_reserved2 resd 2
- endstruc
-
-%ifndef DEPEND
-%if ext2_inode_size != 128
-%error "ext2_inode definition bogus"
-%endif
-%endif
-
-;
-; Structure definition for ext2 block group descriptor
-;
- struc ext2_group_desc
-bg_block_bitmap resd 1 ; Block bitmap block
-bg_inode_bitmap resd 1 ; Inode bitmap block
-bg_inode_table resd 1 ; Inode table block
-bg_free_blocks_count resw 1 ; Free blocks count
-bg_free_inodes_count resw 1 ; Free inodes count
-bg_used_dirs_count resw 1 ; Used inodes count
-bg_pad resw 1
-bg_reserved resd 3
- endstruc
-
-%ifndef DEPEND
-%if ext2_group_desc_size != 32
-%error "ext2_group_desc definition bogus"
-%endif
-%endif
-
-%define ext2_group_desc_lg2size 5
-
-;
-; Structure definition for ext2 directory entry
-;
- struc ext2_dir_entry
-d_inode resd 1 ; Inode number
-d_rec_len resw 1 ; Directory entry length
-d_name_len resb 1 ; Name length
-d_file_type resb 1 ; File type
-d_name equ $
- endstruc
diff --git a/core/extern.inc b/core/extern.inc
new file mode 100644
index 00000000..95a9c88d
--- /dev/null
+++ b/core/extern.inc
@@ -0,0 +1,26 @@
+;
+; extern.inc
+;
+; Prototypes for external functions
+
+%ifndef EXTERN_INC
+%define EXTERN_INC
+
+ ; rllpack.c
+ extern rllpack, rllunpack
+
+ ; hello.c
+ extern hello
+
+ ; fs.c
+ extern fs_init, searchdir, getfssec, mangle_name, load_config
+ extern unmangle_name, close_file
+
+ ; dir.c
+ extern opendir, readdir, closedir
+%if IS_PXELINUX
+ ; pxe.c
+ extern unload_pxe, reset_pxe
+%endif
+
+%endif ; EXTERN_INC
diff --git a/core/extlinux.asm b/core/extlinux.asm
index ac5fb6f0..1ac749bc 100644
--- a/core/extlinux.asm
+++ b/core/extlinux.asm
@@ -18,914 +18,19 @@
%define IS_EXTLINUX 1
%include "head.inc"
-%include "ext2_fs.inc"
;
; Some semi-configurable constants... change on your own risk.
;
my_id equ extlinux_id
-; NASM 0.98.38 croaks if these are equ's rather than macros...
-FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null)
-FILENAME_MAX equ (1 << FILENAME_MAX_LG2) ; Max mangled filename size
-NULLFILE equ 0 ; Null character == empty filename
-NULLOFFSET equ 0 ; Position in which to look
-retry_count equ 16 ; How patient are we with the disk?
-%assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top
-LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with
-
-MAX_OPEN_LG2 equ 6 ; log2(Max number of open files)
-MAX_OPEN equ (1 << MAX_OPEN_LG2)
-
-SECTOR_SHIFT equ 9
-SECTOR_SIZE equ (1 << SECTOR_SHIFT)
-
-MAX_SYMLINKS equ 64 ; Maximum number of symlinks per lookup
-SYMLINK_SECTORS equ 2 ; Max number of sectors in a symlink
- ; (should be >= FILENAME_MAX)
-
-ROOT_DIR_WORD equ 0x002F
-CUR_DIR_DWORD equ 0x00002F2E
-
-;
-; The following structure is used for "virtual kernels"; i.e. LILO-style
-; option labels. The options we permit here are `kernel' and `append
-; Since there is no room in the bottom 64K for all of these, we
-; stick them in high memory and copy them down before we need them.
-;
- struc vkernel
-vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!**
-vk_rname: resb FILENAME_MAX ; Real name
-vk_appendlen: resw 1
-vk_type: resb 1 ; Type of file
- alignb 4
-vk_append: resb max_cmd_len+1 ; Command line
- alignb 4
-vk_end: equ $ ; Should be <= vk_size
- endstruc
-
-;
-; File structure. This holds the information for each currently open file.
-;
- struc open_file_t
-file_bytesleft resd 1 ; Number of bytes left (0 = free)
-file_sector resd 1 ; Next linear sector to read
-file_in_sec resd 1 ; Sector where inode lives
-file_in_off resw 1
-file_mode resw 1
- endstruc
-
-%ifndef DEPEND
-%if (open_file_t_size & (open_file_t_size-1))
-%error "open_file_t is not a power of 2"
-%endif
-%endif
-
-; ---------------------------------------------------------------------------
-; BEGIN CODE
-; ---------------------------------------------------------------------------
-
-;
-; Memory below this point is reserved for the BIOS and the MBR
-;
- section .earlybss
-trackbufsize equ 8192
-trackbuf resb trackbufsize ; Track buffer goes here
- ; ends at 2800h
-
- section .bss
-SuperBlock resb 1024 ; ext2 superblock
-ClustSize resd 1 ; Bytes/cluster ("block")
-ClustMask resd 1 ; Sectors/cluster - 1
-PtrsPerBlock1 resd 1 ; Pointers/cluster
-PtrsPerBlock2 resd 1 ; (Pointers/cluster)^2
-DriveNumber resb 1 ; BIOS drive number
-ClustShift resb 1 ; Shift count for sectors/cluster
-ClustByteShift resb 1 ; Shift count for bytes/cluster
-
- alignb open_file_t_size
-Files resb MAX_OPEN*open_file_t_size
-
-;
-; Common bootstrap code for disk-based derivatives
-;
-%include "diskstart.inc"
-
-;
-; Load the real (ext2) superblock; 1024 bytes long at offset 1024
-;
- mov bx,SuperBlock
- mov eax,1024 >> SECTOR_SHIFT
- mov bp,ax
- call getlinsecsr
-
-;
-; Compute some values...
-;
- xor edx,edx
- inc edx
-
- ; s_log_block_size = log2(blocksize) - 10
- mov cl,[SuperBlock+s_log_block_size]
- add cl,10
- mov [ClustByteShift],cl
- mov eax,edx
- shl eax,cl
- mov [ClustSize],eax
-
- sub cl,SECTOR_SHIFT
- mov [ClustShift],cl
- shr eax,SECTOR_SHIFT
- mov [SecPerClust],eax
- dec eax
- mov [ClustMask],eax
-
- add cl,SECTOR_SHIFT-2 ; 4 bytes/pointer
- shl edx,cl
- mov [PtrsPerBlock1],edx
- shl edx,cl
- mov [PtrsPerBlock2],edx
-
-;
-; Common initialization code
-;
-%include "init.inc"
-%include "cpuinit.inc"
-
-;
-; Initialize the metadata cache
-;
- call initcache
-
-;
-; Now, everything is "up and running"... patch kaboom for more
-; verbosity and using the full screen system
-;
- ; E9 = JMP NEAR
- mov dword [kaboom.patch],0e9h+((kaboom2-(kaboom.patch+3)) << 8)
-
-;
-; Now we're all set to start with our *real* business. First load the
-; configuration file (if any) and parse it.
-;
-; In previous versions I avoided using 32-bit registers because of a
-; rumour some BIOSes clobbered the upper half of 32-bit registers at
-; random. I figure, though, that if there are any of those still left
-; they probably won't be trying to install Linux on them...
-;
-; The code is still ripe with 16-bitisms, though. Not worth the hassle
-; to take'm out. In fact, we may want to put them back if we're going
-; to boot ELKS at some point.
-;
-
-;
-; Load configuration file
-;
-load_config:
- mov si,config_name ; Save config file name
- mov di,ConfigName
- call strcpy
- mov dword [CurrentDirName],CUR_DIR_DWORD ; Write './',0,0 to the CurrentDirName
- call build_curdir_str
-
- mov di,ConfigName
- call open
- jz no_config_file
-
-;
-; Now we have the config file open. Parse the config file and
-; run the user interface.
-;
-%include "ui.inc"
-
-;
-; getlinsec_ext: same as getlinsec, except load any sector from the zero
-; block as all zeros; use to load any data derived
-; from an ext2 block pointer, i.e. anything *except the
-; superblock.*
-;
-getonesec_ext:
- mov bp,1
-
-getlinsec_ext:
- cmp eax,[SecPerClust]
- jae getlinsecsr ; Nothing fancy
-
- ; If we get here, at least part of what we want is in the
- ; zero block. Zero one sector at a time and loop.
- push eax
- push cx
- xchg di,bx
- xor eax,eax
- mov cx,SECTOR_SIZE >> 2
- rep stosd
- xchg di,bx
- pop cx
- pop eax
- inc eax
- dec bp
- jnz getlinsec_ext
- ret
-
-;
-; allocate_file: Allocate a file structure
-;
-; If successful:
-; ZF set
-; BX = file pointer
-; In unsuccessful:
-; ZF clear
-;
-allocate_file:
- TRACER 'a'
- push cx
- mov bx,Files
- mov cx,MAX_OPEN
-.check: cmp dword [bx], byte 0
- je .found
- add bx,open_file_t_size ; ZF = 0
- loop .check
- ; ZF = 0 if we fell out of the loop
-.found: pop cx
- ret
-;
-; open_inode:
-; Open a file indicated by an inode number in EAX
-;
-; NOTE: This file considers finding a zero-length file an
-; error. This is so we don't have to deal with that special
-; case elsewhere in the program (most loops have the test
-; at the end).
-;
-; If successful:
-; ZF clear
-; SI = file pointer
-; EAX = file length in bytes
-; ThisInode = the first 128 bytes of the inode
-; If unsuccessful
-; ZF set
-;
-; Assumes CS == DS == ES.
-;
-open_inode.allocate_failure:
- xor eax,eax
- pop bx
- pop di
- ret
-
-open_inode:
- push di
- push bx
- call allocate_file
- jnz .allocate_failure
-
- push cx
- push gs
- ; First, get the appropriate inode group and index
- dec eax ; There is no inode 0
- xor edx,edx
- mov [bx+file_sector],edx
- div dword [SuperBlock+s_inodes_per_group]
- ; EAX = inode group; EDX = inode within group
- push edx
-
- ; Now, we need the block group descriptor.
- ; To get that, we first need the relevant descriptor block.
-
- shl eax, ext2_group_desc_lg2size ; Get byte offset in desc table
- xor edx,edx
- div dword [ClustSize]
- ; eax = block #, edx = offset in block
- add eax,dword [SuperBlock+s_first_data_block]
- inc eax ; s_first_data_block+1
- mov cl,[ClustShift]
- shl eax,cl
- push edx
- shr edx,SECTOR_SHIFT
- add eax,edx
- pop edx
- and dx,SECTOR_SIZE-1
- call getcachesector ; Get the group descriptor
- add si,dx
- mov esi,[gs:si+bg_inode_table] ; Get inode table block #
- pop eax ; Get inode within group
- movzx edx, word [SuperBlock+s_inode_size]
- mul edx
- ; edx:eax = byte offset in inode table
- div dword [ClustSize]
- ; eax = block # versus inode table, edx = offset in block
- add eax,esi
- shl eax,cl ; Turn into sector
- push dx
- shr edx,SECTOR_SHIFT
- add eax,edx
- mov [bx+file_in_sec],eax
- pop dx
- and dx,SECTOR_SIZE-1
- mov [bx+file_in_off],dx
-
- call getcachesector
- add si,dx
- mov cx,EXT2_GOOD_OLD_INODE_SIZE >> 2
- mov di,ThisInode
- gs rep movsd
-
- mov ax,[ThisInode+i_mode]
- mov [bx+file_mode],ax
- mov eax,[ThisInode+i_size]
- mov [bx+file_bytesleft],eax
- mov si,bx
- and eax,eax ; ZF clear unless zero-length file
- pop gs
- pop cx
- pop bx
- pop di
- ret
-
- section .bss
- alignb 4
-ThisInode resb EXT2_GOOD_OLD_INODE_SIZE ; The most recently opened inode
-
- section .text
-;
-; close_file:
-; Deallocates a file structure (pointer in SI)
-; Assumes CS == DS.
-;
-close_file:
- and si,si
- jz .closed
- mov dword [si],0 ; First dword == file_bytesleft
- xor si,si
-.closed: ret
-
-;
-; searchdir:
-; Search the root directory for a pre-mangled filename in DS:DI.
-;
-; NOTE: This file considers finding a zero-length file an
-; error. This is so we don't have to deal with that special
-; case elsewhere in the program (most loops have the test
-; at the end).
-;
-; If successful:
-; ZF clear
-; SI = file pointer
-; DX:AX = EAX = file length in bytes
-; If unsuccessful
-; ZF set
-;
-; Assumes CS == DS == ES; *** IS THIS CORRECT ***?
-;
-searchdir:
- push bx
- push cx
- push bp
- mov byte [SymlinkCtr],MAX_SYMLINKS
-
- mov eax,[CurrentDir]
-.begin_path:
-.leadingslash:
- cmp byte [di],'/' ; Absolute filename?
- jne .gotdir
- mov eax,EXT2_ROOT_INO
- inc di ; Skip slash
- jmp .leadingslash
-.gotdir:
-
- ; At this point, EAX contains the directory inode,
- ; and DS:DI contains a pathname tail.
-.open:
- push eax ; Save directory inode
-
- call open_inode
- jz .missing ; If error, done
-
- mov cx,[si+file_mode]
- shr cx,S_IFSHIFT ; Get file type
-
- cmp cx,T_IFDIR
- je .directory
-
- add sp,4 ; Drop directory inode
-
- cmp cx,T_IFREG
- je .file
- cmp cx,T_IFLNK
- je .symlink
-
- ; Otherwise, something bad...
-.err:
- call close_file
-.err_noclose:
- xor eax,eax
- xor si,si
- cwd ; DX <- 0
-
-.done:
- and eax,eax ; Set/clear ZF
- pop bp
- pop cx
- pop bx
- ret
-
-.missing:
- add sp,4 ; Drop directory inode
- jmp .done
-
- ;
- ; It's a file.
- ;
-.file:
- cmp byte [di],0 ; End of path?
- je .done ; If so, done
- jmp .err ; Otherwise, error
-
- ;
- ; It's a directory.
- ;
-.directory:
- pop dword [ThisDir] ; Remember what directory we're searching
-
- cmp byte [di],0 ; More path?
- je .err ; If not, bad
-
-.skipslash: ; Skip redundant slashes
- cmp byte [di],'/'
- jne .readdir
- inc di
- jmp .skipslash
-
-.readdir:
- mov cx,[SecPerClust]
- push cx
- shl cx,SECTOR_SHIFT
- mov bx,trackbuf
- add cx,bx
- mov [EndBlock],cx
- pop cx
- push bx
- call getfssec
- pop bx
- pushf ; Save EOF flag
- push si ; Save filesystem pointer
-.getent:
- cmp bx,[EndBlock]
- jae .endblock
-
- push di
- cmp dword [bx+d_inode],0 ; Zero inode = void entry
- je .nope
-
- movzx cx,byte [bx+d_name_len]
- lea si,[bx+d_name]
- repe cmpsb
- je .maybe
-.nope:
- pop di
- add bx,[bx+d_rec_len]
- jmp .getent
-
-.endblock:
- pop si
- popf
- jnc .readdir ; There is more
- jmp .err ; Otherwise badness...
-
-.maybe:
- mov eax,[bx+d_inode]
-
- ; Does this match the end of the requested filename?
- cmp byte [di],0
- je .finish
- cmp byte [di],'/'
- jne .nope
-
- ; We found something; now we need to open the file
-.finish:
- pop bx ; Adjust stack (di)
- pop si
- call close_file ; Close directory
- pop bx ; Adjust stack (flags)
- jmp .open
-
- ;
- ; It's a symlink. We have to determine if it's a fast symlink
- ; (data stored in the inode) or not (data stored as a regular
- ; file.) Either which way, we start from the directory
- ; which we just visited if relative, or from the root directory
- ; if absolute, and append any remaining part of the path.
- ;
-.symlink:
- dec byte [SymlinkCtr]
- jz .err ; Too many symlink references
-
- cmp eax,SYMLINK_SECTORS*SECTOR_SIZE
- jae .err ; Symlink too long
-
- ; Computation for fast symlink, as defined by ext2/3 spec
- xor ecx,ecx
- cmp [ThisInode+i_file_acl],ecx
- setne cl ; ECX <- i_file_acl ? 1 : 0
- cmp [ThisInode+i_blocks],ecx
- jne .slow_symlink
-
- ; It's a fast symlink
-.fast_symlink:
- call close_file ; We've got all we need
- mov si,ThisInode+i_block
-
- push di
- mov di,SymlinkTmpBuf
- mov ecx,eax
- rep movsb
- pop si
-
-.symlink_finish:
- cmp byte [si],0
- je .no_slash
- mov al,'/'
- stosb
-.no_slash:
- mov bp,SymlinkTmpBufEnd
- call strecpy
- jc .err_noclose ; Buffer overflow
-
- ; Now copy it to the "real" buffer; we need to have
- ; two buffers so we avoid overwriting the tail on the
- ; next copy
- mov si,SymlinkTmpBuf
- mov di,SymlinkBuf
- push di
- call strcpy
- pop di
- mov eax,[ThisDir] ; Resume searching previous directory
- jmp .begin_path
-
-.slow_symlink:
- mov bx,SymlinkTmpBuf
- mov cx,SYMLINK_SECTORS
- call getfssec
- ; The EOF closed the file
-
- mov si,di ; SI = filename tail
- mov di,SymlinkTmpBuf
- add di,ax ; AX = file length
- jmp .symlink_finish
-
-
- section .bss
- alignb 4
-SymlinkBuf resb SYMLINK_SECTORS*SECTOR_SIZE+64
-SymlinkTmpBuf equ trackbuf
-SymlinkTmpBufEnd equ trackbuf+SYMLINK_SECTORS*SECTOR_SIZE+64
-ThisDir resd 1
-EndBlock resw 1
-SymlinkCtr resb 1
-
- section .text
-;
-; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
-; to by ES:DI; ends on encountering any whitespace.
-; DI is preserved.
-;
-; This verifies that a filename is < FILENAME_MAX characters,
-; doesn't contain whitespace, zero-pads the output buffer,
-; and removes redundant slashes,
-; so "repe cmpsb" can do a compare, and the
-; path-searching routine gets a bit of an easier job.
-;
-; FIX: we may want to support \-escapes here (and this would
-; be the place.)
-;
-mangle_name:
- push di
- push bx
- xor ax,ax
- mov cx,FILENAME_MAX-1
- mov bx,di
-
-.mn_loop:
- lodsb
- cmp al,' ' ; If control or space, end
- jna .mn_end
- cmp al,ah ; Repeated slash?
- je .mn_skip
- xor ah,ah
- cmp al,'/'
- jne .mn_ok
- mov ah,al
-.mn_ok stosb
-.mn_skip: loop .mn_loop
-.mn_end:
- cmp bx,di ; At the beginning of the buffer?
- jbe .mn_zero
- cmp byte [di-1],'/' ; Terminal slash?
- jne .mn_zero
-.mn_kill: dec di ; If so, remove it
- inc cx
- jmp short .mn_end
-.mn_zero:
- inc cx ; At least one null byte
- xor ax,ax ; Zero-fill name
- rep stosb
- pop bx
- pop di
- ret ; Done
-
-;
-; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
-; filename to the conventional representation. This is needed
-; for the BOOT_IMAGE= parameter for the kernel.
-;
-; DS:SI -> input mangled file name
-; ES:DI -> output buffer
-;
-; On return, DI points to the first byte after the output name,
-; which is set to a null byte.
-;
-unmangle_name: call strcpy
- dec di ; Point to final null byte
- ret
-
-;
-;
-; kaboom2: once everything is loaded, replace the part of kaboom
-; starting with "kaboom.patch" with this part
-
-kaboom2:
- mov si,err_bootfailed
- call writestr
- cmp byte [kaboom.again+1],18h ; INT 18h version?
- je .int18
- call getchar
- call vgaclearmode
- int 19h ; And try once more to boot...
-.norge: jmp short .norge ; If int 19h returned; this is the end
-.int18:
- call vgaclearmode
- int 18h
-.noreg: jmp short .noreg ; Nynorsk
-
-
-;
-; linsector: Convert a linear sector index in a file to a linear sector number
-; EAX -> linear sector number
-; DS:SI -> open_file_t
-;
-; Returns next sector number in EAX; CF on EOF (not an error!)
-;
-linsector:
- push gs
- push ebx
- push esi
- push edi
- push ecx
- push edx
- push ebp
-
- push eax ; Save sector index
- mov cl,[ClustShift]
- shr eax,cl ; Convert to block number
- push eax
- mov eax,[si+file_in_sec]
- mov bx,si
- call getcachesector ; Get inode
- add si,[bx+file_in_off] ; Get *our* inode
- pop eax
- lea ebx,[i_block+4*eax]
- cmp eax,EXT2_NDIR_BLOCKS
- jb .direct
- mov ebx,i_block+4*EXT2_IND_BLOCK
- sub eax,EXT2_NDIR_BLOCKS
- mov ebp,[PtrsPerBlock1]
- cmp eax,ebp
- jb .ind1
- mov ebx,i_block+4*EXT2_DIND_BLOCK
- sub eax,ebp
- mov ebp,[PtrsPerBlock2]
- cmp eax,ebp
- jb .ind2
- mov ebx,i_block+4*EXT2_TIND_BLOCK
- sub eax,ebp
-
-.ind3:
- ; Triple indirect; eax contains the block no
- ; with respect to the start of the tind area;
- ; ebx contains the pointer to the tind block.
- xor edx,edx
- div dword [PtrsPerBlock2]
- ; EAX = which dind block, EDX = pointer within dind block
- push ax
- shr eax,SECTOR_SHIFT-2
- mov ebp,[gs:si+bx]
- shl ebp,cl
- add eax,ebp
- call getcachesector
- pop bx
- and bx,(SECTOR_SIZE >> 2)-1
- shl bx,2
- mov eax,edx ; The ind2 code wants the remainder...
-
-.ind2:
- ; Double indirect; eax contains the block no
- ; with respect to the start of the dind area;
- ; ebx contains the pointer to the dind block.
- xor edx,edx
- div dword [PtrsPerBlock1]
- ; EAX = which ind block, EDX = pointer within ind block
- push ax
- shr eax,SECTOR_SHIFT-2
- mov ebp,[gs:si+bx]
- shl ebp,cl
- add eax,ebp
- call getcachesector
- pop bx
- and bx,(SECTOR_SIZE >> 2)-1
- shl bx,2
- mov eax,edx ; The int1 code wants the remainder...
-
-.ind1:
- ; Single indirect; eax contains the block no
- ; with respect to the start of the ind area;
- ; ebx contains the pointer to the ind block.
- push ax
- shr eax,SECTOR_SHIFT-2
- mov ebp,[gs:si+bx]
- shl ebp,cl
- add eax,ebp
- call getcachesector
- pop bx
- and bx,(SECTOR_SIZE >> 2)-1
- shl bx,2
-
-.direct:
- mov ebx,[gs:bx+si] ; Get the pointer
-
- pop eax ; Get the sector index again
- shl ebx,cl ; Convert block number to sector
- and eax,[ClustMask] ; Add offset within block
- add eax,ebx
-
- pop ebp
- pop edx
- pop ecx
- pop edi
- pop esi
- pop ebx
- pop gs
- ret
-
-;
-; getfssec: Get multiple sectors from a file
-;
-; Same as above, except SI is a pointer to a open_file_t
-;
-; ES:BX -> Buffer
-; DS:SI -> Pointer to open_file_t
-; CX -> Sector count (0FFFFh = until end of file)
-; Must not exceed the ES segment
-; Returns CF=1 on EOF (not necessarily error)
-; On return ECX = number of bytes read
-; All arguments are advanced to reflect data read.
-;
-getfssec:
- push ebp
- push eax
- push edx
- push edi
-
- movzx ecx,cx
- push ecx ; Sectors requested read
- mov eax,[si+file_bytesleft]
- add eax,SECTOR_SIZE-1
- shr eax,SECTOR_SHIFT
- cmp ecx,eax ; Number of sectors left
- jbe .lenok
- mov cx,ax
-.lenok:
-.getfragment:
- mov eax,[si+file_sector] ; Current start index
- mov edi,eax
- call linsector
- push eax ; Fragment start sector
- mov edx,eax
- xor ebp,ebp ; Fragment sector count
-.getseccnt:
- inc bp
- dec cx
- jz .do_read
- xor eax,eax
- mov ax,es
- shl ax,4
- add ax,bx ; Now DI = how far into 64K block we are
- not ax ; Bytes left in 64K block
- inc eax
- shr eax,SECTOR_SHIFT ; Sectors left in 64K block
- cmp bp,ax
- jnb .do_read ; Unless there is at least 1 more sector room...
- inc edi ; Sector index
- inc edx ; Linearly next sector
- mov eax,edi
- call linsector
- ; jc .do_read
- cmp edx,eax
- je .getseccnt
-.do_read:
- pop eax ; Linear start sector
- pushad
- call getlinsec_ext
- popad
- push bp
- shl bp,9
- add bx,bp ; Adjust buffer pointer
- pop bp
- add [si+file_sector],ebp ; Next sector index
- jcxz .done
- jnz .getfragment
- ; Fall through
-.done:
- pop ecx ; Sectors requested read
- shl ecx,SECTOR_SHIFT
- sub [si+file_bytesleft],ecx
- jnbe .noteof ; CF=0 in this case
- add ecx,[si+file_bytesleft] ; Actual number of bytes read
- call close_file
- stc ; We hit EOF
-.noteof:
- pop edi
- pop edx
- pop eax
- pop ebp
- ret
-
-build_curdir_str:
- ret
-
-; -----------------------------------------------------------------------------
-; Common modules
-; -----------------------------------------------------------------------------
-
-%include "getc.inc" ; getc et al
-%include "conio.inc" ; Console I/O
-%include "plaincon.inc" ; writechr
-%include "writestr.inc" ; String output
-%include "writehex.inc" ; Hexadecimal output
-%include "configinit.inc" ; Initialize configuration
-%include "parseconfig.inc" ; High-level config file handling
-%include "parsecmd.inc" ; Low-level config file handling
-%include "bcopy32.inc" ; 32-bit bcopy
-%include "loadhigh.inc" ; Load a file into high memory
-%include "font.inc" ; VGA font stuff
-%include "graphics.inc" ; VGA graphics
-%include "highmem.inc" ; High memory sizing
-%include "strcpy.inc" ; strcpy()
-%include "strecpy.inc" ; strcpy with end pointer check
-%include "cache.inc" ; Metadata disk cache
-%include "idle.inc" ; Idle handling
-%include "adv.inc" ; Auxillary Data Vector
-%include "localboot.inc" ; Disk-based local boot
-
-; -----------------------------------------------------------------------------
-; Begin data section
-; -----------------------------------------------------------------------------
-
- section .data
-copyright_str db ' Copyright (C) 1994-'
- asciidec YEAR
- db ' H. Peter Anvin et al', CR, LF, 0
-err_bootfailed db CR, LF, 'Boot failed: please change disks and press '
- db 'a key to continue.', CR, LF, 0
-config_name db 'extlinux.conf',0 ; Unmangled form
-
-;
-; Config file keyword table
-;
-%include "keywords.inc"
-
-;
-; Extensions to search for (in *forward* order).
-;
- alignz 4
-exten_table: db '.cbt' ; COMBOOT (specific)
- db '.img' ; Disk image
- db '.bs', 0 ; Boot sector
- db '.com' ; COMBOOT (same as DOS)
- db '.c32' ; COM32
-exten_table_end:
- dd 0, 0 ; Need 8 null bytes here
-
-;
-; Misc initialized (data) variables
-;
-%ifdef debug ; This code for debugging only
-debug_magic dw 0D00Dh ; Debug code sentinel
-%endif
+ section .rodata
alignz 4
-BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf
-BufSafeBytes dw trackbufsize ; = how many bytes?
-%ifndef DEPEND
-%if ( trackbufsize % SECTOR_SIZE ) != 0
-%error trackbufsize must be a multiple of SECTOR_SIZE
-%endif
-%endif
+ROOT_FS_OPS:
+ extern ext2_fs_ops
+ dd ext2_fs_ops
+ extern btrfs_fs_ops
+ dd btrfs_fs_ops
+ dd 0
+
+%include "diskfs.inc"
diff --git a/core/font.inc b/core/font.inc
index 4090e5af..12236358 100644
--- a/core/font.inc
+++ b/core/font.inc
@@ -16,7 +16,7 @@
;; VGA font handling code
;;
- section .text
+ section .text16
;
; loadfont: Load a .psf font file and install it onto the VGA console
@@ -141,12 +141,12 @@ vidrows_ok: mov [VidRows],al
popa
ret
- section .data
+ section .data16
alignz 2
VGAFontSize dw 16 ; Defaults to 16 byte font
UserFont db 0 ; Using a user-specified font
- section .bss1
+ section .bss16
alignb 4
GXPixCols resw 1 ; Graphics mode pixel columns
GXPixRows resw 1 ; Graphics mode pixel rows
diff --git a/core/fs.c b/core/fs.c
new file mode 100644
index 00000000..0eac0f26
--- /dev/null
+++ b/core/fs.c
@@ -0,0 +1,300 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <fs.h>
+#include <cache.h>
+
+/* The currently mounted filesystem */
+struct fs_info *this_fs = NULL;
+static struct fs_info fs;
+struct inode *this_inode = NULL;
+
+/* Actual file structures (we don't have malloc yet...) */
+struct file files[MAX_OPEN];
+
+/*
+ * Get a new inode structure
+ */
+struct inode *alloc_inode(struct fs_info *fs, uint32_t ino, size_t data)
+{
+ struct inode *inode = zalloc(sizeof(struct inode) + data);
+ if (inode) {
+ inode->fs = fs;
+ inode->ino = ino;
+ }
+ return inode;
+}
+
+/*
+ * Get an empty file structure
+ */
+static struct file *alloc_file(void)
+{
+ int i;
+ struct file *file = files;
+
+ for (i = 0; i < MAX_OPEN; i++) {
+ if (!file->fs)
+ return file;
+ file++;
+ }
+
+ return NULL;
+}
+
+/*
+ * Close and free a file structure
+ */
+static inline void free_file(struct file *file)
+{
+ memset(file, 0, sizeof *file);
+}
+
+void _close_file(struct file *file)
+{
+ if (file->fs)
+ file->fs->fs_ops->close_file(file);
+ free_file(file);
+}
+
+/*
+ * Convert between a 16-bit file handle and a file structure
+ */
+inline uint16_t file_to_handle(struct file *file)
+{
+ return file ? (file - files)+1 : 0;
+}
+inline struct file *handle_to_file(uint16_t handle)
+{
+ return handle ? &files[handle-1] : NULL;
+}
+
+void load_config(void)
+{
+ int err;
+ err = this_fs->fs_ops->load_config();
+
+#if 0
+ printf("Loading config file %s\n", err ? "failed" : "successed");
+#endif
+}
+
+void mangle_name(com32sys_t *regs)
+{
+ const char *src = MK_PTR(regs->ds, regs->esi.w[0]);
+ char *dst = MK_PTR(regs->es, regs->edi.w[0]);
+
+ this_fs->fs_ops->mangle_name(dst, src);
+}
+
+
+void unmangle_name(com32sys_t *regs)
+{
+ const char *src = MK_PTR(regs->ds, regs->esi.w[0]);
+ char *dst = MK_PTR(regs->es, regs->edi.w[0]);
+
+ dst = this_fs->fs_ops->unmangle_name(dst, src);
+
+ /* Update the di register to point to the last null char */
+ regs->edi.w[0] = OFFS_WRT(dst, regs->es);
+}
+
+
+void getfssec(com32sys_t *regs)
+{
+ int sectors;
+ bool have_more;
+ uint32_t bytes_read;
+ char *buf;
+ struct file *file;
+ uint16_t handle;
+
+ sectors = regs->ecx.w[0];
+
+ handle = regs->esi.w[0];
+ file = handle_to_file(handle);
+
+ buf = MK_PTR(regs->es, regs->ebx.w[0]);
+ bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more);
+
+ /*
+ * If we reach EOF, the filesystem driver will have already closed
+ * the underlying file... this really should be cleaner.
+ */
+ if (!have_more) {
+ _close_file(file);
+ regs->esi.w[0] = 0;
+ }
+
+ regs->ecx.l = bytes_read;
+}
+
+
+void searchdir(com32sys_t *regs)
+{
+ char *name = MK_PTR(regs->ds, regs->edi.w[0]);
+ struct inode *inode;
+ struct inode *parent;
+ struct file *file;
+ char part[256];
+ char *p;
+ int symlink_count = 6;
+
+#if 0
+ printf("filename: %s\n", name);
+#endif
+
+ if (!(file = alloc_file()))
+ goto err_no_close;
+ file->fs = this_fs;
+
+ /* if we have ->searchdir method, call it */
+ if (file->fs->fs_ops->searchdir) {
+ file->fs->fs_ops->searchdir(name, file);
+
+ if (file->open_file) {
+ regs->esi.w[0] = file_to_handle(file);
+ regs->eax.l = file->file_len;
+ regs->eflags.l &= ~EFLAGS_ZF;
+ return;
+ }
+
+ goto err;
+ }
+
+
+ /* else, try the generic-path-lookup method */
+ if (*name == '/') {
+ inode = this_fs->fs_ops->iget_root(this_fs);
+ while(*name == '/')
+ name++;
+ } else {
+ inode = this_inode;
+ }
+ parent = inode;
+
+ while (*name) {
+ p = part;
+ while (*name && *name != '/')
+ *p++ = *name++;
+ *p = '\0';
+ if (strcmp(part, ".")) {
+ inode = this_fs->fs_ops->iget(part, parent);
+ if (!inode)
+ goto err;
+ if (inode->mode == I_SYMLINK) {
+ if (!this_fs->fs_ops->follow_symlink ||
+ --symlink_count == 0 || /* limit check */
+ inode->size >= BLOCK_SIZE(this_fs))
+ goto err;
+ name = this_fs->fs_ops->follow_symlink(inode, name);
+ free_inode(inode);
+ continue;
+ }
+
+ /*
+ * For the relative path searching used in FAT and ISO fs.
+ */
+ if ((this_fs->fs_ops->fs_flags & FS_THISIND) &&
+ (this_inode != parent)){
+ if (this_inode)
+ free_inode(this_inode);
+ this_inode = parent;
+ }
+
+ if (parent != this_inode)
+ free_inode(parent);
+ parent = inode;
+ }
+ if (!*name)
+ break;
+ while (*name == '/')
+ name++;
+ }
+
+ file->inode = inode;
+ file->offset = 0;
+
+ regs->esi.w[0] = file_to_handle(file);
+ regs->eax.l = inode->size;
+ regs->eflags.l &= ~EFLAGS_ZF;
+ return;
+
+err:
+ _close_file(file);
+err_no_close:
+ regs->esi.w[0] = 0;
+ regs->eax.l = 0;
+ regs->eflags.l |= EFLAGS_ZF;
+}
+
+void close_file(com32sys_t *regs)
+{
+ uint16_t handle = regs->esi.w[0];
+ struct file *file;
+
+ if (handle) {
+ file = handle_to_file(handle);
+ _close_file(file);
+ }
+}
+
+/*
+ * it will do:
+ * initialize the memory management function;
+ * set up the vfs fs structure;
+ * initialize the device structure;
+ * invoke the fs-specific init function;
+ * initialize the cache if we need one;
+ * finally, get the current inode for relative path looking.
+ *
+ */
+void fs_init(com32sys_t *regs)
+{
+ uint8_t disk_devno = regs->edx.b[0];
+ uint8_t disk_cdrom = regs->edx.b[1];
+ sector_t disk_offset = regs->ecx.l | ((sector_t)regs->ebx.l << 32);
+ uint16_t disk_heads = regs->esi.w[0];
+ uint16_t disk_sectors = regs->edi.w[0];
+ int blk_shift = -1;
+ struct device *dev = NULL;
+ /* ops is a ptr list for several fs_ops */
+ const struct fs_ops **ops = (const struct fs_ops **)regs->eax.l;
+
+ /* Initialize malloc() */
+ mem_init();
+
+ while ((blk_shift < 0) && *ops) {
+ /* set up the fs stucture */
+ fs.fs_ops = *ops;
+
+ /*
+ * This boldly assumes that we don't mix FS_NODEV filesystems
+ * with FS_DEV filesystems...
+ */
+ if (fs.fs_ops->fs_flags & FS_NODEV) {
+ fs.fs_dev = NULL;
+ } else {
+ if (!dev)
+ dev = device_init(disk_devno, disk_cdrom, disk_offset,
+ disk_heads, disk_sectors);
+ fs.fs_dev = dev;
+ }
+ /* invoke the fs-specific init code */
+ blk_shift = fs.fs_ops->fs_init(&fs);
+ ops++;
+ }
+ if (blk_shift < 0) {
+ printf("No valid file system found!\n");
+ while (1)
+ ;
+ }
+ this_fs = &fs;
+
+ /* initialize the cache */
+ if (fs.fs_dev && fs.fs_dev->cache_data)
+ cache_init(fs.fs_dev, blk_shift);
+
+ if (fs.fs_ops->iget_current)
+ this_inode = fs.fs_ops->iget_current(&fs);
+}
diff --git a/core/fs/btrfs/btrfs.c b/core/fs/btrfs/btrfs.c
new file mode 100644
index 00000000..31e24f77
--- /dev/null
+++ b/core/fs/btrfs/btrfs.c
@@ -0,0 +1,655 @@
+/*
+ * btrfs.c -- readonly btrfs support for syslinux
+ * Some data structures are derivated from btrfs-tools-0.19 ctree.h
+ * Copyright 2009 Intel Corporation; author: alek.du@intel.com
+ *
+ * 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., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <cache.h>
+#include <core.h>
+#include <disk.h>
+#include <fs.h>
+#include "btrfs.h"
+
+/* compare function used for bin_search */
+typedef int (*cmp_func)(void *ptr1, void *ptr2);
+
+/* simple but useful bin search, used for chunk search and btree search */
+static int bin_search(void *ptr, int item_size, void *cmp_item, cmp_func func,
+ int min, int max, int *slot)
+{
+ int low = min;
+ int high = max;
+ int mid;
+ int ret;
+ unsigned long offset;
+ void *item;
+
+ while (low < high) {
+ mid = (low + high) / 2;
+ offset = mid * item_size;
+
+ item = ptr + offset;
+ ret = func(item, cmp_item);
+
+ if (ret < 0)
+ low = mid + 1;
+ else if (ret > 0)
+ high = mid;
+ else {
+ *slot = mid;
+ return 0;
+ }
+ }
+ *slot = low;
+ return 1;
+}
+
+struct open_file_t {
+ u64 devid; /* always 1 if allocated, reserved for multi disks */
+ u64 bytenr; /* start offset in devid */
+ u64 pos; /* current offset in file */
+};
+
+static struct open_file_t Files[MAX_OPEN];
+static int cache_ready;
+static struct fs_info *fs;
+static struct btrfs_chunk_map chunk_map;
+static struct btrfs_super_block sb;
+/* used for small chunk read for btrfs_read */
+#define RAW_BUF_SIZE 4096
+static u8 raw_buf[RAW_BUF_SIZE];
+static u64 fs_tree;
+
+static int btrfs_comp_chunk_map(struct btrfs_chunk_map_item *m1,
+ struct btrfs_chunk_map_item *m2)
+{
+ if (m1->logical > m2->logical)
+ return 1;
+ if (m1->logical < m2->logical)
+ return -1;
+ return 0;
+}
+
+/* insert a new chunk mapping item */
+static void insert_map(struct btrfs_chunk_map_item *item)
+{
+ int ret;
+ int slot;
+ int i;
+
+ if (chunk_map.map == NULL) { /* first item */
+ chunk_map.map_length = BTRFS_MAX_CHUNK_ENTRIES;
+ chunk_map.map = (struct btrfs_chunk_map_item *)
+ malloc(chunk_map.map_length * sizeof(*chunk_map.map));
+ chunk_map.map[0] = *item;
+ chunk_map.cur_length = 1;
+ return;
+ }
+ ret = bin_search(chunk_map.map, sizeof(*item), item,
+ (cmp_func)btrfs_comp_chunk_map, 0,
+ chunk_map.cur_length, &slot);
+ if (ret == 0)/* already in map */
+ return;
+ if (chunk_map.cur_length == BTRFS_MAX_CHUNK_ENTRIES) {
+ /* should be impossible */
+ printf("too many chunk items\n");
+ return;
+ }
+ for (i = chunk_map.cur_length; i > slot; i--)
+ chunk_map.map[i] = chunk_map.map[i-1];
+ chunk_map.map[slot] = *item;
+ chunk_map.cur_length++;
+}
+
+/*
+ * from sys_chunk_array or chunk_tree, we can convert a logical address to
+ * a physical address we can not support multi device case yet
+ */
+static u64 logical_physical(u64 logical)
+{
+ struct btrfs_chunk_map_item item;
+ int slot, ret;
+
+ item.logical = logical;
+ ret = bin_search(chunk_map.map, sizeof(*chunk_map.map), &item,
+ (cmp_func)btrfs_comp_chunk_map, 0,
+ chunk_map.cur_length, &slot);
+ if (ret == 0)
+ slot++;
+ else if (slot == 0)
+ return -1;
+ if (logical >=
+ chunk_map.map[slot-1].logical + chunk_map.map[slot-1].length)
+ return -1;
+ return chunk_map.map[slot-1].physical + logical -
+ chunk_map.map[slot-1].logical;
+}
+
+/* raw read from disk, offset and count are bytes */
+static int raw_read(char *buf, u64 offset, u64 count)
+{
+ struct disk *disk = fs->fs_dev->disk;
+ size_t max = RAW_BUF_SIZE >> disk->sector_shift;
+ size_t off, cnt, done, total;
+ sector_t sec;
+
+ total = count;
+ while (count > 0) {
+ sec = offset >> disk->sector_shift;
+ off = offset - (sec << disk->sector_shift);
+ done = disk->rdwr_sectors(disk, raw_buf, sec, max, 0);
+ if (done == 0)/* no data */
+ break;
+ cnt = (done << disk->sector_shift) - off;
+ if (cnt > count)
+ cnt = count;
+ memcpy(buf, raw_buf + off, cnt);
+ count -= cnt;
+ buf += cnt;
+ offset += cnt;
+ if (done != max)/* no enough sectors */
+ break;
+ }
+ return total - count;
+}
+
+/* cache read from disk, offset and count are bytes */
+static int cache_read(char *buf, u64 offset, u64 count)
+{
+ size_t block_size = fs->fs_dev->cache_block_size;
+ struct cache_struct *cs;
+ size_t off, cnt, total;
+ block_t block;
+
+ total = count;
+ while (count > 0) {
+ block = offset / block_size;
+ off = offset % block_size;
+ cs = get_cache_block(fs->fs_dev, block);
+ if (cs == NULL)/* no data */
+ break;
+ cnt = block_size - off;
+ if (cnt > count)
+ cnt = count;
+ memcpy(buf, cs->data + off, cnt);
+ count -= cnt;
+ buf += cnt;
+ offset += cnt;
+ }
+ return total - count;
+}
+
+static int btrfs_read(char *buf, u64 offset, u64 count)
+{
+ if (cache_ready)
+ return cache_read(buf, offset, count);
+ return raw_read(buf, offset, count);
+}
+
+/* btrfs has several super block mirrors, need to calculate their location */
+static inline u64 btrfs_sb_offset(int mirror)
+{
+ u64 start = 16 * 1024;
+ if (mirror)
+ return start << (BTRFS_SUPER_MIRROR_SHIFT * mirror);
+ return BTRFS_SUPER_INFO_OFFSET;
+}
+
+/* find the most recent super block */
+static void btrfs_read_super_block(void)
+{
+ int i;
+ int ret;
+ u8 fsid[BTRFS_FSID_SIZE];
+ u64 offset;
+ u64 transid = 0;
+ struct btrfs_super_block buf;
+
+ /* find most recent super block */
+ for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
+ offset = btrfs_sb_offset(i);
+ ret = btrfs_read((char *)&buf, offset, sizeof(buf));
+ if (ret < sizeof(buf))
+ break;
+
+ if (buf.bytenr != offset ||
+ strncmp((char *)(&buf.magic), BTRFS_MAGIC,
+ sizeof(buf.magic)))
+ continue;
+
+ if (i == 0)
+ memcpy(fsid, buf.fsid, sizeof(fsid));
+ else if (memcmp(fsid, buf.fsid, sizeof(fsid)))
+ continue;
+
+ if (buf.generation > transid) {
+ memcpy(&sb, &buf, sizeof(sb));
+ transid = buf.generation;
+ }
+ }
+}
+
+static inline unsigned long btrfs_chunk_item_size(int num_stripes)
+{
+ return sizeof(struct btrfs_chunk) +
+ sizeof(struct btrfs_stripe) * (num_stripes - 1);
+}
+
+static void clear_path(struct btrfs_path *path)
+{
+ memset(path, 0, sizeof(*path));
+}
+
+static int btrfs_comp_keys(struct btrfs_disk_key *k1, struct btrfs_disk_key *k2)
+{
+ if (k1->objectid > k2->objectid)
+ return 1;
+ if (k1->objectid < k2->objectid)
+ return -1;
+ if (k1->type > k2->type)
+ return 1;
+ if (k1->type < k2->type)
+ return -1;
+ if (k1->offset > k2->offset)
+ return 1;
+ if (k1->offset < k2->offset)
+ return -1;
+ return 0;
+}
+
+/* seach tree directly on disk ... */
+static int search_tree(u64 loffset, struct btrfs_disk_key *key,
+ struct btrfs_path *path)
+{
+ u8 buf[BTRFS_MAX_LEAF_SIZE];
+ struct btrfs_header *header = (struct btrfs_header *)buf;
+ struct btrfs_node *node = (struct btrfs_node *)buf;
+ struct btrfs_leaf *leaf = (struct btrfs_leaf *)buf;
+ int slot, ret;
+ u64 offset;
+
+ offset = logical_physical(loffset);
+ btrfs_read((char *)header, offset, sizeof(*header));
+ if (header->level) {/*node*/
+ btrfs_read((char *)&node->ptrs[0], offset + sizeof(*header),
+ sb.nodesize - sizeof(*header));
+ path->itemsnr[header->level] = header->nritems;
+ path->offsets[header->level] = loffset;
+ ret = bin_search(&node->ptrs[0], sizeof(struct btrfs_key_ptr),
+ key, (cmp_func)btrfs_comp_keys,
+ path->slots[header->level], header->nritems, &slot);
+ if (ret && slot > path->slots[header->level])
+ slot--;
+ path->slots[header->level] = slot;
+ ret = search_tree(node->ptrs[slot].blockptr, key, path);
+ } else {/*leaf*/
+ btrfs_read((char *)&leaf->items, offset + sizeof(*header),
+ sb.leafsize - sizeof(*header));
+ path->itemsnr[header->level] = header->nritems;
+ path->offsets[0] = loffset;
+ ret = bin_search(&leaf->items[0], sizeof(struct btrfs_item),
+ key, (cmp_func)btrfs_comp_keys, path->slots[0],
+ header->nritems, &slot);
+ if (ret && slot > path->slots[header->level])
+ slot--;
+ path->slots[0] = slot;
+ path->item = leaf->items[slot];
+ btrfs_read((char *)&path->data,
+ offset + sizeof(*header) + leaf->items[slot].offset,
+ leaf->items[slot].size);
+ }
+ return ret;
+}
+
+/* return 0 if leaf found */
+static int next_leaf(struct btrfs_disk_key *key, struct btrfs_path *path)
+{
+ int slot;
+ int level = 1;
+
+ while (level < BTRFS_MAX_LEVEL) {
+ if (!path->itemsnr[level]) /* no more nodes */
+ return 1;
+ slot = path->slots[level] + 1;
+ if (slot >= path->itemsnr[level]) {
+ level++;
+ continue;;
+ }
+ path->slots[level] = slot;
+ path->slots[level-1] = 0; /* reset low level slots info */
+ search_tree(path->offsets[level], key, path);
+ break;
+ }
+ if (level == BTRFS_MAX_LEVEL)
+ return 1;
+ return 0;
+}
+
+/* return 0 if slot found */
+static int next_slot(struct btrfs_disk_key *key, struct btrfs_path *path)
+{
+ int slot;
+
+ if (!path->itemsnr[0])
+ return 1;
+ slot = path->slots[0] + 1;
+ if (slot >= path->itemsnr[0])
+ return 1;
+ path->slots[0] = slot;
+ search_tree(path->offsets[0], key, path);
+ return 0;
+}
+
+/*
+ * read chunk_array in super block
+ */
+static void btrfs_read_sys_chunk_array(void)
+{
+ struct btrfs_chunk_map_item item;
+ struct btrfs_disk_key *key;
+ struct btrfs_chunk *chunk;
+ int cur;
+
+ /* read chunk array in superblock */
+ cur = 0;
+ while (cur < sb.sys_chunk_array_size) {
+ key = (struct btrfs_disk_key *)(sb.sys_chunk_array + cur);
+ cur += sizeof(*key);
+ chunk = (struct btrfs_chunk *)(sb.sys_chunk_array + cur);
+ cur += btrfs_chunk_item_size(chunk->num_stripes);
+ /* insert to mapping table, ignore multi stripes */
+ item.logical = key->offset;
+ item.length = chunk->length;
+ item.devid = chunk->stripe.devid;
+ item.physical = chunk->stripe.offset;/*ignore other stripes */
+ insert_map(&item);
+ }
+}
+
+/* read chunk items from chunk_tree and insert them to chunk map */
+static void btrfs_read_chunk_tree(void)
+{
+ struct btrfs_disk_key search_key;
+ struct btrfs_chunk *chunk;
+ struct btrfs_chunk_map_item item;
+ struct btrfs_path path;
+
+ if (!(sb.flags & BTRFS_SUPER_FLAG_METADUMP)) {
+ if (sb.num_devices > 1)
+ printf("warning: only support single device btrfs\n");
+ /* read chunk from chunk_tree */
+ search_key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
+ search_key.type = BTRFS_CHUNK_ITEM_KEY;
+ search_key.offset = 0;
+ clear_path(&path);
+ search_tree(sb.chunk_root, &search_key, &path);
+ do {
+ do {
+ if (path.item.key.objectid !=
+ BTRFS_FIRST_CHUNK_TREE_OBJECTID)
+ break;
+ chunk = (struct btrfs_chunk *)(path.data);
+ /* insert to mapping table, ignore stripes */
+ item.logical = path.item.key.offset;
+ item.length = chunk->length;
+ item.devid = chunk->stripe.devid;
+ item.physical = chunk->stripe.offset;
+ insert_map(&item);
+ } while (!next_slot(&search_key, &path));
+ if (path.item.key.objectid !=
+ BTRFS_FIRST_CHUNK_TREE_OBJECTID)
+ break;
+ } while (!next_leaf(&search_key, &path));
+ }
+}
+
+static inline u64 btrfs_name_hash(const char *name, int len)
+{
+ return btrfs_crc32c((u32)~1, name, len);
+}
+
+/* search a file with full path in fs_tree, do not support ../ ./ style path */
+static int btrfs_search_fs_tree(const char *fullpath, u64 *offset,
+ u64 *size, u8 *type)
+{
+ char name[256];
+ char *tmp = name;
+ u64 objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
+ int ret;
+ struct btrfs_disk_key search_key;
+ struct btrfs_path path;
+ struct btrfs_dir_item dir_item;
+ struct btrfs_inode_item inode_item;
+ struct btrfs_file_extent_item extent_item;
+
+ *tmp = '\0';
+ while (1) {
+ char c = *(fullpath++);
+
+ *(tmp++) = c;
+ if (!c)
+ break;
+ if (c == '/') {
+ *(tmp-1) = '\0';
+ if (strlen(name)) {/* a "real" dir */
+ search_key.objectid = objectid;
+ search_key.type = BTRFS_DIR_ITEM_KEY;
+ search_key.offset =
+ btrfs_name_hash(name, strlen(name));
+ clear_path(&path);
+ ret = search_tree(fs_tree, &search_key, &path);
+ if (ret)
+ return ret; /* not found */
+ dir_item = *(struct btrfs_dir_item *)path.data;
+ /* found the name but it is not a dir ? */
+ if (dir_item.type != BTRFS_FT_DIR) {
+ printf("%s is not a dir\n", name);
+ return -1;
+ }
+ objectid = dir_item.location.objectid;
+ }
+ tmp = name;
+ *tmp = '\0';
+ }
+ }
+ /* get file dir_item */
+ if (!strlen(name))/* no file part */
+ return -1;
+ search_key.objectid = objectid;
+ search_key.type = BTRFS_DIR_ITEM_KEY;
+ search_key.offset = btrfs_name_hash(name, strlen(name));
+ clear_path(&path);
+ ret = search_tree(fs_tree, &search_key, &path);
+ if (ret)
+ return ret; /* not found */
+ dir_item = *(struct btrfs_dir_item *)path.data;
+ *type = dir_item.type;
+ /* found the name but it is not a file ? */
+ if (*type != BTRFS_FT_REG_FILE && *type != BTRFS_FT_SYMLINK) {
+ printf("%s is not a file\n", name);
+ return -1;
+ }
+
+ /* get inode */
+ search_key = dir_item.location;
+ clear_path(&path);
+ ret = search_tree(fs_tree, &search_key, &path);
+ if (ret)
+ return ret; /* not found */
+ inode_item = *(struct btrfs_inode_item *)path.data;
+
+ /* get file_extent_item */
+ search_key.objectid = dir_item.location.objectid;
+ search_key.type = BTRFS_EXTENT_DATA_KEY;
+ search_key.offset = 0;
+ clear_path(&path);
+ ret = search_tree(fs_tree, &search_key, &path);
+ if (ret)
+ return ret; /* not found */
+ extent_item = *(struct btrfs_file_extent_item *)path.data;
+ *size = inode_item.size;
+ if (extent_item.type == BTRFS_FILE_EXTENT_INLINE)/* inline file */
+ *offset = path.offsets[0] + sizeof(struct btrfs_header)
+ + path.item.offset
+ + offsetof(struct btrfs_file_extent_item, disk_bytenr);
+ else
+ *offset = extent_item.disk_bytenr;
+
+ return 0;
+}
+
+static struct open_file_t *alloc_file(void)
+{
+ struct open_file_t *file = Files;
+ int i;
+
+ for (i = 0; i < MAX_OPEN; i++) {
+ if (file->devid == 0) /* found it */
+ return file;
+ file++;
+ }
+
+ return NULL; /* not found */
+}
+
+static inline void close_pvt(struct open_file_t *of)
+{
+ of->devid = 0;
+}
+
+static void btrfs_close_file(struct file *file)
+{
+ close_pvt(file->open_file);
+}
+
+static void btrfs_searchdir(char *filename, struct file *file)
+{
+ struct open_file_t *open_file;
+ u64 offset, size;
+ char name[FILENAME_MAX];
+ char *fname = filename;
+ u8 type;
+ int ret;
+
+ file->open_file = NULL;
+ file->file_len = 0;
+ do {
+ ret = btrfs_search_fs_tree(fname, &offset, &size, &type);
+ if (ret)
+ break;
+ if (type == BTRFS_FT_SYMLINK) {
+ btrfs_read(name, logical_physical(offset), size);
+ name[size] = '\0';
+ fname = name;
+ continue;
+ }
+ open_file = alloc_file();
+ file->open_file = (void *)open_file;
+ if (open_file) {
+ /* we may support multi devices later on */
+ open_file->devid = 1;
+ open_file->bytenr = offset;
+ open_file->pos = 0;
+ file->file_len = size;
+ }
+ break;
+ } while (1);
+}
+
+/* Load the config file, return 1 if failed, or 0 */
+static int btrfs_load_config(void)
+{
+ char *config_name = "extlinux.conf";/* use same config name as ext2 too? */
+ com32sys_t regs;
+
+ strcpy(ConfigName, config_name);
+ *(uint16_t *)CurrentDirName = ROOT_DIR_WORD;
+
+ memset(&regs, 0, sizeof regs);
+ regs.edi.w[0] = OFFS_WRT(ConfigName, 0);
+ call16(core_open, &regs, &regs);
+
+ return !!(regs.eflags.l & EFLAGS_ZF);
+}
+
+static uint32_t btrfs_getfssec(struct file *gfile, char *buf, int sectors,
+ bool *have_more)
+{
+ struct disk *disk = fs->fs_dev->disk;
+ struct open_file_t *file = gfile->open_file;
+ u32 sec_shift = fs->fs_dev->disk->sector_shift;
+ u32 phy = logical_physical(file->bytenr + file->pos);
+ u32 sec = phy >> sec_shift;
+ u32 off = phy - (sec << sec_shift);
+ u32 remain = gfile->file_len - file->pos;
+ u32 remain_sec = (remain + (1 << sec_shift) - 1) >> sec_shift;
+ u32 size;
+
+ if (sectors > remain_sec)
+ sectors = remain_sec;
+ /* btrfs extent is continus */
+ disk->rdwr_sectors(disk, buf, sec, sectors, 0);
+ size = sectors << sec_shift;
+ if (size > remain)
+ size = remain;
+ file->pos += size;
+ *have_more = remain - size;
+
+ if (off)/* inline file is not started with sector boundary */
+ memcpy(buf, buf + off, size);
+
+ return size;
+}
+
+static void btrfs_get_fs_tree(void)
+{
+ struct btrfs_disk_key search_key;
+ struct btrfs_path path;
+ struct btrfs_root_item *tree;
+
+ /* find fs_tree from tree_root */
+ search_key.objectid = BTRFS_FS_TREE_OBJECTID;
+ search_key.type = BTRFS_ROOT_ITEM_KEY;
+ search_key.offset = -1;
+ clear_path(&path);
+ search_tree(sb.root, &search_key, &path);
+ tree = (struct btrfs_root_item *)path.data;
+ fs_tree = tree->bytenr;
+}
+
+/* init. the fs meta data, return the block size shift bits. */
+static int btrfs_fs_init(struct fs_info *_fs)
+{
+ btrfs_init_crc32c();
+
+ fs = _fs;
+ btrfs_read_super_block();
+ if (strncmp((char *)(&sb.magic), BTRFS_MAGIC, sizeof(sb.magic)))
+ return -1;
+ btrfs_read_sys_chunk_array();
+ btrfs_read_chunk_tree();
+ btrfs_get_fs_tree();
+ cache_ready = 1;
+ return BTRFS_BLOCK_SHIFT;/* to determine cache size */
+}
+
+const struct fs_ops btrfs_fs_ops = {
+ .fs_name = "btrfs",
+ .fs_flags = 0,
+ .fs_init = btrfs_fs_init,
+ .searchdir = btrfs_searchdir,
+ .getfssec = btrfs_getfssec,
+ .close_file = btrfs_close_file,
+ .mangle_name = generic_mangle_name,
+ .unmangle_name = generic_unmangle_name,
+ .load_config = btrfs_load_config
+};
diff --git a/core/fs/btrfs/btrfs.h b/core/fs/btrfs/btrfs.h
new file mode 100644
index 00000000..8ec8afe3
--- /dev/null
+++ b/core/fs/btrfs/btrfs.h
@@ -0,0 +1,275 @@
+#ifndef _BTRFS_H_
+#define _BTRFS_H_
+
+#include <stdint.h>
+#include <zconf.h>
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+/* type that store on disk, but it is same as cpu type for i386 arch */
+typedef u16 __le16;
+typedef u32 __le32;
+typedef u64 __le64;
+
+#include "crc32c.h"
+#define btrfs_crc32c crc32c_le
+
+#define BTRFS_SUPER_INFO_OFFSET (64 * 1024)
+#define BTRFS_SUPER_INFO_SIZE 4096
+#define BTRFS_MAX_LEAF_SIZE 4096
+#define BTRFS_BLOCK_SHIFT 12
+
+#define BTRFS_SUPER_MIRROR_MAX 3
+#define BTRFS_SUPER_MIRROR_SHIFT 12
+#define BTRFS_CSUM_SIZE 32
+#define BTRFS_FSID_SIZE 16
+#define BTRFS_LABEL_SIZE 256
+#define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048
+#define BTRFS_UUID_SIZE 16
+
+#define BTRFS_MAGIC "_BHRfS_M"
+
+#define BTRFS_SUPER_FLAG_METADUMP (1ULL << 33)
+
+#define BTRFS_DEV_ITEM_KEY 216
+#define BTRFS_CHUNK_ITEM_KEY 228
+#define BTRFS_ROOT_ITEM_KEY 132
+#define BTRFS_EXTENT_DATA_KEY 108
+#define BTRFS_DIR_ITEM_KEY 84
+
+#define BTRFS_EXTENT_TREE_OBJECTID 2ULL
+#define BTRFS_FS_TREE_OBJECTID 5ULL
+
+#define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL
+
+#define BTRFS_FILE_EXTENT_INLINE 0
+#define BTRFS_FILE_EXTENT_REG 1
+#define BTRFS_FILE_EXTENT_PREALLOC 2
+
+#define BTRFS_MAX_LEVEL 8
+#define BTRFS_MAX_CHUNK_ENTRIES 256
+
+#define BTRFS_FT_REG_FILE 1
+#define BTRFS_FT_DIR 2
+#define BTRFS_FT_SYMLINK 7
+
+#define ROOT_DIR_WORD 0x002f
+
+struct btrfs_dev_item {
+ __le64 devid;
+ __le64 total_bytes;
+ __le64 bytes_used;
+ __le32 io_align;
+ __le32 io_width;
+ __le32 sector_size;
+ __le64 type;
+ __le64 generation;
+ __le64 start_offset;
+ __le32 dev_group;
+ u8 seek_speed;
+ u8 bandwidth;
+ u8 uuid[BTRFS_UUID_SIZE];
+ u8 fsid[BTRFS_UUID_SIZE];
+} __attribute__ ((__packed__));
+
+struct btrfs_super_block {
+ u8 csum[BTRFS_CSUM_SIZE];
+ /* the first 3 fields must match struct btrfs_header */
+ u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
+ __le64 bytenr; /* this block number */
+ __le64 flags;
+
+ /* allowed to be different from the btrfs_header from here own down */
+ __le64 magic;
+ __le64 generation;
+ __le64 root;
+ __le64 chunk_root;
+ __le64 log_root;
+
+ /* this will help find the new super based on the log root */
+ __le64 log_root_transid;
+ __le64 total_bytes;
+ __le64 bytes_used;
+ __le64 root_dir_objectid;
+ __le64 num_devices;
+ __le32 sectorsize;
+ __le32 nodesize;
+ __le32 leafsize;
+ __le32 stripesize;
+ __le32 sys_chunk_array_size;
+ __le64 chunk_root_generation;
+ __le64 compat_flags;
+ __le64 compat_ro_flags;
+ __le64 incompat_flags;
+ __le16 csum_type;
+ u8 root_level;
+ u8 chunk_root_level;
+ u8 log_root_level;
+ struct btrfs_dev_item dev_item;
+
+ char label[BTRFS_LABEL_SIZE];
+
+ /* future expansion */
+ __le64 reserved[32];
+ u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
+} __attribute__ ((__packed__));
+
+struct btrfs_disk_key {
+ __le64 objectid;
+ u8 type;
+ __le64 offset;
+} __attribute__ ((__packed__));
+
+struct btrfs_stripe {
+ __le64 devid;
+ __le64 offset;
+ u8 dev_uuid[BTRFS_UUID_SIZE];
+} __attribute__ ((__packed__));
+
+struct btrfs_chunk {
+ __le64 length;
+ __le64 owner;
+ __le64 stripe_len;
+ __le64 type;
+ __le32 io_align;
+ __le32 io_width;
+ __le32 sector_size;
+ __le16 num_stripes;
+ __le16 sub_stripes;
+ struct btrfs_stripe stripe;
+} __attribute__ ((__packed__));
+
+struct btrfs_header {
+ /* these first four must match the super block */
+ u8 csum[BTRFS_CSUM_SIZE];
+ u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
+ __le64 bytenr; /* which block this node is supposed to live in */
+ __le64 flags;
+
+ /* allowed to be different from the super from here on down */
+ u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
+ __le64 generation;
+ __le64 owner;
+ __le32 nritems;
+ u8 level;
+} __attribute__ ((__packed__));
+
+struct btrfs_item {
+ struct btrfs_disk_key key;
+ __le32 offset;
+ __le32 size;
+} __attribute__ ((__packed__));
+
+struct btrfs_leaf {
+ struct btrfs_header header;
+ struct btrfs_item items[];
+} __attribute__ ((__packed__));
+
+struct btrfs_key_ptr {
+ struct btrfs_disk_key key;
+ __le64 blockptr;
+ __le64 generation;
+} __attribute__ ((__packed__));
+
+struct btrfs_node {
+ struct btrfs_header header;
+ struct btrfs_key_ptr ptrs[];
+} __attribute__ ((__packed__));
+
+/* remember how we get to a node/leaf */
+struct btrfs_path {
+ u64 offsets[BTRFS_MAX_LEVEL];
+ int itemsnr[BTRFS_MAX_LEVEL];
+ int slots[BTRFS_MAX_LEVEL];
+ /* remember last slot's item and data */
+ struct btrfs_item item;
+ u8 data[BTRFS_MAX_LEAF_SIZE];
+};
+
+/* store logical offset to physical offset mapping */
+struct btrfs_chunk_map_item {
+ u64 logical;
+ u64 length;
+ u64 devid;
+ u64 physical;
+};
+
+struct btrfs_chunk_map {
+ struct btrfs_chunk_map_item *map;
+ u32 map_length;
+ u32 cur_length;
+};
+
+struct btrfs_timespec {
+ __le64 sec;
+ __le32 nsec;
+} __attribute__ ((__packed__));
+
+struct btrfs_inode_item {
+ /* nfs style generation number */
+ __le64 generation;
+ /* transid that last touched this inode */
+ __le64 transid;
+ __le64 size;
+ __le64 nbytes;
+ __le64 block_group;
+ __le32 nlink;
+ __le32 uid;
+ __le32 gid;
+ __le32 mode;
+ __le64 rdev;
+ __le64 flags;
+
+ /* modification sequence number for NFS */
+ __le64 sequence;
+
+ /*
+ * a little future expansion, for more than this we can
+ * just grow the inode item and version it
+ */
+ __le64 reserved[4];
+ struct btrfs_timespec atime;
+ struct btrfs_timespec ctime;
+ struct btrfs_timespec mtime;
+ struct btrfs_timespec otime;
+} __attribute__ ((__packed__));
+
+struct btrfs_root_item {
+ struct btrfs_inode_item inode;
+ __le64 generation;
+ __le64 root_dirid;
+ __le64 bytenr;
+ __le64 byte_limit;
+ __le64 bytes_used;
+ __le64 last_snapshot;
+ __le64 flags;
+ __le32 refs;
+ struct btrfs_disk_key drop_progress;
+ u8 drop_level;
+ u8 level;
+} __attribute__ ((__packed__));
+
+struct btrfs_dir_item {
+ struct btrfs_disk_key location;
+ __le64 transid;
+ __le16 data_len;
+ __le16 name_len;
+ u8 type;
+} __attribute__ ((__packed__));
+
+struct btrfs_file_extent_item {
+ __le64 generation;
+ __le64 ram_bytes;
+ u8 compression;
+ u8 encryption;
+ __le16 other_encoding; /* spare for later use */
+ u8 type;
+ __le64 disk_bytenr;
+ __le64 disk_num_bytes;
+ __le64 offset;
+ __le64 num_bytes;
+} __attribute__ ((__packed__));
+
+#endif
diff --git a/core/fs/btrfs/crc32c.h b/core/fs/btrfs/crc32c.h
new file mode 100644
index 00000000..2c317384
--- /dev/null
+++ b/core/fs/btrfs/crc32c.h
@@ -0,0 +1,50 @@
+/*
+ * Copied from Linux kernel crypto/crc32c.c
+ * Copyright (c) 2004 Cisco Systems, Inc.
+ * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+/*
+ * This is the CRC-32C table
+ * Generated with:
+ * width = 32 bits
+ * poly = 0x1EDC6F41
+ * reflect input bytes = true
+ * reflect output bytes = true
+ */
+
+static u32 crc32c_table[256];
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+static inline u32 crc32c_le(u32 crc, const char *data, size_t length)
+{
+ while (length--)
+ crc = crc32c_table[(u8)(crc ^ *data++)] ^ (crc >> 8);
+
+ return crc;
+}
+
+static inline void btrfs_init_crc32c(void)
+{
+ int i, j;
+ u32 v;
+ const u32 poly = 0x82F63B78; /* Bit-reflected CRC32C polynomial */
+
+ for (i = 0; i < 256; i++) {
+ v = i;
+ for (j = 0; j < 8; j++) {
+ v = (v >> 1) ^ ((v & 1) ? poly : 0);
+ }
+ crc32c_table[i] = v;
+ }
+}
diff --git a/core/fs/ext2/bmap.c b/core/fs/ext2/bmap.c
new file mode 100644
index 00000000..e4698d0c
--- /dev/null
+++ b/core/fs/ext2/bmap.c
@@ -0,0 +1,185 @@
+/*
+ * The logical block -> physical block routine.
+ *
+ * Copyright (C) 2009 Liu Aleaxander -- All rights reserved. This file
+ * may be redistributed under the terms of the GNU Public License.
+ */
+
+#include <stdio.h>
+#include <fs.h>
+#include <disk.h>
+#include <cache.h>
+#include "ext2_fs.h"
+
+
+static struct ext4_extent_header *
+ext4_find_leaf(struct fs_info *fs, struct ext4_extent_header *eh, block_t block)
+{
+ struct ext4_extent_idx *index;
+ struct cache_struct *cs;
+ block_t blk;
+ int i;
+
+ while (1) {
+ if (eh->eh_magic != EXT4_EXT_MAGIC)
+ return NULL;
+ if (eh->eh_depth == 0)
+ return eh;
+
+ index = EXT4_FIRST_INDEX(eh);
+ for (i = 0; i < (int)eh->eh_entries; i++) {
+ if (block < index[i].ei_block)
+ break;
+ }
+ if (--i < 0)
+ return NULL;
+
+ blk = index[i].ei_leaf_hi;
+ blk = (blk << 32) + index[i].ei_leaf_lo;
+ cs = get_cache_block(fs->fs_dev, blk);
+ eh = (struct ext4_extent_header *)cs->data;
+ }
+}
+
+/* handle the ext4 extents to get the phsical block number */
+static uint64_t bmap_extent(struct fs_info *fs,
+ struct inode *inode,
+ uint32_t block)
+{
+ struct ext4_extent_header *leaf;
+ struct ext4_extent *ext;
+ int i;
+ block_t start;
+
+ leaf = ext4_find_leaf(fs, (struct ext4_extent_header *)inode->pvt, block);
+ if (!leaf) {
+ printf("ERROR, extent leaf not found\n");
+ return 0;
+ }
+
+ ext = EXT4_FIRST_EXTENT(leaf);
+ for (i = 0; i < leaf->eh_entries; i++) {
+ if (block < ext[i].ee_block)
+ break;
+ }
+ if (--i < 0) {
+ printf("ERROR, not find the right block\n");
+ return 0;
+ }
+
+ /* got it */
+ block -= ext[i].ee_block;
+ if (block >= ext[i].ee_len)
+ return 0;
+ start = ext[i].ee_start_hi;
+ start = (start << 32) + ext[i].ee_start_lo;
+
+ return start + block;
+}
+
+
+/*
+ * handle the traditional block map, like indirect, double indirect
+ * and triple indirect
+ */
+static unsigned int bmap_traditional(struct fs_info *fs,
+ struct inode *inode,
+ uint32_t block)
+{
+ int addr_per_block = BLOCK_SIZE(fs) >> 2;
+ uint32_t direct_blocks = EXT2_NDIR_BLOCKS,
+ indirect_blocks = addr_per_block,
+ double_blocks = addr_per_block * addr_per_block,
+ triple_blocks = double_blocks * addr_per_block;
+ struct cache_struct *cs;
+
+ /* direct blocks */
+ if (block < direct_blocks)
+ return ((uint32_t *)inode->pvt)[block];
+
+ /* indirect blocks */
+ block -= direct_blocks;
+ if (block < indirect_blocks) {
+ block_t ind_block = ((uint32_t *)inode->pvt)[EXT2_IND_BLOCK];
+
+ if (!ind_block)
+ return 0;
+ cs = get_cache_block(fs->fs_dev, ind_block);
+
+ return ((uint32_t *)cs->data)[block];
+ }
+
+
+ /* double indirect blocks */
+ block -= indirect_blocks;
+ if (block < double_blocks) {
+ block_t dou_block = ((uint32_t *)inode->pvt)[EXT2_DIND_BLOCK];
+
+ if (!dou_block)
+ return 0;
+ cs = get_cache_block(fs->fs_dev, dou_block);
+
+ dou_block = ((uint32_t *)cs->data)[block / indirect_blocks];
+ if (!dou_block)
+ return 0;
+ cs = get_cache_block(fs->fs_dev, dou_block);
+
+ return ((uint32_t *)cs->data)[block % addr_per_block];
+ }
+
+
+ /* triple indirect block */
+ block -= double_blocks;
+ if (block < triple_blocks) {
+ block_t tri_block = ((uint32_t *)inode->pvt)[EXT2_TIND_BLOCK];
+
+ if (!tri_block)
+ return 0;
+ cs = get_cache_block(fs->fs_dev, tri_block);
+
+ tri_block = ((uint32_t *)cs->data)[block / double_blocks];
+ if (!tri_block)
+ return 0;
+ cs = get_cache_block(fs->fs_dev, tri_block);
+
+ tri_block = (block / addr_per_block) % addr_per_block;
+ tri_block = ((uint32_t *)cs->data)[tri_block];
+ if (!tri_block)
+ return 0;
+ cs = get_cache_block(fs->fs_dev, tri_block);
+
+ return ((uint32_t *)cs->data)[block % addr_per_block];
+ }
+
+
+ /* File too big, can not handle */
+ printf("ERROR, file too big\n");
+ return 0;
+}
+
+
+/**
+ * Map the logical block to physic block where the file data stores.
+ * In EXT4, there are two ways to handle the map process, extents and indirect.
+ * EXT4 uses a inode flag to mark extent file and indirect block file.
+ *
+ * @fs: the fs_info structure.
+ * @inode: the inode structure.
+ * @block: the logical blcok needed to be maped.
+ * @retrun: the physic block number.
+ *
+ */
+block_t bmap(struct fs_info *fs, struct inode * inode, int block)
+{
+ block_t ret;
+
+ if (block < 0)
+ return 0;
+
+ if (inode->flags & EXT4_EXTENTS_FLAG)
+ ret = bmap_extent(fs, inode, block);
+ else
+ ret = bmap_traditional(fs, inode, block);
+
+ return ret;
+}
diff --git a/core/fs/ext2/ext2.c b/core/fs/ext2/ext2.c
new file mode 100644
index 00000000..b8c4e104
--- /dev/null
+++ b/core/fs/ext2/ext2.c
@@ -0,0 +1,476 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/dirent.h>
+#include <cache.h>
+#include <core.h>
+#include <disk.h>
+#include <fs.h>
+#include "ext2_fs.h"
+
+/*
+ * just like the function strcpy(), except it returns non-zero if overflow.
+ *
+ */
+static int strecpy(char *dst, const char *src, char *end)
+{
+ while (*src != '\0')
+ *dst++ = *src++;
+ *dst = '\0';
+
+ if (dst > end)
+ return 1;
+ else
+ return 0;
+}
+
+static void ext2_close_file(struct file *file)
+{
+ if (file->inode) {
+ file->offset = 0;
+ free_inode(file->inode);
+ }
+}
+
+/*
+ * get the group's descriptor of group_num
+ */
+struct ext2_group_desc * ext2_get_group_desc(struct fs_info *fs,
+ uint32_t group_num)
+{
+ struct ext2_sb_info *sbi = EXT2_SB(fs);
+ uint32_t desc_block, desc_index;
+ struct ext2_group_desc *desc_data_block;
+ struct cache_struct *cs;
+
+ if (group_num >= sbi->s_groups_count) {
+ printf ("ext2_get_group_desc"
+ "block_group >= groups_count - "
+ "block_group = %d, groups_count = %d",
+ group_num, sbi->s_groups_count);
+
+ return NULL;
+ }
+
+ desc_block = group_num / sbi->s_desc_per_block;
+ desc_index = group_num % sbi->s_desc_per_block;
+
+ desc_block += sbi->s_first_data_block + 1;
+
+ cs = get_cache_block(fs->fs_dev, desc_block);
+ desc_data_block = cs->data;
+
+ return &desc_data_block[desc_index];
+}
+
+
+
+/**
+ * linsector:
+ *
+ * Convert a linear sector index in a file to linear sector number
+ *
+ * well, alought this function converts a linear sector number to
+ * physic sector number, it uses block cache in the implemention.
+ *
+ * @param: lin_sector, the lineral sector index
+ *
+ * @return: physic sector number
+ */
+static sector_t linsector(struct inode *inode, uint32_t lin_sector)
+{
+ struct fs_info *fs = inode->fs;
+ int blk_bits = fs->block_shift - fs->sector_shift;
+ block_t block = bmap(fs, inode, lin_sector >> blk_bits);
+
+ return (block << blk_bits) + (lin_sector & ((1 << blk_bits) - 1));
+}
+
+
+/**
+ * getlinsec_ext:
+ *
+ * same as getlinsec, except load any sector from the zero
+ * block as all zeros; use to load any data derived from
+ * n ext2 block pointer, i.e. anything *except the superblock
+ *
+ */
+static void getlinsec_ext(struct fs_info *fs, char *buf,
+ sector_t sector, int sector_cnt)
+{
+ int ext_cnt = 0;
+ int sec_per_block = 1 << (fs->block_shift - fs->sector_shift);
+ struct disk *disk = fs->fs_dev->disk;
+
+ if (sector < sec_per_block) {
+ ext_cnt = sec_per_block - sector;
+ memset(buf, 0, ext_cnt << fs->sector_shift);
+ buf += ext_cnt << fs->sector_shift;
+ }
+
+ sector += ext_cnt;
+ sector_cnt -= ext_cnt;
+ disk->rdwr_sectors(disk, buf, sector, sector_cnt, 0);
+}
+
+/*
+ * Get multiple sectors from a file
+ *
+ * Alought we have made the buffer data based on block size,
+ * we use sector for implemention; because reading multiple
+ * sectors (then can be multiple blocks) is what the function
+ * do. So, let it be based on sectors.
+ *
+ */
+static uint32_t ext2_getfssec(struct file *file, char *buf,
+ int sectors, bool *have_more)
+{
+ struct inode *inode = file->inode;
+ struct fs_info *fs = file->fs;
+ int sector_left, next_sector, sector_idx;
+ int frag_start, con_sec_cnt;
+ int bytes_read = sectors << fs->sector_shift;
+ uint32_t bytesleft = inode->size - file->offset;
+
+ sector_left = (bytesleft + SECTOR_SIZE(fs) - 1) >> fs->sector_shift;
+ if (sectors > sector_left)
+ sectors = sector_left;
+
+ sector_idx = file->offset >> fs->sector_shift;
+ while (sectors) {
+ /*
+ * get the frament
+ */
+ next_sector = frag_start = linsector(inode, sector_idx);
+ con_sec_cnt = 0;
+
+ /* get the consective sectors count */
+ do {
+ con_sec_cnt ++;
+ sectors --;
+ if (sectors <= 0)
+ break;
+
+ /* if sectors >= the sectors left in the 64K block, break and read */
+ if (sectors >= (((~(uint32_t)buf&0xffff)|((uint32_t)buf&0xffff0000)) + 1))
+ break;
+
+ sector_idx++;
+ next_sector++;
+ } while (next_sector == linsector(inode, sector_idx));
+
+#if 0
+ printf("You are reading data stored at sector --0x%x--0x%x\n",
+ frag_start, frag_start + con_sec_cnt -1);
+#endif
+ getlinsec_ext(fs, buf, frag_start, con_sec_cnt);
+ buf += con_sec_cnt << fs->sector_shift;
+ } while(sectors);
+
+ if (bytes_read >= bytesleft) {
+ bytes_read = bytesleft;
+ *have_more = 0;
+ } else {
+ *have_more = 1;
+ }
+ file->offset += bytes_read;
+
+ return bytes_read;
+}
+
+/*
+ * Unlike strncmp, ext2_match_entry returns 1 for success, 0 for failure.
+ */
+static inline int ext2_match_entry (const char * const name,
+ struct ext2_dir_entry * de)
+{
+ if (!de->d_inode)
+ return 0;
+ if (strlen(name) != de->d_name_len)
+ return 0;
+ return !strncmp(name, de->d_name, de->d_name_len);
+}
+
+
+/*
+ * p is at least 6 bytes before the end of page
+ */
+static inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p)
+{
+ return (struct ext2_dir_entry *)((char*)p + p->d_rec_len);
+}
+
+/*
+ * find a dir entry, return it if found, or return NULL.
+ */
+static struct ext2_dir_entry *
+ext2_find_entry(struct fs_info *fs, struct inode *inode, char *dname)
+{
+ int index = 0;
+ block_t block;
+ uint32_t i = 0;
+ struct ext2_dir_entry *de;
+ struct cache_struct *cs;
+
+ if (!(block = bmap(fs, inode, index++)))
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, block);
+ de = (struct ext2_dir_entry *)cs->data;
+
+ while(i < (int)inode->size) {
+ if (ext2_match_entry(dname, de))
+ return de;
+ i += de->d_rec_len;
+ if (i >= (int)inode->size)
+ break;
+ if ((char *)de >= (char *)cs->data + BLOCK_SIZE(fs)) {
+ if (!(block = bmap(fs, inode, index++)))
+ break;
+ cs = get_cache_block(fs->fs_dev, block);
+ de = (struct ext2_dir_entry *)cs->data;
+ continue;
+ }
+
+ de = ext2_next_entry(de);
+ }
+
+ return NULL;
+}
+
+static struct ext2_inode * get_inode(struct fs_info *fs, int inr)
+{
+ struct ext2_group_desc *desc;
+ struct cache_struct *cs;
+ uint32_t inode_group, inode_offset;
+ uint32_t block_num, block_off;
+
+ inr--;
+ inode_group = inr / EXT2_INODES_PER_GROUP(fs);
+ inode_offset = inr % EXT2_INODES_PER_GROUP(fs);
+ desc = ext2_get_group_desc(fs, inode_group);
+ if (!desc)
+ return NULL;
+
+ block_num = desc->bg_inode_table +
+ inode_offset / EXT2_INODES_PER_BLOCK(fs);
+ block_off = inode_offset % EXT2_INODES_PER_BLOCK(fs);
+
+ cs = get_cache_block(fs->fs_dev, block_num);
+
+ return cs->data + block_off * EXT2_SB(fs)->s_inode_size;
+}
+
+static inline int get_inode_mode(int mode)
+{
+ mode >>= S_IFSHIFT;
+ if (mode == T_IFDIR)
+ mode = I_DIR;
+ else if (mode == T_IFLNK)
+ mode = I_SYMLINK;
+ else
+ mode = I_FILE; /* we treat others as FILE */
+ return mode;
+}
+
+static void fill_inode(struct inode *inode, struct ext2_inode *e_inode)
+{
+ inode->mode = get_inode_mode(e_inode->i_mode);
+ inode->size = e_inode->i_size;
+ inode->atime = e_inode->i_atime;
+ inode->ctime = e_inode->i_ctime;
+ inode->mtime = e_inode->i_mtime;
+ inode->dtime = e_inode->i_dtime;
+ inode->blocks = e_inode->i_blocks;
+ inode->flags = e_inode->i_flags;
+ inode->file_acl = e_inode->i_file_acl;
+ memcpy(inode->pvt, e_inode->i_block, EXT2_N_BLOCKS * sizeof(uint32_t *));
+}
+
+static struct inode *ext2_iget_by_inr(struct fs_info *fs, uint32_t inr)
+{
+ struct ext2_inode *e_inode;
+ struct inode *inode;
+
+ e_inode = get_inode(fs, inr);
+ if (!(inode = alloc_inode(fs, inr, EXT2_N_BLOCKS*sizeof(uint32_t *))))
+ return NULL;
+ fill_inode(inode, e_inode);
+
+ return inode;
+}
+
+static struct inode *ext2_iget_root(struct fs_info *fs)
+{
+ return ext2_iget_by_inr(fs, EXT2_ROOT_INO);
+}
+
+static struct inode *ext2_iget_current(struct fs_info *fs)
+{
+ extern int CurrentDir;
+
+ return ext2_iget_by_inr(fs, CurrentDir);
+}
+
+static struct inode *ext2_iget(char *dname, struct inode *parent)
+{
+ struct ext2_dir_entry *de;
+ struct fs_info *fs = parent->fs;
+
+ de = ext2_find_entry(fs, parent, dname);
+ if (!de)
+ return NULL;
+
+ return ext2_iget_by_inr(fs, de->d_inode);
+}
+
+
+static char * ext2_follow_symlink(struct inode *inode, const char *name_left)
+{
+ struct fs_info *fs = inode->fs;
+ int sec_per_block = 1 << (fs->block_shift - fs->sector_shift);
+ int fast_symlink;
+ char *symlink_buf;
+ char *p;
+ struct cache_struct *cs;
+
+ symlink_buf = malloc(BLOCK_SIZE(fs));
+ if (!symlink_buf) {
+ malloc_error("symlink buffer");
+ return NULL;
+ }
+ fast_symlink = (inode->file_acl ? sec_per_block : 0) == inode->blocks;
+ if (fast_symlink) {
+ memcpy(symlink_buf, inode->pvt, inode->size);
+ } else {
+ cs = get_cache_block(fs->fs_dev, *(uint32_t *)inode->pvt);
+ memcpy(symlink_buf, cs->data, inode->size);
+ }
+ p = symlink_buf + inode->size;
+
+ if (*name_left)
+ *p++ = '/';
+ if (strecpy(p, name_left, symlink_buf + BLOCK_SIZE(fs))) {
+ free(symlink_buf);
+ return NULL;
+ }
+ if(!(p = strdup(symlink_buf)))
+ return symlink_buf;
+
+ free(symlink_buf);
+ return p;
+}
+
+/*
+ * Read one directory entry at a time
+ */
+static struct dirent * ext2_readdir(struct file *file)
+{
+ struct fs_info *fs = file->fs;
+ struct inode *inode = file->inode;
+ struct dirent *dirent;
+ struct ext2_dir_entry *de;
+ struct cache_struct *cs;
+ int index = file->offset >> fs->block_shift;
+ block_t block;
+
+ if (!(block = bmap(fs, inode, index)))
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, block);
+ de = (struct ext2_dir_entry *)(cs->data + (file->offset & (BLOCK_SIZE(fs) - 1)));
+
+ if (!(dirent = malloc(sizeof(*dirent)))) {
+ malloc_error("dirent structure in ext2_readdir");
+ return NULL;
+ }
+ dirent->d_ino = de->d_inode;
+ dirent->d_off = file->offset;
+ dirent->d_reclen = de->d_rec_len;
+ dirent->d_type = de->d_file_type;
+ memcpy(dirent->d_name, de->d_name, de->d_name_len);
+ dirent->d_name[de->d_name_len] = '\0';
+
+ file->offset += de->d_rec_len; /* Update for next reading */
+
+ return dirent;
+}
+
+/* Load the config file, return 1 if failed, or 0 */
+static int ext2_load_config(void)
+{
+ char *config_name = "extlinux.conf";
+ com32sys_t regs;
+
+ strcpy(ConfigName, config_name);
+ *(uint32_t *)CurrentDirName = 0x00002f2e;
+
+ memset(&regs, 0, sizeof regs);
+ regs.edi.w[0] = OFFS_WRT(ConfigName, 0);
+ call16(core_open, &regs, &regs);
+
+ return !!(regs.eflags.l & EFLAGS_ZF);
+}
+
+
+/*
+ * init. the fs meta data, return the block size bits.
+ */
+static int ext2_fs_init(struct fs_info *fs)
+{
+ struct disk *disk = fs->fs_dev->disk;
+ struct ext2_sb_info *sbi;
+ struct ext2_super_block sb;
+
+ /* read the super block */
+ disk->rdwr_sectors(disk, &sb, 2, 2, 0);
+
+ /* check if it is ext2, since we also support btrfs now */
+ if (sb.s_magic != EXT2_SUPER_MAGIC)
+ return -1;
+
+ sbi = malloc(sizeof(*sbi));
+ if (!sbi) {
+ malloc_error("ext2_sb_info structure");
+ return -1;
+ }
+ fs->fs_info = sbi;
+
+ if (sb.s_magic != EXT2_SUPER_MAGIC) {
+ printf("ext2 mount error: it's not a EXT2/3/4 file system!\n");
+ return 0;
+ }
+
+ fs->sector_shift = disk->sector_shift;
+ fs->block_shift = sb.s_log_block_size + 10;
+ fs->sector_size = 1 << fs->sector_shift;
+ fs->block_size = 1 << fs->block_shift;
+
+ sbi->s_inodes_per_group = sb.s_inodes_per_group;
+ sbi->s_blocks_per_group = sb.s_blocks_per_group;
+ sbi->s_inodes_per_block = BLOCK_SIZE(fs) / sb.s_inode_size;
+ if (sb.s_desc_size < sizeof(struct ext2_group_desc))
+ sb.s_desc_size = sizeof(struct ext2_group_desc);
+ sbi->s_desc_per_block = BLOCK_SIZE(fs) / sb.s_desc_size;
+ sbi->s_groups_count = (sb.s_blocks_count - sb.s_first_data_block
+ + EXT2_BLOCKS_PER_GROUP(fs) - 1)
+ / EXT2_BLOCKS_PER_GROUP(fs);
+ sbi->s_first_data_block = sb.s_first_data_block;
+ sbi->s_inode_size = sb.s_inode_size;
+
+ return fs->block_shift;
+}
+
+const struct fs_ops ext2_fs_ops = {
+ .fs_name = "ext2",
+ .fs_flags = FS_USEMEM,
+ .fs_init = ext2_fs_init,
+ .searchdir = NULL,
+ .getfssec = ext2_getfssec,
+ .close_file = ext2_close_file,
+ .mangle_name = generic_mangle_name,
+ .unmangle_name = generic_unmangle_name,
+ .load_config = ext2_load_config,
+ .iget_root = ext2_iget_root,
+ .iget_current = ext2_iget_current,
+ .iget = ext2_iget,
+ .follow_symlink = ext2_follow_symlink,
+ .readdir = ext2_readdir
+};
diff --git a/core/fs/ext2/ext2_fs.h b/core/fs/ext2/ext2_fs.h
new file mode 100644
index 00000000..b74038ea
--- /dev/null
+++ b/core/fs/ext2/ext2_fs.h
@@ -0,0 +1,299 @@
+#ifndef __EXT2_FS_H
+#define __EXT2_FS_H
+
+#include <stdint.h>
+
+#define EXT2_SUPER_MAGIC 0xEF53
+
+#define EXT2_GOOD_OLD_REV 0 // The good old (original) format
+#define EXT2_DYNAMIC_REV 1 // V2 format w/ dynamic inode sizes
+#define EXT2_GOOD_OLD_INODE_SIZE 128
+
+// Special inode numbers
+#define EXT2_BAD_INO 1 // Bad blocks inode
+#define EXT2_ROOT_INO 2 // Root inode
+#define EXT2_BOOT_LOADER_INO 5 // Boot loader inode
+#define EXT2_UNDEL_DIR_INO 6 // Undelete directory inode
+#define EXT3_RESIZE_INO 7 // Reserved group descriptors inode
+#define EXT3_JOURNAL_INO 8 // Journal inode
+
+// We're readonly, so we only care about incompat features.
+#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
+#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
+#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
+#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
+#define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
+
+#define EXT2_NDIR_BLOCKS 12
+#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
+#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK+1)
+#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK+1)
+#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK+1)
+
+
+/* for EXT4 extent */
+#define EXT4_EXT_MAGIC 0xf30a
+#define EXT4_EXTENTS_FLAG 0x00080000
+
+/*
+ * File types and file modes
+ */
+#define S_IFDIR 0040000 // Directory
+#define S_IFCHR 0020000 // Character device
+#define S_IFBLK 0060000 // Block device
+#define S_IFREG 0100000 // Regular file
+#define S_IFIFO 0010000 // FIFO
+#define S_IFLNK 0120000 // Symbolic link
+#define S_IFSOCK 0140000 // Socket
+
+#define S_IFSHIFT 12
+
+#define T_IFDIR (S_IFDIR >> S_IFSHIFT)
+#define T_IFCHR (S_IFCHR >> S_IFSHIFT)
+#define T_IFBLK (S_IFBLK >> S_IFSHIFT)
+#define T_IFREG (S_IFREG >> S_IFSHIFT)
+#define T_IFIFO (S_IFIFO >> S_IFSHIFT)
+#define T_IFLNK (S_IFLNK >> S_IFSHIFT)
+#define T_IFSOCK (S_IFSOCK >> S_IFSHIFT)
+
+
+#define ext2_group_desc_lg2size 5
+
+
+
+/*
+ * super block structure:
+ * include/linux/ext2_fs.h
+ */
+struct ext2_super_block {
+ uint32_t s_inodes_count; /* Inodes count */
+ uint32_t s_blocks_count; /* Blocks count */
+ uint32_t s_r_blocks_count; /* Reserved blocks count */
+ uint32_t s_free_blocks_count; /* Free blocks count */
+ uint32_t s_free_inodes_count; /* Free inodes count */
+ uint32_t s_first_data_block; /* First Data Block */
+ uint32_t s_log_block_size; /* Block size */
+ uint32_t s_log_frag_size; /* Fragment size */
+ uint32_t s_blocks_per_group; /* # Blocks per group */
+ uint32_t s_frags_per_group; /* # Fragments per group */
+ uint32_t s_inodes_per_group; /* # Inodes per group */
+ uint32_t s_mtime; /* Mount time */
+ uint32_t s_wtime; /* Write time */
+ uint16_t s_mnt_count; /* Mount count */
+ int16_t s_max_mnt_count; /* Maximal mount count */
+ uint16_t s_magic; /* Magic signature */
+ uint16_t s_state; /* File system state */
+ uint16_t s_errors; /* Behaviour when detecting errors */
+ uint16_t s_minor_rev_level;
+ uint32_t s_lastcheck; /* time of last check */
+ uint32_t s_checkinterval; /* max. time between checks */
+ uint32_t s_creator_os; /* OS */
+ uint32_t s_rev_level; /* Revision level */
+ uint16_t s_def_resuid; /* Default uid for reserved blocks */
+ uint16_t s_def_resgid; /* Default gid for reserved blocks */
+
+ uint32_t s_first_ino; /* First non-reserved inode */
+ uint16_t s_inode_size; /* size of inode structure */
+ uint16_t s_block_group_nr; /* block group # of this superblock */
+ uint32_t s_feature_compat; /* compatible feature set */
+ uint32_t s_feature_incompat; /* incompatible feature set */
+ uint32_t s_feature_ro_compat; /* readonly-compatible feature set */
+ uint8_t s_uuid[16]; /* 128-bit uuid for volume */
+ char s_volume_name[16]; /* volume name */
+ char s_last_mounted[64]; /* directory where last mounted */
+ uint32_t s_algorithm_usage_bitmap; /* For compression */
+ uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
+ uint8_t s_prealloc_dir_blocks;
+ uint16_t s_reserved_gdt_blocks; /* Per group desc for online growth */
+ /*
+ * Journaling support valid if EXT4_FEATURE_COMPAT_HAS_JOURNAL set.
+ */
+ uint8_t s_journal_uuid[16]; /* uuid of journal superblock */
+ uint32_t s_journal_inum; /* inode number of journal file */
+ uint32_t s_journal_dev; /* device number of journal file */
+ uint32_t s_last_orphan; /* start of list of inodes to delete */
+ uint32_t s_hash_seed[4]; /* HTREE hash seed */
+ uint8_t s_def_hash_version; /* Default hash version to use */
+ uint8_t s_reserved_char_pad;
+ uint16_t s_desc_size; /* size of group descriptor */
+ uint32_t s_default_mount_opts;
+ uint32_t s_first_meta_bg; /* First metablock block group */
+ uint32_t s_mkfs_time; /* When the filesystem was created */
+ uint32_t s_jnl_blocks[17]; /* Backup of the journal inode */
+ /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
+ uint32_t s_blocks_count_hi; /* Blocks count */
+ uint32_t s_r_blocks_count_hi; /* Reserved blocks count */
+ uint32_t s_free_blocks_count_hi;/* Free blocks count */
+ uint16_t s_min_extra_isize; /* All inodes have at least # bytes */
+ uint16_t s_want_extra_isize; /* New inodes should reserve # bytes */
+ uint32_t s_flags; /* Miscellaneous flags */
+ uint16_t s_raid_stride; /* RAID stride */
+ uint16_t s_mmp_interval; /* # seconds to wait in MMP checking */
+ uint64_t s_mmp_block; /* Block for multi-mount protection */
+ uint32_t s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
+ uint8_t s_log_groups_per_flex; /* FLEX_BG group size */
+ uint8_t s_reserved_char_pad2;
+ uint16_t s_reserved_pad;
+ uint32_t s_reserved[162]; /* Padding to the end of the block */
+};
+
+/*******************************************************************************
+#ifndef DEPEND
+#if ext2_super_block_size != 1024
+#error ext2_super_block definition bogus
+#endif
+#endif
+*******************************************************************************/
+
+/*
+ * ext2 group desc structure:
+ */
+struct ext2_group_desc {
+ uint32_t bg_block_bitmap; /* Blocks bitmap block */
+ uint32_t bg_inode_bitmap; /* Inodes bitmap block */
+ uint32_t bg_inode_table; /* Inodes table block */
+ uint16_t bg_free_blocks_count; /* Free blocks count */
+ uint16_t bg_free_inodes_count; /* Free inodes count */
+ uint16_t bg_used_dirs_count; /* Directories count */
+ uint16_t bg_pad;
+ uint32_t bg_reserved[3];
+};
+
+/*******************************************************************************
+#ifndef DEPEND
+#if ext2_group_desc_size != 32
+#error ext2_group_desc definition bogus
+#endif
+#endif
+*******************************************************************************/
+
+
+/*
+ * ext2 inode structure:
+ */
+struct ext2_inode {
+ uint16_t i_mode; /* File mode */
+ uint16_t i_uid; /* Owner Uid */
+ uint32_t i_size; /* 4: Size in bytes */
+ uint32_t i_atime; /* Access time */
+ uint32_t i_ctime; /* 12: Creation time */
+ uint32_t i_mtime; /* Modification time */
+ uint32_t i_dtime; /* 20: Deletion Time */
+ uint16_t i_gid; /* Group Id */
+ uint16_t i_links_count; /* 24: Links count */
+ uint32_t i_blocks; /* Blocks count */
+ uint32_t i_flags; /* 32: File flags */
+ uint32_t l_i_reserved1;
+ uint32_t i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */
+ uint32_t i_version; /* File version (for NFS) */
+ uint32_t i_file_acl; /* File ACL */
+ uint32_t i_dir_acl; /* Directory ACL */
+ uint32_t i_faddr; /* Fragment address */
+ uint8_t l_i_frag; /* Fragment number */
+ uint8_t l_i_fsize; /* Fragment size */
+ uint16_t i_pad1;
+ uint32_t l_i_reserved2[2];
+};
+
+/*******************************************************************************
+#ifndef DEPEND
+#if ext2_inode_size != 128
+#error ext2_inode definition bogus
+#endif
+#endif
+*******************************************************************************/
+
+
+#define EXT2_NAME_LEN 255
+struct ext2_dir_entry {
+ unsigned int d_inode; /* Inode number */
+ unsigned short d_rec_len; /* Directory entry length */
+ unsigned char d_name_len; /* Name length */
+ unsigned char d_file_type;
+ char d_name[EXT2_NAME_LEN]; /* File name */
+};
+
+/*******************************************************************************
+#define EXT2_DIR_PAD 4
+#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
+#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
+ ~EXT2_DIR_ROUND)
+*******************************************************************************/
+
+
+
+
+
+
+/*
+ * This is the extent on-disk structure.
+ * It's used at the bottom of the tree.
+ */
+struct ext4_extent {
+ uint32_t ee_block; /* first logical block extent covers */
+ uint16_t ee_len; /* number of blocks covered by extent */
+ uint16_t ee_start_hi; /* high 16 bits of physical block */
+ uint32_t ee_start_lo; /* low 32 bits of physical block */
+};
+
+/*
+ * This is index on-disk structure.
+ * It's used at all the levels except the bottom.
+ */
+struct ext4_extent_idx {
+ uint32_t ei_block; /* index covers logical blocks from 'block' */
+ uint32_t ei_leaf_lo; /* pointer to the physical block of the next *
+ * level. leaf or next index could be there */
+ uint16_t ei_leaf_hi; /* high 16 bits of physical block */
+ uint16_t ei_unused;
+};
+
+/*
+ * Each block (leaves and indexes), even inode-stored has header.
+ */
+struct ext4_extent_header {
+ uint16_t eh_magic; /* probably will support different formats */
+ uint16_t eh_entries; /* number of valid entries */
+ uint16_t eh_max; /* capacity of store in entries */
+ uint16_t eh_depth; /* has tree real underlying blocks? */
+ uint32_t eh_generation; /* generation of the tree */
+};
+
+
+
+#define EXT4_FIRST_EXTENT(header) ( (struct ext4_extent *)(header + 1) )
+#define EXT4_FIRST_INDEX(header) ( (struct ext4_extent_idx *) (header + 1) )
+
+
+/*
+ * The ext2 super block information in memory
+ */
+struct ext2_sb_info {
+ uint32_t s_inodes_per_block;/* Number of inodes per block */
+ uint32_t s_inodes_per_group;/* Number of inodes in a group */
+ uint32_t s_blocks_per_group;/* Number of blocks in a group */
+ uint32_t s_desc_per_block; /* Number of group descriptors per block */
+ uint32_t s_groups_count; /* Number of groups in the fs */
+ uint32_t s_first_data_block; /* First Data Block */
+ int s_inode_size;
+};
+
+static inline struct ext2_sb_info *EXT2_SB(struct fs_info *fs)
+{
+ return fs->fs_info;
+}
+
+#define EXT2_BLOCKS_PER_GROUP(fs) (EXT2_SB(fs)->s_blocks_per_group)
+#define EXT2_INODES_PER_GROUP(fs) (EXT2_SB(fs)->s_inodes_per_group)
+#define EXT2_INODES_PER_BLOCK(fs) (EXT2_SB(fs)->s_inodes_per_block)
+#define EXT2_DESC_PER_BLOCK(fs) (EXT2_SB(fs)->s_desc_per_block)
+
+
+/*
+ * functions
+ */
+block_t bmap(struct fs_info *, struct inode *, int);
+
+
+#endif /* ext2_fs.h */
diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c
new file mode 100644
index 00000000..13cf674d
--- /dev/null
+++ b/core/fs/fat/fat.c
@@ -0,0 +1,860 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/dirent.h>
+#include <cache.h>
+#include <core.h>
+#include <disk.h>
+#include <fs.h>
+#include <klibc/compiler.h>
+#include "codepage.h"
+#include "fat_fs.h"
+
+static struct inode * new_fat_inode(struct fs_info *fs)
+{
+ struct inode *inode = alloc_inode(fs, 0, sizeof(struct fat_pvt_inode));
+ if (!inode)
+ malloc_error("inode structure");
+
+ return inode;
+}
+
+
+static void vfat_close_file(struct file *file)
+{
+ if (file->inode) {
+ file->offset = 0;
+ free_inode(file->inode);
+ }
+}
+
+
+/*
+ * Check for a particular sector in the FAT cache
+ */
+static struct cache_struct * get_fat_sector(struct fs_info *fs, sector_t sector)
+{
+ return get_cache_block(fs->fs_dev, FAT_SB(fs)->fat + sector);
+}
+
+static uint32_t get_next_cluster(struct fs_info *fs, uint32_t clust_num)
+{
+ uint32_t next_cluster;
+ sector_t fat_sector;
+ uint32_t offset;
+ int lo, hi;
+ struct cache_struct *cs;
+ uint32_t sector_mask = SECTOR_SIZE(fs) - 1;
+
+ switch(FAT_SB(fs)->fat_type) {
+ case FAT12:
+ offset = clust_num + (clust_num >> 1);
+ fat_sector = offset >> SECTOR_SHIFT(fs);
+ offset &= sector_mask;
+ cs = get_fat_sector(fs, fat_sector);
+ if (offset == sector_mask) {
+ /*
+ * we got the end of the one fat sector,
+ * but we have just one byte and we need two,
+ * so store the low part, then read the next fat
+ * sector, read the high part, then combine it.
+ */
+ lo = *(uint8_t *)(cs->data + offset);
+ cs = get_fat_sector(fs, fat_sector + 1);
+ hi = *(uint8_t *)cs->data;
+ next_cluster = (hi << 8) + lo;
+ } else {
+ next_cluster = *(uint16_t *)(cs->data + offset);
+ }
+
+ if (clust_num & 0x0001)
+ next_cluster >>= 4; /* cluster number is ODD */
+ else
+ next_cluster &= 0x0fff; /* cluster number is EVEN */
+ break;
+
+ case FAT16:
+ offset = clust_num << 1;
+ fat_sector = offset >> SECTOR_SHIFT(fs);
+ offset &= sector_mask;
+ cs = get_fat_sector(fs, fat_sector);
+ next_cluster = *(uint16_t *)(cs->data + offset);
+ break;
+
+ case FAT32:
+ offset = clust_num << 2;
+ fat_sector = offset >> SECTOR_SHIFT(fs);
+ offset &= sector_mask;
+ cs = get_fat_sector(fs, fat_sector);
+ next_cluster = *(uint32_t *)(cs->data + offset);
+ next_cluster &= 0x0fffffff;
+ break;
+ }
+
+ return next_cluster;
+}
+
+
+static sector_t get_next_sector(struct fs_info* fs, uint32_t sector)
+{
+ struct fat_sb_info *sbi = FAT_SB(fs);
+ sector_t data_area = sbi->data;
+ sector_t data_sector;
+ uint32_t cluster;
+ int clust_shift = sbi->clust_shift;
+
+ if (sector < data_area) {
+ /* Root directory sector... */
+ sector++;
+ if (sector >= data_area)
+ sector = 0; /* Ran out of root directory, return EOF */
+ return sector;
+ }
+
+ data_sector = sector - data_area;
+ if ((data_sector + 1) & sbi->clust_mask) /* Still in the same cluster */
+ return sector + 1; /* Next sector inside cluster */
+
+ /* get a new cluster */
+ cluster = data_sector >> clust_shift;
+ cluster = get_next_cluster(fs, cluster + 2) - 2;
+
+ if (cluster >= sbi->clusters)
+ return 0;
+
+ /* return the start of the new cluster */
+ sector = (cluster << clust_shift) + data_area;
+ return sector;
+}
+
+/*
+ * Here comes the place I don't like VFAT fs most; if we need seek
+ * the file to the right place, we need get the right sector address
+ * from begining everytime! Since it's a kind a signle link list, we
+ * need to traver from the head-node to find the right node in that list.
+ *
+ * What a waste of time!
+ */
+static sector_t get_the_right_sector(struct file *file)
+{
+ struct inode *inode = file->inode;
+ uint32_t sector_pos = file->offset >> SECTOR_SHIFT(file->fs);
+ uint32_t where;
+ sector_t sector;
+
+ if (sector_pos < PVT(inode)->offset) {
+ /* Reverse seek */
+ where = 0;
+ sector = PVT(inode)->start;
+ } else {
+ where = PVT(inode)->offset;
+ sector = PVT(inode)->here;
+ }
+
+ while (where < sector_pos) {
+ sector = get_next_sector(file->fs, sector);
+ where++;
+ }
+
+ PVT(inode)->offset = sector_pos;
+ PVT(inode)->here = sector;
+
+ return sector;
+}
+
+/*
+ * Get the next sector in sequence
+ */
+static sector_t next_sector(struct file *file)
+{
+ struct inode *inode = file->inode;
+ sector_t sector = get_next_sector(file->fs, PVT(inode)->here);
+ PVT(inode)->offset++;
+ PVT(inode)->here = sector;
+
+ return sector;
+}
+
+/**
+ * __getfssec:
+ *
+ * get multiple sectors from a file
+ *
+ * This routine makes sure the subransfers do not cross a 64K boundary
+ * and will correct the situation if it does, UNLESS *sectos* cross
+ * 64K boundaries.
+ *
+ */
+static void __getfssec(struct fs_info *fs, char *buf,
+ struct file *file, uint32_t sectors)
+{
+ sector_t curr_sector = get_the_right_sector(file);
+ sector_t frag_start , next_sector;
+ uint32_t con_sec_cnt;
+ struct disk *disk = fs->fs_dev->disk;
+
+ while (sectors) {
+ /* get fragment */
+ con_sec_cnt = 0;
+ frag_start = curr_sector;
+
+ do {
+ /* get consective sector count */
+ con_sec_cnt++;
+ sectors--;
+ next_sector = get_next_sector(fs, curr_sector);
+ curr_sector++;
+ } while (sectors && next_sector == curr_sector);
+
+ PVT(file->inode)->offset += con_sec_cnt;
+ PVT(file->inode)->here = next_sector;
+
+ /* do read */
+ disk->rdwr_sectors(disk, buf, frag_start, con_sec_cnt, 0);
+ buf += con_sec_cnt << SECTOR_SHIFT(fs);/* adjust buffer pointer */
+
+ curr_sector = next_sector;
+ }
+}
+
+
+
+/**
+ * get multiple sectors from a file
+ *
+ * @param: buf, the buffer to store the read data
+ * @param: file, the file structure pointer
+ * @param: sectors, number of sectors wanna read
+ * @param: have_more, set one if has more
+ *
+ * @return: number of bytes read
+ *
+ */
+static uint32_t vfat_getfssec(struct file *file, char *buf, int sectors,
+ bool *have_more)
+{
+ struct fs_info *fs = file->fs;
+ uint32_t bytes_left = file->inode->size - file->offset;
+ uint32_t bytes_read = sectors << fs->sector_shift;
+ int sector_left;
+
+ sector_left = (bytes_left + SECTOR_SIZE(fs) - 1) >> fs->sector_shift;
+ if (sectors > sector_left)
+ sectors = sector_left;
+
+ __getfssec(fs, buf, file, sectors);
+
+ if (bytes_read >= bytes_left) {
+ bytes_read = bytes_left;
+ *have_more = 0;
+ } else {
+ *have_more = 1;
+ }
+ file->offset += bytes_read;
+
+ return bytes_read;
+}
+
+/*
+ * Mangle a filename pointed to by src into a buffer pointed to by dst;
+ * ends on encountering any whitespace.
+ *
+ */
+static void vfat_mangle_name(char *dst, const char *src)
+{
+ char *p = dst;
+ char c;
+ int i = FILENAME_MAX -1;
+
+ /*
+ * Copy the filename, converting backslash to slash and
+ * collapsing duplicate separators.
+ */
+ while (not_whitespace(c = *src)) {
+ if (c == '\\')
+ c = '/';
+
+ if (c == '/') {
+ if (src[1] == '/' || src[1] == '\\') {
+ src++;
+ i--;
+ continue;
+ }
+ }
+ i--;
+ *dst++ = *src++;
+ }
+
+ /* Strip terminal slashes or whitespace */
+ while (1) {
+ if (dst == p)
+ break;
+ if (*(dst-1) == '/' && dst-1 == p) /* it's the '/' case */
+ break;
+ if ((*(dst-1) != '/') && (*(dst-1) != '.'))
+ break;
+
+ dst--;
+ i++;
+ }
+
+ i++;
+ for (; i > 0; i --)
+ *dst++ = '\0';
+}
+
+/*
+ * Mangle a normal style string to DOS style string.
+ */
+static void mangle_dos_name(char *mangle_buf, char *src)
+{
+ int i;
+ unsigned char c;
+
+ i = 0;
+ while (i < 11) {
+ c = *src++;
+
+ if ((c <= ' ') || (c == '/'))
+ break;
+
+ if (c == '.') {
+ while (i < 8)
+ mangle_buf[i++] = ' ';
+ i = 8;
+ continue;
+ }
+
+ c = codepage.upper[c];
+ if (i == 0 && c == 0xe5)
+ c = 0x05; /* Special hack for the first byte only! */
+
+ mangle_buf[i++] = c;
+ }
+ while (i < 11)
+ mangle_buf[i++] = ' ';
+
+ mangle_buf[i] = '\0';
+}
+
+/*
+ * Match a string name against a longname. "len" is the number of
+ * codepoints in the input; including padding.
+ *
+ * Returns true on match.
+ */
+static bool vfat_match_longname(const char *str, const uint16_t *match,
+ int len)
+{
+ unsigned char c;
+ uint16_t cp;
+
+ while (len) {
+ cp = *match++;
+ c = *str++;
+ if (cp != codepage.uni[0][c] && cp != codepage.uni[1][c])
+ return false;
+ if (!c)
+ break;
+ }
+
+ if (c)
+ return false;
+
+ /* Any padding entries must be FFFF */
+ while (len)
+ if (*match++ != 0xffff)
+ return false;
+
+ return true;
+}
+
+/*
+ * Convert an UTF-16 longname to the system codepage; return
+ * the length on success or -1 on failure.
+ */
+static int vfat_cvt_longname(char *entry_name, const uint16_t *long_name)
+{
+ struct unicache {
+ uint16_t utf16;
+ uint8_t cp;
+ };
+ static struct unicache unicache[256];
+ struct unicache *uc;
+ uint16_t cp;
+ unsigned int c;
+ char *p = entry_name;
+
+ do {
+ cp = *long_name++;
+ uc = &unicache[cp % 256];
+
+ if (__likely(uc->utf16 == cp)) {
+ *p++ = uc->cp;
+ } else {
+ for (c = 0; c < 512; c++) {
+ /* This is a bit hacky... */
+ if (codepage.uni[0][c] == cp) {
+ uc->utf16 = cp;
+ *p++ = uc->cp = (uint8_t)c;
+ goto found;
+ }
+ }
+ return -1; /* Impossible character */
+ found:
+ ;
+ }
+ } while (cp);
+
+ return (p-entry_name)-1;
+}
+
+static void copy_long_chunk(uint16_t *buf, const struct fat_dir_entry *de)
+{
+ const struct fat_long_name_entry *le =
+ (const struct fat_long_name_entry *)de;
+
+ memcpy(buf, le->name1, 5 * 2);
+ memcpy(buf + 5, le->name2, 6 * 2);
+ memcpy(buf + 11, le->name3, 2 * 2);
+}
+
+static uint8_t get_checksum(char *dir_name)
+{
+ int i;
+ uint8_t sum = 0;
+
+ for (i = 11; i; i--)
+ sum = ((sum & 1) << 7) + (sum >> 1) + *dir_name++;
+ return sum;
+}
+
+
+/* compute the first sector number of one dir where the data stores */
+static inline sector_t first_sector(struct fs_info *fs,
+ const struct fat_dir_entry *dir)
+{
+ const struct fat_sb_info *sbi = FAT_SB(fs);
+ sector_t first_clust;
+ sector_t sector;
+
+ first_clust = (dir->first_cluster_high << 16) + dir->first_cluster_low;
+ sector = ((first_clust - 2) << sbi->clust_shift) + sbi->data;
+
+ return sector;
+}
+
+static inline int get_inode_mode(uint8_t attr)
+{
+ if (attr == FAT_ATTR_DIRECTORY)
+ return I_DIR;
+ else
+ return I_FILE;
+}
+
+
+static struct inode *vfat_find_entry(char *dname, struct inode *dir)
+{
+ struct fs_info *fs = dir->fs;
+ struct inode *inode;
+ struct fat_dir_entry *de;
+ struct fat_long_name_entry *long_de;
+ struct cache_struct *cs;
+
+ char mangled_name[12];
+ uint16_t long_name[260]; /* == 20*13 */
+ int long_len;
+
+ sector_t dir_sector = PVT(dir)->start;
+ uint8_t vfat_init, vfat_next, vfat_csum = 0;
+ uint8_t id;
+ int slots;
+ int entries;
+ int checksum;
+ int long_match = 0;
+
+ slots = (strlen(dname) + 12) / 13;
+ if (slots > 20)
+ return NULL; /* Name too long */
+
+ slots |= 0x40;
+ vfat_init = vfat_next = slots;
+ long_len = slots*13;
+
+ /* Produce the shortname version, in case we need it. */
+ mangle_dos_name(mangled_name, dname);
+
+ while (dir_sector) {
+ cs = get_cache_block(fs->fs_dev, dir_sector);
+ de = (struct fat_dir_entry *)cs->data;
+ entries = 1 << (fs->sector_shift - 5);
+
+ while (entries--) {
+ if (de->name[0] == 0)
+ return NULL;
+
+ if (de->attr == 0x0f) {
+ /*
+ * It's a long name entry.
+ */
+ long_de = (struct fat_long_name_entry *)de;
+ id = long_de->id;
+ if (id != vfat_next)
+ goto not_match;
+
+ if (id & 0x40) {
+ /* get the initial checksum value */
+ vfat_csum = long_de->checksum;
+ id &= 0x3f;
+ long_len = id * 13;
+
+ /* ZERO the long_name buffer */
+ memset(long_name, 0, sizeof long_name);
+ } else {
+ if (long_de->checksum != vfat_csum)
+ goto not_match;
+ }
+
+ vfat_next = --id;
+
+ /* got the long entry name */
+ copy_long_chunk(long_name + id*13, de);
+
+ /*
+ * If we got the last entry, check it.
+ * Or, go on with the next entry.
+ */
+ if (id == 0) {
+ if (!vfat_match_longname(dname, long_name, long_len))
+ goto not_match;
+ long_match = 1;
+ }
+ de++;
+ continue; /* Try the next entry */
+ } else {
+ /*
+ * It's a short entry
+ */
+ if (de->attr & 0x08) /* ignore volume labels */
+ goto not_match;
+
+ if (long_match) {
+ /*
+ * We already have a VFAT long name match. However, the
+ * match is only valid if the checksum matches.
+ */
+ checksum = get_checksum(de->name);
+ if (checksum == vfat_csum)
+ goto found; /* Got it */
+ } else {
+ if (!memcmp(mangled_name, de->name, 11))
+ goto found;
+ }
+ }
+
+ not_match:
+ vfat_next = vfat_init;
+ long_match = 0;
+
+ de++;
+ }
+
+ /* Try with the next sector */
+ dir_sector = get_next_sector(fs, dir_sector);
+ }
+ return NULL; /* Nothing found... */
+
+found:
+ inode = new_fat_inode(fs);
+ inode->size = de->file_size;
+ PVT(inode)->start = PVT(inode)->here = first_sector(fs, de);
+ inode->mode = get_inode_mode(de->attr);
+
+ return inode;
+}
+
+static struct inode *vfat_iget_root(struct fs_info *fs)
+{
+ struct inode *inode = new_fat_inode(fs);
+ int root_size = FAT_SB(fs)->root_size;
+
+ /*
+ * For FAT32, the only way to get the root directory size is to
+ * follow the entire FAT chain to the end... which seems pointless.
+ */
+ inode->size = root_size ? root_size << fs->sector_shift : ~0;
+ PVT(inode)->start = PVT(inode)->here = FAT_SB(fs)->root;
+ inode->mode = I_DIR;
+
+ return inode;
+}
+
+static struct inode *vfat_iget(char *dname, struct inode *parent)
+{
+ return vfat_find_entry(dname, parent);
+}
+
+static struct dirent * vfat_readdir(struct file *file)
+{
+ struct fs_info *fs = file->fs;
+ struct dirent *dirent;
+ struct fat_dir_entry *de;
+ struct fat_long_name_entry *long_de;
+ struct cache_struct *cs;
+
+ sector_t sector = get_the_right_sector(file);
+
+ uint16_t long_name[261]; /* == 20*13 + 1 (to guarantee null) */
+ char filename[261];
+
+ uint8_t vfat_init, vfat_next, vfat_csum;
+ uint8_t id;
+ int entries_left;
+ int checksum;
+ int long_entry = 0;
+ int sec_off = file->offset & ((1 << fs->sector_shift) - 1);
+
+ cs = get_cache_block(fs->fs_dev, sector);
+ de = (struct fat_dir_entry *)(cs->data + sec_off);
+ entries_left = ((1 << fs->sector_shift) - sec_off) >> 5;
+
+ vfat_next = vfat_csum = 0xff;
+
+ while (1) {
+ while(entries_left--) {
+ if (de->name[0] == 0)
+ return NULL;
+ if ((uint8_t)de->name[0] == 0xe5)
+ goto invalid;
+
+ if (de->attr == 0x0f) {
+ /*
+ * It's a long name entry.
+ */
+ long_de = (struct fat_long_name_entry *)de;
+ id = long_de->id;
+
+ if (id & 0x40) {
+ /* init vfat_csum and vfat_init */
+ vfat_csum = long_de->checksum;
+ id &= 0x3f;
+ if (id >= 20)
+ goto invalid; /* Too long! */
+
+ vfat_init = id;
+
+ /* ZERO the long_name buffer */
+ memset(long_name, 0, sizeof long_name);
+ } else {
+ if (long_de->checksum != vfat_csum ||
+ id != vfat_next)
+ goto invalid;
+ }
+
+ vfat_next = --id;
+
+ /* got the long entry name */
+ copy_long_chunk(long_name + id*13, de);
+
+ if (id == 0) {
+ int longlen =
+ vfat_cvt_longname(filename, long_name);
+ if (longlen > 0 && longlen < sizeof(dirent->d_name))
+ long_entry = 1;
+ }
+
+ de++;
+ file->offset += sizeof(struct fat_dir_entry);
+ continue; /* Try the next entry */
+ } else {
+ /*
+ * It's a short entry
+ */
+ if (de->attr & 0x08) /* ignore volume labels */
+ goto invalid;
+
+ if (long_entry == 1) {
+ /* Got a long entry */
+ checksum = get_checksum(de->name);
+ if (checksum == vfat_csum)
+ goto got;
+ } else {
+ /* Use the shortname */
+ int i;
+ uint8_t c;
+ char *p = filename;
+
+ for (i = 0; i < 8; i++) {
+ c = de->name[i];
+ if (c == ' ')
+ break;
+ if (de->lcase & LCASE_BASE)
+ c = codepage.lower[c];
+ *p++ = c;
+ }
+ if (de->name[8] != ' ') {
+ *p++ = '.';
+ for (i = 8; i < 11; i++) {
+ c = de->name[i];
+ if (c == ' ')
+ break;
+ if (de->lcase & LCASE_EXT)
+ c = codepage.lower[c];
+ *p++ = c;
+ }
+ }
+ *p = '\0';
+
+ goto got;
+ }
+ }
+
+ invalid:
+ de++;
+ file->offset += sizeof(struct fat_dir_entry);
+ }
+
+ /* Try with the next sector */
+ sector = next_sector(file);
+ if (!sector)
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, sector);
+ de = (struct fat_dir_entry *)cs->data;
+ entries_left = 1 << (fs->sector_shift - 5);
+ }
+
+got:
+ if (!(dirent = malloc(sizeof(*dirent)))) {
+ malloc_error("dirent structure in vfat_readdir");
+ return NULL;
+ }
+ dirent->d_ino = de->first_cluster_low | (de->first_cluster_high << 16);
+ dirent->d_off = file->offset;
+ dirent->d_reclen = 0;
+ dirent->d_type = get_inode_mode(de->attr);
+ strcpy(dirent->d_name, filename);
+
+ file->offset += sizeof(*de); /* Update for next reading */
+
+ return dirent;
+}
+
+/* Load the config file, return 1 if failed, or 0 */
+static int vfat_load_config(void)
+{
+ const char * const syslinux_cfg[] = {
+ "/boot/syslinux/syslinux.cfg",
+ "/syslinux/syslinux.cfg",
+ "/syslinux.cfg"
+ };
+ com32sys_t regs;
+ char *p;
+ int i = 0;
+
+ /*
+ * we use the ConfigName to pass the config path because
+ * it is under the address 0xffff
+ */
+ memset(&regs, 0, sizeof regs);
+ regs.edi.w[0] = OFFS_WRT(ConfigName, 0);
+ for (; i < 3; i++) {
+ strcpy(ConfigName, syslinux_cfg[i]);
+ call16(core_open, &regs, &regs);
+
+ /* if zf flag set, then failed; try another */
+ if (! (regs.eflags.l & EFLAGS_ZF))
+ break;
+ }
+ if (i == 3) {
+ printf("no config file found\n");
+ return 1; /* no config file */
+ }
+
+ strcpy(ConfigName, "syslinux.cfg");
+ strcpy(CurrentDirName, syslinux_cfg[i]);
+ p = strrchr(CurrentDirName, '/');
+ *(p + 1) = '\0'; /* In case we met '/syslinux.cfg' */
+
+ return 0;
+}
+
+static inline __constfunc uint32_t bsr(uint32_t num)
+{
+ asm("bsrl %1,%0" : "=r" (num) : "rm" (num));
+ return num;
+}
+
+/* init. the fs meta data, return the block size in bits */
+static int vfat_fs_init(struct fs_info *fs)
+{
+ struct fat_bpb fat;
+ struct fat_sb_info *sbi;
+ struct disk *disk = fs->fs_dev->disk;
+ int sectors_per_fat;
+ uint32_t clusters;
+ sector_t total_sectors;
+
+ fs->sector_shift = fs->block_shift = disk->sector_shift;
+ fs->sector_size = 1 << fs->sector_shift;
+ fs->block_size = 1 << fs->block_shift;
+
+ disk->rdwr_sectors(disk, &fat, 0, 1, 0);
+
+ sbi = malloc(sizeof(*sbi));
+ if (!sbi)
+ malloc_error("fat_sb_info structure");
+ fs->fs_info = sbi;
+
+ sectors_per_fat = fat.bxFATsecs ? : fat.fat32.bxFATsecs_32;
+ total_sectors = fat.bxSectors ? : fat.bsHugeSectors;
+
+ sbi->fat = fat.bxResSectors;
+ sbi->root = sbi->fat + sectors_per_fat * fat.bxFATs;
+ sbi->root_size = root_dir_size(fs, &fat);
+ sbi->data = sbi->root + sbi->root_size;
+
+ sbi->clust_shift = bsr(fat.bxSecPerClust);
+ sbi->clust_byte_shift = sbi->clust_shift + fs->sector_shift;
+ sbi->clust_mask = fat.bxSecPerClust - 1;
+ sbi->clust_size = fat.bxSecPerClust << fs->sector_shift;
+
+ clusters = (total_sectors - sbi->data) >> sbi->clust_shift;
+ if (clusters <= 0xff4) {
+ sbi->fat_type = FAT12;
+ } else if (clusters <= 0xfff4) {
+ sbi->fat_type = FAT16;
+ } else {
+ sbi->fat_type = FAT32;
+
+ if (clusters > 0x0ffffff4)
+ clusters = 0x0ffffff4; /* Maximum possible */
+
+ if (fat.fat32.extended_flags & 0x80) {
+ /* Non-mirrored FATs, we need to read the active one */
+ sbi->fat += (fat.fat32.extended_flags & 0x0f) * sectors_per_fat;
+ }
+
+ /* FAT32: root directory is a cluster chain */
+ sbi->root = sbi->data
+ + ((fat.fat32.root_cluster-2) << sbi->clust_shift);
+ }
+ sbi->clusters = clusters;
+
+ /* for SYSLINUX, the cache is based on sector size */
+ return fs->sector_shift;
+}
+
+const struct fs_ops vfat_fs_ops = {
+ .fs_name = "vfat",
+ .fs_flags = FS_USEMEM | FS_THISIND,
+ .fs_init = vfat_fs_init,
+ .searchdir = NULL,
+ .getfssec = vfat_getfssec,
+ .close_file = vfat_close_file,
+ .mangle_name = vfat_mangle_name,
+ .unmangle_name = generic_unmangle_name,
+ .load_config = vfat_load_config,
+ .readdir = vfat_readdir,
+ .iget_root = vfat_iget_root,
+ .iget_current = NULL,
+ .iget = vfat_iget,
+};
diff --git a/core/fs/fat/fat_fs.h b/core/fs/fat/fat_fs.h
new file mode 100644
index 00000000..60b5aee1
--- /dev/null
+++ b/core/fs/fat/fat_fs.h
@@ -0,0 +1,156 @@
+#ifndef FAT_FS_H
+#define FAT_FS_H
+
+#include <stdint.h>
+
+#define FAT_DIR_ENTRY_SIZE 32
+#define DIRENT_SHIFT 5
+
+#define FAT_ATTR_READ_ONLY 0x01
+#define FAT_ATTR_HIDDEN 0x02
+#define FAT_ATTR_SYSTEM 0x04
+#define FAT_ATTR_VOLUME_ID 0x08
+#define FAT_ATTR_DIRECTORY 0x10
+#define FAT_ATTR_ARCHIVE 0x20
+
+#define FAT_MAXFILE 256
+
+#define FAT_ATTR_LONG_NAME (FAT_ATTR_READ_ONLY \
+ | FAT_ATTR_HIDDEN \
+ | FAT_ATTR_SYSTEM \
+ | FAT_ATTR_VOLUME_ID)
+
+#define FAT_ATTR_VALID (FAT_ATTR_READ_ONLY \
+ | FAT_ATTR_HIDDEN \
+ | FAT_ATTR_SYSTEM \
+ | FAT_ATTR_DIRECTORY \
+ | FAT_ATTR_ARCHIVE)
+
+enum fat_type{ FAT12, FAT16, FAT32 };
+
+/*
+ * The fat file system structures
+ */
+
+struct fat_bpb {
+ uint8_t jmp_boot[3];
+ uint8_t oem_name[8];
+ uint16_t sector_size;
+ uint8_t bxSecPerClust;
+ uint16_t bxResSectors;
+ uint8_t bxFATs;
+ uint16_t bxRootDirEnts;
+ uint16_t bxSectors;
+ uint8_t media;
+ uint16_t bxFATsecs;
+ uint16_t sectors_per_track;
+ uint16_t num_heads;
+ uint32_t num_hidden_sectors;
+ uint32_t bsHugeSectors;
+
+ union {
+ struct {
+ uint8_t num_ph_drive;
+ uint8_t reserved;
+ uint8_t boot_sig;
+ uint32_t num_serial;
+ uint8_t label[11];
+ uint8_t fstype[8];
+ } __attribute__ ((packed)) fat12_16;
+
+ struct {
+ uint32_t bxFATsecs_32;
+ uint16_t extended_flags;
+ uint16_t fs_version;
+ uint32_t root_cluster;
+ uint16_t fs_info;
+ uint16_t backup_boot_sector;
+ uint8_t reserved[12];
+ uint8_t num_ph_drive;
+ uint8_t reserved1;
+ uint8_t boot_sig;
+ uint32_t num_serial;
+ uint8_t label[11];
+ uint8_t fstype[8];
+ } __attribute__ ((packed)) fat32;
+
+ } __attribute__ ((packed));
+
+ uint8_t pad[422]; /* padding to 512 Bytes (one sector) */
+
+} __attribute__ ((packed));
+
+/*
+ * The fat file system info in memory
+ */
+struct fat_sb_info {
+ sector_t fat; /* The FAT region */
+ sector_t root; /* The root dir region */
+ sector_t data; /* The data region */
+
+ uint32_t clusters; /* Total number of clusters */
+ int root_size; /* The root dir size in sectores */
+
+ int clust_shift; /* based on sectors */
+ int clust_byte_shift; /* based on bytes */
+ int clust_mask;
+ int clust_size;
+
+ int fat_type;
+} __attribute__ ((packed));
+
+struct fat_dir_entry {
+ char name[11];
+ uint8_t attr;
+ uint8_t lcase;
+ uint8_t c_time_tenth;
+ uint16_t c_time;
+ uint16_t c_date;
+ uint16_t a_date;
+ uint16_t first_cluster_high;
+ uint16_t w_time;
+ uint16_t w_date;
+ uint16_t first_cluster_low;
+ uint32_t file_size;
+} __attribute__ ((packed));
+
+#define LCASE_BASE 8 /* basename is lower case */
+#define LCASE_EXT 16 /* extension is lower case */
+
+struct fat_long_name_entry {
+ uint8_t id;
+ uint16_t name1[5];
+ uint8_t attr;
+ uint8_t reserved;
+ uint8_t checksum;
+ uint16_t name2[6];
+ uint16_t first_cluster;
+ uint16_t name3[2];
+} __attribute__ ((packed));
+
+static inline struct fat_sb_info *FAT_SB(struct fs_info *fs)
+{
+ return fs->fs_info;
+}
+
+/*
+ * Count the root dir size in sectors
+ */
+static inline int root_dir_size(struct fs_info *fs, struct fat_bpb *fat)
+{
+ return (fat->bxRootDirEnts + SECTOR_SIZE(fs)/32 - 1)
+ >> (SECTOR_SHIFT(fs) - 5);
+}
+
+/*
+ * FAT private inode information
+ */
+struct fat_pvt_inode {
+ sector_t start; /* Starting sector */
+ sector_t offset; /* Current sector offset */
+ sector_t here; /* Sector corresponding to offset */
+};
+
+#define PVT(i) ((struct fat_pvt_inode *)((i)->pvt))
+
+#endif /* fat_fs.h */
diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c
new file mode 100644
index 00000000..e6911644
--- /dev/null
+++ b/core/fs/iso9660/iso9660.c
@@ -0,0 +1,452 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/dirent.h>
+#include <core.h>
+#include <cache.h>
+#include <disk.h>
+#include <fs.h>
+#include "iso9660_fs.h"
+
+static struct inode *new_iso_inode(struct fs_info *fs)
+{
+ return alloc_inode(fs, 0, sizeof(uint32_t));
+}
+
+
+static void iso_close_file(struct file *file)
+{
+ if (file->inode) {
+ file->offset = 0;
+ free_inode(file->inode);
+ }
+}
+
+static inline struct iso_sb_info * ISO_SB(struct fs_info *fs)
+{
+ return fs->fs_info;
+}
+
+/*
+ * Mangle a filename pointed to by src into a buffer pointed
+ * to by dst; ends on encountering any whitespace.
+ * dst is preserved.
+ *
+ * This verifies that a filename is < FilENAME_MAX characters,
+ * doesn't contain whitespace, zero-pads the output buffer,
+ * and removes trailing dots and redumndant slashes, so "repe
+ * cmpsb" can do a compare, and the path-searching routine gets
+ * a bit of an easier job.
+ *
+ */
+static void iso_mangle_name(char *dst, const char *src)
+{
+ char *p = dst;
+ int i = FILENAME_MAX - 1;
+
+ while (not_whitespace(*src)) {
+ if ( *src == '/' ) {
+ if ( *(src+1) == '/' ) {
+ i--;
+ src++;
+ continue;
+ }
+ }
+
+ *dst++ = *src ++;
+ i--;
+ }
+
+ while ( 1 ) {
+ if ( dst == p )
+ break;
+
+ if ( (*(dst-1) != '.') && (*(dst-1) != '/') )
+ break;
+
+ dst --;
+ i ++;
+ }
+
+ i ++;
+ for (; i > 0; i -- )
+ *dst++ = '\0';
+}
+
+static int iso_convert_name(char *dst, char *src, int len)
+{
+ int i = 0;
+ char c;
+
+ for (; i < len; i++) {
+ c = src[i];
+ if (!c)
+ break;
+
+ /* remove ';1' in the end */
+ if (c == ';' && i == len - 2 && src[i + 1] == '1')
+ break;
+ /* convert others ';' to '.' */
+ if (c == ';')
+ c = '.';
+ *dst++ = c;
+ }
+
+ /* Then remove the terminal dots */
+ while (*(dst - 1) == '.') {
+ if (i <= 2)
+ break;
+ dst--;
+ i--;
+ }
+ *dst = 0;
+
+ return i;
+}
+
+/*
+ * Unlike strcmp, it does return 1 on match, or reutrn 0 if not match.
+ */
+static int iso_compare_name(char *de_name, int len, char *file_name)
+{
+ char iso_file_name[256];
+ char *p = iso_file_name;
+ char c1, c2;
+ int i;
+
+ i = iso_convert_name(iso_file_name, de_name, len);
+
+ if (i != (int)strlen(file_name))
+ return 0;
+
+ while (i--) {
+ c1 = *p++;
+ c2 = *file_name++;
+
+ /* convert to lower case */
+ c1 |= 0x20;
+ c2 |= 0x20;
+ if (c1 != c2)
+ return 0;
+ }
+
+ return 1;
+}
+
+static inline int cdrom_read_blocks(struct disk *disk, void *buf,
+ int block, int blocks)
+{
+ return disk->rdwr_sectors(disk, buf, block, blocks, 0);
+}
+
+/*
+ * Get multiple clusters from a file, given the file pointer.
+ */
+static uint32_t iso_getfssec(struct file *file, char *buf,
+ int blocks, bool *have_more)
+{
+ struct fs_info *fs = file->fs;
+ struct disk *disk = fs->fs_dev->disk;
+ uint32_t bytes_read = blocks << fs->block_shift;
+ uint32_t bytes_left = file->inode->size - file->offset;
+ uint32_t blocks_left = (bytes_left + BLOCK_SIZE(file->fs) - 1)
+ >> file->fs->block_shift;
+ block_t block = *(uint32_t *)file->inode->pvt
+ + (file->offset >> fs->block_shift);
+
+ if (blocks > blocks_left)
+ blocks = blocks_left;
+ cdrom_read_blocks(disk, buf, block, blocks);
+
+ if (bytes_read >= bytes_left) {
+ bytes_read = bytes_left;
+ *have_more = 0;
+ } else {
+ *have_more = 1;
+ }
+
+ file->offset += bytes_read;
+ return bytes_read;
+}
+
+/*
+ * Find a entry in the specified dir with name _dname_.
+ */
+static struct iso_dir_entry *iso_find_entry(char *dname, struct inode *inode)
+{
+ struct fs_info *fs = inode->fs;
+ block_t dir_block = *(uint32_t *)inode->pvt;
+ int i = 0, offset = 0;
+ char *de_name;
+ int de_name_len, de_len;
+ struct iso_dir_entry *de;
+ struct iso_dir_entry tmpde;
+ struct cache_struct *cs = NULL;
+
+ while (1) {
+ if (!cs) {
+ if (++i > inode->blocks)
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, dir_block++);
+ de = (struct iso_dir_entry *)cs->data;
+ offset = 0;
+ }
+ de = (struct iso_dir_entry *)(cs->data + offset);
+
+ de_len = de->length;
+ if (de_len == 0) { /* move on to the next block */
+ cs = NULL;
+ continue;
+ }
+ offset += de_len;
+
+ /* Make sure we have a full directory entry */
+ if (offset >= BLOCK_SIZE(fs)) {
+ int slop = de_len + BLOCK_SIZE(fs) - offset;
+
+ memcpy(&tmpde, de, slop);
+ offset &= BLOCK_SIZE(fs) - 1;
+ if (offset) {
+ if (++i > inode->blocks)
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, dir_block++);
+ memcpy((void *)&tmpde + slop, cs->data, offset);
+ }
+ de = &tmpde;
+ }
+
+ if (de_len < 33) {
+ printf("Corrupted directory entry in sector %u\n",
+ (uint32_t)(dir_block - 1));
+ return NULL;
+ }
+
+ de_name_len = de->name_len;
+ de_name = de->name;
+ /* Handling the special case ".' and '..' here */
+ if((de_name_len == 1) && (*de_name == 0)) {
+ de_name = ".";
+ } else if ((de_name_len == 1) && (*de_name == 1)) {
+ de_name ="..";
+ de_name_len = 2;
+ }
+ if (iso_compare_name(de_name, de_name_len, dname))
+ return de;
+ }
+}
+
+static inline int get_inode_mode(uint8_t flags)
+{
+ if (flags & 0x02)
+ return I_DIR;
+ else
+ return I_FILE;
+}
+
+static struct inode *iso_get_inode(struct fs_info *fs,
+ struct iso_dir_entry *de)
+{
+ struct inode *inode = new_iso_inode(fs);
+ if (!inode)
+ return NULL;
+
+ inode->mode = get_inode_mode(de->flags);
+ inode->size = *(uint32_t *)de->size;
+ *(uint32_t *)inode->pvt = *(uint32_t *)de->extent;
+ inode->blocks = (inode->size + BLOCK_SIZE(fs) - 1)
+ >> fs->block_shift;
+
+ return inode;
+}
+
+
+static struct inode *iso_iget_root(struct fs_info *fs)
+{
+ struct inode *inode = new_iso_inode(fs);
+ struct iso_dir_entry *root = &ISO_SB(fs)->root;
+
+ if (!inode)
+ return NULL;
+
+ inode->mode = I_DIR;
+ inode->size = *(uint32_t *)root->size;
+ *(uint32_t *)inode->pvt = *(uint32_t *)root->extent;
+ inode->blocks = (inode->size + BLOCK_SIZE(fs) - 1)
+ >> fs->block_shift;
+
+ return inode;
+}
+
+static struct inode *iso_iget(char *dname, struct inode *parent)
+{
+ struct iso_dir_entry *de;
+
+ de = iso_find_entry(dname, parent);
+ if (!de)
+ return NULL;
+
+ return iso_get_inode(parent->fs, de);
+}
+
+/* Convert to lower case string */
+static void tolower_str(char *str)
+{
+ while (*str) {
+ if (*str >= 'A' && *str <= 'Z')
+ *str = *str + 0x20;
+ str++;
+ }
+}
+
+static struct dirent *iso_readdir(struct file *file)
+{
+ struct fs_info *fs = file->fs;
+ struct inode *inode = file->inode;
+ struct iso_dir_entry *de, tmpde;
+ struct dirent *dirent;
+ struct cache_struct *cs = NULL;
+ block_t block = *(uint32_t *)file->inode->pvt
+ + (file->offset >> fs->block_shift);
+ int offset = file->offset & (BLOCK_SIZE(fs) - 1);
+ int i = 0;
+ int de_len, de_name_len;
+ char *de_name;
+
+ while (1) {
+ if (!cs) {
+ if (++i > inode->blocks)
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, block++);
+ }
+ de = (struct iso_dir_entry *)(cs->data + offset);
+
+ de_len = de->length;
+ if (de_len == 0) { /* move on to the next block */
+ cs = NULL;
+ file->offset = (file->offset + BLOCK_SIZE(fs) - 1)
+ >> fs->block_shift;
+ continue;
+ }
+ offset += de_len;
+
+ /* Make sure we have a full directory entry */
+ if (offset >= BLOCK_SIZE(fs)) {
+ int slop = de_len + BLOCK_SIZE(fs) - offset;
+
+ memcpy(&tmpde, de, slop);
+ offset &= BLOCK_SIZE(fs) - 1;
+ if (offset) {
+ if (++i > inode->blocks)
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, block++);
+ memcpy((void *)&tmpde + slop, cs->data, offset);
+ }
+ de = &tmpde;
+ }
+
+ if (de_len < 33) {
+ printf("Corrupted directory entry in sector %u\n",
+ (uint32_t)(block - 1));
+ return NULL;
+ }
+
+ de_name_len = de->name_len;
+ de_name = de->name;
+ /* Handling the special case ".' and '..' here */
+ if((de_name_len == 1) && (*de_name == 0)) {
+ de_name = ".";
+ } else if ((de_name_len == 1) && (*de_name == 1)) {
+ de_name ="..";
+ de_name_len = 2;
+ }
+
+ break;
+ }
+
+ if (!(dirent = malloc(sizeof(*dirent)))) {
+ malloc_error("dirent structure in iso_readdir");
+ return NULL;
+ }
+
+ dirent->d_ino = 0; /* Inode number is invalid to ISO fs */
+ dirent->d_off = file->offset;
+ dirent->d_reclen = de_len;
+ dirent->d_type = get_inode_mode(de->flags);
+ iso_convert_name(dirent->d_name, de_name, de_name_len);
+ tolower_str(dirent->d_name);
+
+ file->offset += de_len; /* Update for next reading */
+
+ return dirent;
+}
+
+/* Load the config file, return 1 if failed, or 0 */
+static int iso_load_config(void)
+{
+ const char *config_file[] = {
+ "/boot/isolinux/isolinux.cfg",
+ "/isolinux/isolinux.cfg"
+ };
+ com32sys_t regs;
+ int i = 0;
+ char *p;
+
+ for (; i < 2; i++) {
+ memset(&regs, 0, sizeof regs);
+ strcpy(ConfigName, config_file[i]);
+ regs.edi.w[0] = OFFS_WRT(ConfigName, 0);
+ call16(core_open, &regs, &regs);
+ if (!(regs.eflags.l & EFLAGS_ZF))
+ break;
+ }
+ if (i == 2) {
+ printf("No config file found\n");
+ return 1;
+ }
+
+ strcpy(ConfigName, "isolinux.cfg");
+ strcpy(CurrentDirName, config_file[i]);
+ p = strrchr(CurrentDirName, '/');
+ *p = '\0';
+
+ return 0;
+}
+
+
+static int iso_fs_init(struct fs_info *fs)
+{
+ struct iso_sb_info *sbi;
+
+ sbi = malloc(sizeof(*sbi));
+ if (!sbi) {
+ malloc_error("iso_sb_info structure");
+ return 1;
+ }
+ fs->fs_info = sbi;
+
+ cdrom_read_blocks(fs->fs_dev->disk, trackbuf, 16, 1);
+ memcpy(&sbi->root, trackbuf + ROOT_DIR_OFFSET, sizeof(sbi->root));
+
+ fs->sector_shift = fs->fs_dev->disk->sector_shift;
+ fs->block_shift = 11;
+ fs->sector_size = 1 << fs->sector_shift;
+ fs->block_size = 1 << fs->block_shift;
+
+ return fs->block_shift;
+}
+
+
+const struct fs_ops iso_fs_ops = {
+ .fs_name = "iso",
+ .fs_flags = FS_USEMEM | FS_THISIND,
+ .fs_init = iso_fs_init,
+ .searchdir = NULL,
+ .getfssec = iso_getfssec,
+ .close_file = iso_close_file,
+ .mangle_name = iso_mangle_name,
+ .unmangle_name = generic_unmangle_name,
+ .load_config = iso_load_config,
+ .iget_root = iso_iget_root,
+ .iget_current = NULL,
+ .iget = iso_iget,
+ .readdir = iso_readdir
+};
diff --git a/core/fs/iso9660/iso9660_fs.h b/core/fs/iso9660/iso9660_fs.h
new file mode 100644
index 00000000..e77ae109
--- /dev/null
+++ b/core/fs/iso9660/iso9660_fs.h
@@ -0,0 +1,27 @@
+#ifndef ISO9660_FS_H
+#define ISO9660_FS_H
+
+#include <stdint.h>
+
+/* The root dir entry offset in the primary volume descriptor */
+#define ROOT_DIR_OFFSET 156
+
+struct iso_dir_entry {
+ uint8_t length; /* 00 */
+ uint8_t ext_attr_length; /* 01 */
+ uint8_t extent[8]; /* 02 */
+ uint8_t size[8]; /* 0a */
+ uint8_t date[7]; /* 12 */
+ uint8_t flags; /* 19 */
+ uint8_t file_unit_size; /* 1a */
+ uint8_t interleave; /* 1b */
+ uint8_t volume_sequence_number[4]; /* 1c */
+ uint8_t name_len; /* 20 */
+ char name[0]; /* 21 */
+};
+
+struct iso_sb_info {
+ struct iso_dir_entry root;
+};
+
+#endif /* iso9660_fs.h */
diff --git a/core/fs/lib/mangle.c b/core/fs/lib/mangle.c
new file mode 100644
index 00000000..813099fb
--- /dev/null
+++ b/core/fs/lib/mangle.c
@@ -0,0 +1,47 @@
+/**
+ * mangle_name:
+ *
+ * Mangle a filename pointed to by src into a buffer pointed
+ * to by dst; ends on encountering any whitespace.
+ * dst is preserved.
+ *
+ * This verifies that a filename is < FILENAME_MAX characters,
+ * doesn't contain whitespace, zero-pads the output buffer,
+ * and removes redundant slashes.
+ *
+ */
+
+#include <string.h>
+#include "fs.h"
+
+void generic_mangle_name(char *dst, const char *src)
+{
+ char *p = dst;
+ int i = FILENAME_MAX-1;
+
+ while (not_whitespace(*src)) {
+ if (*src == '/') {
+ if (src[1] == '/') {
+ src++;
+ i--;
+ continue;
+ }
+ }
+ i--;
+ *dst++ = *src++;
+ }
+
+ while (1) {
+ if (dst == p)
+ break;
+ if (dst[-1] != '/')
+ break;
+
+ dst--;
+ i++;
+ }
+
+ i++;
+ for (; i > 0; i --)
+ *dst++ = '\0';
+}
diff --git a/core/fs/pxe/dhcp_option.c b/core/fs/pxe/dhcp_option.c
new file mode 100644
index 00000000..0787078a
--- /dev/null
+++ b/core/fs/pxe/dhcp_option.c
@@ -0,0 +1,270 @@
+#include <stdio.h>
+#include <string.h>
+#include <core.h>
+#include <sys/cpu.h>
+#include "pxe.h"
+
+char LocalDomain[256];
+
+int over_load;
+uint8_t uuid_type;
+char uuid[17];
+
+void parse_dhcp_options(void *, int, int);
+
+static void subnet_mask(void *data, int opt_len)
+{
+ if (opt_len != 4)
+ return;
+ net_mask = *(uint32_t *)data;
+}
+
+static void router(void *data, int opt_len)
+{
+ if (opt_len != 4)
+ return;
+ gate_way = *(uint32_t *)data;
+}
+
+static void dns_servers(void *data, int opt_len)
+{
+ int num = opt_len >> 2;
+ int i;
+
+ if (num > DNS_MAX_SERVERS)
+ num = DNS_MAX_SERVERS;
+
+ for (i = 0; i < num; i++) {
+ dns_server[i] = *(uint32_t *)data;
+ data += 4;
+ }
+
+#if 0
+ /*
+ * if you find you got no corret DNS server, you can add
+ * it here manually. BUT be carefull the DNS_MAX_SERVERS
+ */
+ if (i < DNS_MAX_SERVERS ) {
+ dns_server[i++] = your_master_dns_server;
+ dns_server[i++] = your_second_dns_server;
+ }
+#endif
+}
+
+static void local_domain(void *data, int opt_len)
+{
+ char *p = (char *)data + opt_len;
+ char *ld = LocalDomain;
+ char end = *p;
+
+ *p = '\0'; /* Zero-terminate option */
+ dns_mangle(&ld, data);
+ *p = end; /* Restore ending byte */
+}
+
+static void vendor_encaps(void *data, int opt_len)
+{
+ /* Only recongnize PXELINUX options */
+ parse_dhcp_options(data, opt_len, 208);
+}
+
+static void option_overload(void *data, int opt_len)
+{
+ if (opt_len != 1)
+ return;
+ over_load = *(uint8_t *)data;
+}
+
+
+static void server(void *data, int opt_len)
+{
+ uint32_t ip;
+
+ if (opt_len != 4)
+ return;
+
+ if (server_ip)
+ return;
+
+ ip = *(uint32_t *)data;
+ if (ip_ok(ip))
+ server_ip = ip;
+}
+
+static void client_identifier(void *data, int opt_len)
+{
+ if (opt_len > MAC_MAX || opt_len < 2 ||
+ MAC_len != (opt_len >> 8) ||
+ *(uint8_t *)data != MAC_type)
+ return;
+
+ opt_len --;
+ MAC_len = opt_len & 0xff;
+ memcpy(MAC, data+1, opt_len);
+ MAC[opt_len] = 0;
+}
+
+static void bootfile_name(void *data, int opt_len)
+{
+ strncpy(boot_file, data, opt_len);
+ boot_file[opt_len] = 0;
+}
+
+static void uuid_client_identifier(void *data, int opt_len)
+{
+ int type = *(uint8_t *)data;
+ if (opt_len != 17 ||
+ (type | have_uuid))
+ return;
+
+ have_uuid = 1;
+ uuid_type = type;
+ memcpy(uuid, data+1, 16);
+ uuid[16] = 0;
+}
+
+static void pxelinux_configfile(void *data, int opt_len)
+{
+ DHCPMagic |= 2;
+ strncpy(ConfigName, data, opt_len);
+ ConfigName[opt_len] = 0;
+}
+
+static void pxelinux_pathprefix(void *data,int opt_len)
+{
+ DHCPMagic |= 4;
+ strncpy(path_prefix, data, opt_len);
+ path_prefix[opt_len] = 0;
+}
+
+static void pxelinux_reboottime(void *data, int opt_len)
+{
+ if ((opt_len && 0xff) != 4)
+ return ;
+
+ RebootTime = ntohl(*(uint32_t *)data);
+ DHCPMagic |= 8; /* Got reboot time */
+}
+
+
+struct dhcp_options {
+ int opt_num;
+ void (*fun) (void *, int);
+};
+
+static struct dhcp_options dhcp_opts[] = {
+ {1, subnet_mask},
+ {3, router},
+ {6, dns_servers},
+ {15, local_domain},
+ {43, vendor_encaps},
+ {52, option_overload},
+ {54, server},
+ {61, client_identifier},
+ {67, bootfile_name},
+ {97, uuid_client_identifier},
+ {209, pxelinux_configfile},
+ {210, pxelinux_pathprefix},
+ {211, pxelinux_reboottime}
+};
+
+/*
+ * Parse a sequence of DHCP options, pointed to by _option_;
+ * -- some DHCP servers leave option fields unterminated
+ * in violation of the spec.
+ *
+ * filter contains the minimum value for the option to recognize
+ * -- this is used to restrict parsing to PXELINUX-specific options only.
+ */
+void parse_dhcp_options(void *option, int size, int filter)
+{
+ uint8_t opt_num;
+ uint8_t opt_len;
+ uint8_t opt_filter = filter == 208 ? 208 : 0;
+ int opt_entries = sizeof(dhcp_opts) / sizeof(dhcp_opts[0]);
+ int i = 0;
+ char *p = option;
+ struct dhcp_options *opt;
+
+ if (opt_filter)
+ printf("***NOTE!:*** we hit a pxelinux-specific options\n");
+
+ while (size --) {
+ opt_num = *p++;
+
+ if (!size)
+ break;
+ if (opt_num == 0)
+ continue;
+ if (opt_num == 0xff)
+ break;
+
+ /* Anything else will have a lenght filed */
+ opt_len = *p++; /* c <- option lenght */
+ size = size - opt_len - 1;
+ if (size < 0)
+ break;
+ if (opt_num < opt_filter) { /* Is the option value valid */
+ option += opt_len; /* Try next */
+ continue;
+ }
+
+ opt = dhcp_opts;
+ for (i = 0; i < opt_entries; i++) {
+ if (opt_num == opt->opt_num) {
+ opt->fun(p, opt_len);
+ break;
+ }
+ opt ++;
+ }
+
+ /* parse next */
+ p += opt_len;
+ }
+}
+
+/*
+ * parse_dhcp
+ *
+ * Parse a DHCP packet. This includes dealing with "overloaded"
+ * option fields (see RFC 2132, section 9.3)
+ *
+ * This should fill in the following global variables, if the
+ * information is present:
+ *
+ * MyIP - client IP address
+ * server_ip - boot server IP address
+ * net_mask - network mask
+ * gate_way - default gateway router IP
+ * boot_file - boot file name
+ * DNSServers - DNS server IPs
+ * LocalDomain - Local domain name
+ * MAC_len, MAC - Client identifier, if MAC_len == 0
+ *
+ * This assumes the DHCP packet is in "trackbuf".
+ *
+ */
+void parse_dhcp(int pkt_len)
+{
+ struct bootp_t *dhcp = (struct bootp_t *)trackbuf;
+ int opt_len;
+
+ over_load = 0;
+ if (ip_ok(dhcp->yip))
+ MyIP = dhcp->yip;
+
+ if (ip_ok(dhcp->sip))
+ server_ip = dhcp->sip;
+
+ opt_len = (char *)dhcp + pkt_len - (char *)&dhcp->options;
+ if (opt_len && (dhcp->option_magic == BOOTP_OPTION_MAGIC))
+ parse_dhcp_options(&dhcp->options, opt_len, 0);
+
+ if (over_load & 1)
+ parse_dhcp_options(&dhcp->bootfile, 128, 0);
+ else if (dhcp->bootfile[0])
+ strcpy(boot_file, dhcp->bootfile);
+
+ if (over_load & 2)
+ parse_dhcp_options(dhcp->sname, 64, 0);
+}
diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c
new file mode 100644
index 00000000..15560447
--- /dev/null
+++ b/core/fs/pxe/dnsresolv.c
@@ -0,0 +1,341 @@
+#include <stdio.h>
+#include <string.h>
+#include <core.h>
+#include "pxe.h"
+
+/* DNS CLASS values we care about */
+#define CLASS_IN 1
+
+/* DNS TYPE values we care about */
+#define TYPE_A 1
+#define TYPE_CNAME 5
+
+/*
+ * The DNS header structure
+ */
+struct dnshdr {
+ uint16_t id;
+ uint16_t flags;
+ /* number of entries in the question section */
+ uint16_t qdcount;
+ /* number of resource records in the answer section */
+ uint16_t ancount;
+ /* number of name server resource records in the authority records section*/
+ uint16_t nscount;
+ /* number of resource records in the additional records section */
+ uint16_t arcount;
+} __attribute__ ((packed));
+
+/*
+ * The DNS query structure
+ */
+struct dnsquery {
+ uint16_t qtype;
+ uint16_t qclass;
+} __attribute__ ((packed));
+
+/*
+ * The DNS Resource recodes structure
+ */
+struct dnsrr {
+ uint16_t type;
+ uint16_t class;
+ uint32_t ttl;
+ uint16_t rdlength; /* The lenght of this rr data */
+ char rdata[];
+} __attribute__ ((packed));
+
+
+uint32_t dns_server[DNS_MAX_SERVERS] = {0, };
+
+
+/*
+ * Turn a string in _src_ into a DNS "label set" in _dst_; returns the
+ * number of dots encountered. On return, *dst is updated.
+ */
+int dns_mangle(char **dst, const char *p)
+{
+ char *q = *dst;
+ char *count_ptr;
+ char c;
+ int dots = 0;
+
+ count_ptr = q;
+ *q++ = 0;
+
+ while (1) {
+ c = *p++;
+ if (c == 0 || c == ':')
+ break;
+ if (c == '.') {
+ dots++;
+ count_ptr = q;
+ *q++ = 0;
+ continue;
+ }
+
+ *count_ptr += 1;
+ *q++ = c;
+ }
+
+ if (*count_ptr)
+ *q++ = 0;
+
+ /* update the strings */
+ *dst = q;
+ return dots;
+}
+
+
+/*
+ * Compare two sets of DNS labels, in _s1_ and _s2_; the one in _s2_
+ * is allowed pointers relative to a packet in buf.
+ *
+ */
+static bool dns_compare(const void *s1, const void *s2, const void *buf)
+{
+ const uint8_t *q = s1;
+ const uint8_t *p = s2;
+ unsigned int c0, c1;
+
+ while (1) {
+ c0 = p[0];
+ if (c0 >= 0xc0) {
+ /* Follow pointer */
+ c1 = p[1];
+ p = (const uint8_t *)buf + ((c0 - 0xc0) << 8) + c1;
+ } else if (c0) {
+ c0++; /* Include the length byte */
+ if (memcmp(q, p, c0))
+ return false;
+ q += c0;
+ p += c0;
+ } else {
+ return *q == 0;
+ }
+ }
+}
+
+/*
+ * Copy a DNS label into a buffer, considering the possibility that we might
+ * have to follow pointers relative to "buf".
+ * Returns a pointer to the first free byte *after* the terminal null.
+ */
+static void *dns_copylabel(void *dst, const void *src, const void *buf)
+{
+ uint8_t *q = dst;
+ const uint8_t *p = src;
+ unsigned int c0, c1;
+
+ while (1) {
+ c0 = p[0];
+ if (c0 >= 0xc0) {
+ /* Follow pointer */
+ c1 = p[1];
+ p = (const uint8_t *)buf + ((c0 - 0xc0) << 8) + c1;
+ } else if (c0) {
+ c0++; /* Include the length byte */
+ memcpy(q, p, c0);
+ p += c0;
+ q += c0;
+ } else {
+ *q++ = 0;
+ return q;
+ }
+ }
+}
+
+/*
+ * Skip past a DNS label set in DS:SI
+ */
+static char *dns_skiplabel(char *label)
+{
+ uint8_t c;
+
+ while (1) {
+ c = *label++;
+ if (c >= 0xc0)
+ return ++label; /* pointer is two bytes */
+ if (c == 0)
+ return label;
+ label += c;
+ }
+}
+
+/*
+ * Actual resolver function
+ * Points to a null-terminated or :-terminated string in _name_
+ * and returns the ip addr in _ip_ if it exists and can be found.
+ * If _ip_ = 0 on exit, the lookup failed. _name_ will be updated
+ *
+ */
+uint32_t dns_resolv(const char *name)
+{
+ static char __lowmem DNSSendBuf[PKTBUF_SIZE];
+ static char __lowmem DNSRecvBuf[PKTBUF_SIZE];
+ char *p;
+ int err;
+ int dots;
+ int same;
+ int rd_len;
+ int ques, reps; /* number of questions and replies */
+ uint8_t timeout;
+ const uint8_t *timeout_ptr = TimeoutTable;
+ uint32_t oldtime;
+ uint32_t srv;
+ uint32_t *srv_ptr = dns_server;
+ struct dnshdr *hd1 = (struct dnshdr *)DNSSendBuf;
+ struct dnshdr *hd2 = (struct dnshdr *)DNSRecvBuf;
+ struct dnsquery *query;
+ struct dnsrr *rr;
+ static __lowmem struct s_PXENV_UDP_WRITE udp_write;
+ static __lowmem struct s_PXENV_UDP_READ udp_read;
+
+ /* First, fill the DNS header struct */
+ hd1->id++; /* New query ID */
+ hd1->flags = htons(0x0100); /* Recursion requested */
+ hd1->qdcount = htons(1); /* One question */
+ hd1->ancount = 0; /* No answers */
+ hd1->nscount = 0; /* No NS */
+ hd1->arcount = 0; /* No AR */
+
+ p = DNSSendBuf + sizeof(struct dnshdr);
+ dots = dns_mangle(&p, name); /* store the CNAME */
+
+ if (!dots) {
+ p--; /* Remove final null */
+ /* Uncompressed DNS label set so it ends in null */
+ strcpy(p, LocalDomain);
+ }
+
+ /* Fill the DNS query packet */
+ query = (struct dnsquery *)p;
+ query->qtype = htons(TYPE_A);
+ query->qclass = htons(CLASS_IN);
+ p += sizeof(struct dnsquery);
+
+ /* Now send it to name server */
+ timeout_ptr = TimeoutTable;
+ timeout = *timeout_ptr++;
+ while (srv_ptr < dns_server + DNS_MAX_SERVERS) {
+ srv = *srv_ptr++;
+ if (!srv)
+ continue; /* just move on before runing the time out */
+ udp_write.status = 0;
+ udp_write.ip = srv;
+ udp_write.gw = ((srv ^ MyIP) & net_mask) ? gate_way : 0;
+ udp_write.src_port = DNS_LOCAL_PORT;
+ udp_write.dst_port = DNS_PORT;
+ udp_write.buffer_size = p - DNSSendBuf;
+ udp_write.buffer = FAR_PTR(DNSSendBuf);
+ err = pxe_call(PXENV_UDP_WRITE, &udp_write);
+ if (err || udp_write.status != 0)
+ continue;
+
+ oldtime = jiffies();
+ while (1) {
+ udp_read.status = 0;
+ udp_read.src_ip = srv;
+ udp_read.dest_ip = MyIP;
+ udp_read.s_port = DNS_PORT;
+ udp_read.d_port = DNS_LOCAL_PORT;
+ udp_read.buffer_size = DNS_MAX_PACKET;
+ udp_read.buffer = FAR_PTR(DNSRecvBuf);
+ err = pxe_call(PXENV_UDP_READ, &udp_read);
+ if (err || udp_read.status)
+ continue;
+
+ /* Got a packet, deal with it... */
+ if (hd2->id == hd1->id)
+ break;
+
+ if (jiffies()-oldtime >= timeout) {
+ /* time out */
+ timeout = *timeout_ptr++;
+ if (!timeout)
+ return 0; /* All time ticks run out */
+ else
+ goto again;
+ }
+ }
+ if ((hd2->flags ^ 0x80) & htons(0xf80f))
+ goto badness;
+
+ ques = htons(hd2->qdcount); /* Questions */
+ reps = htons(hd2->ancount); /* Replies */
+ p = DNSRecvBuf + sizeof(struct dnshdr);
+ while (ques--) {
+ p = dns_skiplabel(p); /* Skip name */
+ p += 4; /* Skip question trailer */
+ }
+
+ /* Parse the replies */
+ while (reps--) {
+ same = dns_compare(DNSSendBuf + sizeof(struct dnshdr),
+ p, DNSRecvBuf);
+ p = dns_skiplabel(p);
+ rr = (struct dnsrr *)p;
+ rd_len = ntohs(rr->rdlength);
+ if (same && ntohs(rr->class) == CLASS_IN) {
+ switch (ntohs(rr->type)) {
+ case TYPE_A:
+ if (rd_len == 4)
+ return *(uint32_t *)rr->rdata;
+ break;
+ case TYPE_CNAME:
+ dns_copylabel(DNSSendBuf + sizeof(struct dnshdr),
+ rr->rdata, DNSRecvBuf);
+ /*
+ * We should probably rescan the packet from the top
+ * here, and technically we might have to send a whole
+ * new request here...
+ */
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* not the one we want, try next */
+ p += sizeof(struct dnsrr) + rd_len;
+ }
+
+ badness:
+ /*
+ *
+ ; We got back no data from this server.
+ ; Unfortunately, for a recursive, non-authoritative
+ ; query there is no such thing as an NXDOMAIN reply,
+ ; which technically means we can't draw any
+ ; conclusions. However, in practice that means the
+ ; domain doesn't exist. If this turns out to be a
+ ; problem, we may want to add code to go through all
+ ; the servers before giving up.
+
+ ; If the DNS server wasn't capable of recursion, and
+ ; isn't capable of giving us an authoritative reply
+ ; (i.e. neither AA or RA set), then at least try a
+ ; different setver...
+ */
+ if (hd2->flags == htons(0x480))
+ continue;
+
+ break; /* failed */
+
+ again:
+ continue;
+ }
+
+ return 0;
+}
+
+
+/*
+ * the one should be called from ASM file
+ */
+void pxe_dns_resolv(com32sys_t *regs)
+{
+ const char *name = MK_PTR(regs->ds, regs->esi.w[0]);
+
+ regs->eax.l = dns_resolv(name);
+}
diff --git a/core/fs/pxe/idle.c b/core/fs/pxe/idle.c
new file mode 100644
index 00000000..5393ae1d
--- /dev/null
+++ b/core/fs/pxe/idle.c
@@ -0,0 +1,110 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2008 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdio.h>
+#include <string.h>
+#include <core.h>
+#include <fs.h>
+#include <minmax.h>
+#include <sys/cpu.h>
+#include "pxe.h"
+
+static void pxe_idle_poll(void)
+{
+ static __lowmem char junk_pkt[PKTBUF_SIZE];
+ static __lowmem t_PXENV_UDP_READ read_buf;
+
+ memset(&read_buf, 0, sizeof read_buf);
+
+ read_buf.src_ip = 0; /* Any destination */
+ read_buf.dest_ip = MyIP;
+ read_buf.s_port = 0; /* Any source port */
+ read_buf.d_port = htons(9); /* Discard port (not used...) */
+ read_buf.buffer_size = sizeof junk_pkt;
+ read_buf.buffer = FAR_PTR(junk_pkt);
+
+ pxe_call(PXENV_UDP_READ, &read_buf);
+}
+
+static uint32_t pxe_detect_nic_type(void)
+{
+ static __lowmem t_PXENV_UNDI_GET_NIC_TYPE nic_type;
+
+ if (pxe_call(PXENV_UNDI_GET_NIC_TYPE, &nic_type))
+ return -1; /* Unknown NIC */
+
+ if (nic_type.NicType != PCI_NIC && nic_type.NicType != CardBus_NIC)
+ return -1; /* Not a PCI NIC */
+
+ /*
+ * Return VID:DID as a single number, with the VID in the high word
+ * -- this is opposite from the usual order, but it makes it easier to
+ * enforce that the table is sorted.
+ */
+ return (nic_type.info.pci.Vendor_ID << 16) + nic_type.info.pci.Dev_ID;
+}
+
+#define PCI_DEV(vid, did) (((vid) << 16) + (did))
+
+/* This array should be sorted!! */
+static const uint32_t pxe_need_idle_drain[] =
+{
+ /*
+ * Older Broadcom NICs: they need receive calls on idle to avoid
+ * FIFO stalls.
+ */
+ PCI_DEV(0x14e4, 0x1659), /* BCM5721 */
+ PCI_DEV(0x14e4, 0x165a), /* BCM5722 */
+ PCI_DEV(0x14e4, 0x165b), /* BCM5723 */
+ PCI_DEV(0x14e4, 0x1668), /* BCM5714 */
+ PCI_DEV(0x14e4, 0x1669), /* BCM5714S */
+ PCI_DEV(0x14e4, 0x166a), /* BCM5780 */
+ PCI_DEV(0x14e4, 0x1673), /* BCM5755M */
+ PCI_DEV(0x14e4, 0x1674), /* BCM5756ME */
+ PCI_DEV(0x14e4, 0x1678), /* BCM5715 */
+ PCI_DEV(0x14e4, 0x1679), /* BCM5715S */
+ PCI_DEV(0x14e4, 0x167b), /* BCM5755 */
+};
+
+void pxe_idle_init(void)
+{
+ uint32_t dev_id = pxe_detect_nic_type();
+ int l, h;
+ bool found;
+
+ l = 0;
+ h = sizeof pxe_need_idle_drain / sizeof pxe_need_idle_drain[0] - 1;
+
+ found = false;
+ while (h >= l) {
+ int x = (l+h) >> 1;
+ uint32_t id = pxe_need_idle_drain[x];
+
+ if (id == dev_id) {
+ found = true;
+ break;
+ } else if (id < dev_id) {
+ l = x+1;
+ } else {
+ h = x-1;
+ }
+ }
+
+ if (found)
+ idle_hook_func = pxe_idle_poll;
+}
+
+void pxe_idle_cleanup(void)
+{
+ idle_hook_func = NULL;
+}
diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c
new file mode 100644
index 00000000..ea26ef61
--- /dev/null
+++ b/core/fs/pxe/pxe.c
@@ -0,0 +1,1661 @@
+#include <stdio.h>
+#include <string.h>
+#include <core.h>
+#include <fs.h>
+#include <minmax.h>
+#include <sys/cpu.h>
+#include "pxe.h"
+
+#define GPXE 1
+
+uint32_t server_ip = 0; /* IP address of boot server */
+uint32_t net_mask = 0; /* net_mask of this subnet */
+uint32_t gate_way = 0; /* Default router */
+uint16_t server_port = TFTP_PORT; /* TFTP server port */
+uint16_t real_base_mem; /* Amount of DOS memory after freeing */
+
+char MAC_str[3 * (MAC_MAX + 1)]; /* MAC address as a string */
+char MAC[MAC_MAX + 1]; /* Actual MAC address */
+uint8_t MAC_len; /* MAC address len */
+uint8_t MAC_type; /* MAC address type */
+
+char boot_file[256];
+char path_prefix[256];
+char dot_quad_buf[16];
+
+static struct open_file_t Files[MAX_OPEN];
+static bool has_gpxe;
+static uint32_t gpxe_funcs;
+static uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0};
+int have_uuid = 0;
+
+const uint8_t TimeoutTable[] = {
+ 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, 37, 44, 53, 64, 77,
+ 92, 110, 132, 159, 191, 229, 255, 255, 255, 255, 0
+};
+
+/* PXE unload sequences */
+const uint8_t new_api_unload[] = {
+ PXENV_UDP_CLOSE, PXENV_UNDI_SHUTDOWN,
+ PXENV_UNLOAD_STACK, PXENV_STOP_UNDI, 0
+};
+const uint8_t old_api_unload[] = {
+ PXENV_UDP_CLOSE, PXENV_UNDI_SHUTDOWN,
+ PXENV_UNLOAD_STACK, PXENV_UNDI_CLEANUP, 0
+};
+
+struct tftp_options {
+ const char *str_ptr; /* string pointer */
+ size_t offset; /* offset into socket structre */
+};
+static const struct tftp_options tftp_options[] =
+{
+ { "tsize", offsetof(struct open_file_t, tftp_filesize) },
+ { "blksize", offsetof(struct open_file_t, tftp_blksize) },
+};
+static const int tftp_nopts = sizeof tftp_options / sizeof tftp_options[0];
+
+static void tftp_error(struct open_file_t *file, uint16_t errnum,
+ const char *errstr);
+
+/*
+ * Initialize the Files structure
+ */
+static void files_init(void)
+{
+ int i;
+ struct open_file_t *socket = Files;
+ uint16_t pktbuf = 0;
+ uint16_t nextport = 49152;
+
+ for (i = 0; i < MAX_OPEN; i++) {
+ socket->tftp_pktbuf = pktbuf;
+ socket->tftp_nextport = nextport;
+ pktbuf += PKTBUF_SIZE;
+ nextport++;
+ socket++;
+ }
+}
+
+/*
+ * Allocate a local UDP port structure.
+ * return the socket pointer if success, or null if failure
+ *
+ */
+static struct open_file_t *allocate_socket(void)
+{
+ int i;
+ struct open_file_t *socket = Files;
+ uint16_t nextport;
+
+ for (i = 0; i < MAX_OPEN; i++) {
+ if (!socket->tftp_localport)
+ break;
+ socket++;
+ }
+
+ if (i == MAX_OPEN)
+ return NULL;
+
+ /*
+ * Allocate a socket number. Socket numbers are made guaranteed
+ * unique by including the socket slot number; add a counter value
+ * to keep the numbers from being likely to get immediately
+ * reused. The mask enforces wraparound to the range 49152-57343.
+ */
+ nextport = socket->tftp_nextport;
+ socket->tftp_nextport = (nextport + (1 << MAX_OPEN_LG2)) & 0xdfff;
+ socket->tftp_localport = htons(nextport); /* Socket now in use */
+ return socket;
+}
+
+/*
+ * free socket in _file_.
+ */
+static void free_socket(struct open_file_t *file)
+{
+ /* tftp_nextport and tftp_pktbuf are not cleared */
+ memset(file, 0, offsetof(struct open_file_t, tftp_nextport));
+}
+
+static void pxe_close_file(struct file *file)
+{
+ struct open_file_t *open_file = file->open_file;
+
+ if (open_file->tftp_localport && !open_file->tftp_goteof)
+ tftp_error(open_file, 0, "No error, file close");
+
+ free_socket(open_file);
+}
+
+/**
+ * Take a nubmer of bytes in memory and convert to lower-case hxeadecimal
+ *
+ * @param: dst, output buffer
+ * @param: src, input buffer
+ * @param: count, number of bytes
+ *
+ */
+static void lchexbytes(char *dst, const void *src, int count)
+{
+ uint8_t half;
+ uint8_t c;
+ const uint8_t *s = src;
+
+ for(; count > 0; count--) {
+ c = *s++;
+ half = ((c >> 4) & 0x0f) + '0';
+ *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half;
+
+ half = (c & 0x0f) + '0';
+ *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half;
+ }
+}
+
+/*
+ * just like the lchexbytes, except to upper-case
+ *
+ */
+static void uchexbytes(char *dst, const void *src, int count)
+{
+ uint8_t half;
+ uint8_t c;
+ const uint8_t *s = src;
+
+ for(; count > 0; count--) {
+ c = *s++;
+ half = ((c >> 4) & 0x0f) + '0';
+ *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half;
+
+ half = (c & 0x0f) + '0';
+ *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half;
+ }
+}
+
+/*
+ * Tests an IP address in _ip_ for validity; return with 0 for bad, 1 for good.
+ * We used to refuse class E, but class E addresses are likely to become
+ * assignable unicast addresses in the near future.
+ *
+ */
+int ip_ok(uint32_t ip)
+{
+ if (ip == -1 || /* Refuse the all-one address */
+ (ip & 0xff) == 0 || /* Refuse network zero */
+ (ip & 0xff) == 0xff || /* Refuse loopback */
+ (ip & 0xf0) == 0xe0 ) /* Refuse class D */
+ return 0;
+
+ return 1;
+}
+
+
+/*
+ * Take an IP address (in network byte order) in _ip_ and
+ * output a dotted quad string to _dst_, returns the length
+ * of the dotted quad ip string.
+ *
+ */
+static int gendotquad(char *dst, uint32_t ip)
+{
+ int part;
+ int i = 0, j;
+ char temp[4];
+ char *p = dst;
+
+ for (; i < 4; i++) {
+ j = 0;
+ part = ip & 0xff;
+ do {
+ temp[j++] = (part % 10) + '0';
+ }while(part /= 10);
+ for (; j > 0; j--)
+ *p++ = temp[j-1];
+ *p++ = '.';
+
+ ip >>= 8;
+ }
+ /* drop the last dot '.' and zero-terminate string*/
+ *(--p) = 0;
+
+ return p - dst;
+}
+
+/*
+ * parse the ip_str and return the ip address with *res.
+ * return the the string address after the ip string
+ *
+ */
+static const char *parse_dotquad(const char *ip_str, uint32_t *res)
+{
+ const char *p = ip_str;
+ int i = 0;
+ uint8_t part = 0;
+ uint32_t ip = 0;
+
+ for (; i < 4; i++) {
+ while (is_digit(*p)) {
+ part = part * 10 + *p - '0';
+ p++;
+ }
+ if (i != 3 && *p != '.')
+ return NULL;
+
+ ip = (ip << 8) | part;
+ part = 0;
+ p++;
+ }
+ p --;
+
+ *res = ip;
+ return p;
+}
+
+/*
+ * the ASM pxenv function wrapper, return 1 if error, or 0
+ *
+ */
+int pxe_call(int opcode, void *data)
+{
+ extern void pxenv(void);
+ com32sys_t regs;
+
+#if 0
+ printf("pxe_call op %04x data %p\n", opcode, data);
+#endif
+
+ memset(&regs, 0, sizeof regs);
+ regs.ebx.w[0] = opcode;
+ regs.es = SEG(data);
+ regs.edi.w[0] = OFFS(data);
+ call16(pxenv, &regs, &regs);
+
+ return regs.eflags.l & EFLAGS_CF; /* CF SET if fail */
+}
+
+/**
+ * Send an ERROR packet. This is used to terminate a connection.
+ *
+ * @file: TFTP file pointer
+ * @errnum: Error number (network byte order)
+ * @errstr: Error string (included in packet)
+ */
+static void tftp_error(struct open_file_t *file, uint16_t errnum,
+ const char *errstr)
+{
+ static __lowmem struct {
+ uint16_t err_op;
+ uint16_t err_num;
+ char err_msg[64];
+ } __packed err_buf;
+ static __lowmem struct s_PXENV_UDP_WRITE udp_write;
+ int len = min(strlen(errstr), sizeof(err_buf.err_msg)-1);
+
+ err_buf.err_op = TFTP_ERROR;
+ err_buf.err_num = errnum;
+ memcpy(err_buf.err_msg, errstr, len);
+ err_buf.err_msg[len] = '\0';
+
+ udp_write.src_port = file->tftp_localport;
+ udp_write.dst_port = file->tftp_remoteport;
+ udp_write.ip = file->tftp_remoteip;
+ udp_write.gw = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0;
+ udp_write.buffer = FAR_PTR(&err_buf);
+ udp_write.buffer_size = 4 + len + 1;
+
+ /* If something goes wrong, there is nothing we can do, anyway... */
+ pxe_call(PXENV_UDP_WRITE, &udp_write);
+}
+
+
+/**
+ * Send ACK packet. This is a common operation and so is worth canning.
+ *
+ * @param: file, TFTP block pointer
+ * @param: ack_num, Packet # to ack (network byte order)
+ *
+ */
+static void ack_packet(struct open_file_t *file, uint16_t ack_num)
+{
+ int err;
+ static __lowmem uint16_t ack_packet_buf[2];
+ static __lowmem struct s_PXENV_UDP_WRITE udp_write;
+
+ /* Packet number to ack */
+ ack_packet_buf[0] = TFTP_ACK;
+ ack_packet_buf[1] = ack_num;
+ udp_write.src_port = file->tftp_localport;
+ udp_write.dst_port = file->tftp_remoteport;
+ udp_write.ip = file->tftp_remoteip;
+ udp_write.gw = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0;
+ udp_write.buffer = FAR_PTR(ack_packet_buf);
+ udp_write.buffer_size = 4;
+
+ err = pxe_call(PXENV_UDP_WRITE, &udp_write);
+#if 0
+ printf("sent %s\n", err ? "FAILED" : "OK");
+#endif
+}
+
+
+/**
+ * Get a DHCP packet from the PXE stack into the trackbuf
+ *
+ * @param: type, packet type
+ * @return: buffer size
+ *
+ */
+static int pxe_get_cached_info(int type)
+{
+ int err;
+ static __lowmem struct s_PXENV_GET_CACHED_INFO get_cached_info;
+ printf(" %02x", type);
+
+ get_cached_info.Status = 0;
+ get_cached_info.PacketType = type;
+ get_cached_info.BufferSize = 8192;
+ get_cached_info.Buffer = FAR_PTR(trackbuf);
+ err = pxe_call(PXENV_GET_CACHED_INFO, &get_cached_info);
+ if (err) {
+ printf("PXE API call failed, error %04x\n", err);
+ kaboom();
+ }
+
+ return get_cached_info.BufferSize;
+}
+
+
+
+#if GPXE
+
+/*
+ * Return true if and only if the buffer pointed to by
+ * url is a URL -- it must contain :// and it must be the
+ * first colon.
+ */
+static inline bool is_url(const char *url)
+{
+ const char *p = strchr(url, ':');
+
+ return p && p[1] == '/' && p[2] == '/';
+}
+
+
+/*
+ * Return CF=0 if and only if the buffer pointed to by DS:SI is a URL
+ * (contains ://) *and* the gPXE extensions API is available. No
+ * registers modified.
+ */
+static bool is_gpxe(const char *url)
+{
+ static bool already;
+
+ if (!is_url(url))
+ return false;
+
+ if (!has_gpxe && !already) {
+ fputs("URL syntax, but gPXE extensions not detected, tring plain TFTP...\n", stdout);
+ already = true;
+ }
+
+ return has_gpxe;
+}
+
+/**
+ * Get a fresh packet from a gPXE socket
+ * @param: file -> socket structure
+ *
+ */
+static void get_packet_gpxe(struct open_file_t *file)
+{
+ static __lowmem struct s_PXENV_FILE_READ file_read;
+ int err;
+
+ while (1) {
+ file_read.FileHandle = file->tftp_remoteport;
+ file_read.Buffer.offs = file->tftp_pktbuf;
+ file_read.Buffer.seg = PKTBUF_SEG;
+ file_read.BufferSize = PKTBUF_SIZE;
+ err = pxe_call(PXENV_FILE_READ, &file_read);
+ if (!err) /* successed */
+ break;
+
+ if (file_read.Status != PXENV_STATUS_TFTP_OPEN)
+ kaboom();
+ }
+
+ file->tftp_dataptr = file->tftp_pktbuf;
+ file->tftp_bytesleft = file_read.BufferSize;
+ file->tftp_filepos += file_read.BufferSize;
+
+ if (file->tftp_bytesleft == 0)
+ file->tftp_filesize = file->tftp_filepos;
+
+ /* if we're done here, close the file */
+ if (file->tftp_filesize > file->tftp_filepos)
+ return;
+
+ /* Got EOF, close it */
+ file->tftp_goteof = 1;
+ pxe_call(PXENV_FILE_CLOSE, &file_read);
+}
+#endif /* GPXE */
+
+
+/*
+ * mangle a filename pointed to by _src_ into a buffer pointed
+ * to by _dst_; ends on encountering any whitespace.
+ *
+ * The first four bytes of the manged name is the IP address of
+ * the download host, 0 for no host, or -1 for a gPXE URL.
+ *
+ */
+static void pxe_mangle_name(char *dst, const char *src)
+{
+ const char *p = src;
+ uint32_t ip = server_ip;
+ int i = 0;
+
+#if GPXE
+ if (is_url(src)) {
+ ip = -1;
+ goto store;
+ }
+#endif
+
+ if (*p == 0 || !(p = strstr(src, "::"))) {
+ /* seems no ip, so make ip to 0 */
+ p = src;
+ ip = 0;
+ } else if (p == src) {
+ /* skip the first two-colon */
+ p += 2;
+ } else {
+ /*
+ * we have a :: prefix of some sort, it could be either a DNS
+ * name or dot-quad IP address. Try the dot-quad first.
+ */
+ p = src;
+ if ((p = parse_dotquad(p, &ip)) && !strncmp(p, "::", 2)) {
+ p += 2;
+ } else {
+ ip = dns_resolv(p);
+ if (ip && (p = strchr(p, ':')) && p[1] == ':') {
+ p += 2;
+ } else {
+ /* no ip, too */
+ p = src;
+ ip = 0;
+ }
+ }
+ }
+
+ store:
+ *(uint32_t *)dst = ip;
+ dst += 4;
+ i = FILENAME_MAX - 5;
+
+ do {
+ if (!not_whitespace(*p))
+ break;
+ *dst++ = *p++;
+ } while (i--);
+
+ i++;
+ while (i) {
+ *dst++ = 0;
+ i--;
+ }
+}
+
+
+/*
+ * Does the opposite of mangle_name; converts a DOS-mangled
+ * filename to the conventional representation. This is
+ * needed for the BOOT_IMAGE= parameter for the kernel.
+ */
+static char *pxe_unmangle_name(char *dst, const char *src)
+{
+ uint32_t ip = *(uint32_t *)src;
+ int ip_len = 0;
+
+ if (ip != 0 && ip != -1) {
+ ip_len = gendotquad(dst, *(uint32_t *)src);
+ dst += ip_len;
+ }
+ src += 4;
+ return stpcpy(dst, src);
+}
+
+/*
+ * Get a fresh packet if the buffer is drained, and we haven't hit
+ * EOF yet. The buffer should be filled immediately after draining!
+ */
+static void fill_buffer(struct open_file_t *file)
+{
+ int err;
+ int last_pkt;
+ const uint8_t *timeout_ptr = TimeoutTable;
+ uint8_t timeout;
+ uint16_t buffersize;
+ uint32_t oldtime;
+ void *data = NULL;
+ static __lowmem struct s_PXENV_UDP_READ udp_read;
+
+ if (file->tftp_bytesleft || file->tftp_goteof)
+ return;
+
+#if GPXE
+ if (file->tftp_localport == 0xffff) {
+ get_packet_gpxe(file);
+ return;
+ }
+#endif
+
+
+ /*
+ * Start by ACKing the previous packet; this should cause
+ * the next packet to be sent.
+ */
+ ack_again:
+ ack_packet(file, file->tftp_lastpkt);
+
+ timeout_ptr = TimeoutTable;
+ timeout = *timeout_ptr++;
+ oldtime = jiffies();
+ while (timeout) {
+ udp_read.buffer.offs = file->tftp_pktbuf;
+ udp_read.buffer.seg = PKTBUF_SEG;
+ udp_read.buffer_size = PKTBUF_SIZE;
+ udp_read.src_ip = file->tftp_remoteip;
+ udp_read.dest_ip = MyIP;
+ udp_read.s_port = file->tftp_remoteport;
+ udp_read.d_port = file->tftp_localport;
+ err = pxe_call(PXENV_UDP_READ, &udp_read);
+ if (err) {
+ uint32_t now = jiffies();
+
+ if (now-oldtime >= timeout) {
+ oldtime = now;
+ timeout = *timeout_ptr++;
+ if (!timeout)
+ break;
+ }
+ continue;
+ }
+
+ if (udp_read.buffer_size < 4) /* Bad size for a DATA packet */
+ continue;
+
+ data = MK_PTR(PKTBUF_SEG, file->tftp_pktbuf);
+ if (*(uint16_t *)data != TFTP_DATA) /* Not a data packet */
+ continue;
+
+ /* If goes here, recevie OK, break */
+ break;
+ }
+
+ /* time runs out */
+ if (timeout == 0)
+ kaboom();
+
+ last_pkt = file->tftp_lastpkt;
+ last_pkt = ntohs(last_pkt); /* Host byte order */
+ last_pkt++;
+ last_pkt = htons(last_pkt); /* Network byte order */
+ if (*(uint16_t *)(data + 2) != last_pkt) {
+ /*
+ * Wrong packet, ACK the packet and try again.
+ * This is presumably because the ACK got lost,
+ * so the server just resent the previous packet.
+ */
+#if 0
+ printf("Wrong packet, wanted %04x, got %04x\n", \
+ htons(last_pkt), htons(*(uint16_t *)(data+2)));
+#endif
+ goto ack_again;
+ }
+
+ /* It's the packet we want. We're also EOF if the size < blocksize */
+ file->tftp_lastpkt = last_pkt; /* Update last packet number */
+ buffersize = udp_read.buffer_size - 4; /* Skip TFTP header */
+ file->tftp_dataptr = file->tftp_pktbuf + 4;
+ file->tftp_filepos += buffersize;
+ file->tftp_bytesleft = buffersize;
+ if (buffersize < file->tftp_blksize) {
+ /* it's the last block, ACK packet immediately */
+ ack_packet(file, *(uint16_t *)(data + 2));
+
+ /* Make sure we know we are at end of file */
+ file->tftp_filesize = file->tftp_filepos;
+ file->tftp_goteof = 1;
+ }
+}
+
+
+/**
+ * getfssec: Get multiple clusters from a file, given the starting cluster.
+ * In this case, get multiple blocks from a specific TCP connection.
+ *
+ * @param: fs, the fs_info structure address, in pxe, we don't use this.
+ * @param: buf, buffer to store the read data
+ * @param: openfile, TFTP socket pointer
+ * @param: blocks, 512-byte block count; 0FFFFh = until end of file
+ *
+ * @return: the bytes read
+ *
+ */
+static uint32_t pxe_getfssec(struct file *gfile, char *buf,
+ int blocks, bool *have_more)
+{
+ struct open_file_t *file = gfile->open_file;
+ int count = blocks;
+ int chunk;
+ int bytes_read = 0;
+
+ count <<= TFTP_BLOCKSIZE_LG2;
+ while (count) {
+ fill_buffer(file); /* If we have no 'fresh' buffer, get it */
+ if (!file->tftp_bytesleft)
+ break;
+
+ chunk = count;
+ if (chunk > file->tftp_bytesleft)
+ chunk = file->tftp_bytesleft;
+ file->tftp_bytesleft -= chunk;
+ memcpy(buf, MK_PTR(PKTBUF_SEG, file->tftp_dataptr), chunk);
+ file->tftp_dataptr += chunk;
+ buf += chunk;
+ bytes_read += chunk;
+ count -= chunk;
+ }
+
+
+ if (file->tftp_bytesleft || (file->tftp_filepos < file->tftp_filesize)) {
+ fill_buffer(file);
+ *have_more = 1;
+ } else if (file->tftp_goteof) {
+ /*
+ * The socket is closed and the buffer drained; the caller will
+ * call close_file and therefore free the socket.
+ */
+ *have_more = 0;
+ }
+
+ return bytes_read;
+ }
+
+
+
+/*
+ * Fill the packet tail with the tftp informations then retures the lenght
+ */
+static int fill_tail(char *dst)
+{
+ static const char tail[] = "octet\0""tsize\0""0\0""blksize\0""1408";
+
+ memcpy(dst, tail, sizeof tail);
+ return sizeof tail;
+}
+
+
+/**
+ * Open a TFTP connection to the server
+ *
+ * @param:filename, the file we wanna open
+ *
+ * @out: open_file_t structure, stores in file->open_file
+ * @ouT: the lenght of this file, stores in file->file_len
+ *
+ */
+static void pxe_searchdir(char *filename, struct file *file)
+{
+ char *buf = packet_buf;
+ char *p = filename;
+ char *options;
+ char *data;
+ struct open_file_t *open_file;
+ static __lowmem struct s_PXENV_UDP_WRITE udp_write;
+ static __lowmem struct s_PXENV_UDP_READ udp_read;
+ static __lowmem struct s_PXENV_FILE_OPEN file_open;
+ const struct tftp_options *tftp_opt;
+ int i = 0;
+ int err;
+ int buffersize;
+ const uint8_t *timeout_ptr;
+ uint8_t timeout;
+ uint32_t oldtime;
+ uint16_t tid;
+ uint16_t opcode;
+ uint16_t blk_num;
+ uint32_t ip;
+ uint32_t opdata, *opdata_ptr;
+
+ open_file = allocate_socket();
+ if (!open_file) {
+ file->file_len = 0;
+ file->open_file = NULL;
+ return;
+ }
+
+ timeout_ptr = TimeoutTable; /* Reset timeout */
+
+ sendreq:
+ udp_write.buffer.offs = OFFS_WRT(buf, 0);
+ udp_write.buffer.seg = 0;
+ *(uint16_t *)buf = TFTP_RRQ; /* TFTP opcode */
+ buf += 2;
+
+ ip = *(uint32_t *)p; /* ip <- server override (if any) */
+ p += 4;
+ if (ip == 0) {
+ /* Have prefix */
+ strcpy(buf, path_prefix);
+ buf += strlen(path_prefix);
+ ip = server_ip; /* Get the default server */
+ }
+
+ strcpy(buf, p); /* Copy the filename */
+ buf += strlen(p) + 1; /* advance the pointer, null char included */
+
+#if GPXE
+ if (is_gpxe(packet_buf + 2)) {
+ file_open.Status = PXENV_STATUS_BAD_FUNC;
+ file_open.FileName.offs = OFFS(packet_buf + 2);
+ file_open.FileName.seg = SEG(packet_buf + 2);
+ err = pxe_call(PXENV_FILE_OPEN, &file_open);
+ if (err)
+ goto done;
+
+ open_file->tftp_localport = -1;
+ open_file->tftp_remoteport = file_open.FileHandle;
+ open_file->tftp_filesize = -1;
+ goto done;
+ }
+#endif /* GPXE */
+
+ open_file->tftp_remoteip = ip;
+ tid = open_file->tftp_localport; /* TID(local port No) */
+ udp_write.ip = ip;
+ udp_write.gw = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0;
+ udp_write.src_port = tid;
+ udp_write.dst_port = server_port;
+ buf += fill_tail(buf);
+ udp_write.buffer_size = buf - packet_buf;
+ err = pxe_call(PXENV_UDP_WRITE, &udp_write);
+ if (err || udp_write.status != 0)
+ goto failure; /*
+ * In fact, the 'failure' target will not do
+ * a failure thing; it will move on to the
+ * next timeout, then tries again until
+ * _real_ time out
+ */
+
+ /*
+ * Danger, Will Robinson! We need to support tiemout
+ * and retry lest we just lost a packet ...
+ */
+
+ /* Packet transmitted OK, now we need to receive */
+ timeout = *timeout_ptr++;
+ oldtime = jiffies();
+ for (;;) {
+ buf = packet_buf;
+ udp_read.buffer.offs = OFFS_WRT(buf, 0);
+ udp_read.buffer.seg = 0;
+ udp_read.buffer_size = 2048;
+ udp_read.dest_ip = MyIP;
+ udp_read.d_port = tid;
+ err = pxe_call(PXENV_UDP_READ, &udp_read);
+ if (err) {
+ uint32_t now = jiffies();
+ if (now-oldtime >= timeout)
+ goto failure;
+ continue;
+ }
+
+ /* Make sure the packet actually came from the server */
+ if (udp_read.src_ip == open_file->tftp_remoteip)
+ break;
+ }
+
+ /* Got packet; reset timeout */
+ timeout_ptr = TimeoutTable;
+ open_file->tftp_remoteport = udp_read.s_port;
+
+ /* filesize <- -1 == unknown */
+ open_file->tftp_filesize = -1;
+ /* Default blksize unless blksize option negotiated */
+ open_file->tftp_blksize = TFTP_BLOCKSIZE;
+ buffersize = udp_read.buffer_size - 2; /* bytes after opcode */
+ if (buffersize < 0)
+ goto failure; /* Garbled reply */
+
+ /*
+ * Get the opcode type, and parse it
+ */
+ opcode = *(uint16_t *)packet_buf;
+ switch (opcode) {
+ case TFTP_ERROR:
+ open_file->tftp_filesize = 0;
+ break; /* ERROR reply; don't try again */
+
+ case TFTP_DATA:
+ /*
+ * If the server doesn't support any options, we'll get a
+ * DATA reply instead of OACK. Stash the data in the file
+ * buffer and go with the default value for all options...
+ *
+ * We got a DATA packet, meaning no options are
+ * suported. Save the data away and consider the
+ * length undefined, *unless* this is the only
+ * data packet...
+ */
+ buffersize -= 2;
+ if (buffersize < 0)
+ goto failure;
+ data = packet_buf + 2;
+ blk_num = *(uint16_t *)data;
+ data += 2;
+ if (blk_num != htons(1))
+ goto failure;
+ open_file->tftp_lastpkt = blk_num;
+ if (buffersize > TFTP_BLOCKSIZE)
+ goto err_reply; /* Corrupt */
+ else if (buffersize < TFTP_BLOCKSIZE) {
+ /*
+ * This is the final EOF packet, already...
+ * We know the filesize, but we also want to
+ * ack the packet and set the EOF flag.
+ */
+ open_file->tftp_filesize = buffersize;
+ open_file->tftp_goteof = 1;
+ ack_packet(open_file, blk_num);
+ }
+
+ open_file->tftp_bytesleft = buffersize;
+ open_file->tftp_dataptr = open_file->tftp_pktbuf;
+ memcpy(MK_PTR(PKTBUF_SEG, open_file->tftp_pktbuf), data, buffersize);
+ break;
+
+ case TFTP_OACK:
+ /*
+ * Now we need to parse the OACK packet to get the transfer
+ * and packet sizes.
+ */
+
+ options = packet_buf + 2;
+ p = options;
+
+ while (buffersize) {
+ char *opt = p;
+
+ /*
+ * If we find an option which starts with a NUL byte,
+ * (a null option), we're either seeing garbage that some
+ * TFTP servers add to the end of the packet, or we have
+ * no clue how to parse the rest of the packet (what is
+ * an option name and what is a value?) In either case,
+ * discard the rest.
+ */
+ if (!*opt)
+ goto done;
+
+ while (buffersize) {
+ if (!*p)
+ break; /* Found a final null */
+ *p++ |= 0x20;
+ buffersize--;
+ }
+ if (!buffersize)
+ break; /* Unterminated option */
+
+ /* Consume the terminal null */
+ p++;
+ buffersize--;
+
+ if (!buffersize)
+ break; /* No option data */
+
+ /*
+ * Parse option pointed to by options; guaranteed to be
+ * null-terminated
+ */
+ tftp_opt = tftp_options;
+ for (i = 0; i < tftp_nopts; i++) {
+ if (!strcmp(opt, tftp_opt->str_ptr))
+ break;
+ tftp_opt++;
+ }
+ if (i == tftp_nopts)
+ goto err_reply; /* Non-negotitated option returned,
+ no idea what it means ...*/
+
+ /* get the address of the filed that we want to write on */
+ opdata_ptr = (uint32_t *)((char *)open_file + tftp_opt->offset);
+ opdata = 0;
+
+ /* do convert a number-string to decimal number, just like atoi */
+ while (buffersize--) {
+ uint8_t d = *p++;
+ if (d == '\0')
+ break; /* found a final null */
+ d -= '0';
+ if (d > 9)
+ goto err_reply; /* Not a decimal digit */
+ opdata = opdata*10 + d;
+ }
+ *opdata_ptr = opdata;
+ }
+ break;
+
+ default:
+ printf("TFTP unknown opcode %d\n", ntohs(opcode));
+ goto err_reply;
+ }
+
+done:
+ if (!open_file->tftp_filesize) {
+ free_socket(open_file);
+ file->file_len = 0;
+ file->open_file = NULL;
+ return;
+ }
+ file->open_file = (void *)open_file;
+ file->file_len = open_file->tftp_filesize;
+ return;
+
+err_reply:
+ /* Build the TFTP error packet */
+ tftp_error(open_file, TFTP_EOPTNEG, "TFTP protocol error");
+ printf("TFTP server sent an incomprehesible reply\n");
+ kaboom();
+
+failure:
+ timeout_ptr++;
+ if (*timeout_ptr)
+ goto sendreq; /* Try again */
+}
+
+
+/*
+ * Store standard filename prefix
+ */
+static void get_prefix(void)
+{
+ int len;
+ char *p;
+ char c;
+
+ if (DHCPMagic & 0x04) /* Did we get a path prefix option */
+ goto got_prefix;
+
+ strcpy(path_prefix, boot_file);
+ len = strlen(path_prefix);
+ p = &path_prefix[len - 1];
+
+ while (len--) {
+ c = *p--;
+ c |= 0x20;
+
+ c = (c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'z') ||
+ (c == '.' || c == '-');
+ if (!c)
+ break;
+ };
+
+ if (len < 0)
+ p --;
+
+ *(p + 2) = 0; /* Zero-terminate after delimiter */
+
+ got_prefix:
+ printf("TFTP prefix: %s\n", path_prefix);
+ strcpy(CurrentDirName, path_prefix);
+}
+
+ /*
+ * try to load a config file, if found, return 1, or return 0
+ *
+ */
+static int try_load(char *config_name)
+{
+ com32sys_t regs;
+
+ printf("Trying to load: %-50s ", config_name);
+ pxe_mangle_name(KernelName, config_name);
+
+ memset(&regs, 0, sizeof regs);
+ regs.edi.w[0] = OFFS_WRT(KernelName, 0);
+ call16(core_open, &regs, &regs);
+ if (regs.eflags.l & EFLAGS_ZF) {
+ printf(" [FAILED]\n");
+ return 0;
+ } else {
+ printf(" [ OK ]\n");
+ return 1;
+ }
+}
+
+
+/* Load the config file, return 1 if failed, or 0 */
+static int pxe_load_config(void)
+{
+ const char *cfgprefix = "pxelinux.cfg/";
+ const char *default_str = "default";
+ char *config_file;
+ char *last;
+ char *p;
+ uint8_t *uuid_ptr;
+ int tries = 8;
+
+ get_prefix();
+ if (DHCPMagic & 0x02) {
+ /* We got a DHCP option, try it first */
+ if (try_load(boot_file))
+ return 0;
+ }
+
+ /*
+ * Have to guess config file name ...
+ */
+ memcpy(ConfigName, cfgprefix, strlen(cfgprefix));
+ config_file = ConfigName + strlen(cfgprefix);
+
+ /* Try loading by UUID */
+ if (have_uuid) {
+ uuid_ptr = uuid_dashes;
+ p = config_file;
+ while (*uuid_ptr) {
+ int len = *uuid_ptr;
+ char *src = uuid;
+
+ lchexbytes(p, src, len);
+ p += len * 2;
+ src += len;
+ uuid_ptr++;
+ *p++ = '-';
+ }
+ /* Remove last dash and zero-terminate */
+ *--p = '\0';
+ if (try_load(ConfigName))
+ return 0;
+ }
+
+ /* Try loading by MAC address */
+ strcpy(config_file, MAC_str);
+ if (try_load(ConfigName))
+ return 0;
+
+ /* Nope, try hexadecimal IP prefixes... */
+ uchexbytes(config_file, (uint8_t *)&MyIP, 4); /* Convet to hex string */
+ last = &config_file[8];
+ while (tries) {
+ *last = '\0'; /* Zero-terminate string */
+ if (try_load(ConfigName))
+ return 0;
+ last--; /* Drop one character */
+ tries--;
+ };
+
+ /* Final attempt: "default" string */
+ strcpy(config_file, default_str);
+ if (try_load(ConfigName))
+ return 0;
+
+ printf("Unable to locate configuration file\n");
+ kaboom();
+}
+
+/*
+ * Generate the botif string, and the hardware-based config string
+ */
+static void make_bootif_string(void)
+{
+ char mac[18];
+ char *src = mac;
+ char *dst = MAC_str;
+ int i = MAC_len + 1;
+
+ *(uint8_t *)src++ = MAC_type;
+ memcpy(src, MAC, MAC_len);
+ src = mac;
+ for (; i > 0; i--) {
+ lchexbytes(dst, src, 1);
+ dst += 2;
+ src += 1;
+ *dst++ = '-';
+ }
+ *(dst - 1) = 0; /* Drop the last '-' and null-terminate string */
+ strcat(BOOTIFStr, "BOOTIF=");
+ strcat(BOOTIFStr, MAC_str);
+
+#if 0
+ printf("%s\n", BOOTIFStr);
+#endif
+}
+/*
+ * Generate an ip=<client-ip>:<boot-server-ip>:<gw-ip>:<netmask>
+ * option into IPOption based on a DHCP packet in trackbuf.
+ *
+ */
+static void genipopt(void)
+{
+ char *p = IPOption;
+ int ip_len;
+
+ strcpy(p, "ip=");
+ p += 3;
+
+ ip_len = gendotquad(p, MyIP);
+ p += ip_len;
+ *p++ = ':';
+
+ ip_len = gendotquad(p, server_ip);
+ p += ip_len;
+ *p++ = ':';
+
+ ip_len = gendotquad(p, gate_way);
+ p += ip_len;
+ *p++ = ':';
+
+ ip_len = gendotquad(p, net_mask);
+}
+
+
+/* Generate ip= option and print the ip adress */
+static void ip_init(void)
+{
+ uint32_t ip = MyIP;
+
+ genipopt();
+ gendotquad(dot_quad_buf, ip);
+
+ ip = ntohl(ip);
+ printf("My IP address seems to be %08X %s\n", ip, dot_quad_buf);
+ printf("%s\n", IPOption);
+}
+
+/*
+ * Validity check on possible !PXE structure in buf
+ * return 1 for success, 0 for failure.
+ *
+ */
+static int is_pxe(const void *buf)
+{
+ const struct pxe_t *pxe = buf;
+ const uint8_t *p = buf;
+ int i = pxe->structlength;
+ uint8_t sum = 0;
+
+ if (i < sizeof(struct pxe_t) ||
+ memcmp(pxe->signature, "!PXE", 4))
+ return 0;
+
+ while (i--)
+ sum += *p++;
+
+ return sum == 0;
+}
+
+/*
+ * Just like is_pxe, it checks PXENV+ structure
+ *
+ */
+static int is_pxenv(const void *buf)
+{
+ const struct pxenv_t *pxenv = buf;
+ const uint8_t *p = buf;
+ int i = pxenv->length;
+ uint8_t sum = 0;
+
+ /* The pxeptr field isn't present in old versions */
+ if (i < offsetof(struct pxenv_t, pxeptr) ||
+ memcmp(pxenv->signature, "PXENV+", 6))
+ return 0;
+
+ while (i--)
+ sum += *p++;
+
+ return sum == 0;
+}
+
+
+
+/*
+ * memory_scan_for_pxe_struct:
+ * memory_scan_for_pxenv_struct:
+ *
+ * If none of the standard methods find the !PXE/PXENV+ structure,
+ * look for it by scanning memory.
+ *
+ * return the corresponding pxe structure if found, or NULL;
+ */
+static const void *memory_scan(uintptr_t start, int (*func)(const void *))
+{
+ const char *ptr;
+
+ /* Scan each 16 bytes of conventional memory before the VGA region */
+ for (ptr = (const char *)start; ptr < (const char *)0xA0000; ptr += 16) {
+ if (func(ptr))
+ return ptr; /* found it! */
+ ptr += 16;
+ }
+ return NULL;
+}
+
+static const struct pxe_t *memory_scan_for_pxe_struct(void)
+{
+ extern uint16_t BIOS_fbm; /* Starting segment */
+
+ return memory_scan(BIOS_fbm << 10, is_pxe);
+}
+
+static const struct pxenv_t *memory_scan_for_pxenv_struct(void)
+{
+ return memory_scan(0x10000, is_pxenv);
+}
+
+/*
+ * Find the !PXE structure; we search for the following, in order:
+ *
+ * a. !PXE structure as SS:[SP + 4]
+ * b. PXENV+ structure at [ES:BX]
+ * c. INT 1Ah AX=0x5650 -> PXENV+
+ * d. Search memory for !PXE
+ * e. Search memory for PXENV+
+ *
+ * If we find a PXENV+ structure, we try to find a !PXE structure from
+ * if if the API version is 2.1 or later
+ *
+ */
+static int pxe_init(void)
+{
+ extern void pxe_int1a(void);
+ char plan = 'A';
+ uint16_t seg, off;
+ uint16_t code_seg, code_len;
+ uint16_t data_seg, data_len;
+ const char *base = GET_PTR(InitStack);
+ com32sys_t regs;
+ const char *type;
+ const struct pxenv_t *pxenv;
+ const struct pxe_t *pxe;
+
+ /* Assume API version 2.1 */
+ APIVer = 0x201;
+
+ /* Plan A: !PXE structure as SS:[SP + 4] */
+ off = *(const uint16_t *)(base + 48);
+ seg = *(const uint16_t *)(base + 50);
+ pxe = MK_PTR(seg, off);
+ if (is_pxe(pxe))
+ goto have_pxe;
+
+ /* Plan B: PXENV+ structure at [ES:BX] */
+ plan++;
+ off = *(const uint16_t *)(base + 24); /* Original BX */
+ seg = *(const uint16_t *)(base + 4); /* Original ES */
+ pxenv = MK_PTR(seg, off);
+ if (is_pxenv(pxenv))
+ goto have_pxenv;
+
+ /* Plan C: PXENV+ structure via INT 1Ah AX=5650h */
+ plan++;
+ memset(&regs, 0, sizeof regs);
+ regs.eax.w[0] = 0x5650;
+ call16(pxe_int1a, &regs, &regs);
+ if (!(regs.eflags.l & EFLAGS_CF) && (regs.eax.w[0] == 0x564e)) {
+ pxenv = MK_PTR(regs.es, regs.ebx.w[0]);
+ if (is_pxenv(pxenv))
+ goto have_pxenv;
+ }
+
+ /* Plan D: !PXE memory scan */
+ plan++;
+ if ((pxe = memory_scan_for_pxe_struct()))
+ goto have_pxe;
+
+ /* Plan E: PXENV+ memory scan */
+ plan++;
+ if ((pxenv = memory_scan_for_pxenv_struct()))
+ goto have_pxenv;
+
+ /* Found nothing at all !! */
+ printf("No !PXE or PXENV+ API found; we're dead...\n");
+ kaboom();
+
+ have_pxenv:
+ APIVer = pxenv->version;
+ printf("Found PXENV+ structure\nPXE API version is %04x\n", APIVer);
+
+ /* if the API version number is 0x0201 or higher, use the !PXE structure */
+ if (APIVer >= 0x201) {
+ if (pxenv->length >= sizeof(struct pxenv_t)) {
+ pxe = GET_PTR(pxenv->pxeptr);
+ if (is_pxe(pxe))
+ goto have_pxe;
+ /*
+ * Nope, !PXE structure missing despite API 2.1+, or at least
+ * the pointer is missing. Do a last-ditch attempt to find it
+ */
+ if ((pxe = memory_scan_for_pxe_struct()))
+ goto have_pxe;
+ }
+ APIVer = 0x200; /* PXENV+ only, assume version 2.00 */
+ }
+
+ /* Otherwise, no dice, use PXENV+ structure */
+ data_len = pxenv->undidatasize;
+ data_seg = pxenv->undidataseg;
+ code_len = pxenv->undicodesize;
+ code_seg = pxenv->undicodeseg;
+ PXEEntry = pxenv->rmentry;
+ type = "PXENV+";
+ goto have_entrypoint;
+
+ have_pxe:
+ data_len = pxe->seg[PXE_Seg_UNDIData].size;
+ data_seg = pxe->seg[PXE_Seg_UNDIData].sel;
+ code_len = pxe->seg[PXE_Seg_UNDICode].size;
+ code_seg = pxe->seg[PXE_Seg_UNDICode].sel;
+ PXEEntry = pxe->entrypointsp;
+ type = "!PXE";
+
+ have_entrypoint:
+ printf("%s entry point found (we hope) at %04X:%04X via plan %c\n",
+ type, PXEEntry.seg, PXEEntry.offs, plan);
+ printf("UNDI code segment at %04X len %04X\n", code_seg, code_len);
+ printf("UNDI data segment at %04X len %04X\n", data_seg, data_len);
+
+ code_seg = code_seg + ((code_len + 15) >> 4);
+ data_seg = data_seg + ((data_len + 15) >> 4);
+
+ real_base_mem = max(code_seg, data_seg) >> 6; /* Convert to kilobytes */
+
+ return 0;
+}
+
+/*
+ * See if we have gPXE
+ */
+static void gpxe_init(void)
+{
+ int err;
+ static __lowmem struct s_PXENV_FILE_API_CHECK api_check;
+
+ if (APIVer >= 0x201) {
+ api_check.Size = sizeof api_check;
+ api_check.Magic = 0x91d447b2;
+ err = pxe_call(PXENV_FILE_API_CHECK, &api_check);
+ if (!err && api_check.Magic == 0xe9c17b20)
+ gpxe_funcs = api_check.APIMask;
+ }
+
+ /* Necessary functions for us to use the gPXE file API */
+ has_gpxe = (~gpxe_funcs & 0x4b) == 0;
+}
+
+/*
+ * Initialize UDP stack
+ *
+ */
+static void udp_init(void)
+{
+ int err;
+ static __lowmem struct s_PXENV_UDP_OPEN udp_open;
+ udp_open.src_ip = MyIP;
+ err = pxe_call(PXENV_UDP_OPEN, &udp_open);
+ if (err || udp_open.status) {
+ printf("Failed to initialize UDP stack ");
+ printf("%d\n", udp_open.status);
+ kaboom();
+ }
+}
+
+
+/*
+ * Network-specific initialization
+ */
+static void network_init(void)
+{
+ struct bootp_t *bp = (struct bootp_t *)trackbuf;
+ int pkt_len;
+
+ *LocalDomain = 0; /* No LocalDomain received */
+
+ /*
+ * Get the DHCP client identifiers (query info 1)
+ */
+ printf("Getting cached packet ");
+ pkt_len = pxe_get_cached_info(1);
+ parse_dhcp(pkt_len);
+ /*
+ * We don't use flags from the request packet, so
+ * this is a good time to initialize DHCPMagic...
+ * Initialize it to 1 meaning we will accept options found;
+ * in earlier versions of PXELINUX bit 0 was used to indicate
+ * we have found option 208 with the appropriate magic number;
+ * we no longer require that, but MAY want to re-introduce
+ * it in the future for vendor encapsulated options.
+ */
+ *(char *)&DHCPMagic = 1;
+
+ /*
+ * Get the BOOTP/DHCP packet that brought us file (and an IP
+ * address). This lives in the DHCPACK packet (query info 2)
+ */
+ pkt_len = pxe_get_cached_info(2);
+ parse_dhcp(pkt_len);
+ /*
+ * Save away MAC address (assume this is in query info 2. If this
+ * turns out to be problematic it might be better getting it from
+ * the query info 1 packet
+ */
+ MAC_len = bp->hardlen > 16 ? 0 : bp->hardlen;
+ MAC_type = bp->hardware;
+ memcpy(MAC, bp->macaddr, MAC_len);
+
+ /*
+ * Get the boot file and other info. This lives in the CACHED_REPLY
+ * packet (query info 3)
+ */
+ pkt_len = pxe_get_cached_info(3);
+ parse_dhcp(pkt_len);
+ printf("\n");
+
+ make_bootif_string();
+ ip_init();
+
+ /*
+ * Check to see if we got any PXELINUX-specific DHCP options; in particular,
+ * if we didn't get the magic enable, do not recognize any other options.
+ */
+ if ((DHCPMagic & 1) == 0)
+ DHCPMagic = 0;
+
+ udp_init();
+}
+
+/*
+ * Initialize pxe fs
+ *
+ */
+static int pxe_fs_init(struct fs_info *fs)
+{
+ (void)fs; /* drop the compile warning message */
+
+ /* Initialize the Files structure */
+ files_init();
+
+ /* Find the PXE stack */
+ pxe_init();
+
+ /* See if we also have a gPXE stack */
+ gpxe_init();
+
+ /* Network-specific initialization */
+ network_init();
+
+ /* Initialize network-card-specific idle handling */
+ pxe_idle_init();
+
+ return 0;
+}
+
+/*
+ * Look to see if we are on an EFI CSM system. Some EFI
+ * CSM systems put the BEV stack in low memory, which means
+ * a return to the PXE stack will crash the system. However,
+ * INT 18h works reliably, so in that case hack the stack and
+ * point the "return address" to an INT 18h instruction.
+ *
+ * Hack the stack instead of the much simpler "just invoke INT 18h
+ * if we want to reset", so that chainloading other NBPs will work.
+ *
+ * This manipulates the real-mode InitStack directly. It relies on this
+ * *not* being a currently active stack, i.e. the former
+ * USE_PXE_PROVIDED_STACK no longer works.
+ */
+extern far_ptr_t InitStack;
+
+struct efi_struct {
+ uint32_t magic;
+ uint8_t csum;
+ uint8_t len;
+} __attribute__((packed));
+#define EFI_MAGIC (('$' << 24)+('E' << 16)+('F' << 8)+'I')
+
+static inline bool is_efi(const struct efi_struct *efi)
+{
+ /*
+ * We don't verify the checksum, because it seems some CSMs leave
+ * it at zero, sigh...
+ */
+ return (efi->magic == EFI_MAGIC) && (efi->len >= 83);
+}
+
+static void install_efi_csm_hack(void)
+{
+ static const uint8_t efi_csm_hack[] =
+ {
+ 0xcd, 0x18, /* int $0x18 */
+ 0xea, 0xf0, 0xff, 0x00, 0xf0, /* ljmpw $0xf000,$0xfff0 */
+ 0xf4 /* hlt */
+ };
+ uint16_t *retcode;
+
+ retcode = GET_PTR(*(far_ptr_t *)((char *)GET_PTR(InitStack) + 44));
+
+ /* Don't do this if the return already points to int $0x18 */
+ if (*retcode != 0x18cd) {
+ uint32_t efi_ptr;
+ bool efi = false;
+
+ for (efi_ptr = 0xe0000 ; efi_ptr < 0x100000 ; efi_ptr += 16) {
+ if (is_efi((const struct efi_struct *)efi_ptr)) {
+ efi = true;
+ break;
+ }
+ }
+
+ if (efi) {
+ uint8_t *src = GET_PTR(InitStack);
+ uint8_t *dst = src - sizeof efi_csm_hack;
+
+ memmove(dst, src, 52);
+ memcpy(dst+52, efi_csm_hack, sizeof efi_csm_hack);
+ InitStack.offs -= sizeof efi_csm_hack;
+
+ /* Clobber the return address */
+ *(uint16_t *)(dst+44) = OFFS_WRT(dst+52, InitStack.seg);
+ *(uint16_t *)(dst+46) = InitStack.seg;
+ }
+ }
+}
+
+void reset_pxe(void)
+{
+ static __lowmem struct s_PXENV_UDP_CLOSE udp_close;
+ extern void gpxe_unload(void);
+
+ pxe_idle_cleanup();
+
+ printf("reset_pxe\n");
+
+ pxe_call(PXENV_UDP_CLOSE, &udp_close);
+
+ if (gpxe_funcs & 0x80) {
+ /* gPXE special unload implemented */
+ call16(gpxe_unload, &zero_regs, NULL);
+ }
+
+ install_efi_csm_hack();
+}
+
+/*
+ * This function unloads the PXE and UNDI stacks and
+ * unclaims the memory.
+ */
+void unload_pxe(void)
+{
+ uint8_t api;
+ const uint8_t *api_ptr;
+ uint16_t flag = 0;
+ int err;
+ int int_addr;
+ static __lowmem struct s_PXENV_UNLOAD_STACK unload_stack;
+
+ if (KeepPXE) {
+ /*
+ * We want to keep PXE around, but still we should reset
+ * it to the standard bootup configuration.
+ */
+ reset_pxe();
+ return;
+ }
+
+ pxe_idle_cleanup();
+
+ api_ptr = major_ver(APIVer) >= 2 ? new_api_unload : old_api_unload;
+ while((api = *api_ptr++)) {
+ memset(&unload_stack, 0, sizeof unload_stack);
+ err = pxe_call(api, &unload_stack);
+ if (err || unload_stack.Status != PXENV_STATUS_SUCCESS)
+ goto cant_free;
+ }
+
+ flag = 0xff00;
+ if (real_base_mem <= BIOS_fbm) /* Santiy check */
+ goto cant_free;
+ flag ++;
+
+ /* Check that PXE actually unhooked the INT 0x1A chain */
+ int_addr = (int)MK_PTR(*(uint16_t *)(4*0x1a+2), *(uint16_t *)(4*0x1a));
+ int_addr >>= 10;
+ if (int_addr >= real_base_mem || int_addr < BIOS_fbm) {
+ BIOS_fbm = real_base_mem;
+ return;
+ }
+
+cant_free:
+ printf("Failed to free base memory error %04x-%08x\n",
+ flag, *(uint32_t *)(4 * 0x1a));
+ return;
+}
+
+
+
+const struct fs_ops pxe_fs_ops = {
+ .fs_name = "pxe",
+ .fs_flags = FS_NODEV,
+ .fs_init = pxe_fs_init,
+ .searchdir = pxe_searchdir,
+ .getfssec = pxe_getfssec,
+ .close_file = pxe_close_file,
+ .mangle_name = pxe_mangle_name,
+ .unmangle_name = pxe_unmangle_name,
+ .load_config = pxe_load_config,
+ .iget_current = NULL
+};
diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h
new file mode 100644
index 00000000..f62fa7a7
--- /dev/null
+++ b/core/fs/pxe/pxe.h
@@ -0,0 +1,224 @@
+/* -----------------------------------------------------------------------
+ *
+ * Copyright 1999-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * 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., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * pxe.h
+ *
+ * PXE opcodes
+ *
+ */
+#ifndef PXE_H
+#define PXE_H
+
+#include <syslinux/pxe_api.h>
+#include "fs.h" /* For MAX_OPEN, should go away */
+
+/*
+ * Some basic defines...
+ */
+#define TFTP_PORT htons(69) /* Default TFTP port */
+#define TFTP_BLOCKSIZE_LG2 9
+#define TFTP_BLOCKSIZE (1 << TFTP_BLOCKSIZE_LG2)
+#define PKTBUF_SEG 0x4000
+#define PKTBUF_SIZE (65536 / MAX_OPEN)
+
+#define is_digit(c) (((c) >= '0') && ((c) <= '9'))
+#define major_ver(v) (((v) >> 8) && 0xff)
+
+/*
+ * TFTP operation codes
+ */
+#define TFTP_RRQ htons(1) // Read rest
+#define TFTP_WRQ htons(2) // Write rest
+#define TFTP_DATA htons(3) // Data packet
+#define TFTP_ACK htons(4) // ACK packet
+#define TFTP_ERROR htons(5) // ERROR packet
+#define TFTP_OACK htons(6) // OACK packet
+
+/*
+ * TFTP error codes
+ */
+#define TFTP_EUNDEF htons(0) // Unspecified error
+#define TFTP_ENOTFOUND htons(1) // File not found
+#define TFTP_EACCESS htons(2) // Access violation
+#define TFTP_ENOSPACE htons(3) // Disk full
+#define TFTP_EBADOP htons(4) // Invalid TFTP operation
+#define TFTP_EBADID htons(5) // Unknown transfer
+#define TFTP_EEXISTS htons(6) // File exists
+#define TFTP_ENOUSER htons(7) // No such user
+#define TFTP_EOPTNEG htons(8) // Option negotiation failure
+
+
+#define BOOTP_OPTION_MAGIC htonl(0x63825363)
+#define MAC_MAX 32
+
+/* Defines for DNS */
+#define DNS_PORT htons(53) /* Default DNS port */
+#define DNS_MAX_PACKET 512 /* Defined by protocol */
+/* All local DNS queries come from this port */
+#define DNS_LOCAL_PORT htons(60053)
+#define DNS_MAX_SERVERS 4 /* Max no of DNS servers */
+
+
+/*
+ * structures
+ */
+
+struct pxenv_t {
+ uint8_t signature[6]; /* PXENV+ */
+ uint16_t version;
+ uint8_t length;
+ uint8_t checksum;
+ segoff16_t rmentry;
+ uint32_t pmoffset;
+ uint16_t pmselector;
+ uint16_t stackseg;
+ uint16_t stacksize;
+ uint16_t bc_codeseg;
+ uint16_t bc_codesize;
+ uint16_t bc_dataseg;
+ uint16_t bc_datasize;
+ uint16_t undidataseg;
+ uint16_t undidatasize;
+ uint16_t undicodeseg;
+ uint16_t undicodesize;
+ segoff16_t pxeptr;
+} __packed;
+
+struct pxe_t {
+ uint8_t signature[4]; /* !PXE */
+ uint8_t structlength;
+ uint8_t structcksum;
+ uint8_t structrev;
+ uint8_t _pad1;
+ segoff16_t undiromid;
+ segoff16_t baseromid;
+ segoff16_t entrypointsp;
+ segoff16_t entrypointesp;
+ segoff16_t statuscallout;
+ uint8_t _pad2;
+ uint8_t segdesccnt;
+ uint16_t firstselector;
+ pxe_segdesc_t seg[7];
+} __packed;
+
+enum pxe_segments {
+ PXE_Seg_Stack = 0,
+ PXE_Seg_UNDIData = 1,
+ PXE_Seg_UNDICode = 2,
+ PXE_Seg_UNDICodeWrite = 3,
+ PXE_Seg_BC_Data = 4,
+ PXE_Seg_BC_Code = 5,
+ PXE_Seg_BC_CodeWrite = 6
+};
+
+struct bootp_t {
+ uint8_t opcode; /* BOOTP/DHCP "opcode" */
+ uint8_t hardware; /* ARP hreadware type */
+ uint8_t hardlen; /* Hardware address length */
+ uint8_t gatehops; /* Used by forwarders */
+ uint32_t ident; /* Transaction ID */
+ uint16_t seconds; /* Seconds elapsed */
+ uint16_t flags; /* Broadcast flags */
+ uint32_t cip; /* Cient IP */
+ uint32_t yip; /* "Your" IP */
+ uint32_t sip; /* Next Server IP */
+ uint32_t gip; /* Relay agent IP */
+ uint8_t macaddr[16]; /* Client MAC address */
+ uint8_t sname[64]; /* Server name (optional) */
+ char bootfile[128]; /* Boot file name */
+ uint32_t option_magic; /* Vendor option magic cookie */
+ uint8_t options[1260]; /* Vendor options */
+} __attribute__ ((packed));
+
+struct open_file_t {
+ uint16_t tftp_localport; /* Local port number (0=not in us)*/
+ uint16_t tftp_remoteport; /* Remote port number */
+ uint32_t tftp_remoteip; /* Remote IP address */
+ uint32_t tftp_filepos; /* bytes downloaded (includeing buffer) */
+ uint32_t tftp_filesize; /* Total file size(*) */
+ uint32_t tftp_blksize; /* Block size for this connection(*) */
+ uint16_t tftp_bytesleft; /* Unclaimed data bytes */
+ uint16_t tftp_lastpkt; /* Sequence number of last packet (NBO) */
+ uint16_t tftp_dataptr; /* Pointer to available data */
+ uint8_t tftp_goteof; /* 1 if the EOF packet received */
+ uint8_t tftp_unused; /* Currently unused */
+ /* These values are preinitialized and not zeroed on close */
+ uint16_t tftp_nextport; /* Next port number for this slot (HBO) */
+ uint16_t tftp_pktbuf; /* Packet buffer offset */
+} __attribute__ ((packed));
+
+/*
+ * Variable externs
+ */
+extern uint32_t server_ip;
+extern uint32_t MyIP;
+extern uint32_t net_mask;
+extern uint32_t gate_way;
+extern uint16_t server_port;
+
+extern char MAC_str[];
+extern char MAC[];
+extern char BOOTIFStr[];
+extern uint8_t MAC_len;
+extern uint8_t MAC_type;
+
+extern uint8_t DHCPMagic;
+extern uint32_t RebootTime;
+
+extern char boot_file[];
+extern char path_prefix[];
+extern char LocalDomain[];
+
+extern char packet_buf[];
+
+extern char IPOption[];
+extern char dot_quad_buf[];
+
+extern uint32_t dns_server[];
+
+extern uint16_t real_base_mem;
+extern uint16_t APIVer;
+extern far_ptr_t PXEEntry;
+extern uint8_t KeepPXE;
+
+extern far_ptr_t InitStack;
+
+extern int have_uuid;
+extern uint8_t uuid_type;
+extern char uuid[];
+
+extern uint16_t BIOS_fbm;
+extern const uint8_t TimeoutTable[];
+
+
+/*
+ * functions
+ */
+
+/* pxe.c */
+int ip_ok(uint32_t);
+int pxe_call(int, void *);
+
+/* dhcp_options.c */
+void parse_dhcp(int);
+void parse_dhcp_options(void *, int, int);
+
+/* dnsresolv.c */
+int dns_mangle(char **, const char *);
+uint32_t dns_resolv(const char *);
+
+/* idle.c */
+void pxe_idle_init(void);
+void pxe_idle_cleanup(void);
+
+#endif /* pxe.h */
diff --git a/core/getc.inc b/core/getc.inc
index bb12047b..48b9f774 100644
--- a/core/getc.inc
+++ b/core/getc.inc
@@ -60,8 +60,9 @@ getc_file_lg2 equ 4 ; Size of getc_file as a power of 2
;
; close: Output: CF set if nothing open
;
-open:
- call searchdir
+ global core_open
+core_open:
+ pm_call searchdir
jz openfd.ret
openfd:
push bx
@@ -82,11 +83,11 @@ openfd:
.ret: ret
.stack_full:
- call close_file
+ pm_call close_file
xor ax,ax ; ZF <- 1
pop bx
ret
-
+
getc:
push bx
push si
@@ -135,7 +136,7 @@ getc:
mov [di+gc_bufbytes],si ; In case SI == 0
jz .empty
mov cx,bytes_per_getc >> SECTOR_SHIFT
- call getfssec
+ pm_call getfssec
mov [di+gc_bufbytes],cx
mov [di+gc_file],si
jcxz .empty
@@ -177,7 +178,7 @@ close:
push si
mov bx,[CurrentGetC]
mov si,[bx+gc_file]
- call close_file
+ pm_call close_file
add bx,getc_file_size
mov [CurrentGetC],bx
pop si
@@ -321,7 +322,7 @@ parseint:
.isk: shl ebx,10 ; * 2^10
jmp .fini
- section .bss1
+ section .bss16
alignb 4
NumBuf resb 15 ; Buffer to load number
NumBufEnd resb 1 ; Last byte in NumBuf
@@ -329,14 +330,14 @@ NumBufEnd resb 1 ; Last byte in NumBuf
GetCStack resb getc_file_size*MAX_GETC
.end equ $
- section .data
+ section .data16
CurrentGetC dw GetCStack.end ; GetCStack empty
;
; unhexchar: Convert a hexadecimal digit in AL to the equivalent number;
; return CF=1 if not a hex digit
;
- section .text
+ section .text16
unhexchar:
cmp al,'0'
jb .ret ; If failure, CF == 1 already
diff --git a/core/graphics.inc b/core/graphics.inc
index 26925e9a..a8d28515 100644
--- a/core/graphics.inc
+++ b/core/graphics.inc
@@ -21,7 +21,7 @@
;
; Assumes CS == DS == ES.
;
- section .text
+ section .text16
vgadisplayfile:
; This is a cheap and easy way to make sure the screen is
@@ -322,7 +322,7 @@ vgacursorcommon:
ret
- section .data
+ section .data16
; Map colors to consecutive DAC registers
linear_color db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0
@@ -330,7 +330,7 @@ linear_color db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0
; of this byte.
UsingVGA db 0
- section .bss2
+ section .bss16
alignb 4
LSSHeader equ $
LSSMagic resd 1 ; Magic number
diff --git a/core/head.inc b/core/head.inc
index 7117b4ee..18ce132c 100644
--- a/core/head.inc
+++ b/core/head.inc
@@ -20,9 +20,15 @@
%ifndef _HEAD_INC
%define _HEAD_INC
+%if __NASM_MAJOR__ < 2
+ %error "NASM 2.00 or later required to compile correctly"
+%endif
+
%include "macros.inc"
%include "config.inc"
%include "layout.inc"
+%include "pmcall.inc"
+%include "extern.inc"
%include "kernel.inc"
%include "bios.inc"
%include "tracers.inc"
diff --git a/core/hello.c b/core/hello.c
new file mode 100644
index 00000000..a1591111
--- /dev/null
+++ b/core/hello.c
@@ -0,0 +1,30 @@
+#include <stddef.h>
+#include <com32.h>
+#include <stdio.h>
+#include <string.h>
+
+
+void myputchar(int c)
+{
+ static com32sys_t ireg;
+
+ if (c == '\n')
+ myputchar('\r');
+
+ ireg.eax.b[1] = 0x02;
+ ireg.edx.b[0] = c;
+ __intcall(0x21, &ireg, NULL);
+}
+
+void myputs(const char *str)
+{
+ while (*str)
+ myputchar(*str++);
+}
+
+void hello(void)
+{
+ static char hello_str[] = "Hello, World!";
+
+ printf("%s from (%s)\n", hello_str, __FILE__); /* testing */
+}
diff --git a/core/highmem.inc b/core/highmem.inc
index 1f8349bd..ea386ffc 100644
--- a/core/highmem.inc
+++ b/core/highmem.inc
@@ -17,7 +17,7 @@
;; mem= command on the command line while booting a new kernel.
;;
- section .text
+ section .text16
;
; This is set up as a subroutine; it will set up the global variable
@@ -150,9 +150,9 @@ got_highmem:
pop es
ret ; Done!
- section .bss
+ section .bss16
alignb 4
E820Buf resd 5 ; INT 15:E820 data buffer
E820Mem resd 1 ; Memory detected by E820
E820Max resd 1 ; Is E820 memory capped?
-HighMemSize resd 1 ; End of memory pointer (bytes)
+; HighMemSize is defined in com32.inc
diff --git a/core/idle.inc b/core/idle.inc
index bd134ff6..8d699733 100644
--- a/core/idle.inc
+++ b/core/idle.inc
@@ -11,19 +11,19 @@
;;
;; -----------------------------------------------------------------------
- section .text
+ section .text16
TICKS_TO_IDLE equ 4
reset_idle:
- push ax
- mov ax,[cs:BIOS_timer]
- mov [cs:IdleTimer],ax
- pop ax
+ push eax
+ mov eax,[cs:__jiffies]
+ mov [cs:IdleTimer],eax
+ pop eax
sti ; Guard against BIOS/PXE brokenness...
ret
do_idle:
- push ax
+ push eax
push ds
push es
mov ax,cs
@@ -54,25 +54,33 @@ do_idle:
pop si
sti
.ok:
- mov ax,[BIOS_timer]
- sub ax,[IdleTimer]
- cmp ax,TICKS_TO_IDLE
+ mov eax,[__jiffies]
+ sub eax,[IdleTimer]
+ cmp eax,TICKS_TO_IDLE
jb .done
- call [IdleHook]
+
+ mov eax,[idle_hook_func]
+ and eax,eax
+ jz .no_idle_hook
+ pm_call eax
+.no_idle_hook:
cmp word [NoHalt],0
jne .done
hlt
.done:
pop es
pop ds
- pop ax
+ pop eax
.ret: ret
- section .data
-IdleHook dw do_idle.ret
+ section .data16
+ alignz 4
+ global idle_hook_func
+idle_hook_func dd 0
NoHalt dw 0
hlt_err db 'ERROR: idle with IF=0', CR, LF, 0
- section .bss
-IdleTimer resw 1
+ section .bss16
+ alignb 4
+IdleTimer resd 1
diff --git a/core/include/cache.h b/core/include/cache.h
new file mode 100644
index 00000000..7518bc84
--- /dev/null
+++ b/core/include/cache.h
@@ -0,0 +1,25 @@
+#ifndef _CACHE_H
+#define _CACHE_H
+
+#include <stdint.h>
+#include <com32.h>
+#include "disk.h"
+#include "fs.h"
+
+#define MAX_CACHE_ENTRIES 0x10 /* I find even this is enough:) */
+
+/* The cache structure */
+struct cache_struct {
+ block_t block;
+ struct cache_struct *prev;
+ struct cache_struct *next;
+ void *data;
+};
+
+
+/* functions defined in cache.c */
+void cache_init(struct device *, int);
+struct cache_struct* get_cache_block(struct device *, block_t);
+void print_cache(struct device *);
+
+#endif /* cache.h */
diff --git a/core/include/codepage.h b/core/include/codepage.h
new file mode 100644
index 00000000..a24d90f5
--- /dev/null
+++ b/core/include/codepage.h
@@ -0,0 +1,27 @@
+/*
+ * Codepage data structure as generated by cptable.pl
+ */
+#ifndef CODEPAGE_H
+#define CODEPAGE_H
+
+#include <stdint.h>
+
+#define CODEPAGE_MAGIC UINT64_C(0x51d21eb158a8b3d4)
+
+struct codepage {
+ uint64_t magic;
+ uint32_t reserved[6];
+
+ uint8_t upper[256]; /* Codepage upper case table */
+ uint8_t lower[256]; /* Codepage lower case table */
+
+ /*
+ * The primary Unicode match is the same case, i.e. A -> A,
+ * the secondary Unicode match is the opposite case, i.e. A -> a.
+ */
+ uint16_t uni[2][256]; /* Primary and alternate Unicode matches */
+};
+
+extern const struct codepage codepage;
+
+#endif /* CODEPAGE_H */
diff --git a/core/include/core.h b/core/include/core.h
new file mode 100644
index 00000000..cdf92446
--- /dev/null
+++ b/core/include/core.h
@@ -0,0 +1,61 @@
+#ifndef CORE_H
+#define CORE_H
+
+#include <klibc/compiler.h>
+#include <com32.h>
+
+extern char core_xfer_buf[65536];
+extern char core_cache_buf[65536];
+extern char trackbuf[];
+extern char CurrentDirName[];
+extern char ConfigName[];
+extern char KernelName[];
+
+/* diskstart.inc isolinux.asm*/
+extern void getlinsec(void);
+
+/* getc.inc */
+extern void core_open(void);
+
+/* idle.inc */
+extern void (*idle_hook_func)(void);
+
+/* hello.c */
+extern void myputs(const char*);
+
+/* malloc.c */
+extern void *malloc(size_t);
+extern void *zalloc(size_t);
+extern void free(void *);
+extern void mem_init(void);
+
+void __cdecl core_intcall(uint8_t, const com32sys_t *, com32sys_t *);
+void __cdecl core_farcall(uint32_t, const com32sys_t *, com32sys_t *);
+int __cdecl core_cfarcall(uint32_t, const void *, uint32_t);
+
+extern const com32sys_t zero_regs;
+void call16(void (*)(void), const com32sys_t *, com32sys_t *);
+
+/*
+ * __lowmem is in the low 1 MB; __bss16 in the low 64K
+ */
+#define __lowmem __attribute((nocommon,section(".lowmem")))
+#define __bss16 __attribute((nocommon,section(".bss16")))
+
+/*
+ * Death! The macro trick is to avoid symbol conflict with
+ * the real-mode symbol kaboom.
+ */
+__noreturn _kaboom(void);
+#define kaboom() _kaboom()
+
+/*
+ * Basic timer function...
+ */
+extern const volatile uint32_t __jiffies;
+static inline uint32_t jiffies(void)
+{
+ return __jiffies;
+}
+
+#endif /* CORE_H */
diff --git a/core/include/disk.h b/core/include/disk.h
new file mode 100644
index 00000000..da6555ae
--- /dev/null
+++ b/core/include/disk.h
@@ -0,0 +1,36 @@
+#ifndef DISK_H
+#define DISK_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef uint64_t sector_t;
+typedef uint64_t block_t;
+
+/*
+ * struct disk: contains the information about a specific disk and also
+ * contains the I/O function.
+ */
+struct disk {
+ uint8_t disk_number; /* in BIOS style */
+ uint8_t type; /* CHS or EDD */
+ uint16_t sector_size; /* gener512B or 2048B */
+ uint8_t sector_shift;
+
+ uint8_t h, s; /* CHS geometry */
+ uint8_t pad;
+
+ sector_t part_start; /* the start address of this partition(in sectors) */
+
+ int (*rdwr_sectors)(struct disk *, void *, sector_t, size_t, bool);
+};
+
+extern void read_sectors(char *, sector_t, int);
+extern void getoneblk(struct disk *, char *, block_t, int);
+
+/* diskio.c */
+struct disk *disk_init(uint8_t, bool, sector_t, uint16_t, uint16_t);
+struct device *device_init(uint8_t, bool, sector_t, uint16_t, uint16_t);
+
+#endif /* DISK_H */
diff --git a/core/include/fs.h b/core/include/fs.h
new file mode 100644
index 00000000..394b2ae1
--- /dev/null
+++ b/core/include/fs.h
@@ -0,0 +1,172 @@
+#ifndef FS_H
+#define FS_H
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <string.h>
+#include <com32.h>
+#include <stdio.h>
+#include "core.h"
+#include "disk.h"
+
+/*
+ * Maximum number of open files. This is *currently* constrained by the
+ * fact that PXE needs to be able to fit all its packet buffers into a
+ * 64K segment; this should be fixed by moving the packet buffers to high
+ * memory.
+ */
+#define MAX_OPEN_LG2 5
+#define MAX_OPEN (1 << MAX_OPEN_LG2)
+
+#define FILENAME_MAX_LG2 8
+#define FILENAME_MAX (1 << FILENAME_MAX_LG2)
+
+#define BLOCK_SIZE(fs) ((fs)->block_size)
+#define BLOCK_SHIFT(fs) ((fs)->block_shift)
+#define SECTOR_SIZE(fs) ((fs)->sector_size)
+#define SECTOR_SHIFT(fs) ((fs)->sector_shift)
+
+struct fs_info {
+ const struct fs_ops *fs_ops;
+ struct device *fs_dev;
+ void *fs_info; /* The fs-specific information */
+ int sector_shift, sector_size;
+ int block_shift, block_size;
+};
+
+extern struct fs_info *this_fs;
+
+struct dirent; /* Directory entry structure */
+struct file;
+enum fs_flags {
+ FS_NODEV = 1 << 0,
+ FS_USEMEM = 1 << 1, /* If we need a malloc routine, set it */
+
+ /*
+ * Update the this_inode pointer at each part of path searching. This
+ * flag is just used for FAT and ISO fs for now.
+ */
+ FS_THISIND = 1 << 2,
+};
+
+struct fs_ops {
+ /* in fact, we use fs_ops structure to find the right fs */
+ const char *fs_name;
+ enum fs_flags fs_flags;
+
+ int (*fs_init)(struct fs_info *);
+ void (*searchdir)(char *, struct file *);
+ uint32_t (*getfssec)(struct file *, char *, int, bool *);
+ void (*close_file)(struct file *);
+ void (*mangle_name)(char *, const char *);
+ char * (*unmangle_name)(char *, const char *);
+ int (*load_config)(void);
+
+ struct inode * (*iget_root)(struct fs_info *);
+ struct inode * (*iget_current)(struct fs_info *);
+ struct inode * (*iget)(char *, struct inode *);
+ char * (*follow_symlink)(struct inode *, const char *);
+
+ /* the _dir_ stuff */
+ struct dirent * (*readdir)(struct file *);
+};
+
+enum inode_mode {I_FILE, I_DIR, I_SYMLINK};
+
+/*
+ * The inode structure, including the detail file information
+ */
+struct inode {
+ struct fs_info *fs; /* The filesystem this inode is associated with */
+ int mode; /* FILE , DIR or SYMLINK */
+ uint32_t size;
+ uint32_t ino; /* Inode number */
+ uint32_t atime; /* Access time */
+ uint32_t mtime; /* Modify time */
+ uint32_t ctime; /* Create time */
+ uint32_t dtime; /* Delete time */
+ int blocks; /* How many blocks the file take */
+ uint32_t flags;
+ uint32_t file_acl;
+ char pvt[0]; /* Private filesystem data */
+};
+
+extern struct inode *this_inode;
+
+struct open_file_t;
+
+struct file {
+ struct fs_info *fs;
+ union {
+ /* For the new universal-path_lookup */
+ struct {
+ struct inode *inode; /* The file-specific information */
+ uint32_t offset; /* for next read */
+ };
+
+ /* For the old searhdir method */
+ struct {
+ struct open_file_t *open_file;/* The fs-specific open file struct */
+ uint32_t file_len;
+ };
+ };
+};
+
+
+enum dev_type {CHS, EDD};
+
+/*
+ * Generic functions that filesystem drivers may choose to use
+ */
+void generic_mangle_name(char *, const char *);
+#define generic_unmangle_name stpcpy
+
+/*
+ * Struct device contains:
+ * the pointer points to the disk structure,
+ * the cache stuff.
+ */
+struct device {
+ struct disk *disk;
+
+ /* the cache stuff */
+ char* cache_data;
+ void* cache_head;
+ uint16_t cache_block_size;
+ uint16_t cache_entries;
+ uint32_t cache_size;
+};
+
+/*
+ * Our definition of "not whitespace"
+ */
+static inline bool not_whitespace(char c)
+{
+ return (unsigned char)c > ' ';
+}
+
+/*
+ * Inode allocator/deallocator
+ */
+struct inode *alloc_inode(struct fs_info *fs, uint32_t ino, size_t data);
+static inline void free_inode(struct inode * inode)
+{
+ free(inode);
+}
+
+static inline void malloc_error(char *obj)
+{
+ printf("Out of memory: can't allocate memory for %s\n", obj);
+ kaboom();
+}
+
+/*
+ * functions
+ */
+void mangle_name(com32sys_t *);
+void searchdir(com32sys_t *);
+void _close_file(struct file *);
+inline uint16_t file_to_handle(struct file *);
+inline struct file *handle_to_file(uint16_t);
+
+#endif /* FS_H */
diff --git a/core/init.inc b/core/init.inc
index 0b213ace..a3fe3041 100644
--- a/core/init.inc
+++ b/core/init.inc
@@ -2,6 +2,7 @@
; -----------------------------------------------------------------------
;
; Copyright 2004-2008 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
@@ -17,10 +18,20 @@
; Common initialization code (inline)
;
- section .text
+ section .text16
common_init:
- ; Now set up screen parameters
- call adjust_screen
+ ; Initialize PM invocation framework
+ call pm_init
+
+ ; Decompress PM code to its target location
+ pm_call pm_decompress
+ cmp eax,__pm_code_len
+ jne kaboom
+
+;
+; Initialize timer
+;
+ call timer_init
;
; Initialize configuration information
@@ -28,20 +39,87 @@ common_init:
call reset_config
;
-; Clear Files structures
+; Set up the COMBOOT APIs
+;
+ call comboot_setup_api
+
+;
+; Now set up screen parameters
+;
+ call adjust_screen
+
+;
+; CPU-dependent initialization and related checks.
+;
+check_escapes:
+ mov ah,02h ; Check keyboard flags
+ int 16h
+ mov [KbdFlags],al ; Save for boot prompt check
+ test al,04h ; Ctrl->skip 386 check
+ jnz skip_checks
+
+;
+; Now check that there is sufficient low (DOS) memory
+;
+; NOTE: Linux doesn't use all of real_mode_seg, but we use the same
+; segment for COMBOOT images, which can use all 64K
+;
+dosram_k equ (real_mode_seg+0x1000) >> 6 ; Minimum DOS memory (K)
+ int 12h
+ cmp ax,dosram_k
+ jae enough_ram
+ mov si,err_noram
+ call writestr_early
+ jmp kaboom
+enough_ram:
+skip_checks:
+
+ section .data16
+err_noram db 'It appears your computer has less than '
+ asciidec dosram_k
+ db 'K of low ("DOS")'
+ db CR, LF
+ db 'RAM. Syslinux needs at least this amount to boot. If you get'
+ db CR, LF
+ db 'this message in error, hold down the Ctrl key while'
+ db CR, LF
+ db 'booting, and I will take your word for it.', CR, LF, 0
+ section .text16
+
+;
+; The code to decompress the PM code and initialize other segments.
;
- mov di,Files
- mov cx,(MAX_OPEN*open_file_t_size)/4
+ extern _lzo1x_decompress_asm_fast
+
+ section .textnr
+ bits 32
+pm_decompress:
+ push 0 ; Space for decompressed size
+ push esp ; Pointer to previous word
+ push __pm_code_start ; Target address
+ push dword [lzo_data_size] ; Compressed size
+ push dword __pm_code_lma
+ call _lzo1x_decompress_asm_fast
+ add esp,16
+ pop RM_EAX ; Decompressed size
+
+ ; Zero bss sections (but not .earlybss, since it may
+ ; contain already-live data.)
xor eax,eax
+ mov edi,__bss_start
+ mov ecx,__bss_dwords
+ rep stosd
+ mov edi,__bss16_start
+ mov ecx,__bss16_dwords
rep stosd
+ mov edi,__high_clear_start ; .uibss, .auxseg, .lowmem
+ mov ecx,__high_clear_dwords
+ rep stosd
+
+ ret
+
+ section .data16
+lzo_data_size dd 0 ; filled in by compressor
-%if IS_PXELINUX
- mov di,Files+tftp_pktbuf
- mov cx,MAX_OPEN
-.setbufptr:
- mov [di],ax
- add di,open_file_t_size
- add ax,PKTBUF_SIZE
- loop .setbufptr
-%endif
- section .text ; This is an inline file...
+ section .text16
+ bits 16
diff --git a/core/isolinux.asm b/core/isolinux.asm
index 2627c2df..fef3e560 100644
--- a/core/isolinux.asm
+++ b/core/isolinux.asm
@@ -26,14 +26,10 @@
; Some semi-configurable constants... change on your own risk.
;
my_id equ isolinux_id
-FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null)
-FILENAME_MAX equ (1 << FILENAME_MAX_LG2)
NULLFILE equ 0 ; Zero byte == null file name
NULLOFFSET equ 0 ; Position in which to look
retry_count equ 6 ; How patient are we with the BIOS?
%assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top
-MAX_OPEN_LG2 equ 6 ; log2(Max number of open files)
-MAX_OPEN equ (1 << MAX_OPEN_LG2)
SECTOR_SHIFT equ 11 ; 2048 bytes/sector (El Torito requirement)
SECTOR_SIZE equ (1 << SECTOR_SHIFT)
@@ -72,12 +68,6 @@ file_left resd 1 ; Number of sectors left
%endif
%endif
- struc dir_t
-dir_lba resd 1 ; Directory start (LBA)
-dir_len resd 1 ; Length in bytes
-dir_clust resd 1 ; Length in clusters
- endstruc
-
; ---------------------------------------------------------------------------
; BEGIN CODE
; ---------------------------------------------------------------------------
@@ -86,18 +76,15 @@ dir_clust resd 1 ; Length in clusters
; Memory below this point is reserved for the BIOS and the MBR
;
section .earlybss
+ global trackbuf
trackbufsize equ 8192
trackbuf resb trackbufsize ; Track buffer goes here
; ends at 2800h
; Some of these are touched before the whole image
- ; is loaded. DO NOT move this to .uibss.
- section .bss2
+ ; is loaded. DO NOT move this to .bss16/.uibss.
+ section .earlybss
alignb 4
-ISOFileName resb 64 ; ISO filename canonicalization buffer
-ISOFileNameEnd equ $
-CurrentDir resb dir_t_size ; Current directory
-RootDir resb dir_t_size ; Root directory
FirstSecSum resd 1 ; Checksum of bytes 64-2048
ImageDwords resd 1 ; isolinux.bin size, dwords
InitStack resd 1 ; Initial stack pointer (SS:SP)
@@ -190,10 +177,7 @@ dsp_dummy: resb 1 ; Scratch, safe to overwrite
_spec_end equ $
_spec_len equ _spec_end - _spec_start
- alignb open_file_t_size
-Files resb MAX_OPEN*open_file_t_size
-
- section .text
+ section .init
;;
;; Primary entry point. Because BIOSes are buggy, we only load the first
;; CD-ROM sector (2K) of the file, so the number one priority is actually
@@ -203,6 +187,7 @@ StackBuf equ $-44 ; 44 bytes needed for
; the bootsector chainloading
; code!
OrigESDI equ StackBuf-4 ; The high dword on the stack
+StackTop equ OrigESDI
bootsec equ $
@@ -410,8 +395,8 @@ found_file:
sub eax,SECTOR_SIZE-3 ; ... minus sector loaded
shr eax,2 ; bytes->dwords
mov [ImageDwords],eax ; boot file dwords
- add eax,(2047 >> 2)
- shr eax,9 ; dwords->sectors
+ add eax,((SECTOR_SIZE-1) >> 2)
+ shr eax,SECTOR_SHIFT-2 ; dwords->sectors
mov [ImageSectors],ax ; boot file sectors
mov eax,[bi_file] ; Address of code to load
@@ -423,34 +408,54 @@ found_file:
call crlf
%endif
- ; Just in case some BIOSes have problems with
- ; segment wraparound, use the normalized address
- mov bx,((7C00h+2048) >> 4)
- mov es,bx
- xor bx,bx
+ ; Load the rest of the file. However, just in case there
+ ; are still BIOSes with 64K wraparound problems, we have to
+ ; take some extra precautions. Since the normal load
+ ; address (7C00h) is *not* 2K-sector-aligned, the safest
+ ; way to deal with this is to load into the xfer_buf_seg
+ ; and then copy the data in place.
+MaxLMA equ xfer_buf_seg << 4
+
+ mov bx,(7C00h+SECTOR_SIZE) >> 4
mov bp,[ImageSectors]
-%ifdef DEBUG_MESSAGES
- push ax
- mov si,size_msg
- call writemsg
- mov ax,bp
- call writehex4
- call crlf
- pop ax
-%endif
+
+.more:
+ push bx
+ push bp
+ mov dx,xfer_buf_seg
+ mov es,dx
+ mov fs,dx
+ xor bx,bx
+
+ cmp bp,0x10000 >> SECTOR_SHIFT
+ jbe .ok
+ mov bp,0x10000 >> SECTOR_SHIFT
+.ok:
+ push bp
call getlinsec
+ pop dx
+ pop bp
+ pop bx
+
+ mov es,bx
+ xor si,si
+ xor di,di
+ mov cx,dx
+ shl cx,SECTOR_SHIFT-2
+ fs rep movsd
+
+ mov cx,dx
+ shl cx,SECTOR_SHIFT-4
+ add bx,cx
+ sub bp,dx
+ jnz .more
push ds
pop es
-%ifdef DEBUG_MESSAGES
- mov si,loaded_msg
- call writemsg
-%endif
-
; Verify the checksum on the loaded image.
verify_image:
- mov si,7C00h+2048
+ mov si,7C00h+SECTOR_SIZE
mov bx,es
mov ecx,[ImageDwords]
mov edi,[FirstSecSum] ; First sector checksum
@@ -697,9 +702,7 @@ writemsg: push ax
;
writechr:
- jmp near writechr_simple ; 3-byte jump
-
-writechr_simple:
+.simple:
pushfd
pushad
mov ah,0Eh
@@ -747,6 +750,7 @@ getonesec:
; ES:BX - Target buffer
; BP - Sector count
;
+ global getlinsec
getlinsec: jmp word [cs:GetlinsecPtr]
%ifndef DEBUG_MESSAGES
@@ -1012,6 +1016,7 @@ xint13: mov byte [RetryCount],retry_count
; kaboom: write a message and bail out. Wait for a user keypress,
; then do a hard reboot.
;
+ global kaboom
disk_error:
kaboom:
RESET_STACK_AND_SEGS AX
@@ -1044,8 +1049,6 @@ startup_msg: db 'Starting up, DL = ', 0
spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
secsize_msg: db 'Sector size ', 0
offset_msg: db 'Main image LBA = ', 0
-size_msg: db 'Sectors to load = ', 0
-loaded_msg: db 'Loaded boot image, verifying...', CR, LF, 0
verify_msg: db 'Image checksum verified.', CR, LF, 0
allread_msg db 'Main image read, jumping to main code...', CR, LF, 0
%endif
@@ -1081,6 +1084,7 @@ bios_ebios: dw getlinsec_ebios, bios_ebios_str
%endif
; Maximum transfer size
+ global MaxTransfer
MaxTransfer dw 127 ; Hard disk modes
MaxTransferCD dw 32 ; CD mode
@@ -1094,6 +1098,8 @@ rl_checkpt equ $ ; Must be <= 800h
; End of code and data that have to be in the first sector
; ----------------------------------------------------------------------------
+ section .text16
+
all_read:
; Test tracers
@@ -1104,10 +1110,14 @@ all_read:
; Common initialization code
;
%include "init.inc"
-%include "cpuinit.inc"
; Patch the writechr routine to point to the full code
- mov word [writechr+1], writechr_full-(writechr+3)
+ mov di,writechr
+ mov al,0e9h
+ stosb
+ mov ax,writechr_full-2
+ sub ax,di
+ stosw
; Tell the user we got this far...
%ifndef DEBUG_MESSAGES ; Gets messy with debugging on
@@ -1135,95 +1145,31 @@ all_read:
; (which will be at 16 only for a single-session disk!); from the PVD
; we should be able to find the rest of what we need to know.
;
-get_fs_structures:
- mov eax,[bi_pvd]
- mov bx,trackbuf
- call getonesec
+ pushad
+ mov eax,ROOT_FS_OPS
+ mov dl,[DriveNumber]
+ cmp word [BIOSType],bios_cdrom
+ sete dh ; 1 for cdrom, 0 for hybrid mode
+ mov ecx,[bsHidden]
+ mov ebx,[bsHidden+4]
+ mov si,[bsHeads]
+ mov di,[bsSecPerTrack]
+ pm_call fs_init
+ popad
- mov eax,[trackbuf+156+2]
- mov [RootDir+dir_lba],eax
- mov [CurrentDir+dir_lba],eax
-%ifdef DEBUG_MESSAGES
- mov si,dbg_rootdir_msg
- call writemsg
- call writehex8
- call crlf
-%endif
- mov eax,[trackbuf+156+10]
- mov [RootDir+dir_len],eax
- mov [CurrentDir+dir_len],eax
- add eax,SECTOR_SIZE-1
- shr eax,SECTOR_SHIFT
- mov [RootDir+dir_clust],eax
- mov [CurrentDir+dir_clust],eax
-
- ; Look for an isolinux directory, and if found,
- ; make it the current directory instead of the root
- ; directory.
- ; Also copy the name of the directory to CurrentDirName
- mov word [CurrentDirName],ROOT_DIR_WORD ; Write '/',0 to the CurrentDirName
- mov di,boot_dir ; Search for /boot/isolinux
- mov al,02h
- push di
- call searchdir_iso
- pop di
- jnz .found_dir
- mov di,isolinux_dir
- mov al,02h ; Search for /isolinux
- push di
- call searchdir_iso
- pop di
- jz .no_isolinux_dir
-.found_dir:
- ; Copy current directory name to CurrentDirName
- push si
- push di
- mov si,di
- mov di,CurrentDirName
- call strcpy
- mov byte [di],0 ;done in case it's not word aligned
- dec di
- mov byte [di],'/'
- pop di
- pop si
+ section .rodata
+ alignz 4
+ROOT_FS_OPS:
+ extern iso_fs_ops
+ dd iso_fs_ops
+ dd 0
- mov [CurrentDir+dir_len],eax
- mov eax,[si+file_left]
- mov [CurrentDir+dir_clust],eax
- xor eax,eax ; Free this file pointer entry
- xchg eax,[si+file_sector]
- mov [CurrentDir+dir_lba],eax
-%ifdef DEBUG_MESSAGES
- push si
- mov si,dbg_isodir_msg
- call writemsg
- pop si
- call writehex8
- call crlf
-%endif
-.no_isolinux_dir:
+ section .text16
;
; Locate the configuration file
;
-load_config:
-%ifdef DEBUG_MESSAGES
- mov si,dbg_config_msg
- call writemsg
-%endif
-
- mov si,config_name
- mov di,ConfigName
- call strcpy
-
- mov di,ConfigName
- call open
- jz no_config_file ; Not found or empty
-
-%ifdef DEBUG_MESSAGES
- mov si,dbg_configok_msg
- call writemsg
-%endif
+ pm_call load_config
;
; Now we have the config file open. Parse the config file and
@@ -1264,7 +1210,7 @@ is_disk_image:
mov bx,trackbuf
mov cx,1 ; Load 1 sector
- call getfssec
+ pm_call getfssec
cmp word [trackbuf+510],0aa55h ; Boot signature
jne .bad_image ; Image not bootable
@@ -1361,391 +1307,23 @@ is_disk_image:
mov al,bl
.done_sector: ret
-;
-; close_file:
-; Deallocates a file structure (pointer in SI)
-; Assumes CS == DS.
-;
-close_file:
- and si,si
- jz .closed
- mov dword [si],0 ; First dword == file_left
- xor si,si
-.closed: ret
-
-;
-; searchdir:
-;
-; Open a file
-;
-; On entry:
-; DS:DI = filename
-; If successful:
-; ZF clear
-; SI = file pointer
-; EAX = file length in bytes
-; If unsuccessful
-; ZF set
-;
-; Assumes CS == DS == ES, and trashes BX and CX.
-;
-; searchdir_iso is a special entry point for ISOLINUX only. In addition
-; to the above, searchdir_iso passes a file flag mask in AL. This is useful
-; for searching for directories.
-;
-alloc_failure:
- xor ax,ax ; ZF <- 1
- ret
-
-searchdir:
- xor al,al
-searchdir_iso:
- mov [ISOFlags],al
- TRACER 'S'
- call allocate_file ; Temporary file structure for directory
- jnz alloc_failure
- push es
- push ds
- pop es ; ES = DS
- mov si,CurrentDir
- cmp byte [di],'/' ; If filename begins with slash
- jne .not_rooted
- inc di ; Skip leading slash
- mov si,RootDir ; Reference root directory instead
-.not_rooted:
- mov eax,[si+dir_clust]
- mov [bx+file_left],eax
- shl eax,SECTOR_SHIFT
- mov [bx+file_bytesleft],eax
- mov eax,[si+dir_lba]
- mov [bx+file_sector],eax
- mov edx,[si+dir_len]
-
-.look_for_slash:
- mov ax,di
-.scan:
- mov cl,[di]
- inc di
- and cl,cl
- jz .isfile
- cmp cl,'/'
- jne .scan
- mov [di-1],byte 0 ; Terminate at directory name
- mov cl,02h ; Search for directory
- xchg cl,[ISOFlags]
-
- push di ; Save these...
- push cx
-
- ; Create recursion stack frame...
- push word .resume ; Where to "return" to
- push es
-.isfile: xchg ax,di
-
-.getsome:
- ; Get a chunk of the directory
- ; This relies on the fact that ISOLINUX doesn't change SI
- mov si,trackbuf
- TRACER 'g'
- pushad
- xchg bx,si
- mov cx,[BufSafe]
- call getfssec
- popad
-
-.compare:
- movzx eax,byte [si] ; Length of directory entry
- cmp al,33
- jb .next_sector
- TRACER 'c'
- mov cl,[si+25]
- xor cl,[ISOFlags]
- test cl, byte 8Eh ; Unwanted file attributes!
- jnz .not_file
- pusha
- movzx cx,byte [si+32] ; File identifier length
- add si,byte 33 ; File identifier offset
- TRACER 'i'
- call iso_compare_names
- popa
- je .success
-.not_file:
- sub edx,eax ; Decrease bytes left
- jbe .failure
- add si,ax ; Advance pointer
-
-.check_overrun:
- ; Did we finish the buffer?
- cmp si,trackbuf+trackbufsize
- jb .compare ; No, keep going
-
- jmp short .getsome ; Get some more directory
-
-.next_sector:
- ; Advance to the beginning of next sector
- lea ax,[si+SECTOR_SIZE-1]
- and ax,~(SECTOR_SIZE-1)
- sub ax,si
- jmp short .not_file ; We still need to do length checks
-
-.failure: xor eax,eax ; ZF = 1
- mov [bx+file_sector],eax
- pop es
- ret
-
-.success:
- mov eax,[si+2] ; Location of extent
- mov [bx+file_sector],eax
- mov eax,[si+10] ; Data length
- mov [bx+file_bytesleft],eax
- push eax
- add eax,SECTOR_SIZE-1
- shr eax,SECTOR_SHIFT
- mov [bx+file_left],eax
- pop eax
- jz .failure ; Empty file?
- ; ZF = 0
- mov si,bx
- pop es
- ret
-
-.resume: ; We get here if we were only doing part of a lookup
- ; This relies on the fact that .success returns bx == si
- xchg edx,eax ; Directory length in edx
- pop cx ; Old ISOFlags
- pop di ; Next filename pointer
- mov byte [di-1], '/' ; Restore slash
- mov [ISOFlags],cl ; Restore the flags
- jz .failure ; Did we fail? If so fail for real!
- jmp .look_for_slash ; Otherwise, next level
-
-;
-; allocate_file: Allocate a file structure
-;
-; If successful:
-; ZF set
-; BX = file pointer
-; In unsuccessful:
-; ZF clear
-;
-allocate_file:
- TRACER 'a'
- push cx
- mov bx,Files
- mov cx,MAX_OPEN
-.check: cmp dword [bx], byte 0
- je .found
- add bx,open_file_t_size ; ZF = 0
- loop .check
- ; ZF = 0 if we fell out of the loop
-.found: pop cx
- ret
-
-;
-; iso_compare_names:
-; Compare the names DS:SI and DS:DI and report if they are
-; equal from an ISO 9660 perspective. SI is the name from
-; the filesystem; CX indicates its length, and ';' terminates.
-; DI is expected to end with a null.
-;
-; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
-;
-iso_compare_names:
- ; First, terminate and canonicalize input filename
- push di
- mov di,ISOFileName
-.canon_loop: jcxz .canon_end
- lodsb
- dec cx
- cmp al,';'
- je .canon_end
- and al,al
- je .canon_end
- stosb
- cmp di,ISOFileNameEnd-1 ; Guard against buffer overrun
- jb .canon_loop
-.canon_end:
- cmp di,ISOFileName
- jbe .canon_done
- cmp byte [di-1],'.' ; Remove terminal dots
- jne .canon_done
- dec di
- jmp short .canon_end
-.canon_done:
- mov [di],byte 0 ; Null-terminate string
- pop di
- mov si,ISOFileName
-.compare:
- lodsb
- mov ah,[di]
- inc di
- and ax,ax
- jz .success ; End of string for both
- and al,al ; Is either one end of string?
- jz .failure ; If so, failure
- and ah,ah
- jz .failure
- or ax,2020h ; Convert to lower case
- cmp al,ah
- je .compare
-.failure: and ax,ax ; ZF = 0 (at least one will be nonzero)
-.success: ret
-
-;
-; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
-; to by ES:DI; ends on encountering any whitespace.
-; DI is preserved.
-;
-; This verifies that a filename is < FILENAME_MAX characters,
-; doesn't contain whitespace, zero-pads the output buffer,
-; and removes trailing dots and redundant slashes,
-; so "repe cmpsb" can do a compare, and the
-; path-searching routine gets a bit of an easier job.
-;
-mangle_name:
- push di
- push bx
- xor ax,ax
- mov cx,FILENAME_MAX-1
- mov bx,di
-
-.mn_loop:
- lodsb
- cmp al,' ' ; If control or space, end
- jna .mn_end
- cmp al,ah ; Repeated slash?
- je .mn_skip
- xor ah,ah
- cmp al,'/'
- jne .mn_ok
- mov ah,al
-.mn_ok stosb
-.mn_skip: loop .mn_loop
-.mn_end:
- cmp bx,di ; At the beginning of the buffer?
- jbe .mn_zero
- cmp byte [es:di-1],'.' ; Terminal dot?
- je .mn_kill
- cmp byte [es:di-1],'/' ; Terminal slash?
- jne .mn_zero
-.mn_kill: dec di ; If so, remove it
- inc cx
- jmp short .mn_end
-.mn_zero:
- inc cx ; At least one null byte
- xor ax,ax ; Zero-fill name
- rep stosb
- pop bx
- pop di
- ret ; Done
-
-;
-; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
-; filename to the conventional representation. This is needed
-; for the BOOT_IMAGE= parameter for the kernel.
-;
-; DS:SI -> input mangled file name
-; ES:DI -> output buffer
-;
-; On return, DI points to the first byte after the output name,
-; which is set to a null byte.
-;
-unmangle_name: call strcpy
- dec di ; Point to final null byte
- ret
-
-;
-; getfssec: Get multiple clusters from a file, given the file pointer.
-;
-; On entry:
-; ES:BX -> Buffer
-; SI -> File pointer
-; CX -> Cluster count
-; On exit:
-; SI -> File pointer (or 0 on EOF)
-; CF = 1 -> Hit EOF
-; ECX -> Bytes actually read
-;
-getfssec:
- TRACER 'F'
- push ds
- push cs
- pop ds ; DS <- CS
-
- movzx ecx,cx
- cmp ecx,[si+file_left]
- jna .ok_size
- mov ecx,[si+file_left]
-.ok_size:
-
- pushad
- mov eax,[si+file_sector]
- mov bp,cx
- TRACER 'l'
- call getlinsec
- popad
-
- ; ECX[31:16] == 0 here...
- add [si+file_sector],ecx
- sub [si+file_left],ecx
- shl ecx,SECTOR_SHIFT ; Convert to bytes
- cmp ecx,[si+file_bytesleft]
- jb .not_all
- mov ecx,[si+file_bytesleft]
-.not_all: sub [si+file_bytesleft],ecx
- jnz .ret ; CF = 0 in this case...
- push eax
- xor eax,eax
- mov [si+file_sector],eax ; Unused
- mov si,ax
- pop eax
- stc
-.ret:
- pop ds
- TRACER 'f'
- ret
; -----------------------------------------------------------------------------
; Common modules
; -----------------------------------------------------------------------------
-%include "getc.inc" ; getc et al
-%include "conio.inc" ; Console I/O
-%include "configinit.inc" ; Initialize configuration
-%include "parseconfig.inc" ; High-level config file handling
-%include "parsecmd.inc" ; Low-level config file handling
-%include "bcopy32.inc" ; 32-bit bcopy
-%include "loadhigh.inc" ; Load a file into high memory
-%include "font.inc" ; VGA font stuff
-%include "graphics.inc" ; VGA graphics
-%include "highmem.inc" ; High memory sizing
-%include "strcpy.inc" ; strcpy()
+%include "common.inc" ; Universal modules
%include "rawcon.inc" ; Console I/O w/o using the console functions
-%include "idle.inc" ; Idle handling
-%include "adv.inc" ; Auxillary Data Vector
%include "localboot.inc" ; Disk-based local boot
; -----------------------------------------------------------------------------
; Begin data section
; -----------------------------------------------------------------------------
- section .data
-
-default_str db 'default', 0
-default_len equ ($-default_str)
-boot_dir db '/boot' ; /boot/isolinux
-isolinux_dir db '/isolinux', 0
-config_name db 'isolinux.cfg', 0
+ section .data16
err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0
-%ifdef DEBUG_MESSAGES
-dbg_rootdir_msg db 'Root directory at LBA = ', 0
-dbg_isodir_msg db 'isolinux directory at LBA = ', 0
-dbg_config_msg db 'About to load config file...', CR, LF, 0
-dbg_configok_msg db 'Configuration file opened...', CR, LF, 0
-%endif
-
;
; Config file keyword table
;
diff --git a/core/kaboom.c b/core/kaboom.c
new file mode 100644
index 00000000..d639915a
--- /dev/null
+++ b/core/kaboom.c
@@ -0,0 +1,16 @@
+/*
+ * kaboom.c
+ */
+
+#include "core.h"
+
+#undef kaboom
+
+__noreturn _kaboom(void)
+{
+ extern void kaboom(void);
+ call16(kaboom, &zero_regs, NULL);
+ /* Do this if kaboom somehow returns... */
+ for (;;)
+ asm volatile("hlt");
+}
diff --git a/core/layout.inc b/core/layout.inc
index 8c2e2485..c67105ad 100644
--- a/core/layout.inc
+++ b/core/layout.inc
@@ -38,11 +38,12 @@ LATEBSS_START equ 0B800h
section .earlybss nobits
section .config write progbits align=4
section .replacestub exec write progbits align=16
+ section .gentextnr exec write nobits align=16
- ; Use .bss for things that doesn't have to be in low memory;
- ; with .bss1 and .bss2 to offload. .earlybss should be used
- ; for things that absolutely have to be below 0x7c00.
- section .bss write nobits align=16
+ ; Use .bss16 for things that doesn't have to be in low memory;
+ ; .earlybss should be used for things that absolutely have
+ ; to be below 0x7c00.
+ section .bss16 write nobits align=16
%if 0 ; IS_PXELINUX
; Warning here: RBFG build 22 randomly overwrites
@@ -54,11 +55,11 @@ LATEBSS_START equ 0B800h
RBFG_brainfuck: resb 2048 ; Bigger than an Ethernet packet...
%endif
- section .bss2 write nobits align=16
-
- section .text exec write progbits align=16
+ section .init exec write progbits align=1
+ section .text16 exec write progbits align=1
+ section .textnr exec nowrite progbits align=1
section .bcopyxx exec write progbits align=16
- section .data write progbits align=16
+ section .data16 write progbits align=16
section .adv write nobits align=512
@@ -68,20 +69,26 @@ RBFG_brainfuck: resb 2048 ; Bigger than an Ethernet packet...
; the spillover from the last fractional sector load.
section .uibss write nobits align=16
- ; Normal bss...
- section .bss1 write nobits align=16
-
; Symbols from linker script
%macro SECINFO 1
extern __%1_start, __%1_lma, __%1_end
extern __%1_len, __%1_dwords
%endmacro
+ SECINFO bss16
+ SECINFO uibss
SECINFO config
SECINFO replacestub
+ SECINFO pm_code
+ SECINFO high_clear
+
+ SECINFO bss
+
+ extern free_high_memory
+
global _start
- section .text
+ section .text16
;
; Segment assignments in the bottom 640K
@@ -89,15 +96,20 @@ RBFG_brainfuck: resb 2048 ; Bigger than an Ethernet packet...
; failure!
;
; 0000h - main code/data segment (and BIOS segment)
-
-xfer_buf_seg equ 1000h
-aux_seg equ 2000h
+;
+; This stuff really should come from the linker...
+;
+ global xfer_buf_seg, core_xfer_buf
+xfer_buf_seg equ 3000h
+core_xfer_buf equ xfer_buf_seg << 4
serial_buf_size equ 4096 ; Should be a power of 2
;
; Contents of aux_seg
;
+ extern aux_seg ; Actual segment assigned by linker
+
struc aux
.fontbuf resb 8192
.serial resb serial_buf_size
@@ -105,7 +117,8 @@ serial_buf_size equ 4096 ; Should be a power of 2
alignb 4096 ; Align the next segment to 4K
endstruc
-aux_seg_end equ aux_seg + (aux_size >> 4)
+ section .auxseg write nobits align=16
+auxseg resb aux_size
;
; Bounce buffer for I/O to high mem
@@ -113,14 +126,11 @@ aux_seg_end equ aux_seg + (aux_size >> 4)
; is somewhat excessive. Sector alignment is obligatory, however.
;
-%if IS_ISOLINUX
-; ISOLINUX doesn't have a block cache yet
-real_mode_seg equ aux_seg_end
-%else
-cache_seg equ aux_seg_end ; 64K area for metadata cache
-real_mode_seg equ cache_seg + 1000h
+ global cache_seg, core_cache_buf
+cache_seg equ 4000h ; 64K area for metadata cache
+core_cache_buf equ cache_seg << 4
+real_mode_seg equ 5000h
pktbuf_seg equ cache_seg ; PXELINUX packet buffers
-%endif
comboot_seg equ real_mode_seg ; COMBOOT image loading zone
diff --git a/core/ldlinux.asm b/core/ldlinux.asm
index 0808e6e8..23540ea5 100644
--- a/core/ldlinux.asm
+++ b/core/ldlinux.asm
@@ -22,1417 +22,19 @@
;
; ****************************************************************************
-%ifndef IS_MDSLINUX
%define IS_SYSLINUX 1
-%endif
%include "head.inc"
;
; Some semi-configurable constants... change on your own risk.
;
my_id equ syslinux_id
-FILENAME_MAX_LG2 equ 6 ; log2(Max filename size Including final null)
-FILENAME_MAX equ (1<<FILENAME_MAX_LG2) ; Max mangled filename size
-NULLFILE equ 0 ; First char space == null filename
-NULLOFFSET equ 0 ; Position in which to look
-retry_count equ 16 ; How patient are we with the disk?
-%assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top
-LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with
-MAX_OPEN_LG2 equ 6 ; log2(Max number of open files)
-MAX_OPEN equ (1 << MAX_OPEN_LG2)
-
-SECTOR_SHIFT equ 9
-SECTOR_SIZE equ (1 << SECTOR_SHIFT)
-
-DIRENT_SHIFT equ 5
-DIRENT_SIZE equ (1 << DIRENT_SHIFT)
-
-ROOT_DIR_WORD equ 0x002F
-
-;
-; The following structure is used for "virtual kernels"; i.e. LILO-style
-; option labels. The options we permit here are `kernel' and `append
-; Since there is no room in the bottom 64K for all of these, we
-; stick them in high memory and copy them down before we need them.
-;
- struc vkernel
-vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!**
-vk_rname: resb FILENAME_MAX ; Real name
-vk_appendlen: resw 1
-vk_type: resb 1 ; Type of file
- alignb 4
-vk_append: resb max_cmd_len+1 ; Command line
- alignb 4
-vk_end: equ $ ; Should be <= vk_size
- endstruc
-
-;
-; File structure. This holds the information for each currently open file.
-;
- struc open_file_t
-file_sector resd 1 ; Sector pointer (0 = structure free)
-file_bytesleft resd 1 ; Number of bytes left
-file_left resd 1 ; Number of sectors left
- resd 1 ; Unused
- endstruc
-
-;
-; Structure for codepage files
-;
- struc cp
-.magic resd 2 ; 8-byte magic number
-.reserved resd 6 ; Reserved for future use
-.uppercase resb 256 ; Internal upper-case table
-.unicode resw 256 ; Unicode matching table
-.unicode_alt resw 256 ; Alternate Unicode matching table
- endstruc
-
-%ifndef DEPEND
-%if (open_file_t_size & (open_file_t_size-1))
-%error "open_file_t is not a power of 2"
-%endif
-%endif
-
-; ---------------------------------------------------------------------------
-; BEGIN CODE
-; ---------------------------------------------------------------------------
-
-;
-; Memory below this point is reserved for the BIOS and the MBR
-;
- section .earlybss
-trackbufsize equ 8192
-trackbuf resb trackbufsize ; Track buffer goes here
- ; ends at 2800h
-
- section .bss
- alignb 4
-FAT resd 1 ; Location of (first) FAT
-RootDirArea resd 1 ; Location of root directory area
-RootDir resd 1 ; Location of root directory proper
-DataArea resd 1 ; Location of data area
-RootDirSize resd 1 ; Root dir size in sectors
-TotalSectors resd 1 ; Total number of sectors
-ClustSize resd 1 ; Bytes/cluster
-ClustMask resd 1 ; Sectors/cluster - 1
-Clusters resd 1 ; Total number of clusters
-CopySuper resb 1 ; Distinguish .bs versus .bss
-DriveNumber resb 1 ; BIOS drive number
-ClustShift resb 1 ; Shift count for sectors/cluster
-ClustByteShift resb 1 ; Shift count for bytes/cluster
-
- alignb open_file_t_size
-Files resb MAX_OPEN*open_file_t_size
-
-;
-; Common bootstrap code for disk-based derivatives
-;
-%include "diskstart.inc"
-
-;
-; Compute some information about this filesystem.
-;
-
-; First, generate the map of regions
-genfatinfo:
- mov edx,[bxSectors]
- and dx,dx
- jnz .have_secs
- mov edx,[bsHugeSectors]
-.have_secs:
- mov [TotalSectors],edx
-
- mov eax,[bxResSectors]
- mov [FAT],eax ; Beginning of FAT
- mov edx,[bxFATsecs]
- and dx,dx
- jnz .have_fatsecs
- mov edx,[bootsec+36] ; FAT32 BPB_FATsz32
-.have_fatsecs:
- imul edx,[bxFATs]
- add eax,edx
- mov [RootDirArea],eax ; Beginning of root directory
- mov [RootDir],eax ; For FAT12/16 == root dir location
-
- mov edx,[bxRootDirEnts]
- add dx,SECTOR_SIZE/32-1
- shr dx,SECTOR_SHIFT-5
- mov [RootDirSize],edx
- add eax,edx
- mov [DataArea],eax ; Beginning of data area
-
-; Next, generate a cluster size shift count and mask
- mov eax,[bxSecPerClust]
- bsr cx,ax
- mov [ClustShift],cl
- push cx
- add cl,SECTOR_SHIFT
- mov [ClustByteShift],cl
- pop cx
- dec ax
- mov [ClustMask],eax
- inc ax
- shl eax,SECTOR_SHIFT
- mov [ClustSize],eax
-
-;
-; FAT12, FAT16 or FAT28^H^H32? This computation is fscking ridiculous.
-;
-getfattype:
- mov eax,[TotalSectors]
- sub eax,[DataArea]
- shr eax,cl ; cl == ClustShift
- mov cl,nextcluster_fat12-(nextcluster+2)
- cmp eax,0xFF4 ; FAT12 limit
- jbe .setsize
- mov cl,nextcluster_fat16-(nextcluster+2)
- cmp eax,0xFFF4 ; FAT16 limit
- jbe .setsize
- ;
- ; FAT32, root directory is a cluster chain
- ;
- mov ecx,0x0FFFFFF4 ; Max possible cluster count
- cmp eax,ecx
- jb .oksize
- mov eax,ecx
-.oksize:
-
- mov cl,[ClustShift]
- mov edx,[bootsec+44] ; Root directory cluster
- sub edx,2
- shl edx,cl
- add edx,[DataArea]
- mov [RootDir],edx
- mov cl,nextcluster_fat28-(nextcluster+2)
- mov byte [SuperSize],superblock_len_fat32
-.setsize:
- mov byte [nextcluster+1],cl
- mov [Clusters],eax ; Total clusters
-
-;
-; Common initialization code
-;
-%include "cpuinit.inc"
-%include "init.inc"
-
-;
-; Initialize the metadata cache
-;
- call initcache
-
-;
-; Now, everything is "up and running"... patch kaboom for more
-; verbosity and using the full screen system
-;
- ; E9 = JMP NEAR
- mov dword [kaboom.patch],0e9h+((kaboom2-(kaboom.patch+3)) << 8)
-
-;
-; Now we're all set to start with our *real* business. First load the
-; configuration file (if any) and parse it.
-;
-; In previous versions I avoided using 32-bit registers because of a
-; rumour some BIOSes clobbered the upper half of 32-bit registers at
-; random. I figure, though, that if there are any of those still left
-; they probably won't be trying to install Linux on them...
-;
-; The code is still ripe with 16-bitisms, though. Not worth the hassle
-; to take'm out. In fact, we may want to put them back if we're going
-; to boot ELKS at some point.
-;
-
-;
-; Load configuration file
-;
- mov si,config_name ; Save configuration file name
- mov di,ConfigName
- call strcpy
- mov word [CurrentDirName],ROOT_DIR_WORD ; Write '/',0 to the CurrentDirName
-
- mov eax,[RootDir] ; Make the root directory ...
- mov [CurrentDir],eax ; ... the current directory
- mov di,syslinux_cfg1
- push di
- call open
- pop di
- jnz .config_open
- mov di,syslinux_cfg2
- push di
- call open
- pop di
- jnz .config_open
- mov di,syslinux_cfg3
- push di
- call open
- pop di
- jz no_config_file
-.config_open:
- push si
- mov si,di
- push si
- mov di,CurrentDirName
- ; This is inefficient as it will copy more than needed
- ; but not by too much
- call strcpy
- mov ax,config_name ;Cut it down
- pop si
- sub ax,si
- mov di,CurrentDirName
- add di,ax
- mov byte [di],0
- pop si
- mov eax,[PrevDir] ; Make the directory with syslinux.cfg ...
- mov [CurrentDir],eax ; ... the current directory
-
-;
-; Now we have the config file open. Parse the config file and
-; run the user interface.
-;
-%include "ui.inc"
-
-;
-; allocate_file: Allocate a file structure
-;
-; If successful:
-; ZF set
-; BX = file pointer
-; In unsuccessful:
-; ZF clear
-;
-allocate_file:
- TRACER 'a'
- push cx
- mov bx,Files
- mov cx,MAX_OPEN
-.check: cmp dword [bx], byte 0
- je .found
- add bx,open_file_t_size ; ZF = 0
- loop .check
- ; ZF = 0 if we fell out of the loop
-.found: pop cx
- ret
-
-;
-; alloc_fill_dir:
-; Allocate then fill a file structure for a directory starting in
-; sector EAX.
-;
-; Assumes DS == ES == CS.
-;
-; If successful:
-; ZF clear
-; SI = file pointer
-; If unsuccessful
-; ZF set
-; EAX clobbered
-;
-alloc_fill_dir:
- push bx
- call allocate_file
- jnz .alloc_failure
-.found:
- mov si,bx
- mov [si+file_sector],eax ; Current sector
- mov dword [si+file_bytesleft],0 ; Current offset
- mov [si+file_left],eax ; Beginning sector
- pop bx
- ret
-
-.alloc_failure:
- pop bx
- xor eax,eax ; ZF <- 1
- ret
-
-;
-; search_dos_dir:
-; Search a specific directory for a pre-mangled filename in
-; MangledBuf, in the directory starting in sector EAX.
-;
-; NOTE: This file considers finding a zero-length file an
-; error. This is so we don't have to deal with that special
-; case elsewhere in the program (most loops have the test
-; at the end).
-;
-; Assumes DS == ES == CS.
-;
-; If successful:
-; ZF clear
-; SI = file pointer
-; EAX = file length (MAY BE ZERO!)
-; DL = file attribute
-; DH = clobbered
-; If unsuccessful
-; ZF set
-; EAX, SI, DX clobbered
-;
-
-search_dos_dir:
- push bx
- call allocate_file
- jnz .alloc_failure
-
- push cx
- push gs
- push es
- push ds
- pop es ; ES = DS
-
- ; Compute the value of a possible VFAT longname
- ; "last" entry (which, of course, comes first...)
- push ax
- push dx
- mov ax,[NameLen]
- add ax,12
- xor dx,dx
- mov cx,13
- div cx
- or al,40h
- mov [VFATInit],al
- mov [VFATNext],al
- pop dx
- pop ax
-
-.scansector:
- ; EAX <- directory sector to scan
- call getcachesector
- ; GS:SI now points to this sector
-
- mov cx,SECTOR_SIZE/32 ; 32 == directory entry size
-.scanentry:
- cmp byte [gs:si],0
- jz .failure ; Hit directory high water mark
- cmp word [gs:si+11],0Fh ; Long filename
- jne .short_entry
-
- ; Process a VFAT long entry
- pusha
- mov al,[gs:si]
- cmp al,[VFATNext]
- jne .not_us
- mov bl,[gs:si+13]
- test al,40h
- jz .match_csum
- ; Get the initial checksum value
- mov [VFATCsum],bl
- jmp .done_csum
-.match_csum:
- cmp bl,[VFATCsum]
- jne .not_us ; Checksum mismatch
-.done_csum:
- and ax,03fh
- jz .not_us ; Can't be zero...
- dec ax
- mov [VFATNext],al ; Optimistically...
- mov bx,ax
- shl bx,2 ; *4
- add ax,bx ; *5
- add bx,bx ; *8
- add bx,ax ; *13
- cmp bx,[NameLen]
- jae .not_us
- mov di,[NameStart]
- inc si
- mov cx,13
-.vfat_cmp:
- gs lodsw
- push bx
- cmp bx,[NameLen]
- jae .vfat_tail
- movzx bx,byte [bx+di]
- add bx,bx
- cmp ax,[cp_unicode+bx] ; Primary case
- je .ucs_ok
- cmp ax,[cp_unicode_alt+bx] ; Alternate case
- je .ucs_ok
- ; Mismatch...
- jmp .not_us_pop
-.vfat_tail:
- ; *AT* the end we should have 0x0000, *AFTER* the end
- ; we should have 0xFFFF...
- je .vfat_end
- inc ax ; 0xFFFF -> 0x0000
-.vfat_end:
- and ax,ax
- jnz .not_us_pop
-.ucs_ok:
- pop bx
- inc bx
- cmp cx,3
- je .vfat_adj_add2
- cmp cx,9
- jne .vfat_adj_add0
-.vfat_adj_add3: inc si
-.vfat_adj_add2: inc si
-.vfat_adj_add1: inc si
-.vfat_adj_add0:
- loop .vfat_cmp
- ; Okay, if we got here we had a match on this particular
- ; entry... live to see another one.
- popa
- jmp .next_entry
-
-.not_us_pop:
- pop bx
-.not_us:
- popa
- jmp .nomatch
-
-.short_entry:
- test byte [gs:si+11],8 ; Ignore volume labels
- jnz .nomatch
-
- cmp byte [VFATNext],0 ; Do we have a longname match?
- jne .no_long_match
-
- ; We already have a VFAT longname match, however,
- ; the match is only valid if the checksum matches
- push cx
- push si
- push ax
- xor ax,ax
- mov cx,11
-.csum_loop:
- gs lodsb
- ror ah,1
- add ah,al
- loop .csum_loop
- cmp ah,[VFATCsum]
- pop ax
- pop si
- pop cx
- je .found ; Got a match on longname
-
-.no_long_match: ; Look for a shortname match
- push cx
- push si
- push di
- mov di,MangledBuf
- mov cx,11
- gs repe cmpsb
- pop di
- pop si
- pop cx
- je .found
-.nomatch:
- ; Reset the VFAT matching state machine
- mov dh,[VFATInit]
- mov [VFATNext],dh
-.next_entry:
- add si,32
- dec cx
- jnz .scanentry
-
- call nextsector
- jnc .scansector ; CF is set if we're at end
-
- ; If we get here, we failed
-.failure:
- pop es
- pop gs
- pop cx
-.alloc_failure:
- pop bx
- xor eax,eax ; ZF <- 1
- ret
-.found:
- mov eax,[gs:si+28] ; File size
- add eax,SECTOR_SIZE-1
- shr eax,SECTOR_SHIFT
- mov [bx+4],eax ; Sector count
-
- mov cl,[ClustShift]
- mov dx,[gs:si+20] ; High cluster word
- shl edx,16
- mov dx,[gs:si+26] ; Low cluster word
- sub edx,2
- shl edx,cl
- add edx,[DataArea]
- mov [bx],edx ; Starting sector
-
- mov eax,[gs:si+28] ; File length again
- mov dl,[gs:si+11] ; File attribute
- mov si,bx ; File pointer...
- and si,si ; ZF <- 0
-
- pop es
- pop gs
- pop cx
- pop bx
- ret
-
- section .data
+ section .rodata
alignz 4
- ; Note: we have no use of the first 32 bytes (header),
- ; nor of the folloing 32 bytes (case mapping of control
- ; characters), as long as we adjust the offsets appropriately.
-codepage equ $-(32+32)
-codepage_data: incbin "codepage.cp",32+32
-cp_uppercase equ codepage+cp.uppercase
-cp_unicode equ codepage+cp.unicode
-cp_unicode_alt equ codepage+cp.unicode_alt
-codepage_end equ $
-
- section .text
-;
-; Input: UCS-2 character in AX
-; Output: Single byte character in AL, ZF = 1
-; On failure, returns ZF = 0
-;
-ucs2_to_cp:
- push es
- push di
- push cx
- push cs
- pop es
- mov di,cp_unicode
- mov cx,512
- repne scasw
- xchg ax,cx
- pop cx
- pop di
- pop es
- not ax ; Doesn't change the flags!
- ret
+ROOT_FS_OPS:
+ extern vfat_fs_ops
+ dd vfat_fs_ops
+ dd 0
- section .bss
-VFATInit resb 1
-VFATNext resb 1
-VFATCsum resb 1
-
- section .text
-;
-; close_file:
-; Deallocates a file structure (pointer in SI)
-; Assumes CS == DS.
-;
-close_file:
- and si,si
- jz .closed
- mov dword [si],0 ; First dword == file_sector
- xor si,si
-.closed: ret
-
-;
-; close_dir:
-; Deallocates a directory structure (pointer in SI)
-; Assumes CS == DS.
-;
-close_dir:
- and si,si
- jz .closed
- mov dword [si],0 ; First dword == file_sector
- xor si,si
-.closed: ret
-
-;
-; searchdir:
-;
-; Open a file
-;
-; On entry:
-; DS:DI = filename
-; If successful:
-; ZF clear
-; SI = file pointer
-; EAX = file length in bytes
-; If unsuccessful
-; ZF set
-;
-; Assumes CS == DS == ES, and trashes BX and CX.
-;
-searchdir:
- mov eax,[CurrentDir]
- cmp byte [di],'/' ; Root directory?
- jne .notroot
- mov eax,[RootDir]
- inc di
-.notroot:
-
-.pathwalk:
- push eax ; <A> Current directory sector
- mov si,di
-.findend:
- lodsb
- cmp al,' '
- jbe .endpath
- cmp al,'/'
- jne .findend
-.endpath:
- xchg si,di ; GRC: si begin; di end[ /]+1
- pop eax ; <A> Current directory sector
-
- ; GRC Here I need to check if di-1 = si which signifies
- ; we have the desired directory in EAX
- ; What about where the file name = "."; later
- mov dx,di
- dec dx
- cmp dx,si
- jz .founddir
-
- mov [PrevDir],eax ; Remember last directory searched
-
- push di
- call mangle_dos_name ; MangledBuf <- component
- call search_dos_dir
- pop di
- jz .notfound ; Pathname component missing
-
- cmp byte [di-1],'/' ; Do we expect a directory
- je .isdir
-
- ; Otherwise, it should be a file
-.isfile:
- test dl,18h ; Subdirectory|Volume Label
- jnz .badfile ; If not a file, it's a bad thing
-
- ; SI and EAX are already set
- mov [si+file_bytesleft],eax
- push eax
- add eax,SECTOR_SIZE-1
- shr eax,SECTOR_SHIFT
- mov [si+file_left],eax ; Sectors left
- pop eax
- and eax,eax ; EAX != 0
- jz .badfile
- ret ; Done!
-
- ; If we expected a directory, it better be one...
-.isdir:
- test dl,10h ; Subdirectory
- jz .badfile
-
- xor eax,eax
- xchg eax,[si+file_sector] ; Get sector number and free file structure
- jmp .pathwalk ; Walk the next bit of the path
-
- ; Found the desired directory; ZF set but EAX not 0
-.founddir:
- ret
-
-.badfile:
- xor eax,eax
- mov [si],eax ; Free file structure
-
-.notfound:
- xor eax,eax ; Zero out EAX
- ret
-
-;
-; readdir: Read one file from a directory
-;
-; ES:DI -> String buffer (filename)
-; DS:SI -> Pointer to open_file_t
-; DS Must be the SYSLINUX Data Segment
-;
-; Returns the file's name in the filename string buffer
-; EAX returns the file size
-; EBX returns the beginning sector (currently without offsetting)
-; DL returns the file type
-; The directory handle's data is incremented to reflect a name read.
-;
-readdir:
- push ecx
- push bp ; Using bp to transfer between segment registers
- push si
- push es
- push fs ; Using fs to store the current es (from COMBOOT)
- push gs
- mov bp,es
- mov fs,bp
- cmp si,0
- jz .fail
-.load_handle:
- mov eax,[ds:si+file_sector] ; Current sector
- mov ebx,[ds:si+file_bytesleft] ; Current offset
- cmp eax,0
- jz .fail
-.fetch_cache:
- call getcachesector
-.move_current:
- add si,bx ; Resume last position in sector
- mov ecx,SECTOR_SIZE ; 0 out high part
- sub cx,bx
- shr cx,5 ; Number of entries left
-.scanentry:
- cmp byte [gs:si],0
- jz .fail
- cmp word [gs:si+11],0Fh ; Long filename
- jne .short_entry
-
-.vfat_entry:
- push eax
- push ecx
- push si
- push di
-.vfat_ln_info: ; Get info about the line that we're on
- mov al,[gs:si]
- test al,40h
- jz .vfat_tail_ln
- and al,03Fh
- mov ah,1 ; On beginning line
- jmp .vfat_ck_ln
-
-.vfat_tail_ln: ; VFAT tail line processing (later in VFAT, head in name)
- test al,80h ; Invalid data?
- jnz .vfat_abort
- mov ah,0 ; Not on beginning line
- cmp dl,al
- jne .vfat_abort ; Is this the entry we need?
- mov bl,[gs:si+13]
- cmp bl,[VFATCsum]
- je .vfat_cp_ln
- jmp .vfat_abort
-
-.vfat_ck_ln: ; Load this line's VFAT CheckSum
- mov bl,[gs:si+13]
- mov [VFATCsum],bl
-.vfat_cp_ln: ; Copy VFAT line
- dec al ; Store the next line we need
- mov dx,ax ; Use DX to store the progress
- mov cx,13 ; 13 characters per VFAT DIRENT
- cbw ; AH <- 0
- mul cl ; Offset for DI
- add di,ax ; Increment DI
- inc si ; Align to the real characters
-.vfat_cp_chr:
- gs lodsw ; Unicode here!!
- call ucs2_to_cp ; Convert to local codepage
- jnz .vfat_abort ; Use short name if character not on codepage
- stosb ; CAN NOT OVERRIDE es
- cmp al,0
- jz .vfat_find_next ; Null-terminated string; don't process more
- cmp cx,3
- je .vfat_adj_add2
- cmp cx,9
- jne .vfat_adj_add0
-.vfat_adj_add3: inc si
-.vfat_adj_add2: inc si
-.vfat_adj_add1: inc si
-.vfat_adj_add0:
- loop .vfat_cp_chr
- cmp dh,1 ; Is this the first round?
- jnz .vfat_find_next
-.vfat_null_term: ; Need to null-terminate if first line as we rolled over the end
- mov al,0
- stosb
-
-.vfat_find_next: ;Find the next part of the name
- pop di
- pop si
- pop ecx
- pop eax
- cmp dl,0
- jz .vfat_find_info ; We're done with the name
- add si,DIRENT_SIZE
- dec cx
- jnz .vfat_entry
- call nextsector
- jnc .vfat_entry ; CF is set if we're at end
- jmp .fail
-.vfat_find_info: ; Fetch next entry for the size/"INode"
- add si,DIRENT_SIZE
- dec cx
- jnz .get_info
- call nextsector
- jnc .get_info ; CF is set if we're at end
- jmp .fail
-.vfat_abort: ; Something went wrong, skip
- pop di
- pop si
- pop ecx
- pop eax
- jmp .skip_entry
-
-.short_entry:
- test byte [gs:si+11],8 ; Ignore volume labels //HERE
- jnz .skip_entry
- mov edx,eax ;Save current sector
- push cx
- push si
- push di
- mov cx,8
-.short_file:
- gs lodsb
- cmp al,'.'
- jz .short_dot
-.short_file_loop:
- cmp al,' '
- jz .short_skip_bs
- stosb
- loop .short_file_loop
- jmp .short_period
-.short_skip_bs: ; skip blank spaces in FILENAME (before EXT)
- add si,cx
- dec si
-.short_period:
- mov al,'.'
- stosb
- mov cx,3
-.short_ext:
- gs lodsb
- cmp al,' '
- jz .short_done
- stosb
- loop .short_ext
- jmp .short_done
-.short_dot:
- stosb
- gs lodsb
- cmp al,' '
- jz .short_done
- stosb
-.short_done:
- mov al,0 ; Null-terminate the short strings
- stosb
- pop di
- pop si
- pop cx
- mov eax,edx
-.get_info:
- mov ebx,[gs:si+28] ; length
- mov dl,[gs:si+11] ; type
-.next_entry:
- add si,DIRENT_SIZE
- dec cx
- jnz .store_offset
- call nextsector
- jnc .store_sect ; CF is set if we're at end
- jmp .fail
-
-.skip_entry:
- add si,DIRENT_SIZE
- dec cx
- jnz .scanentry
- call nextsector
- jnc .scanentry ; CF is set if we're at end
- jmp .fail
-
-.store_sect:
- pop gs
- pop fs
- pop es
- pop si
- mov [ds:si+file_sector],eax
- mov eax,0 ; Now at beginning of new sector
- jmp .success
-
-.store_offset:
- pop gs
- pop fs
- pop es
- pop si ; cx=num remain; SECTOR_SIZE-(cx*32)=cur pos
- shl ecx,DIRENT_SHIFT
- mov eax,SECTOR_SIZE
- sub eax,ecx
- and eax,0ffffh
-
-.success:
- mov [ds:si+file_bytesleft],eax
- ; "INode" number = ((CurSector-RootSector)*SECTOR_SIZE + Offset)/DIRENT_SIZE)
- mov ecx,eax
- mov eax,[ds:si+file_sector]
- sub eax,[RootDir]
- shl eax,SECTOR_SHIFT
- add eax,ecx
- shr eax,DIRENT_SHIFT
- dec eax
- xchg eax,ebx ; -> EBX=INode, EAX=FileSize
- jmp .done
-
-.fail:
- pop gs
- pop fs
- pop es
- pop si
- call close_dir
- xor eax,eax
- stc
-.done:
- pop bp
- pop ecx
-.end:
- ret
-
- section .bss
- alignb 4
-CurrentDir resd 1 ; Current directory
-PrevDir resd 1 ; Last scanned directory
-
- section .text
-
-;
-;
-; kaboom2: once everything is loaded, replace the part of kaboom
-; starting with "kaboom.patch" with this part
-
-kaboom2:
- mov si,err_bootfailed
- call writestr
- cmp byte [kaboom.again+1],18h ; INT 18h version?
- je .int18
- call getchar
- call vgaclearmode
- int 19h ; And try once more to boot...
-.norge: jmp short .norge ; If int 19h returned; this is the end
-.int18:
- call vgaclearmode
- int 18h
-.noreg: jmp short .noreg ; Nynorsk
-
-;
-; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
-; to by ES:DI; ends on encountering any whitespace.
-; DI is preserved.
-;
-; This verifies that a filename is < FILENAME_MAX characters,
-; doesn't contain whitespace, zero-pads the output buffer,
-; and removes trailing dots and redundant slashes, plus changes
-; backslashes to forward slashes,
-; so "repe cmpsb" can do a compare, and the path-searching routine
-; gets a bit of an easier job.
-;
-;
-mangle_name:
- push di
- push bx
- xor ax,ax
- mov cx,FILENAME_MAX-1
- mov bx,di
-
-.mn_loop:
- lodsb
- cmp al,' ' ; If control or space, end
- jna .mn_end
- cmp al,'\' ; Backslash?
- jne .mn_not_bs
- mov al,'/' ; Change to forward slash
-.mn_not_bs:
- cmp al,ah ; Repeated slash?
- je .mn_skip
- xor ah,ah
- cmp al,'/'
- jne .mn_ok
- mov ah,al
-.mn_ok stosb
-.mn_skip: loop .mn_loop
-.mn_end:
- cmp bx,di ; At the beginning of the buffer?
- jbe .mn_zero
- cmp byte [es:di-1],'.' ; Terminal dot?
- je .mn_kill
- cmp byte [es:di-1],'/' ; Terminal slash?
- jne .mn_zero
-.mn_kill: dec di ; If so, remove it
- inc cx
- jmp short .mn_end
-.mn_zero:
- inc cx ; At least one null byte
- xor ax,ax ; Zero-fill name
- rep stosb
- pop bx
- pop di
- ret ; Done
-
-;
-; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
-; filename to the conventional representation. This is needed
-; for the BOOT_IMAGE= parameter for the kernel.
-; NOTE: A 13-byte buffer is mandatory, even if the string is
-; known to be shorter.
-;
-; DS:SI -> input mangled file name
-; ES:DI -> output buffer
-;
-; On return, DI points to the first byte after the output name,
-; which is set to a null byte.
-;
-unmangle_name: call strcpy
- dec di ; Point to final null byte
- ret
-
-;
-; mangle_dos_name:
-; Mangle a DOS filename component pointed to by DS:SI
-; into [MangledBuf]; ends on encountering any whitespace or
-; slash.
-;
-; WARNING: saves pointers into the buffer for longname
-; matches!
-;
-; Assumes CS == DS == ES.
-;
-
-mangle_dos_name:
- pusha
- mov di,MangledBuf
- mov [NameStart],si
-
- mov cx,11 ; # of bytes to write
- mov bx,cp_uppercase ; Case-conversion table
-.loop:
- lodsb
- cmp al,' ' ; If control or space, end
- jna .end
- cmp al,'/' ; Slash, too
- je .end
- cmp al,'.' ; Period -> space-fill
- je .is_period
- xlatb ; Convert to upper case
- mov ah,cl ; If the first byte (only!)...
- cmp ax,0BE5h ; ... equals E5 hex ...
- jne .charok
- mov al,05h ; ... change it to 05 hex
-.charok: stosb
- loop .loop ; Don't continue if too long
- ; Find the end for the benefit of longname search
-.find_end:
- lodsb
- cmp al,' '
- jna .end
- cmp al,'/'
- jne .find_end
-.end:
- dec si
- sub si,[NameStart]
- mov [NameLen],si
- mov al,' ' ; Space-fill name
- rep stosb ; Doesn't do anything if CX=0
- popa
- ret ; Done
-
-.is_period:
- mov al,' ' ; We need to space-fill
-.period_loop: cmp cx,3 ; If <= 3 characters left
- jbe .loop ; Just ignore it
- stosb ; Otherwise, write a space
- loop .period_loop ; Dec CX and *always* jump
-
- section .bss
- alignb 2
-NameStart resw 1
-NameLen resw 1
-MangledBuf resb 11
-
- section .text
-;
-; getfssec_edx: Get multiple sectors from a file
-;
-; This routine makes sure the subtransfers do not cross a 64K boundary,
-; and will correct the situation if it does, UNLESS *sectors* cross
-; 64K boundaries.
-;
-; ES:BX -> Buffer
-; EDX -> Current sector number
-; CX -> Sector count (0FFFFh = until end of file)
-; Must not exceed the ES segment
-; Returns EDX=0, CF=1 on EOF (not necessarily error)
-; All arguments are advanced to reflect data read.
-;
-getfssec_edx:
- push ebp
- push eax
-.getfragment:
- xor ebp,ebp ; Fragment sector count
- push edx ; Starting sector pointer
-.getseccnt:
- inc bp
- dec cx
- jz .do_read
- xor eax,eax
- mov ax,es
- shl ax,4
- add ax,bx ; Now AX = how far into 64K block we are
- not ax ; Bytes left in 64K block
- inc eax
- shr eax,SECTOR_SHIFT ; Sectors left in 64K block
- cmp bp,ax
- jnb .do_read ; Unless there is at least 1 more sector room...
- mov eax,edx ; Current sector
- inc edx ; Predict it's the linearly next sector
- call nextsector
- jc .do_read
- cmp edx,eax ; Did it match?
- jz .getseccnt
-.do_read:
- pop eax ; Starting sector pointer
- call getlinsecsr
- lea eax,[eax+ebp-1] ; This is the last sector actually read
- shl bp,9
- add bx,bp ; Adjust buffer pointer
- call nextsector
- jc .eof
- mov edx,eax
- and cx,cx
- jnz .getfragment
-.done:
- pop eax
- pop ebp
- ret
-.eof:
- xor edx,edx
- stc
- jmp .done
-
-;
-; getfssec: Get multiple sectors from a file
-;
-; Same as above, except SI is a pointer to a open_file_t
-;
-; ES:BX -> Buffer
-; DS:SI -> Pointer to open_file_t
-; CX -> Sector count (0FFFFh = until end of file)
-; Must not exceed the ES segment
-; Returns CF=1 on EOF (not necessarily error)
-; ECX returns number of bytes read.
-; All arguments are advanced to reflect data read.
-;
-getfssec:
- push edx
- movzx edx,cx
- push edx ; Zero-extended CX
- cmp edx,[si+file_left]
- jbe .sizeok
- mov edx,[si+file_left]
- mov cx,dx
-.sizeok:
- sub [si+file_left],edx
- mov edx,[si+file_sector]
- call getfssec_edx
- mov [si+file_sector],edx
- pop ecx ; Sectors requested read
- shl ecx,SECTOR_SHIFT
- cmp ecx,[si+file_bytesleft]
- ja .eof
-.noteof:
- sub [si+file_bytesleft],ecx ; CF <- 0
- pop edx
- ret
-.eof:
- mov ecx,[si+file_bytesleft]
- call close_file
- pop edx
- stc
- ret
-
-;
-; nextcluster: Advance a cluster pointer in EDI to the next cluster
-; pointed at in the FAT tables. CF=0 on return if end of file.
-;
-nextcluster:
- jmp strict short nextcluster_fat28 ; This gets patched
-
-nextcluster_fat12:
- push eax
- push edx
- push bx
- push cx
- push si
- mov edx,edi
- shr edi,1
- pushf ; Save the shifted-out LSB (=CF)
- add edx,edi
- mov eax,edx
- shr eax,9
- call getfatsector
- mov bx,dx
- and bx,1FFh
- mov cl,[gs:si+bx]
- inc edx
- mov eax,edx
- shr eax,9
- call getfatsector
- mov bx,dx
- and bx,1FFh
- mov ch,[gs:si+bx]
- popf
- jnc .even
- shr cx,4
-.even: and cx,0FFFh
- movzx edi,cx
- lea ax,[di-2]
- cmp ax,[Clusters]
- pop si
- pop cx
- pop bx
- pop edx
- pop eax
- ret
-
-;
-; FAT16 decoding routine.
-;
-nextcluster_fat16:
- push eax
- push si
- push bx
- mov eax,edi
- shr eax,SECTOR_SHIFT-1
- call getfatsector
- mov bx,di
- add bx,bx
- and bx,1FEh
- movzx edi,word [gs:si+bx]
- lea ax,[di-2]
- cmp ax,[Clusters]
- pop bx
- pop si
- pop eax
- ret
-;
-; FAT28 ("FAT32") decoding routine.
-;
-nextcluster_fat28:
- push eax
- push si
- push bx
- mov eax,edi
- shr eax,SECTOR_SHIFT-2
- call getfatsector
- mov bx,di
- add bx,bx
- add bx,bx
- and bx,1FCh
- mov edi,dword [gs:si+bx]
- and edi,0FFFFFFFh ; 28 bits only
- lea eax,[edi-2]
- cmp eax,[Clusters]
- pop bx
- pop si
- pop eax
- ret
-
-;
-; nextsector: Given a sector in EAX on input, return the next sector
-; of the same filesystem object, which may be the root
-; directory or a cluster chain. Returns EOF.
-;
-; Assumes CS == DS.
-;
-nextsector:
- push edi
- push edx
- mov edx,[DataArea]
- mov edi,eax
- sub edi,edx
- jae .isdata
-
- ; Root directory
- inc eax
- cmp eax,edx
- cmc
- jmp .done
-
-.isdata:
- not edi
- test edi,[ClustMask]
- jz .endcluster
-
- ; It's not the final sector in a cluster
- inc eax
- jmp .done
-
-.endcluster:
- push gs ; nextcluster trashes gs
- push cx
- not edi
- mov cl,[ClustShift]
- shr edi,cl
- add edi,2
-
- ; Now EDI contains the cluster number
- call nextcluster
- cmc
- jc .exit ; There isn't anything else...
-
- ; New cluster number now in EDI
- sub edi,2
- shl edi,cl ; CF <- 0, unless something is very wrong
- lea eax,[edi+edx]
-.exit:
- pop cx
- pop gs
-.done:
- pop edx
- pop edi
- ret
-
-;
-; getfatsector: Check for a particular sector (in EAX) in the FAT cache,
-; and return a pointer in GS:SI, loading it if needed.
-;
-; Assumes CS == DS.
-;
-getfatsector:
- add eax,[FAT] ; FAT starting address
- jmp getcachesector
-
-; -----------------------------------------------------------------------------
-; Common modules
-; -----------------------------------------------------------------------------
-
-%include "getc.inc" ; getc et al
-%include "conio.inc" ; Console I/O
-%include "plaincon.inc" ; writechr
-%include "writestr.inc" ; String output
-%include "writehex.inc" ; Hexadecimal output
-%include "configinit.inc" ; Initialize configuration
-%include "parseconfig.inc" ; High-level config file handling
-%include "parsecmd.inc" ; Low-level config file handling
-%include "bcopy32.inc" ; 32-bit bcopy
-%include "loadhigh.inc" ; Load a file into high memory
-%include "font.inc" ; VGA font stuff
-%include "graphics.inc" ; VGA graphics
-%include "highmem.inc" ; High memory sizing
-%include "strcpy.inc" ; strcpy()
-%include "cache.inc" ; Metadata disk cache
-%include "idle.inc" ; Idle handling
-%include "adv.inc" ; Auxillary Data Vector
-%include "localboot.inc" ; Disk-based local boot
-
-; -----------------------------------------------------------------------------
-; Begin data section
-; -----------------------------------------------------------------------------
-
- section .data
-copyright_str db ' Copyright (C) 1994-'
- asciidec YEAR
- db ' H. Peter Anvin et al', CR, LF, 0
-err_bootfailed db CR, LF, 'Boot failed: please change disks and press '
- db 'a key to continue.', CR, LF, 0
-syslinux_cfg1 db '/boot' ; /boot/syslinux/syslinux.cfg
-syslinux_cfg2 db '/syslinux' ; /syslinux/syslinux.cfg
-syslinux_cfg3 db '/' ; /syslinux.cfg
-config_name db 'syslinux.cfg', 0 ; syslinux.cfg
-
-;
-; Config file keyword table
-;
-%include "keywords.inc"
-
-;
-; Extensions to search for (in *forward* order).
-;
-exten_table: db '.cbt' ; COMBOOT (specific)
- db '.bss' ; Boot Sector (add superblock)
- db '.bs', 0 ; Boot Sector
- db '.com' ; COMBOOT (same as DOS)
- db '.c32' ; COM32
-exten_table_end:
- dd 0, 0 ; Need 8 null bytes here
-
-;
-; Misc initialized (data) variables
-;
-%ifdef debug ; This code for debugging only
-debug_magic dw 0D00Dh ; Debug code sentinel
-%endif
-
- alignz 4
-BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf
-BufSafeBytes dw trackbufsize ; = how many bytes?
-%ifndef DEPEND
-%if ( trackbufsize % SECTOR_SIZE ) != 0
-%error trackbufsize must be a multiple of SECTOR_SIZE
-%endif
-%endif
+%include "diskfs.inc"
diff --git a/core/loadhigh.inc b/core/loadhigh.inc
index 8ff9da1c..63ab0010 100644
--- a/core/loadhigh.inc
+++ b/core/loadhigh.inc
@@ -17,7 +17,7 @@
;; Load a file into high memory
;;
- section .text
+ section .text16
;
; load_high: loads (the remainder of) a file into high memory.
@@ -69,7 +69,7 @@ load_high:
push edi ; <C> Target buffer
mov cx,ax
xor bx,bx ; ES:0
- call getfssec ; Load the data into xfer_buf_seg
+ pm_call getfssec ; Load the data into xfer_buf_seg
pop edi ; <C> Target buffer
pushf ; <C> EOF status
lea ebx,[edi+ecx] ; End of data
@@ -103,12 +103,12 @@ load_high:
.overflow: mov si,err_nohighmem
jmp abort_load
- section .data
+ section .data16
err_nohighmem db CR, LF
db 'Not enough memory to load specified image.', CR, LF, 0
- section .bss
+ section .bss16
alignb 2
PauseBird resw 1
- section .text
+ section .text16
diff --git a/core/localboot.inc b/core/localboot.inc
index 03d5cfd9..a66cf206 100644
--- a/core/localboot.inc
+++ b/core/localboot.inc
@@ -22,7 +22,7 @@
; Boot a specified local disk. AX specifies the BIOS disk number; or
; -1 in case we should execute INT 18h ("next device.")
;
- section .text
+ section .text16
local_boot:
call vgaclearmode
@@ -68,9 +68,9 @@ local_boot:
int 18h ; Hope this does the right thing...
jmp kaboom ; If we returned, oh boy...
- section .data
+ section .data16
localboot_msg db 'Booting from local disk...', CR, LF, 0
- section .text
+ section .text16
%endif ; HAS_LOCALBOOT
diff --git a/core/lzo/enter.ash b/core/lzo/enter.ash
new file mode 100644
index 00000000..49c455d6
--- /dev/null
+++ b/core/lzo/enter.ash
@@ -0,0 +1,89 @@
+/* enter.ash -- LZO assembler stuff
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ subl $12,%esp
+
+ cld
+
+ movl INP,%esi
+ movl OUTP,%edi
+#if defined(N_3_EBP)
+ movl $3,%ebp
+#endif
+#if defined(N_255_EBP)
+ movl $255,%ebp
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT)
+#if defined(INIT_OVERRUN)
+ INIT_OVERRUN
+# undef INIT_OVERRUN
+#endif
+ leal -3(%esi),%eax /* 3 == length of EOF code */
+ addl INS,%eax
+ movl %eax,INEND
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+#if defined(INIT_OVERRUN)
+ INIT_OVERRUN
+# undef INIT_OVERRUN
+#endif
+ movl %edi,%eax
+ movl OUTS,%edx
+ addl (%edx),%eax
+ movl %eax,OUTEND
+#endif
+
+
+/*
+vi:ts=4
+*/
+
diff --git a/core/lzo/leave.ash b/core/lzo/leave.ash
new file mode 100644
index 00000000..9550b46f
--- /dev/null
+++ b/core/lzo/leave.ash
@@ -0,0 +1,114 @@
+/* leave.ash -- LZO assembler stuff
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* check uncompressed size */
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+ cmpl OUTEND,%edi
+ ja .L_output_overrun
+#endif
+
+/* check compressed size */
+ movl INP,%edx
+ addl INS,%edx
+ cmpl %edx,%esi /* check compressed size */
+ ja .L_input_overrun
+ jb .L_input_not_consumed
+
+.L_leave:
+ subl OUTP,%edi /* write back the uncompressed size */
+ movl OUTS,%edx
+ movl %edi,(%edx)
+
+ negl %eax
+ addl $12,%esp
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %esi
+ popl %edi
+ popl %ebp
+#if 1
+ ret
+#else
+ jmp .L_end
+#endif
+
+
+.L_error:
+ movl $1,%eax /* LZO_E_ERROR */
+ jmp .L_leave
+
+.L_input_not_consumed:
+ movl $8,%eax /* LZO_E_INPUT_NOT_CONSUMED */
+ jmp .L_leave
+
+.L_input_overrun:
+ movl $4,%eax /* LZO_E_INPUT_OVERRUN */
+ jmp .L_leave
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+.L_output_overrun:
+ movl $5,%eax /* LZO_E_OUTPUT_OVERRUN */
+ jmp .L_leave
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+.L_lookbehind_overrun:
+ movl $6,%eax /* LZO_E_LOOKBEHIND_OVERRUN */
+ jmp .L_leave
+#endif
+
+#if defined(LZO_DEBUG)
+.L_assert_fail:
+ movl $99,%eax
+ jmp .L_leave
+#endif
+
+.L_end:
+
+
+/*
+vi:ts=4
+*/
+
diff --git a/core/lzo/lzo1c_d.ash b/core/lzo/lzo1c_d.ash
new file mode 100644
index 00000000..9969c86a
--- /dev/null
+++ b/core/lzo/lzo1c_d.ash
@@ -0,0 +1,184 @@
+/* lzo1c_d.ash -- assembler implementation of the LZO1C decompression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+ ALIGN3
+.L1:
+ xorl %eax,%eax
+ movb (%esi),%al
+ incl %esi
+ cmpb $32,%al
+ jnb .LMATCH
+
+ orb %al,%al
+ jz .L12
+ movl %eax,%ecx
+.LIT:
+ TEST_OP((%edi,%ecx),%ebx)
+ TEST_IP((%esi,%ecx),%ebx)
+ rep
+ movsb
+.LM1:
+ movb (%esi),%al
+ incl %esi
+
+ cmpb $32,%al
+ jb .LM2
+.LMATCH:
+ cmpb $64,%al
+ jb .LN3
+
+ movl %eax,%ecx
+ andb $31,%al
+ leal -1(%edi),%edx
+ shrl $5,%ecx
+ subl %eax,%edx
+ movb (%esi),%al
+ incl %esi
+
+ shll $5,%eax
+ subl %eax,%edx
+ incl %ecx
+ xchgl %esi,%edx
+ TEST_LOOKBEHIND(%esi)
+ TEST_OP((%edi,%ecx),%ebx)
+ rep
+ movsb
+ movl %edx,%esi
+ jmp .L1
+
+ ALIGN3
+.L12:
+ LODSB
+ leal 32(%eax),%ecx
+ cmpb $248,%al
+ jb .LIT
+
+ movl $280,%ecx
+ subb $248,%al
+ jz .L11
+ xchgl %eax,%ecx
+ xorb %al,%al
+ shll %cl,%eax
+ xchgl %eax,%ecx
+.L11:
+ TEST_OP((%edi,%ecx),%ebx)
+ TEST_IP((%esi,%ecx),%ebx)
+ rep
+ movsb
+ jmp .L1
+
+ ALIGN3
+.LM2:
+ leal -1(%edi),%edx
+ subl %eax,%edx
+ LODSB
+ shll $5,%eax
+ subl %eax,%edx
+ xchgl %esi,%edx
+ TEST_LOOKBEHIND(%esi)
+ TEST_OP(4(%edi),%ebx)
+ movsb
+ movsb
+ movsb
+ movl %edx,%esi
+ movsb
+ xorl %eax,%eax
+ jmp .LM1
+.LN3:
+ andb $31,%al
+ movl %eax,%ecx
+ jnz .LN6
+ movb $31,%cl
+.LN4:
+ LODSB
+ orb %al,%al
+ jnz .LN5
+ addl N_255,%ecx
+ jmp .LN4
+
+ ALIGN3
+.LN5:
+ addl %eax,%ecx
+.LN6:
+ movb (%esi),%al
+ incl %esi
+
+ movl %eax,%ebx
+ andb $63,%al
+ movl %edi,%edx
+ subl %eax,%edx
+
+ movb (%esi),%al
+ incl %esi
+
+ shll $6,%eax
+ subl %eax,%edx
+ cmpl %edi,%edx
+ jz .LEOF
+
+ xchgl %edx,%esi
+ leal 3(%ecx),%ecx
+ TEST_LOOKBEHIND(%esi)
+ TEST_OP((%edi,%ecx),%eax)
+ rep
+ movsb
+
+ movl %edx,%esi
+ xorl %eax,%eax
+ shrl $6,%ebx
+ movl %ebx,%ecx
+ jnz .LIT
+ jmp .L1
+
+.LEOF:
+/**** xorl %eax,%eax eax=0 from above */
+
+ cmpl $1,%ecx /* ecx must be 1 */
+ setnz %al
+
+
+/*
+vi:ts=4
+*/
+
diff --git a/core/lzo/lzo1f_d.ash b/core/lzo/lzo1f_d.ash
new file mode 100644
index 00000000..aa9279e0
--- /dev/null
+++ b/core/lzo/lzo1f_d.ash
@@ -0,0 +1,176 @@
+/* lzo1f_d.ash -- assembler implementation of the LZO1F decompression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+ ALIGN3
+.L0:
+ xorl %eax,%eax
+ movb (%esi),%al
+ incl %esi
+ cmpb $31,%al
+ ja .LM2
+
+ orb %al,%al
+ movl %eax,%ecx
+ jnz .L2
+1:
+ LODSB
+ orb %al,%al
+ jnz 2f
+ addl N_255,%ecx
+ jmp 1b
+2:
+ lea 31(%eax,%ecx),%ecx
+.L2:
+ TEST_OP((%edi,%ecx),%ebx)
+ TEST_IP((%esi,%ecx),%ebx)
+ movb %cl,%al
+ shrl $2,%ecx
+ rep
+ movsl
+ andb $3,%al
+ jz 1f
+ movl (%esi),%ebx
+ addl %eax,%esi
+ movl %ebx,(%edi)
+ addl %eax,%edi
+1:
+ movb (%esi),%al
+ incl %esi
+.LM1:
+ cmpb $31,%al
+ jbe .LM21
+
+.LM2:
+ cmpb $223,%al
+ ja .LM3
+
+ movl %eax,%ecx
+ shrl $2,%eax
+ lea -1(%edi),%edx
+ andb $7,%al
+ shrl $5,%ecx
+ movl %eax,%ebx
+
+ movb (%esi),%al
+ leal (%ebx,%eax,8),%eax
+ incl %esi
+.LM5:
+ subl %eax,%edx
+ addl $2,%ecx
+ xchgl %edx,%esi
+ TEST_LOOKBEHIND(%esi)
+ TEST_OP((%edi,%ecx),%ebx)
+ cmpl $6,%ecx
+ jb 1f
+ cmpl $4,%eax
+ jb 1f
+ movb %cl,%al
+ shrl $2,%ecx
+ rep
+ movsl
+ andb $3,%al
+ movb %al,%cl
+1:
+ rep
+ movsb
+ movl %edx,%esi
+.LN1:
+ movb -2(%esi),%cl
+ andl $3,%ecx
+ jz .L0
+ movl (%esi),%eax
+ addl %ecx,%esi
+ movl %eax,(%edi)
+ addl %ecx,%edi
+ xorl %eax,%eax
+ movb (%esi),%al
+ incl %esi
+ jmp .LM1
+.LM21:
+ TEST_OP(3(%edi),%edx)
+ shrl $2,%eax
+ leal -0x801(%edi),%edx
+ movl %eax,%ecx
+ movb (%esi),%al
+ incl %esi
+ leal (%ecx,%eax,8),%eax
+ subl %eax,%edx
+ TEST_LOOKBEHIND(%edx)
+ movl (%edx),%eax
+ movl %eax,(%edi)
+ addl $3,%edi
+ jmp .LN1
+1:
+ LODSB
+ orb %al,%al
+ jnz 2f
+ addl N_255,%ecx
+ jmp 1b
+2:
+ lea 31(%eax,%ecx),%ecx
+ jmp .LM4
+
+ ALIGN3
+.LM3:
+ andb $31,%al
+ movl %eax,%ecx
+ jz 1b
+.LM4:
+ movl %edi,%edx
+ movw (%esi),%ax
+ addl $2,%esi
+ shrl $2,%eax
+ jnz .LM5
+
+.LEOF:
+/**** xorl %eax,%eax eax=0 from above */
+
+ cmpl $1,%ecx /* ecx must be 1 */
+ setnz %al
+
+
+/*
+vi:ts=4
+*/
+
diff --git a/core/lzo/lzo1x_d.ash b/core/lzo/lzo1x_d.ash
new file mode 100644
index 00000000..aa138354
--- /dev/null
+++ b/core/lzo/lzo1x_d.ash
@@ -0,0 +1,401 @@
+/* lzo1x_d.ash -- assembler implementation of the LZO1X decompression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#if !defined(LZO1X) && !defined(LZO1Y)
+# define LZO1X
+#endif
+
+#if defined(LZO_FAST)
+# define NN 3
+#else
+# define NN 0
+#endif
+
+
+/***********************************************************************
+// init
+************************************************************************/
+
+ xorl %eax,%eax
+ xorl %ebx,%ebx /* high bits 9-32 stay 0 */
+ lodsb
+ cmpb $17,%al
+ jbe .L01
+ subb $17-NN,%al
+#if defined(LZO_FAST)
+ jmp .LFLR
+#else
+ cmpb $4,%al
+ jae .LFLR
+#if 1
+ TEST_OP((%edi,%eax),%edx)
+ TEST_IP((%esi,%eax),%edx)
+ movl %eax,%ecx
+ jmp .LFLR2
+#else
+ jmp .LFLR3
+#endif
+#endif
+
+
+/***********************************************************************
+// literal run
+************************************************************************/
+
+0: addl N_255,%eax
+ TEST_IP(18(%esi,%eax),%edx) /* minimum */
+1: movb (%esi),%bl
+ incl %esi
+ orb %bl,%bl
+ jz 0b
+ leal 18+NN(%eax,%ebx),%eax
+ jmp 3f
+
+
+ ALIGN3
+.L00:
+#ifdef LZO_DEBUG
+ andl $0xffffff00,%eax ; jnz .L_assert_fail
+ andl $0xffffff00,%ebx ; jnz .L_assert_fail
+ xorl %eax,%eax ; xorl %ebx,%ebx
+ xorl %ecx,%ecx ; xorl %edx,%edx
+#endif
+ TEST_IP_R(%esi)
+ LODSB
+.L01:
+ cmpb $16,%al
+ jae .LMATCH
+
+/* a literal run */
+ orb %al,%al
+ jz 1b
+ addl $3+NN,%eax
+3:
+.LFLR:
+ TEST_OP(-NN(%edi,%eax),%edx)
+ TEST_IP(-NN(%esi,%eax),%edx)
+#if defined(LZO_FAST)
+ movl %eax,%ecx
+ NOTL_3(%eax)
+ shrl $2,%ecx
+ andl N_3,%eax
+ COPYL(%esi,%edi,%edx)
+ subl %eax,%esi
+ subl %eax,%edi
+#else
+ movl %eax,%ecx
+ shrl $2,%eax
+ andl N_3,%ecx
+ COPYL_C(%esi,%edi,%edx,%eax)
+.LFLR2:
+ rep
+ movsb
+#endif
+
+#ifdef LZO_DEBUG
+ andl $0xffffff00,%eax ; jnz .L_assert_fail
+ andl $0xffffff00,%ebx ; jnz .L_assert_fail
+ xorl %eax,%eax ; xorl %ebx,%ebx
+ xorl %ecx,%ecx ; xorl %edx,%edx
+#endif
+ LODSB
+ cmpb $16,%al
+ jae .LMATCH
+
+
+/***********************************************************************
+// R1
+************************************************************************/
+
+ TEST_OP(3(%edi),%edx)
+ shrl $2,%eax
+ movb (%esi),%bl
+#if defined(LZO1X)
+ leal -0x801(%edi),%edx
+#elif defined(LZO1Y)
+ leal -0x401(%edi),%edx
+#endif
+ leal (%eax,%ebx,4),%eax
+ incl %esi
+ subl %eax,%edx
+ TEST_LOOKBEHIND(%edx)
+#if defined(LZO_FAST)
+ movl (%edx),%ecx
+ movl %ecx,(%edi)
+#else
+ movb (%edx),%al
+ movb %al,(%edi)
+ movb 1(%edx),%al
+ movb %al,1(%edi)
+ movb 2(%edx),%al
+ movb %al,2(%edi)
+#endif
+ addl N_3,%edi
+ jmp .LMDONE
+
+
+/***********************************************************************
+// M2
+************************************************************************/
+
+ ALIGN3
+.LMATCH:
+ cmpb $64,%al
+ jb .LM3MATCH
+
+/* a M2 match */
+ movl %eax,%ecx
+ shrl $2,%eax
+ leal -1(%edi),%edx
+#if defined(LZO1X)
+ andl $7,%eax
+ movb (%esi),%bl
+ shrl $5,%ecx
+ leal (%eax,%ebx,8),%eax
+#elif defined(LZO1Y)
+ andl N_3,%eax
+ movb (%esi),%bl
+ shrl $4,%ecx
+ leal (%eax,%ebx,4),%eax
+#endif
+ incl %esi
+ subl %eax,%edx
+
+#if defined(LZO_FAST)
+#if defined(LZO1X)
+ addl $1+3,%ecx
+#elif defined(LZO1Y)
+ addl $2,%ecx
+#endif
+#else
+#if defined(LZO1X)
+ incl %ecx
+#elif defined(LZO1Y)
+ decl %ecx
+#endif
+#endif
+
+ cmpl N_3,%eax
+ jae .LCOPYLONG
+ jmp .LCOPYBYTE
+
+
+/***********************************************************************
+// M3
+************************************************************************/
+
+0: addl N_255,%eax
+ TEST_IP(3(%esi),%edx) /* minimum */
+1: movb (%esi),%bl
+ incl %esi
+ orb %bl,%bl
+ jz 0b
+ leal 33+NN(%eax,%ebx),%ecx
+ xorl %eax,%eax
+ jmp 3f
+
+
+ ALIGN3
+.LM3MATCH:
+ cmpb $32,%al
+ jb .LM4MATCH
+
+/* a M3 match */
+ andl $31,%eax
+ jz 1b
+ lea 2+NN(%eax),%ecx
+3:
+#ifdef LZO_DEBUG
+ andl $0xffff0000,%eax ; jnz .L_assert_fail
+#endif
+ movw (%esi),%ax
+ leal -1(%edi),%edx
+ shrl $2,%eax
+ addl $2,%esi
+ subl %eax,%edx
+
+ cmpl N_3,%eax
+ jb .LCOPYBYTE
+
+
+/***********************************************************************
+// copy match
+************************************************************************/
+
+ ALIGN1
+.LCOPYLONG: /* copy match using longwords */
+ TEST_LOOKBEHIND(%edx)
+#if defined(LZO_FAST)
+ leal -3(%edi,%ecx),%eax
+ shrl $2,%ecx
+ TEST_OP_R(%eax)
+ COPYL(%edx,%edi,%ebx)
+ movl %eax,%edi
+ xorl %ebx,%ebx
+#else
+ TEST_OP((%edi,%ecx),%eax)
+ movl %ecx,%ebx
+ shrl $2,%ebx
+ jz 2f
+ COPYL_C(%edx,%edi,%eax,%ebx)
+ andl N_3,%ecx
+ jz 1f
+2: COPYB_C(%edx,%edi,%al,%ecx)
+1:
+#endif
+
+.LMDONE:
+ movb -2(%esi),%al
+ andl N_3,%eax
+ jz .L00
+.LFLR3:
+ TEST_OP((%edi,%eax),%edx)
+ TEST_IP((%esi,%eax),%edx)
+#if defined(LZO_FAST)
+ movl (%esi),%edx
+ addl %eax,%esi
+ movl %edx,(%edi)
+ addl %eax,%edi
+#else
+ COPYB_C(%esi,%edi,%cl,%eax)
+#endif
+
+#ifdef LZO_DEBUG
+ andl $0xffffff00,%eax ; jnz .L_assert_fail
+ andl $0xffffff00,%ebx ; jnz .L_assert_fail
+ xorl %eax,%eax ; xorl %ebx,%ebx
+ xorl %ecx,%ecx ; xorl %edx,%edx
+#endif
+ LODSB
+ jmp .LMATCH
+
+
+ ALIGN3
+.LCOPYBYTE: /* copy match using bytes */
+ TEST_LOOKBEHIND(%edx)
+ TEST_OP(-NN(%edi,%ecx),%eax)
+ xchgl %edx,%esi
+#if defined(LZO_FAST)
+ subl N_3,%ecx
+#endif
+ rep
+ movsb
+ movl %edx,%esi
+ jmp .LMDONE
+
+
+/***********************************************************************
+// M4
+************************************************************************/
+
+0: addl N_255,%ecx
+ TEST_IP(3(%esi),%edx) /* minimum */
+1: movb (%esi),%bl
+ incl %esi
+ orb %bl,%bl
+ jz 0b
+ leal 9+NN(%ebx,%ecx),%ecx
+ jmp 3f
+
+
+ ALIGN3
+.LM4MATCH:
+ cmpb $16,%al
+ jb .LM1MATCH
+
+/* a M4 match */
+ movl %eax,%ecx
+ andl $8,%eax
+ shll $13,%eax /* save in bit 16 */
+ andl $7,%ecx
+ jz 1b
+ addl $2+NN,%ecx
+3:
+#ifdef LZO_DEBUG
+ movl %eax,%edx ; andl $0xfffe0000,%edx ; jnz .L_assert_fail
+#endif
+ movw (%esi),%ax
+ addl $2,%esi
+ leal -0x4000(%edi),%edx
+ shrl $2,%eax
+ jz .LEOF
+ subl %eax,%edx
+ jmp .LCOPYLONG
+
+
+/***********************************************************************
+// M1
+************************************************************************/
+
+ ALIGN3
+.LM1MATCH:
+/* a M1 match */
+ TEST_OP(2(%edi),%edx)
+ shrl $2,%eax
+ movb (%esi),%bl
+ leal -1(%edi),%edx
+ leal (%eax,%ebx,4),%eax
+ incl %esi
+ subl %eax,%edx
+ TEST_LOOKBEHIND(%edx)
+
+ movb (%edx),%al /* we must use this because edx can be edi-1 */
+ movb %al,(%edi)
+ movb 1(%edx),%bl
+ movb %bl,1(%edi)
+ addl $2,%edi
+ jmp .LMDONE
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+.LEOF:
+/**** xorl %eax,%eax eax=0 from above */
+
+ cmpl $3+NN,%ecx /* ecx must be 3/6 */
+ setnz %al
+
+
+/*
+vi:ts=4
+*/
+
diff --git a/core/lzo/lzo1x_f1.S b/core/lzo/lzo1x_f1.S
new file mode 100644
index 00000000..8360e34a
--- /dev/null
+++ b/core/lzo/lzo1x_f1.S
@@ -0,0 +1,63 @@
+/* lzo1x_f1.S -- fast LZO1X decompression in assembler (i386 + gcc)
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#define LZO_FAST
+
+#include "lzo_asm.h"
+
+ .section ".textnr","ax"
+
+ LZO_PUBLIC(lzo1x_decompress_asm_fast)
+
+#include "enter.ash"
+#include "lzo1x_d.ash"
+#include "leave.ash"
+
+ LZO_PUBLIC_END(lzo1x_decompress_asm_fast)
+
+
+/*
+vi:ts=4
+*/
+
diff --git a/core/lzo/lzo_asm.h b/core/lzo/lzo_asm.h
new file mode 100644
index 00000000..55fdf6d1
--- /dev/null
+++ b/core/lzo/lzo_asm.h
@@ -0,0 +1,287 @@
+/* lzo_asm.h -- LZO assembler stuff
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/***********************************************************************
+// <asmconfig.h>
+************************************************************************/
+
+#if !defined(__i386__)
+# error
+#endif
+
+#if !defined(IN_CONFIGURE)
+#if defined(LZO_HAVE_CONFIG_H)
+# include <config.h>
+#else
+ /* manual configuration - see defaults below */
+# if defined(__ELF__)
+# define MFX_ASM_HAVE_TYPE
+# define MFX_ASM_NAME_NO_UNDERSCORES
+# elif defined(__linux__) /* Linux a.out */
+# define MFX_ASM_ALIGN_PTWO
+# elif defined(__DJGPP__)
+# define MFX_ASM_ALIGN_PTWO
+# elif defined(__GO32__) /* djgpp v1 */
+# define MFX_ASM_CANNOT_USE_EBP
+# elif defined(__EMX__)
+# define MFX_ASM_ALIGN_PTWO
+# define MFX_ASM_CANNOT_USE_EBP
+# endif
+#endif
+#endif
+
+#if 1 && defined(__ELF__)
+.section .note.GNU-stack,"",@progbits
+#endif
+#if 0 && defined(__ELF__)
+#undef i386
+.arch i386
+.code32
+#endif
+
+
+/***********************************************************************
+// name always uses underscores
+// [ OLD: name (default: with underscores) ]
+************************************************************************/
+
+#if !defined(LZO_ASM_NAME)
+# define LZO_ASM_NAME(n) _ ## n
+#if 0
+# if defined(MFX_ASM_NAME_NO_UNDERSCORES)
+# define LZO_ASM_NAME(n) n
+# else
+# define LZO_ASM_NAME(n) _ ## n
+# endif
+#endif
+#endif
+
+
+/***********************************************************************
+// .type (default: do not use)
+************************************************************************/
+
+#if !defined(LZO_PUBLIC)
+#if defined(__LZO_DB__)
+# define LZO_PUBLIC(func) \
+ .p2align 4 ; .byte 0,0,0,0,0,0,0 ; .ascii "LZO_START"
+# define LZO_PUBLIC_END(func) \
+ .p2align 4,0x90 ; .ascii "LZO_END"
+#elif defined(MFX_ASM_HAVE_TYPE)
+# define LZO_PUBLIC(func) \
+ ALIGN3 ; .type LZO_ASM_NAME(func),@function ; \
+ .globl LZO_ASM_NAME(func) ; LZO_ASM_NAME(func):
+# define LZO_PUBLIC_END(func) \
+ .size LZO_ASM_NAME(func),.-LZO_ASM_NAME(func)
+#else
+# define LZO_PUBLIC(func) \
+ ALIGN3 ; .globl LZO_ASM_NAME(func) ; LZO_ASM_NAME(func):
+# define LZO_PUBLIC_END(func)
+#endif
+#endif
+
+
+/***********************************************************************
+// .align (default: bytes)
+************************************************************************/
+
+#if !defined(MFX_ASM_ALIGN_BYTES) && !defined(MFX_ASM_ALIGN_PTWO)
+# define MFX_ASM_ALIGN_BYTES
+#endif
+
+#if !defined(LZO_ASM_ALIGN)
+# if defined(MFX_ASM_ALIGN_PTWO)
+# define LZO_ASM_ALIGN(x) .align x
+# else
+# define LZO_ASM_ALIGN(x) .align (1 << (x))
+# endif
+#endif
+
+#define ALIGN1 LZO_ASM_ALIGN(1)
+#define ALIGN2 LZO_ASM_ALIGN(2)
+#define ALIGN3 LZO_ASM_ALIGN(3)
+
+
+/***********************************************************************
+// ebp usage (default: can use)
+************************************************************************/
+
+#if !defined(MFX_ASM_CANNOT_USE_EBP)
+# if 1 && !defined(N_3_EBP) && !defined(N_255_EBP)
+# define N_3_EBP
+# endif
+# if 0 && !defined(N_3_EBP) && !defined(N_255_EBP)
+# define N_255_EBP
+# endif
+#endif
+
+#if defined(N_3_EBP) && defined(N_255_EBP)
+# error
+#endif
+#if defined(MFX_ASM_CANNOT_USE_EBP)
+# if defined(N_3_EBP) || defined(N_255_EBP)
+# error
+# endif
+#endif
+
+#if !defined(N_3)
+# if defined(N_3_EBP)
+# define N_3 %ebp
+# else
+# define N_3 $3
+# endif
+#endif
+
+#if !defined(N_255)
+# if defined(N_255_EBP)
+# define N_255 %ebp
+# define NOTL_3(r) xorl %ebp,r
+# else
+# define N_255 $255
+# endif
+#endif
+
+#if !defined(NOTL_3)
+# define NOTL_3(r) xorl N_3,r
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#ifndef INP
+#define INP 4+36(%esp)
+#define INS 8+36(%esp)
+#define OUTP 12+36(%esp)
+#define OUTS 16+36(%esp)
+#endif
+
+#define INEND 4(%esp)
+#define OUTEND (%esp)
+
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT)
+# define TEST_IP_R(r) cmpl r,INEND ; jb .L_input_overrun
+# define TEST_IP(addr,r) leal addr,r ; TEST_IP_R(r)
+#else
+# define TEST_IP_R(r)
+# define TEST_IP(addr,r)
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+# define TEST_OP_R(r) cmpl r,OUTEND ; jb .L_output_overrun
+# define TEST_OP(addr,r) leal addr,r ; TEST_OP_R(r)
+#else
+# define TEST_OP_R(r)
+# define TEST_OP(addr,r)
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+# define TEST_LOOKBEHIND(r) cmpl OUTP,r ; jb .L_lookbehind_overrun
+#else
+# define TEST_LOOKBEHIND(r)
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#define LODSB movb (%esi),%al ; incl %esi
+
+#define MOVSB(r1,r2,x) movb (r1),x ; incl r1 ; movb x,(r2) ; incl r2
+#define MOVSW(r1,r2,x) movb (r1),x ; movb x,(r2) ; \
+ movb 1(r1),x ; addl $2,r1 ; \
+ movb x,1(r2) ; addl $2,r2
+#define MOVSL(r1,r2,x) movl (r1),x ; addl $4,r1 ; movl x,(r2) ; addl $4,r2
+
+#if defined(LZO_DEBUG)
+#define COPYB_C(r1,r2,x,rc) \
+ cmpl $0,rc ; jz .L_assert_fail; \
+ 9: MOVSB(r1,r2,x) ; decl rc ; jnz 9b
+#define COPYL_C(r1,r2,x,rc) \
+ cmpl $0,rc ; jz .L_assert_fail; \
+ 9: MOVSL(r1,r2,x) ; decl rc ; jnz 9b
+#else
+#define COPYB_C(r1,r2,x,rc) \
+ 9: MOVSB(r1,r2,x) ; decl rc ; jnz 9b
+#define COPYL_C(r1,r2,x,rc) \
+ 9: MOVSL(r1,r2,x) ; decl rc ; jnz 9b
+#endif
+
+#define COPYB(r1,r2,x) COPYB_C(r1,r2,x,%ecx)
+#define COPYL(r1,r2,x) COPYL_C(r1,r2,x,%ecx)
+
+
+/***********************************************************************
+// not used
+************************************************************************/
+
+#if 0
+
+#if 0
+#define REP_MOVSB(x) rep ; movsb
+#define REP_MOVSL(x) shrl $2,%ecx ; rep ; movsl
+#elif 1
+#define REP_MOVSB(x) COPYB(%esi,%edi,x)
+#define REP_MOVSL(x) shrl $2,%ecx ; COPYL(%esi,%edi,x)
+#else
+#define REP_MOVSB(x) rep ; movsb
+#define REP_MOVSL(x) jmp 9f ; 8: movsb ; decl %ecx ; \
+ 9: testl $3,%edi ; jnz 8b ; \
+ movl %ecx,x ; shrl $2,%ecx ; andl $3,x ; \
+ rep ; movsl ; movl x,%ecx ; rep ; movsb
+#endif
+
+#if 1
+#define NEGL(x) negl x
+#else
+#define NEGL(x) xorl $-1,x ; incl x
+#endif
+
+#endif
+
+
+
+/*
+vi:ts=4
+*/
+
diff --git a/core/macros.inc b/core/macros.inc
index 1aa2b2ce..e3aedca1 100644
--- a/core/macros.inc
+++ b/core/macros.inc
@@ -47,7 +47,7 @@
;
; Macros similar to res[bwd], but which works in the code segment (after
-; section .text) or the data segment (section .data)
+; section .text16) or the data segment (section .data16)
;
%macro zb 1.nolist
times %1 db 0
diff --git a/core/malloc.c b/core/malloc.c
new file mode 100644
index 00000000..da4a3430
--- /dev/null
+++ b/core/malloc.c
@@ -0,0 +1,224 @@
+/*
+ * A simple temp malloc for Sysliux project from fstk. For now, just used
+ * in fsc branch, which it's would be easy to remove it when we have a
+ * powerful one, as hpa said this would happen when elflink branch do the
+ * work.
+ *
+ * Copyright (C) 2009 Liu Aleaxander -- All rights reserved. This file
+ * may be redistributed under the terms of the GNU Public License.
+ */
+
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+/* The memory managemant structure */
+struct mem_struct {
+ struct mem_struct *prev;
+ int size;
+ int free;
+};
+
+
+/* First, assume we just need 64K memory */
+static char memory[0x10000];
+
+/* Next free memory address */
+static struct mem_struct *next_start = (struct mem_struct *)memory;
+static uint32_t mem_end = (uint32_t)(memory + 0x10000);
+
+
+static inline struct mem_struct *get_next(struct mem_struct *mm)
+{
+ uint32_t next = (uint32_t)mm + mm->size;
+
+ if (next >= mem_end)
+ return NULL;
+ else
+ return (struct mem_struct *)next;
+}
+
+/*
+ * Here are the _merge_ functions, that merges a adjacent memory region,
+ * from front, or from back, or even merges both. It returns the headest
+ * region mem_struct.
+ *
+ */
+
+static struct mem_struct * merge_front(struct mem_struct *mm,
+ struct mem_struct *prev)
+{
+ struct mem_struct *next = get_next(mm);
+
+ prev->size += mm->size;
+ if (next)
+ next->prev = prev;
+ return prev;
+}
+
+static struct mem_struct * merge_back(struct mem_struct *mm,
+ struct mem_struct *next)
+{
+ mm->free = 1; /* Mark it free first */
+ mm->size += next->size;
+
+ next = get_next(next);
+ if (next)
+ next->prev = mm;
+ return mm;
+}
+
+static struct mem_struct * merge_both(struct mem_struct *mm,
+ struct mem_struct *prev,
+ struct mem_struct *next)
+{
+ prev->size += mm->size + next->size;
+
+ next = get_next(next);
+ if (next)
+ next->prev = prev;
+ return prev;
+}
+
+static inline struct mem_struct * try_merge_front(struct mem_struct *mm)
+{
+ mm->free = 1;
+ if (mm->prev->free)
+ mm = merge_front(mm, mm->prev);
+ return mm;
+}
+
+static inline struct mem_struct * try_merge_back(struct mem_struct *mm)
+{
+ struct mem_struct *next = get_next(mm);
+
+ mm->free = 1;
+ if (next->free)
+ merge_back(mm, next);
+ return mm;
+}
+
+/*
+ * Here's the main function, malloc, which allocates a memory rigon
+ * of size _size_. Returns NULL if failed, or the address newly allocated.
+ *
+ */
+void *malloc(size_t size)
+{
+ struct mem_struct *next = next_start;
+ struct mem_struct *good = next, *prev;
+ int size_needed = (size + sizeof(struct mem_struct) + 3) & ~3;
+
+ while(next) {
+ if (next->free && next->size >= size_needed) {
+ good = next;
+ break;
+ }
+ next = get_next(next);
+ }
+ if (good->size < size_needed) {
+ printf("Out of memory, maybe we need append it\n");
+ return NULL;
+ } else if (good->size == size_needed) {
+ /*
+ * We just found a right memory that with the exact
+ * size we want. So we just Mark it _not_free_ here,
+ * and move on the _next_start_ pointer, even though
+ * the next may not be a right next start.
+ */
+ good->free = 0;
+ next_start = get_next(good);
+ goto out;
+ } else
+ size = good->size; /* save the total size */
+
+ /*
+ * Note: allocate a new memory region will not change
+ * it's prev memory, so we don't need change it here.
+ */
+ good->free = 0; /* Mark it not free any more */
+ good->size = size_needed;
+
+ next = get_next(good);
+ if (next) {
+ next->size = size - size_needed;
+ /* check if it can contain 1 byte allocation at least */
+ if (next->size <= (int)sizeof(struct mem_struct)) {
+ good->size = size; /* restore the original size */
+ next_start = get_next(good);
+ goto out;
+ }
+
+ next->prev = good;
+ next->free = 1;
+ next_start = next; /* Update next_start */
+
+ prev = next;
+ next = get_next(next);
+ if (next)
+ next->prev = prev;
+ } else
+ next_start = (struct mem_struct *)memory;
+out:
+ return (void *)((uint32_t)good + sizeof(struct mem_struct));
+}
+
+void *zalloc(size_t size)
+{
+ void *p = malloc(size);
+ if (p)
+ memset(p, 0, size);
+ return p;
+}
+
+void free(void *ptr)
+{
+ struct mem_struct *mm = ptr - sizeof(*mm);
+ struct mem_struct *prev = mm->prev;
+ struct mem_struct *next = get_next(mm);
+
+ if (!prev)
+ mm = try_merge_back(mm);
+ else if (!next)
+ mm = try_merge_front(mm);
+ else if (prev->free && !next->free)
+ merge_front(mm, prev);
+ else if (!prev->free && next->free)
+ merge_back(mm, next);
+ else if (prev->free && next->free)
+ merge_both(mm, prev, next);
+ else
+ mm->free = 1;
+
+ if (mm < next_start)
+ next_start = mm;
+}
+
+/*
+ * The debug function
+ */
+void check_mem(void)
+{
+ struct mem_struct *next = (struct mem_struct *)memory;
+
+ printf("____________\n");
+ while (next) {
+ printf("%-6d %s\n", next->size, next->free ? "Free" : "Notf");
+ next = get_next(next);
+ }
+ printf("\n");
+}
+
+
+void mem_init(void)
+{
+
+ struct mem_struct *first = (struct mem_struct *)memory;
+
+ first->prev = NULL;
+ first->size = 0x10000;
+ first->free = 1;
+
+ next_start = first;
+}
diff --git a/core/parsecmd.inc b/core/parsecmd.inc
index 1ddd5a0e..ab5a7df9 100644
--- a/core/parsecmd.inc
+++ b/core/parsecmd.inc
@@ -17,7 +17,7 @@
;; Command line parser code
;;
- section .text
+ section .text16
; -------------------------------------------------------------------------
; getcommand: Get a keyword from the current "getc" file and match it
@@ -106,11 +106,12 @@ skipline: cmp al,10 ; Search for LF
jnc skipline
.end: ret
- section .data
+ section .data16
err_badcfg db 'Unknown keyword in configuration file: ',0
err_noparm db 'Missing parameter in configuration file. Keyword: ',0
section .uibss
+ global KernelName
alignb 4
vk_size equ (vk_end + 3) & ~3
VKernelBuf: resb vk_size ; "Current" vkernel
@@ -118,7 +119,7 @@ AppendBuf resb max_cmd_len+1 ; append=
Ontimeout resb max_cmd_len+1 ; ontimeout
Onerror resb max_cmd_len+1 ; onerror
; This could be in .uibss but that makes PXELINUX overflow
- section .bss
+ section .bss16
KbdMap resb 256 ; Keyboard map
FKeyName resb MAX_FKEYS*FILENAME_MAX ; File names for F-key help
KernelCNameLen resw 1 ; Length of unmangled kernel name
@@ -134,3 +135,5 @@ InitRDCName resb FILENAME_MAX ; Unmangled initrd name
%endif
MNameBuf resb FILENAME_MAX
InitRD resb FILENAME_MAX
+
+ section .text16
diff --git a/core/parseconfig.inc b/core/parseconfig.inc
index 65d71c95..af7d514f 100644
--- a/core/parseconfig.inc
+++ b/core/parseconfig.inc
@@ -17,7 +17,7 @@
;; Configuration file operations
;;
- section .text
+ section .text16
;
; "default" or "ui" command, with level (1 = default, 2 = ui)
;
@@ -104,7 +104,7 @@ pc_kernel: cmp byte [VKernel],0
mov [VKernelBuf+vk_type],al
call pc_getline
mov di,VKernelBuf+vk_rname
- call mangle_name
+ pm_call mangle_name
.err: ret
;
@@ -147,8 +147,8 @@ pc_setint16:
pc_filecmd: push ax ; Function to tailcall
call pc_getline
mov di,MNameBuf
- call mangle_name
- call searchdir
+ pm_call mangle_name
+ pm_call searchdir
jnz .ok
pop ax ; Drop the successor function
.ok: ret ; Tailcall if OK, error return
@@ -160,8 +160,8 @@ pc_filecmd: push ax ; Function to tailcall
pc_opencmd: push ax ; Function to tailcall
call pc_getline
mov di,MNameBuf
- call mangle_name
- call open
+ pm_call mangle_name
+ call core_open
jnz .ok
pop ax ; Drop the successor function
.ok: ret ; Tailcall if OK, error return
@@ -289,7 +289,7 @@ pc_serial: call getint
pc_filename: push ax
call pc_getline
pop di
- call mangle_name ; Mangle file name
+ pm_call mangle_name ; Mangle file name
ret
;
@@ -314,7 +314,7 @@ pc_label: call commit_vk ; Commit any current vkernel
mov byte [VKernel],1 ; We've seen a "label" statement
mov si,VKernelBuf+vk_vname ; By default, rname == mangled vname
mov di,VKernelBuf+vk_rname
- call mangle_name
+ pm_call mangle_name
mov si,AppendBuf ; Default append==global append
mov di,VKernelBuf+vk_append
mov cx,[AppendLen]
@@ -409,7 +409,7 @@ commit_vk:
mov cx,7 ; "initrd="
rep movsb
mov si,InitRD
- call unmangle_name
+ pm_call unmangle_name
mov al,' '
stosb
@@ -427,7 +427,7 @@ commit_vk:
mov esi,VKernelBuf
mov edi,[VKernelEnd]
mov ecx,vk_size
- call rllpack
+ pm_call rllpack
mov [VKernelEnd],edi
.nolabel:
ret
@@ -436,11 +436,11 @@ commit_vk:
call writestr
ret
- section .data
+ section .data16
vk_overflow_msg db 'Out of memory parsing config file', CR, LF, 0
SerialNotice db 1 ; Only print this once
- section .bss
+ section .bss16
alignb 4
VKernelEnd resd 1 ; Lowest high memory address used
@@ -474,5 +474,3 @@ IPAppend db 0 ; Default IPAPPEND option
command_line resb max_cmd_len+2 ; Command line buffer
alignb 4
default_cmd resb max_cmd_len+1 ; "default" command line
-
-%include "rllpack.inc"
diff --git a/core/plaincon.inc b/core/plaincon.inc
index 59b2cbb5..c41629d0 100644
--- a/core/plaincon.inc
+++ b/core/plaincon.inc
@@ -2,7 +2,7 @@
; writechr: Write a single character in AL to the console without
; mangling any registers; handle video pages correctly.
;
- section .text
+ section .text16
writechr:
call write_serial ; write to serial port if needed
diff --git a/core/pm.inc b/core/pm.inc
new file mode 100644
index 00000000..9584cda1
--- /dev/null
+++ b/core/pm.inc
@@ -0,0 +1,450 @@
+;; -----------------------------------------------------------------------
+;;
+;; Copyright 1994-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., 53 Temple Place Ste 330,
+;; Boston MA 02111-1307, USA; either version 2 of the License, or
+;; (at your option) any later version; incorporated herein by reference.
+;;
+;; -----------------------------------------------------------------------
+
+;;
+;; pm.inc
+;;
+;; Functions to enter and exit 32-bit protected mode, handle interrupts
+;; and cross-mode calls.
+;;
+;; PM refers to 32-bit flat protected mode; RM to 16-bit real mode.
+;;
+
+ bits 16
+ section .text16
+;
+; _pm_call: call PM routine in low memory from RM
+;
+; on stack = PM routine to call (a 32-bit address)
+;
+; ECX, ESI, EDI passed to the called function;
+; EAX = EBP in the called function points to the stack frame
+; which includes all registers (which can be changed if desired.)
+;
+; All registers and the flags saved/restored
+;
+; This routine is invoked by the pm_call macro.
+;
+_pm_call:
+ pushfd
+ pushad
+ push ds
+ push es
+ push fs
+ push gs
+ mov bp,sp
+ mov ax,cs
+ mov ebx,.pm
+ mov ds,ax
+ jmp enter_pm
+
+ bits 32
+ section .textnr
+.pm:
+ ; EAX points to the top of the RM stack, which is EFLAGS
+ test RM_FLAGSH,02h ; RM EFLAGS.IF
+ jz .no_sti
+ sti
+.no_sti:
+ call [ebp+4*2+9*4+2] ; Entrypoint on RM stack
+ mov bx,.rm
+ jmp enter_rm
+
+ bits 16
+ section .text16
+.rm:
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ popad
+ popfd
+ ret 4 ; Drop entrypoint
+
+;
+; enter_pm: Go to PM with interrupt service configured
+; EBX = PM entry point
+; EAX = EBP = on exit, points to the RM stack as a 32-bit value
+; ECX, EDX, ESI, EDI preserved across this routine
+;
+; Assumes CS == DS
+;
+; This routine doesn't enable interrupts, but the target routine
+; can enable interrupts by executing STI.
+;
+ bits 16
+ section .text16
+enter_pm:
+ cli
+ xor eax,eax
+ mov ds,ax
+ mov ax,ss
+ mov [RealModeSSSP],sp
+ mov [RealModeSSSP+2],ax
+ movzx ebp,sp
+ shl eax,4
+ add ebp,eax ; EBP -> top of real-mode stack
+ cld
+ call enable_a20
+
+.a20ok:
+ mov byte [bcopy_gdt.TSS+5],89h ; Mark TSS unbusy
+
+ lgdt [bcopy_gdt] ; We can use the same GDT just fine
+ lidt [PM_IDT_ptr] ; Set up the IDT
+ mov eax,cr0
+ or al,1
+ mov cr0,eax ; Enter protected mode
+ jmp PM_CS32:.in_pm
+
+ bits 32
+ section .textnr
+.in_pm:
+ xor eax,eax ; Available for future use...
+ mov fs,eax
+ mov gs,eax
+ lldt ax
+
+ mov al,PM_DS32 ; Set up data segments
+ mov es,eax
+ mov ds,eax
+ mov ss,eax
+
+ mov al,PM_TSS ; Be nice to Intel's VT by
+ ltr ax ; giving it a valid TR
+
+ mov esp,[PMESP] ; Load protmode %esp
+ mov eax,ebp ; EAX -> top of real-mode stack
+ jmp ebx ; Go to where we need to go
+
+;
+; enter_rm: Return to RM from PM
+;
+; BX = RM entry point (CS = 0)
+; ECX, EDX, ESI, EDI preserved across this routine
+; EAX clobbered
+; EBP reserved
+;
+; This routine doesn't enable interrupts, but the target routine
+; can enable interrupts by executing STI.
+;
+ bits 32
+ section .textnr
+enter_rm:
+ cli
+ cld
+ mov [PMESP],esp ; Save exit %esp
+ jmp PM_CS16:.in_pm16 ; Return to 16-bit mode first
+
+ bits 16
+ section .text16
+.in_pm16:
+ mov ax,PM_DS16 ; Real-mode-like segment
+ mov es,ax
+ mov ds,ax
+ mov ss,ax
+ mov fs,ax
+ mov gs,ax
+
+ lidt [RM_IDT_ptr] ; Real-mode IDT (rm needs no GDT)
+ xor dx,dx
+ mov eax,cr0
+ and al,~1
+ mov cr0,eax
+ jmp 0:.in_rm
+
+.in_rm: ; Back in real mode
+ lss sp,[cs:RealModeSSSP] ; Restore stack
+ movzx esp,sp ; Make sure the high bits are zero
+ mov ds,dx ; Set up sane segments
+ mov es,dx
+ mov fs,dx
+ mov gs,dx
+ jmp bx ; Go to whereever we need to go...
+
+ section .data16
+ alignz 4
+
+ extern __stack_end
+PMESP dd __stack_end ; Protected-mode ESP
+
+PM_IDT_ptr: dw 8*256-1 ; Length
+ dd IDT ; Offset
+
+;
+; This is invoked on getting an interrupt in protected mode. At
+; this point, we need to context-switch to real mode and invoke
+; the interrupt routine.
+;
+; When this gets invoked, the registers are saved on the stack and
+; AL contains the register number.
+;
+ bits 32
+ section .textnr
+pm_irq:
+ pushad
+ movzx esi,byte [esp+8*4] ; Interrupt number
+ mov ebx,.rm
+ jmp enter_rm ; Go to real mode
+
+ bits 16
+ section .text16
+.rm:
+ pushf ; Flags on stack
+ call far [cs:esi*4] ; Call IVT entry
+ mov ebx,.pm
+ jmp enter_pm ; Go back to PM
+
+ bits 32
+ section .textnr
+.pm:
+ popad
+ add esp,4 ; Drop interrupt number
+ iretd
+
+ bits 16
+ section .text16
+;
+; Routines to enable and disable (yuck) A20. These routines are gathered
+; from tips from a couple of sources, including the Linux kernel and
+; http://www.x86.org/. The need for the delay to be as large as given here
+; is indicated by Donnie Barnes of RedHat, the problematic system being an
+; IBM ThinkPad 760EL.
+;
+
+ section .data16
+ alignz 2
+A20Ptr dw a20_dunno
+
+ section .bss16
+ alignb 4
+A20Test resd 1 ; Counter for testing A20 status
+A20Tries resb 1 ; Times until giving up on A20
+
+ section .text16
+enable_a20:
+ pushad
+ mov byte [cs:A20Tries],255 ; Times to try to make this work
+
+try_enable_a20:
+
+;
+; First, see if we are on a system with no A20 gate, or the A20 gate
+; is already enabled for us...
+;
+a20_none:
+ call a20_test
+ jnz a20_done
+ ; Otherwise, see if we had something memorized...
+ jmp word [cs:A20Ptr]
+
+;
+; Next, try the BIOS (INT 15h AX=2401h)
+;
+a20_dunno:
+a20_bios:
+ mov word [cs:A20Ptr], a20_bios
+ mov ax,2401h
+ pushf ; Some BIOSes muck with IF
+ int 15h
+ popf
+
+ call a20_test
+ jnz a20_done
+
+;
+; Enable the keyboard controller A20 gate
+;
+a20_kbc:
+ mov dl, 1 ; Allow early exit
+ call empty_8042
+ jnz a20_done ; A20 live, no need to use KBC
+
+ mov word [cs:A20Ptr], a20_kbc ; Starting KBC command sequence
+
+ mov al,0D1h ; Write output port
+ out 064h, al
+ call empty_8042_uncond
+
+ mov al,0DFh ; A20 on
+ out 060h, al
+ call empty_8042_uncond
+
+ ; Apparently the UHCI spec assumes that A20 toggle
+ ; ends with a null command (assumed to be for sychronization?)
+ ; Put it here to see if it helps anything...
+ mov al,0FFh ; Null command
+ out 064h, al
+ call empty_8042_uncond
+
+ ; Verify that A20 actually is enabled. Do that by
+ ; observing a word in low memory and the same word in
+ ; the HMA until they are no longer coherent. Note that
+ ; we don't do the same check in the disable case, because
+ ; we don't want to *require* A20 masking (SYSLINUX should
+ ; work fine without it, if the BIOS does.)
+.kbc_wait: push cx
+ xor cx,cx
+.kbc_wait_loop:
+ call a20_test
+ jnz a20_done_pop
+ loop .kbc_wait_loop
+
+ pop cx
+;
+; Running out of options here. Final attempt: enable the "fast A20 gate"
+;
+a20_fast:
+ mov word [cs:A20Ptr], a20_fast
+ in al, 092h
+ or al,02h
+ and al,~01h ; Don't accidentally reset the machine!
+ out 092h, al
+
+.fast_wait: push cx
+ xor cx,cx
+.fast_wait_loop:
+ call a20_test
+ jnz a20_done_pop
+ loop .fast_wait_loop
+
+ pop cx
+
+;
+; Oh bugger. A20 is not responding. Try frobbing it again; eventually give up
+; and report failure to the user.
+;
+ dec byte [cs:A20Tries]
+ jnz a20_dunno ; Did we get the wrong type?
+
+ mov si, err_a20
+ jmp abort_load
+
+ section .data16
+err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0
+ section .text16
+
+;
+; A20 unmasked, proceed...
+;
+a20_done_pop: pop cx
+a20_done: popad
+ ret
+
+;
+; This routine tests if A20 is enabled (ZF = 0). This routine
+; must not destroy any register contents.
+;
+; The no-write early out avoids the io_delay in the (presumably common)
+; case of A20 already enabled (e.g. from a previous call.)
+;
+a20_test:
+ push es
+ push cx
+ push eax
+ mov cx,0FFFFh ; HMA = segment 0FFFFh
+ mov es,cx
+ mov eax,[cs:A20Test]
+ mov cx,32 ; Loop count
+ jmp .test ; First iteration = early out
+.wait: add eax,0x430aea41 ; A large prime number
+ mov [cs:A20Test],eax
+ io_delay ; Serialize, and fix delay
+.test: cmp eax,[es:A20Test+10h]
+ loopz .wait
+.done: pop eax
+ pop cx
+ pop es
+ ret
+
+;
+; Routine to empty the 8042 KBC controller. If dl != 0
+; then we will test A20 in the loop and exit if A20 is
+; suddenly enabled.
+;
+empty_8042_uncond:
+ xor dl,dl
+empty_8042:
+ call a20_test
+ jz .a20_on
+ and dl,dl
+ jnz .done
+.a20_on: io_delay
+ in al, 064h ; Status port
+ test al,1
+ jz .no_output
+ io_delay
+ in al, 060h ; Read input
+ jmp short empty_8042
+.no_output:
+ test al,2
+ jnz empty_8042
+ io_delay
+.done: ret
+
+;
+; This initializes the protected-mode interrupt thunk set
+;
+ section .text16
+pm_init:
+ xor edi,edi
+ mov bx,IDT
+ mov di,IRQStubs
+
+ mov eax,7aeb006ah ; push byte .. jmp short ..
+
+ mov cx,8 ; 8 groups of 32 IRQs
+.gloop:
+ push cx
+ mov cx,32 ; 32 entries per group
+.eloop:
+ mov [bx],di ; IDT offset [15:0]
+ mov word [bx+2],PM_CS32 ; IDT segment
+ mov dword [bx+4],08e00h ; IDT offset [31:16], 32-bit interrupt
+ ; gate, CPL 0 (we don't have a TSS
+ ; set up...)
+ add bx,8
+
+ stosd
+ ; Increment IRQ, decrement jmp short offset
+ add eax,(-4 << 24)+(1 << 8)
+
+ loop .eloop
+
+ ; At the end of each group, replace the EBxx with
+ ; the final E9xxxxxxxx
+ add di,3
+ mov byte [di-5],0E9h ; JMP NEAR
+ mov edx,pm_irq
+ sub edx,edi
+ mov [di-4],edx
+
+ add eax,(0x80 << 24) ; Proper offset for the next one
+ pop cx
+ loop .gloop
+
+ ret
+
+ ; pm_init is called before bss clearing, so put these
+ ; in .earlybss!
+ section .earlybss
+ alignb 8
+IDT: resq 256
+RealModeSSSP resd 1 ; Real-mode SS:SP
+
+ section .gentextnr ; Autogenerated 32-bit code
+IRQStubs: resb 4*256+3*8
+
+ section .text16
+
+%include "callback.inc" ; Real-mode callbacks
diff --git a/core/pmcall.inc b/core/pmcall.inc
new file mode 100644
index 00000000..0a580150
--- /dev/null
+++ b/core/pmcall.inc
@@ -0,0 +1,70 @@
+;;
+;; pmcall.inc
+;;
+;; Macros for the stack frame set up by pm_call, assuming ebp is left
+;; as the RM frame pointer.
+;;
+
+%ifndef PMCALL_INC
+%define PMCALL_INC
+
+%define RM_GS word [ebp]
+%define RM_FS word [ebp+2]
+%define RM_ES word [ebp+4]
+%define RM_DS word [ebp+6]
+
+%define RM_EDI dword [ebp+8]
+%define RM_DI word [ebp+8]
+%define RM_HDI word [ebp+10]
+%define RM_DIL byte [ebp+8]
+%define RM_DIH byte [ebp+9]
+
+%define RM_ESI dword [ebp+12]
+%define RM_SI word [ebp+12]
+%define RM_HSI word [ebp+14]
+%define RM_SIL byte [ebp+12]
+%define RM_SIH byte [ebp+13]
+
+%define RM_EBP dword [ebp+16]
+%define RM_BP word [ebp+16]
+%define RM_HBP word [ebp+18]
+%define RM_BPL byte [ebp+16]
+%define RM_BPH byte [ebp+17]
+
+%define RM_EBX dword [ebp+24]
+%define RM_BX word [ebp+24]
+%define RM_HBX word [ebp+26]
+%define RM_BL byte [ebp+24]
+%define RM_BH byte [ebp+25]
+
+%define RM_EDX dword [ebp+28]
+%define RM_DX word [ebp+28]
+%define RM_HDX word [ebp+30]
+%define RM_DL byte [ebp+28]
+%define RM_DH byte [ebp+29]
+
+%define RM_ECX dword [ebp+32]
+%define RM_CX word [ebp+32]
+%define RM_HCX word [ebp+34]
+%define RM_CL byte [ebp+32]
+%define RM_CH byte [ebp+33]
+
+%define RM_EAX dword [ebp+36]
+%define RM_AX word [ebp+36]
+%define RM_HAX word [ebp+38]
+%define RM_AL byte [ebp+36]
+%define RM_AH byte [ebp+37]
+
+%define RM_EFLAGS dword [ebp+40]
+%define RM_FLAGS word [ebp+40]
+%define RM_HFLAGS word [ebp+42]
+%define RM_FLAGSL byte [ebp+40]
+%define RM_FLAGSH byte [ebp+41]
+
+; Convenience macro to call a PM function
+%macro pm_call 1
+ push dword %1
+ call _pm_call
+%endmacro
+
+%endif ; PMCALL_INC
diff --git a/core/prefix.inc b/core/prefix.inc
new file mode 100644
index 00000000..9c8724b5
--- /dev/null
+++ b/core/prefix.inc
@@ -0,0 +1,17 @@
+;
+; The prefix is a small structure that prefaces the actual code;
+; it gives the compression program necessary information.
+;
+
+ section .prefix nowrite progbits align=16
+pfx_start dd _start ; Start of raw chunk
+pfx_compressed dd __pm_code_lma ; Start of compressed chunk
+pfx_cdatalen dd lzo_data_size ; Pointer to compressed size field
+%if IS_ISOLINUX
+pfx_checksum dd bi_length ; File length and checksum fields
+%else
+pfx_checksum dd 0 ; No checksum
+%endif
+pfx_maxlma dd MaxLMA ; Maximum size
+
+ section .text16
diff --git a/core/printf.c b/core/printf.c
new file mode 100644
index 00000000..b1b0466b
--- /dev/null
+++ b/core/printf.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <unistd.h>
+
+#include "core.h"
+
+int printf(const char *format, ...)
+{
+ char buf[1024];
+ va_list ap;
+ int rv;
+
+ va_start(ap, format);
+ rv = vsnprintf(buf, sizeof buf, format, ap);
+ va_end(ap);
+
+ myputs(buf);
+
+ return rv;
+
+}
diff --git a/core/pxeidle.inc b/core/pxeidle.inc
deleted file mode 100644
index 230fb96a..00000000
--- a/core/pxeidle.inc
+++ /dev/null
@@ -1,122 +0,0 @@
-;; -*- fundamental -*- ---------------------------------------------------
-;;
-;; Copyright 2008 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.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; pxeidle.inc
-;;
-;;
-;; Query for the NIC type, and detect certain special cases.
-;;
-
- section .text
-
-;;
-;; Initializes the idle mechanism based on the device type
-;;
-;; Assumes CS == DS == ES
-;;
-pxe_detect_nic_type:
- pushad
-
- mov di,pxenv_get_nic_type
- mov bx,PXENV_UNDI_GET_NIC_TYPE
- call pxenv
- jc .done
- cmp word [di],0
- jne .done
- cmp byte [di+2],2 ; PCI_NIC
- jne .done ; No list for non-PCI nics
-
- mov cx,pxe_idle_pci_list.len
- mov si,pxe_idle_pci_list
-.look_for_id:
- lodsd
- cmp eax,[di+3] ; VID:DID
- je .found_device
- loop .look_for_id
-.done:
- popad
- ret
-
-.found_device:
- mov word [IdleHook],check_for_arp
- jmp .done
-
-;;
-;; List of devices for which we want to actually issue idle calls.
-;;
- section .data
- alignz 4
-pxe_idle_pci_list:
-;
-; Older Broadcom NICs; these need idle calls to avoid FIFO stalls.
-;
- dw 0x14e4, 0x1659 ; BCM5721
- dw 0x14e4, 0x165a ; BCM5722
- dw 0x14e4, 0x165b ; BCM5723
- dw 0x14e4, 0x1668 ; BCM5714
- dw 0x14e4, 0x1669 ; BCM5714S
- dw 0x14e4, 0x166a ; BCM5780
- dw 0x14e4, 0x166b ; BCM5780S
- dw 0x14e4, 0x1673 ; BCM5755M
- dw 0x14e4, 0x1674 ; BCM5756ME
- dw 0x14e4, 0x1678 ; BCM5715
- dw 0x14e4, 0x1679 ; BCM5715S
- dw 0x14e4, 0x167b ; BCM5755
-;
-.len equ ($-pxe_idle_pci_list) >> 2
-
- section .bss
-pxenv_get_nic_type:
-.status: resw 1
-.nic_type: resb 1
-.vid: resw 1
-.did: resw 1
-.base_class: resb 1
-.sub_class: resb 1
-.prog_intf: resb 1
-.rev: resb 1
-.busdevfunc: resw 1
-.svid: resw 1
-.sdid: resw 1
-
- section .text
-;
-; Call the receive loop while idle. This is done mostly so we can respond to
-; ARP messages, but perhaps in the future this can be used to do network
-; console.
-;
-; hpa sez: people using automatic control on the serial port get very
-; unhappy if we poll for ARP too often (the PXE stack is pretty slow,
-; typically.) Therefore, only poll if at least 4 BIOS timer ticks have
-; passed since the last poll, and reset this when a character is
-; received (call reset_idle).
-;
-; Note: we only do this if pxe_detect_nic_type has set the IdleHook
-; to point to this routine.
-;
-check_for_arp:
- pushad
- mov di,packet_buf
- mov [pxe_udp_read_pkt.buffer],di
- mov [pxe_udp_read_pkt.buffer+2],ds
- mov word [pxe_udp_read_pkt.buffersize],packet_buf_size
- mov eax,[MyIP]
- mov [pxe_udp_read_pkt.dip],eax
- mov word [pxe_udp_read_pkt.lport],htons(9) ; discard port
- mov di,pxe_udp_read_pkt
- mov bx,PXENV_UDP_READ
- call pxenv
- ; Ignore result...
- popad
- ret
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index 6ad15845..58f76ce9 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -8,7 +8,7 @@
; MS-DOS floppies.
;
; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+; 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
@@ -29,52 +29,20 @@
; Some semi-configurable constants... change on your own risk.
;
my_id equ pxelinux_id
-FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null)
-FILENAME_MAX equ (1 << FILENAME_MAX_LG2)
NULLFILE equ 0 ; Zero byte == null file name
NULLOFFSET equ 4 ; Position in which to look
REBOOT_TIME equ 5*60 ; If failure, time until full reset
%assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top
-MAX_OPEN_LG2 equ 5 ; log2(Max number of open sockets)
-MAX_OPEN equ (1 << MAX_OPEN_LG2)
-PKTBUF_SIZE equ (65536/MAX_OPEN) ; Per-socket packet buffer size
-TFTP_PORT equ htons(69) ; Default TFTP port
-; Desired TFTP block size
-; For Ethernet MTU is normally 1500. Unfortunately there seems to
-; be a fair number of networks with "substandard" MTUs which break.
-; The code assumes TFTP_LARGEBLK <= 2K.
-TFTP_MTU equ 1440
-TFTP_LARGEBLK equ (TFTP_MTU-20-8-4) ; MTU - IP hdr - UDP hdr - TFTP hdr
-; Standard TFTP block size
TFTP_BLOCKSIZE_LG2 equ 9 ; log2(bytes/block)
TFTP_BLOCKSIZE equ (1 << TFTP_BLOCKSIZE_LG2)
-%assign USE_PXE_PROVIDED_STACK 0 ; Use stack provided by PXE?
-
-SECTOR_SHIFT equ TFTP_BLOCKSIZE_LG2
-SECTOR_SIZE equ TFTP_BLOCKSIZE
;
-; TFTP operation codes
+; Set to 1 to disable switching to a private stack
;
-TFTP_RRQ equ htons(1) ; Read request
-TFTP_WRQ equ htons(2) ; Write request
-TFTP_DATA equ htons(3) ; Data packet
-TFTP_ACK equ htons(4) ; ACK packet
-TFTP_ERROR equ htons(5) ; ERROR packet
-TFTP_OACK equ htons(6) ; OACK packet
+%assign USE_PXE_PROVIDED_STACK 0 ; Use stack provided by PXE?
-;
-; TFTP error codes
-;
-TFTP_EUNDEF equ htons(0) ; Unspecified error
-TFTP_ENOTFOUND equ htons(1) ; File not found
-TFTP_EACCESS equ htons(2) ; Access violation
-TFTP_ENOSPACE equ htons(3) ; Disk full
-TFTP_EBADOP equ htons(4) ; Invalid TFTP operation
-TFTP_EBADID equ htons(5) ; Unknown transfer
-TFTP_EEXISTS equ htons(6) ; File exists
-TFTP_ENOUSER equ htons(7) ; No such user
-TFTP_EOPTNEG equ htons(8) ; Option negotiation failure
+SECTOR_SHIFT equ TFTP_BLOCKSIZE_LG2
+SECTOR_SIZE equ TFTP_BLOCKSIZE
;
; The following structure is used for "virtual kernels"; i.e. LILO-style
@@ -94,60 +62,6 @@ vk_append: resb max_cmd_len+1 ; Command line
vk_end: equ $ ; Should be <= vk_size
endstruc
-;
-; BOOTP/DHCP packet pattern
-;
- struc bootp_t
-bootp:
-.opcode resb 1 ; BOOTP/DHCP "opcode"
-.hardware resb 1 ; ARP hardware type
-.hardlen resb 1 ; Hardware address length
-.gatehops resb 1 ; Used by forwarders
-.ident resd 1 ; Transaction ID
-.seconds resw 1 ; Seconds elapsed
-.flags resw 1 ; Broadcast flags
-.cip resd 1 ; Client IP
-.yip resd 1 ; "Your" IP
-.sip resd 1 ; Next server IP
-.gip resd 1 ; Relay agent IP
-.macaddr resb 16 ; Client MAC address
-.sname resb 64 ; Server name (optional)
-.bootfile resb 128 ; Boot file name
-.option_magic resd 1 ; Vendor option magic cookie
-.options resb 1260 ; Vendor options
- endstruc
-
-BOOTP_OPTION_MAGIC equ htonl(0x63825363) ; See RFC 2132
-
-;
-; TFTP connection data structure. Each one of these corresponds to a local
-; UDP port. The size of this structure must be a power of 2.
-; HBO = host byte order; NBO = network byte order
-; (*) = written by options negotiation code, must be dword sized
-;
-; For a gPXE connection, we set the local port number to -1 and the
-; remote port number contains the gPXE file handle.
-;
- struc open_file_t
-tftp_localport resw 1 ; Local port number (0 = not in use)
-tftp_remoteport resw 1 ; Remote port number
-tftp_remoteip resd 1 ; Remote IP address
-tftp_filepos resd 1 ; Bytes downloaded (including buffer)
-tftp_filesize resd 1 ; Total file size(*)
-tftp_blksize resd 1 ; Block size for this connection(*)
-tftp_bytesleft resw 1 ; Unclaimed data bytes
-tftp_lastpkt resw 1 ; Sequence number of last packet (NBO)
-tftp_dataptr resw 1 ; Pointer to available data
-tftp_goteof resb 1 ; 1 if the EOF packet received
- resb 3 ; Currently unusued
- ; At end since it should not be zeroed on socked close
-tftp_pktbuf resw 1 ; Packet buffer offset
- endstruc
-%ifndef DEPEND
-%if (open_file_t_size & (open_file_t_size-1))
-%error "open_file_t is not a power of 2"
-%endif
-%endif
; ---------------------------------------------------------------------------
; BEGIN CODE
@@ -157,67 +71,51 @@ tftp_pktbuf resw 1 ; Packet buffer offset
; Memory below this point is reserved for the BIOS and the MBR
;
section .earlybss
+ global trackbuf
trackbufsize equ 8192
trackbuf resb trackbufsize ; Track buffer goes here
; ends at 2800h
- alignb open_file_t_size
-Files resb MAX_OPEN*open_file_t_size
+ ; These fields save information from before the time
+ ; .bss is zeroed... must be in .earlybss
+ global InitStack
+InitStack resd 1
+ section .bss16
alignb FILENAME_MAX
-BootFile resb 256 ; Boot file from DHCP packet
-PathPrefix resb 256 ; Path prefix derived from boot file
-DotQuadBuf resb 16 ; Buffer for dotted-quad IP address
+ global IPOption
IPOption resb 80 ; ip= option buffer
-InitStack resd 1 ; Pointer to reset stack (SS:SP)
PXEStack resd 1 ; Saved stack during PXE call
- section .bss
alignb 4
+ global DHCPMagic, RebootTime, APIVer
RebootTime resd 1 ; Reboot timeout, if set by option
-StrucPtr resd 1 ; Pointer to PXENV+ or !PXE structure
+StrucPtr resw 2 ; Pointer to PXENV+ or !PXE structure
APIVer resw 1 ; PXE API version found
LocalBootType resw 1 ; Local boot return code
-RealBaseMem resw 1 ; Amount of DOS memory after freeing
-OverLoad resb 1 ; Set if DHCP packet uses "overloading"
DHCPMagic resb 1 ; PXELINUX magic flags
; The relative position of these fields matter!
-MAC_MAX equ 32 ; Handle hardware addresses this long
-MACLen resb 1 ; MAC address len
-MACType resb 1 ; MAC address type
-MAC resb MAC_MAX+1 ; Actual MAC address
+ global BOOTIFStr
BOOTIFStr resb 7 ; Space for "BOOTIF="
-MACStr resb 3*(MAC_MAX+1) ; MAC address as a string
-
-; The relative position of these fields matter!
-UUIDType resb 1 ; Type byte from DHCP option
-UUID resb 16 ; UUID, from the PXE stack
-UUIDNull resb 1 ; dhcp_copyoption zero-terminates
-
-;
-; PXE packets which don't need static initialization
-;
- alignb 4
-pxe_unload_stack_pkt:
-.status: resw 1 ; Status
-.reserved: resb 10 ; Reserved
-pxe_unload_stack_pkt_len equ $-pxe_unload_stack_pkt
- alignb 16
- ; BOOTP/DHCP packet buffer
-
- section .bss2
+ section .bss16
+ global packet_buf
alignb 16
packet_buf resb 2048 ; Transfer packet
packet_buf_size equ $-packet_buf
- section .text
+ section .text16
;
; PXELINUX needs more BSS than the other derivatives;
; therefore we relocate it from 7C00h on startup.
;
StackBuf equ $-44 ; Base of stack if we use our own
+StackTop equ StackBuf
+
+ ; PXE loads the whole file, but assume it can't be more
+ ; than (384-31)K in size.
+MaxLMA equ 384*1024
;
; Primary entry point.
@@ -332,387 +230,24 @@ adhcp_copy:
mov si,copyright_str
call writestr_early
-
-
-;
-; Assume API version 2.1, in case we find the !PXE structure without
-; finding the PXENV+ structure. This should really look at the Base
-; Code ROM ID structure in have_pxe, but this is adequate for now --
-; if we have !PXE, we have to be 2.1 or higher, and we don't care
-; about higher versions than that.
-;
- mov word [APIVer],0201h
-
-;
-; Now we need to find the !PXE structure.
-; We search for the following, in order:
;
-; a. !PXE structure as SS:[SP+4]
-; b. PXENV+ structure at [ES:BX]
-; c. INT 1Ah AX=5650h -> PXENV+
-; d. Search memory for !PXE
-; e. Search memory for PXENV+
+; do fs initialize
;
-; If we find a PXENV+ structure, we try to find a !PXE structure from
-; it if the API version is 2.1 or later.
-;
- ; Plan A: !PXE structure as SS:[SP+4]
- lgs bp,[InitStack] ; GS:BP -> original stack
- les bx,[gs:bp+48]
- call is_pxe
- je have_pxe
-
- ; Plan B: PXENV+ structure at [ES:BX]
- inc byte [plan]
- mov bx,[gs:bp+24] ; Original BX
- mov es,[gs:bp+4] ; Original ES
- call is_pxenv
- je have_pxenv
-
- ; Plan C: PXENV+ structure via INT 1Ah AX=5650h
- inc byte [plan]
- mov ax, 5650h
-%if USE_PXE_PROVIDED_STACK == 0
- lss sp,[InitStack]
-%endif
- int 1Ah ; May trash regs
-%if USE_PXE_PROVIDED_STACK == 0
- lss esp,[BaseStack]
-%endif
- sti ; Work around Etherboot bug
-
- jc no_int1a
- cmp ax,564Eh
- jne no_int1a
-
- call is_pxenv
- je have_pxenv
-
-no_int1a:
- ; Plan D: !PXE memory scan
- inc byte [plan]
- call memory_scan_for_pxe_struct ; !PXE scan
- je have_pxe
-
- ; Plan E: PXENV+ memory scan
- inc byte [plan]
- call memory_scan_for_pxenv_struct ; PXENV+ scan
- je have_pxenv
-
- ; Found nothing at all!!
-no_pxe:
- mov si,err_nopxe
- call writestr_early
- jmp kaboom
-
-have_pxenv:
- mov [StrucPtr],bx
- mov [StrucPtr+2],es
-
- mov si,found_pxenv
- call writestr_early
-
- mov si,apiver_str
- call writestr_early
- mov ax,[es:bx+6]
- mov [APIVer],ax
- call writehex4
- call crlf
-
- cmp ax,0201h ; API version 2.1 or higher
- jb .old_api
- cmp byte [es:bx+8],2Ch ; Space for !PXE pointer?
- jb .pxescan
- les bx,[es:bx+28h] ; !PXE structure pointer
- call is_pxe
- je have_pxe
-
- ; Nope, !PXE structure missing despite API 2.1+, or at least
- ; the pointer is missing. Do a last-ditch attempt to find it.
-.pxescan:
- call memory_scan_for_pxe_struct
- je have_pxe
-
- ; Otherwise, no dice, use PXENV+ structure
-.old_api:
- les bx,[StrucPtr]
- push word [es:bx+22h] ; UNDI data len
- push word [es:bx+20h] ; UNDI data seg
- push word [es:bx+26h] ; UNDI code len
- push word [es:bx+24h] ; UNDI code seg
- push dword [es:bx+0Ah] ; PXENV+ entry point
-
- mov si,pxenventry_msg
- jmp have_entrypoint
-
-have_pxe:
- mov [StrucPtr],bx
- mov [StrucPtr+2],es
-
- push word [es:bx+2Eh] ; UNDI data len
- push word [es:bx+28h] ; UNDI data seg
- push word [es:bx+36h] ; UNDI code len
- push word [es:bx+30h] ; UNDI code seg
- push dword [es:bx+10h] ; !PXE entry point
-
- mov si,pxeentry_msg
-
-have_entrypoint:
- push cs
- pop es ; Restore CS == DS == ES
-
- call writestr_early ; !PXE or PXENV+ entry found
-
- pop dword [PXEEntry]
- mov ax,[PXEEntry+2]
- call writehex4
- mov al,':'
- call writechr
- mov ax,[PXEEntry]
- call writehex4
-
- mov si,viaplan_msg
- call writestr_early
-
- mov si,undi_code_msg
- call writestr_early
- pop ax ; UNDI code segment
- call writehex4
- xchg dx,ax
- mov si,len_msg
- call writestr_early
- pop ax ; UNDI code length
- call writehex4
- call crlf
- add ax,15
- shr ax,4
- add dx,ax ; DX = seg of end of UNDI code
-
- mov si,undi_data_msg
- call writestr_early
- pop ax ; UNDI data segment
- call writehex4
- xchg bx,ax
- mov si,len_msg
- call writestr_early
- pop ax ; UNDI data length
- call writehex4
- call crlf
- add ax,15
- shr ax,4
- add ax,bx ; AX = seg of end of UNDI data
-
- cmp ax,dx
- ja .data_on_top
- xchg ax,dx
-.data_on_top:
- ; Could we safely add 63 here before the shift?
- shr ax,6 ; Convert to kilobytes
- mov [RealBaseMem],ax
-
+ mov eax,ROOT_FS_OPS
+ pm_call fs_init
-;
-; Network-specific initialization
-;
- xor ax,ax
- mov [LocalDomain],al ; No LocalDomain received
-
-
-; This is a good time to initialize DHCPMagic...
-; Initialize it to 1 meaning we will accept options found;
-; in earlier versions of PXELINUX bit 0 was used to indicate
-; we have found option 208 with the appropriate magic number;
-; we no longer require that, but MAY want to re-introduce
-; it in the future for vendor encapsulated options.
- mov byte [DHCPMagic],1
-
-;
-; Process any hardwired options the user may have specified. This is
-; different than the actual packets in that there is no header, just
-; an option field.
-;
- mov cx,[bdhcp_len]
- mov si,trackbuf
- call parse_dhcp_options
-
-;
-; The DHCP client identifiers are best gotten from the DHCPREQUEST
-; packet (query info 1).
-;
-query_bootp_1:
- mov si,get_packet_msg
- call writestr_early
-
- mov dl,1
- call pxe_get_cached_info
- call parse_dhcp
-
-;
-; Now attempt to get the BOOTP/DHCP packet that brought us life (and an IP
-; address). This lives in the DHCPACK packet (query info 2).
-;
-query_bootp_2:
- mov dl,2
- call pxe_get_cached_info
- call parse_dhcp ; Parse DHCP packet
-;
-; Save away MAC address (assume this is in query info 2. If this
-; turns out to be problematic it might be better getting it from
-; the query info 1 packet.)
-;
-.save_mac:
- movzx cx,byte [trackbuf+bootp.hardlen]
- cmp cx,16
- jna .mac_ok
- xor cx,cx ; Bad hardware address length
-.mac_ok:
- mov [MACLen],cl
- mov al,[trackbuf+bootp.hardware]
- mov [MACType],al
- mov si,trackbuf+bootp.macaddr
- mov di,MAC
- rep movsb
-
-; Enable this if we really need to zero-pad this field...
-; mov cx,MAC+MAC_MAX+1
-; sub cx,di
-; xor ax,ax
-; rep stosb
-
-;
-; Now, get the boot file and other info. This lives in the CACHED_REPLY
-; packet (query info 3).
-;
-query_bootp_3:
- mov dl,3
- call pxe_get_cached_info
- call parse_dhcp ; Parse DHCP packet
- call crlf
-
-;
-; Process any hardwired options the user may have specified. This is
-; different than the actual packets in that there is no header, just
-; an option field. This handles the "after" options
-;
- mov cx,[adhcp_len]
- mov si,trackbuf+trackbufsize/2
- call parse_dhcp_options
-
-;
-; Generate the bootif string, and the hardware-based config string.
-;
-make_bootif_string:
- mov si,bootif_str
- mov di,BOOTIFStr
- mov cx,bootif_str_len
- rep movsb
-
- movzx cx,byte [MACLen]
- mov si,MACType
- inc cx
-.hexify_mac:
- push cx
- mov cl,1 ; CH == 0 already
- call lchexbytes
- mov al,'-'
- stosb
- pop cx
- loop .hexify_mac
- mov [di-1],cl ; Null-terminate and strip final dash
-;
-; Generate ip= option
-;
- call genipopt
-
-;
-; Print IP address
-;
- mov eax,[MyIP]
- mov di,DotQuadBuf
- push di
- call gendotquad ; This takes network byte order input
-
- xchg ah,al ; Convert to host byte order
- ror eax,16 ; (BSWAP doesn't work on 386)
- xchg ah,al
-
- mov si,myipaddr_msg
- call writestr_early
- call writehex8
- mov al,' '
- call writechr
- pop si ; DotQuadBuf
- call writestr_early
- call crlf
-
- mov si,IPOption
- call writestr_early
- call crlf
-
-;
-; Check to see if we got any PXELINUX-specific DHCP options; in particular,
-; if we didn't get the magic enable, do not recognize any other options.
-;
-check_dhcp_magic:
- test byte [DHCPMagic], 1 ; If we didn't get the magic enable...
- jnz .got_magic
- mov byte [DHCPMagic], 0 ; If not, kill all other options
-.got_magic:
-
-
-;
-; Initialize UDP stack
-;
-udp_init:
- mov eax,[MyIP]
- mov [pxe_udp_open_pkt.sip],eax
- mov di,pxe_udp_open_pkt
- mov bx,PXENV_UDP_OPEN
- call pxenv
- jc .failed
- cmp word [pxe_udp_open_pkt.status], byte 0
- je .success
-.failed: mov si,err_udpinit
- call writestr_early
- jmp kaboom
-.success:
-
-;
-; Check to see if we're using gPXE
-;
-%if GPXE
- ; If we get here, the gPXE status is unknown.
- mov di,gpxe_file_api_check
- mov bx,PXENV_FILE_API_CHECK ; BH = 0
- call pxenv
- jc .nogood
- cmp dword [di+4],0xe9c17b20
- jne .nogood
- mov eax,[di+12]
- mov [GPXEFuncs],eax
- not ax ; Set bits of *missing* functions...
- and ax,01001011b ; The functions we care about
- setz bh
-.nogood:
- mov [HasGPXE],bh
-
- section .data
- alignb 4
-GPXEFuncs dd 0
-HasGPXE db 0
-
- section .text
-%endif
+ section .rodata
+ alignz 4
+ROOT_FS_OPS:
+ extern pxe_fs_ops
+ dd pxe_fs_ops
+ dd 0
-;
-; Common initialization code
-;
-%include "cpuinit.inc"
+ section .text16
;
-; Detect NIC type and initialize the idle mechanism
+; Initialize the idle mechanism
;
- call pxe_detect_nic_type
call reset_idle
;
@@ -730,145 +265,9 @@ HasGPXE db 0
;
;
-; Store standard filename prefix
-;
-prefix: test byte [DHCPMagic], 04h ; Did we get a path prefix option
- jnz .got_prefix
- mov si,BootFile
- mov di,PathPrefix
- cld
- call strcpy
- mov cx,di
- sub cx,PathPrefix+1
- std
- lea si,[di-2] ; Skip final null!
-.find_alnum: lodsb
- or al,20h
- cmp al,'.' ; Count . or - as alphanum
- je .alnum
- cmp al,'-'
- je .alnum
- cmp al,'0'
- jb .notalnum
- cmp al,'9'
- jbe .alnum
- cmp al,'a'
- jb .notalnum
- cmp al,'z'
- ja .notalnum
-.alnum: loop .find_alnum
- dec si
-.notalnum: mov byte [si+2],0 ; Zero-terminate after delimiter
- cld
-.got_prefix:
- mov si,tftpprefix_msg
- call writestr_early
- mov si,PathPrefix
- call writestr_early
- call crlf
-
- ; Set CurrentDirName
- push di
- mov si,PathPrefix
- mov di,CurrentDirName
- call strcpy
- pop di
-
-;
; Load configuration file
;
-find_config:
-
-;
-; Begin looking for configuration file
-;
-config_scan:
- test byte [DHCPMagic], 02h
- jz .no_option
-
- ; We got a DHCP option, try it first
- call .try
- jnz .success
-
-.no_option:
- mov di,ConfigName
- mov si,cfgprefix
- mov cx,cfgprefix_len
- rep movsb
-
- ; Have to guess config file name...
-
- ; Try loading by UUID.
- cmp byte [HaveUUID],0
- je .no_uuid
-
- push di
- mov bx,uuid_dashes
- mov si,UUID
-.gen_uuid:
- movzx cx,byte [bx]
- jcxz .done_uuid
- inc bx
- call lchexbytes
- mov al,'-'
- stosb
- jmp .gen_uuid
-.done_uuid:
- mov [di-1],cl ; Remove last dash and zero-terminate
- pop di
- call .try
- jnz .success
-.no_uuid:
-
- ; Try loading by MAC address
- push di
- mov si,MACStr
- call strcpy
- pop di
- call .try
- jnz .success
-
- ; Nope, try hexadecimal IP prefixes...
-.scan_ip:
- mov cx,4
- mov si,MyIP
- call uchexbytes ; Convert to hex string
-
- mov cx,8 ; Up to 8 attempts
-.tryagain:
- mov byte [di],0 ; Zero-terminate string
- call .try
- jnz .success
- dec di ; Drop one character
- loop .tryagain
-
- ; Final attempt: "default" string
- mov si,default_str ; "default" string
- call strcpy
- call .try
- jnz .success
-
- mov si,err_noconfig
- call writestr_early
- jmp kaboom
-
-.try:
- pusha
- mov si,trying_msg
- call writestr_early
- mov di,ConfigName
- mov si,di
- call writestr_early
- call crlf
- mov si,di
- mov di,KernelName ; Borrow this buffer for mangled name
- call mangle_name
- call open
- popa
- ret
-
-
-.success:
+ pm_call load_config
;
; Linux kernel loading code is common. However, we need to define
@@ -878,7 +277,7 @@ config_scan:
; Unload PXE stack
%define HAVE_UNLOAD_PREP
%macro UNLOAD_PREP 0
- call unload_pxe
+ pm_call unload_pxe
%endmacro
;
@@ -901,7 +300,7 @@ local_boot:
mov si,localboot_msg
call writestr_early
; Restore the environment we were called with
- call reset_pxe
+ pm_call reset_pxe
call cleanup_hardware
lss sp,[InitStack]
pop gs
@@ -919,6 +318,9 @@ local_boot:
; kaboom: write a message and bail out. Wait for quite a while,
; or a user keypress, then do a hard reboot.
;
+; Note: use BIOS_timer here; we may not have jiffies set up.
+;
+ global kaboom
kaboom:
RESET_STACK_AND_SEGS AX
.patch: mov si,bailmsg
@@ -953,748 +355,6 @@ kaboom:
mov word [BIOS_magic],0 ; Cold reboot
jmp 0F000h:0FFF0h ; Reset vector address
-;
-; memory_scan_for_pxe_struct:
-; memory_scan_for_pxenv_struct:
-;
-; If none of the standard methods find the !PXE/PXENV+ structure,
-; look for it by scanning memory.
-;
-; On exit, if found:
-; ZF = 1, ES:BX -> !PXE structure
-; Otherwise:
-; ZF = 0
-;
-; Assumes DS == CS
-; Clobbers AX, BX, CX, DX, SI, ES
-;
-memory_scan_for_pxe_struct:
- mov dx,is_pxe
- mov ax,[BIOS_fbm] ; Starting segment
- shl ax,(10-4) ; Kilobytes -> paragraphs
- jmp memory_scan_common
-
-memory_scan_for_pxenv_struct:
- mov ax,1000h ; Starting segment
- mov dx,is_pxenv
- ; fall through
-
-memory_scan_common:
- dec ax ; To skip inc ax
-.mismatch:
- inc ax
- cmp ax,0A000h-1 ; End of memory
- ja .not_found ; ZF = 0 on not found
- mov es,ax
- xor bx,bx
- call dx
- jne .mismatch
-.not_found:
- ret
-
-;
-; is_pxe:
-; Validity check on possible !PXE structure in ES:BX
-; is_pxenv:
-; Validity check on possible PXENV+ structure in ES:BX
-;
-; Return ZF = 1 on success
-;
-; Clobbers CX and SI
-;
-is_struc:
-.pxe:
- cmp dword [es:bx],'!PXE'
- jne .bad
- movzx cx,byte [es:bx+4]
- cmp cx,58h
- jae .checksum
- ret
-.pxenv:
- cmp dword [es:bx],'PXEN'
- jne .bad
- cmp word [es:bx+4],'V+'
- jne .bad
- movzx cx,[es:bx+8]
- cmp cx,28h
- jb .bad
-.checksum:
- push ax
- mov si,bx
- xor ax,ax
-.loop:
- es lodsb
- add ah,al
- loop .loop
- pop ax
-.bad:
- ret
-
-is_pxe equ is_struc.pxe
-is_pxenv equ is_struc.pxenv
-
-;
-; close_file:
-; Deallocates a file structure (pointer in SI)
-; Assumes CS == DS.
-;
-; XXX: We should check to see if this file is still open on the server
-; side and send a courtesy ERROR packet to the server.
-;
-close_file:
- and si,si
- jz .closed
- mov word [si],0 ; Not in use
-.closed: ret
-
-;
-; searchdir:
-;
-; Open a TFTP connection to the server
-;
-; On entry:
-; DS:DI = mangled filename
-; If successful:
-; ZF clear
-; SI = socket pointer
-; EAX = file length in bytes, or -1 if unknown
-; If unsuccessful
-; ZF set
-;
-
-searchdir:
- push es
- push bx
- push cx
- mov ax,ds
- mov es,ax
- mov si,di
- push bp
- mov bp,sp
-
- call allocate_socket
- jz .ret
-
- mov ax,TimeoutTable ; Reset timeout
-
-.sendreq: push ax ; [bp-2] - Timeout pointer
- push si ; [bp-4] - File name
-
- mov di,packet_buf
- mov [pxe_udp_write_pkt.buffer],di
-
- mov ax,TFTP_RRQ ; TFTP opcode
- stosw
-
- lodsd ; EAX <- server override (if any)
- and eax,eax
- jnz .noprefix ; No prefix, and we have the server
-
- push si ; Add common prefix
- mov si,PathPrefix
- call strcpy
- dec di
- pop si
-
- mov eax,[ServerIP] ; Get default server
-
-.noprefix:
- call strcpy ; Filename
-%if GPXE
- mov si,packet_buf+2
- call is_gpxe
- jnc .gpxe
-%endif
-
- mov [bx+tftp_remoteip],eax
-
- push bx ; [bp-6] - TFTP block
- mov bx,[bx]
- push bx ; [bp-8] - TID (local port no)
-
- mov [pxe_udp_write_pkt.sip],eax
- ; Now figure out the gateway
- xor eax,[MyIP]
- and eax,[Netmask]
- jz .nogwneeded
- mov eax,[Gateway]
-.nogwneeded:
- mov [pxe_udp_write_pkt.gip],eax
- mov [pxe_udp_write_pkt.lport],bx
- mov ax,[ServerPort]
- mov [pxe_udp_write_pkt.rport],ax
- mov si,tftp_tail
- mov cx,tftp_tail_len
- rep movsb
- sub di,packet_buf ; Get packet size
- mov [pxe_udp_write_pkt.buffersize],di
-
- mov di,pxe_udp_write_pkt
- mov bx,PXENV_UDP_WRITE
- call pxenv
- jc .failure
- cmp word [pxe_udp_write_pkt.status],byte 0
- jne .failure
-
- ;
- ; Danger, Will Robinson! We need to support timeout
- ; and retry lest we just lost a packet...
- ;
-
- ; Packet transmitted OK, now we need to receive
-.getpacket: mov bx,[bp-2]
- movzx bx,byte [bx]
- push bx ; [bp-10] - timeout in ticks
- push word [BIOS_timer] ; [bp-12]
-
-.pkt_loop: mov bx,[bp-8] ; TID
- mov di,packet_buf
- mov [pxe_udp_read_pkt.buffer],di
- mov [pxe_udp_read_pkt.buffer+2],ds
- mov word [pxe_udp_read_pkt.buffersize],packet_buf_size
- mov eax,[MyIP]
- mov [pxe_udp_read_pkt.dip],eax
- mov [pxe_udp_read_pkt.lport],bx
- mov di,pxe_udp_read_pkt
- mov bx,PXENV_UDP_READ
- call pxenv
- jnc .got_packet ; Wait for packet
-.no_packet:
- mov dx,[BIOS_timer]
- cmp dx,[bp-12]
- je .pkt_loop
- mov [bp-12],dx
- dec word [bp-10]
- jnz .pkt_loop
- pop ax ; Adjust stack
- pop ax
- jmp .failure
-
-.got_packet:
- mov si,[bp-6] ; TFTP pointer
- mov bx,[bp-8] ; TID
-
- ; Make sure the packet actually came from the server
- ; This is technically not to the TFTP spec?
- mov eax,[si+tftp_remoteip]
- cmp [pxe_udp_read_pkt.sip],eax
- jne .no_packet
-
- ; Got packet - reset timeout
- mov word [bp-2],TimeoutTable
-
- pop ax ; Adjust stack
- pop ax
-
- mov ax,[pxe_udp_read_pkt.rport]
- mov [si+tftp_remoteport],ax
-
- ; filesize <- -1 == unknown
- mov dword [si+tftp_filesize], -1
- ; Default blksize unless blksize option negotiated
- mov word [si+tftp_blksize], TFTP_BLOCKSIZE
-
- movzx ecx,word [pxe_udp_read_pkt.buffersize]
- sub cx,2 ; CX <- bytes after opcode
- jb .failure ; Garbled reply
-
- mov si,packet_buf
- lodsw
-
- cmp ax, TFTP_ERROR
- je .bailnow ; ERROR reply: don't try again
-
- ; If the server doesn't support any options, we'll get
- ; a DATA reply instead of OACK. Stash the data in
- ; the file buffer and go with the default value for
- ; all options...
- cmp ax, TFTP_DATA
- je .no_oack
-
- cmp ax, TFTP_OACK
- jne .err_reply ; Unknown packet type
-
- ; Now we need to parse the OACK packet to get the transfer
- ; and packet sizes.
- ; SI -> first byte of options; [E]CX -> byte count
-.parse_oack:
- jcxz .done_pkt ; No options acked
-
-.get_opt_name:
- ; If we find an option which starts with a NUL byte,
- ; (a null option), we're either seeing garbage that some
- ; TFTP servers add to the end of the packet, or we have
- ; no clue how to parse the rest of the packet (what is
- ; an option name and what is a value?) In either case,
- ; discard the rest.
- cmp byte [si],0
- je .done_pkt
-
- mov di,si
- mov bx,si
-.opt_name_loop: lodsb
- and al,al
- jz .got_opt_name
- or al,20h ; Convert to lowercase
- stosb
- loop .opt_name_loop
- ; We ran out, and no final null
- jmp .done_pkt ; Ignore runt option
-.got_opt_name: ; si -> option value
- dec cx ; bytes left in pkt
- jz .done_pkt ; Option w/o value, ignore
-
- ; Parse option pointed to by bx; guaranteed to be
- ; null-terminated.
- push cx
- push si
- mov si,bx ; -> option name
- mov bx,tftp_opt_table
- mov cx,tftp_opts
-.opt_loop:
- push cx
- push si
- mov di,[bx] ; Option pointer
- mov cx,[bx+2] ; Option len
- repe cmpsb
- pop si
- pop cx
- je .get_value ; OK, known option
- add bx,6
- loop .opt_loop
-
- pop si
- pop cx
- ; Non-negotiated option returned, no idea what it means...
- jmp .err_reply
-
-.get_value: pop si ; si -> option value
- pop cx ; cx -> bytes left in pkt
- mov bx,[bx+4] ; Pointer to data target
- add bx,[bp-6] ; TFTP socket pointer
- xor eax,eax
- xor edx,edx
-.value_loop: lodsb
- and al,al
- jz .got_value
- sub al,'0'
- cmp al, 9
- ja .err_reply ; Not a decimal digit
- imul edx,10
- add edx,eax
- mov [bx],edx
- loop .value_loop
- ; Ran out before final null, accept anyway
- jmp short .done_pkt
-
-.got_value:
- dec cx
- jnz .get_opt_name ; Not end of packet
-
- ; ZF == 1
-
- ; Success, done!
-.done_pkt:
- pop si ; Junk
- pop si ; We want the packet ptr in SI
-
- mov eax,[si+tftp_filesize]
-.got_file: ; SI->socket structure, EAX = size
- and eax,eax ; Set ZF depending on file size
- jz .error_si ; ZF = 1 need to free the socket
-.ret:
- leave ; SP <- BP, POP BP
- pop cx
- pop bx
- pop es
- ret
-
-
-.no_oack: ; We got a DATA packet, meaning no options are
- ; suported. Save the data away and consider the length
- ; undefined, *unless* this is the only data packet...
- mov bx,[bp-6] ; File pointer
- sub cx,2 ; Too short?
- jb .failure
- lodsw ; Block number
- cmp ax,htons(1)
- jne .failure
- mov [bx+tftp_lastpkt],ax
- cmp cx,TFTP_BLOCKSIZE
- ja .err_reply ; Corrupt...
- je .not_eof
- ; This was the final EOF packet, already...
- ; We know the filesize, but we also want to ack the
- ; packet and set the EOF flag.
- mov [bx+tftp_filesize],ecx
- mov byte [bx+tftp_goteof],1
- push si
- mov si,bx
- ; AX = htons(1) already
- call ack_packet
- pop si
-.not_eof:
- mov [bx+tftp_bytesleft],cx
- mov ax,pktbuf_seg
- push es
- mov es,ax
- mov di,tftp_pktbuf
- mov [bx+tftp_dataptr],di
- add cx,3
- shr cx,2
- rep movsd
- pop es
- jmp .done_pkt
-
-.err_reply: ; TFTP protocol error. Send ERROR reply.
- ; ServerIP and gateway are already programmed in
- mov si,[bp-6]
- mov ax,[si+tftp_remoteport]
- mov word [pxe_udp_write_pkt.rport],ax
- mov word [pxe_udp_write_pkt.buffer],tftp_proto_err
- mov word [pxe_udp_write_pkt.buffersize],tftp_proto_err_len
- mov di,pxe_udp_write_pkt
- mov bx,PXENV_UDP_WRITE
- call pxenv
-
- ; Write an error message and explode
- mov si,err_damage
- call writestr_early
- jmp kaboom
-
-.bailnow:
- ; Immediate error - no retry
- mov word [bp-2],TimeoutTableEnd-1
-
-.failure: pop bx ; Junk
- pop bx
- pop si
- pop ax
- inc ax
- cmp ax,TimeoutTableEnd
- jb .sendreq ; Try again
-
-.error: mov si,bx ; Socket pointer
-.error_si: ; Socket pointer already in SI
- call free_socket ; ZF <- 1, SI <- 0
- jmp .ret
-
-
-%if GPXE
-.gpxe:
- push bx ; Socket pointer
- mov di,gpxe_file_open
- mov word [di],2 ; PXENV_STATUS_BAD_FUNC
- mov word [di+4],packet_buf+2 ; Completed URL
- mov [di+6],ds
- mov bx,PXENV_FILE_OPEN
- call pxenv
- pop si ; Socket pointer in SI
- jc .error_si
-
- mov ax,[di+2]
- mov word [si+tftp_localport],-1 ; gPXE URL
- mov [si+tftp_remoteport],ax
- mov di,gpxe_get_file_size
- mov [di+2],ax
-
-%if 0
- ; Disable this for now since gPXE doesn't always
- ; return valid information in PXENV_GET_FILE_SIZE
- mov bx,PXENV_GET_FILE_SIZE
- call pxenv
- mov eax,[di+4] ; File size
- jnc .oksize
-%endif
- or eax,-1 ; Size unknown
-.oksize:
- mov [si+tftp_filesize],eax
- jmp .got_file
-%endif ; GPXE
-
-;
-; allocate_socket: Allocate a local UDP port structure
-;
-; If successful:
-; ZF set
-; BX = socket pointer
-; If unsuccessful:
-; ZF clear
-;
-allocate_socket:
- push cx
- mov bx,Files
- mov cx,MAX_OPEN
-.check: cmp word [bx], byte 0
- je .found
- add bx,open_file_t_size
- loop .check
- xor cx,cx ; ZF = 1
- pop cx
- ret
- ; Allocate a socket number. Socket numbers are made
- ; guaranteed unique by including the socket slot number
- ; (inverted, because we use the loop counter cx); add a
- ; counter value to keep the numbers from being likely to
- ; get immediately reused.
- ;
- ; The NextSocket variable also contains the top two bits
- ; set. This generates a value in the range 49152 to
- ; 57343.
-.found:
- dec cx
- push ax
- mov ax,[NextSocket]
- inc ax
- and ax,((1 << (13-MAX_OPEN_LG2))-1) | 0xC000
- mov [NextSocket],ax
- shl cx,13-MAX_OPEN_LG2
- add cx,ax ; ZF = 0
- xchg ch,cl ; Convert to network byte order
- mov [bx],cx ; Socket in use
- pop ax
- pop cx
- ret
-
-;
-; Free socket: socket in SI; return SI = 0, ZF = 1 for convenience
-;
-free_socket:
- push es
- pusha
- xor ax,ax
- mov es,ax
- mov di,si
- mov cx,tftp_pktbuf >> 1 ; tftp_pktbuf is not cleared
- rep stosw
- popa
- pop es
- xor si,si
- ret
-
-;
-; parse_dotquad:
-; Read a dot-quad pathname in DS:SI and output an IP
-; address in EAX, with SI pointing to the first
-; nonmatching character.
-;
-; Return CF=1 on error.
-;
-; No segment assumptions permitted.
-;
-parse_dotquad:
- push cx
- mov cx,4
- xor eax,eax
-.parseloop:
- mov ch,ah
- mov ah,al
- lodsb
- sub al,'0'
- jb .notnumeric
- cmp al,9
- ja .notnumeric
- aad ; AL += 10 * AH; AH = 0;
- xchg ah,ch
- jmp .parseloop
-.notnumeric:
- cmp al,'.'-'0'
- pushf
- mov al,ah
- mov ah,ch
- xor ch,ch
- ror eax,8
- popf
- jne .error
- loop .parseloop
- jmp .done
-.error:
- loop .realerror ; If CX := 1 then we're done
- clc
- jmp .done
-.realerror:
- stc
-.done:
- dec si ; CF unchanged!
- pop cx
- ret
-
-;
-; is_url: Return CF=0 if and only if the buffer pointed to by
-; DS:SI is a URL (contains ://). No registers modified.
-;
-%if GPXE
-is_url:
- push si
- push eax
-.loop:
- mov eax,[si]
- inc si
- and al,al
- jz .not_url
- and eax,0FFFFFFh
- cmp eax,'://'
- jne .loop
-.done:
- ; CF=0 here
- pop eax
- pop si
- ret
-.not_url:
- stc
- jmp .done
-
-;
-; is_gpxe: Return CF=0 if and only if the buffer pointed to by
-; DS:SI is a URL (contains ://) *and* the gPXE extensions
-; API is available. No registers modified.
-;
-is_gpxe:
- call is_url
- jc .ret ; Not a URL, don't bother
-.again:
- cmp byte [HasGPXE],1
- jnb .ret
- ; CF=1 if not available (0),
- ; CF=0 if known available (1).
-
- inc word [GPXEWarningCtr]
- jnz .skip
-
- push si
- mov si,gpxe_warning_msg
- call writestr
- pop si
-.skip:
- stc
-
-.ret: ret
-
-
- section .data
- alignz 2
-GPXEWarningCtr:
- dw -1 ; Print msg when it goes to 0
-gpxe_warning_msg:
- db 'URL syntax, but gPXE extensions not detected, '
- db 'trying plain TFTP...', CR, LF, 0
-
- section .text
-
-%endif
-
-;
-; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
-; to by ES:DI; ends on encountering any whitespace.
-; DI is preserved.
-;
-; This verifies that a filename is < FILENAME_MAX characters
-; and doesn't contain whitespace, and zero-pads the output buffer,
-; so "repe cmpsb" can do a compare.
-;
-; The first four bytes of the manged name is the IP address of
-; the download host, 0 for no host, or -1 for a gPXE URL.
-;
-; No segment assumptions permitted.
-;
-mangle_name:
- push di
-%if GPXE
- call is_url
- jc .not_url
- or eax,-1 ; It's a URL
- jmp .prefix_done
-.not_url:
-%endif ; GPXE
- push si
- mov eax,[cs:ServerIP]
- cmp byte [si],0
- je .noip ; Null filename?!?!
- cmp word [si],'::' ; Leading ::?
- je .gotprefix
-
-.more:
- inc si
- cmp byte [si],0
- je .noip
- cmp word [si],'::'
- jne .more
-
- ; We have a :: prefix of some sort, it could be either
- ; a DNS name or a dot-quad IP address. Try the dot-quad
- ; first...
-.here:
- pop si
- push si
- call parse_dotquad
- jc .notdq
- cmp word [si],'::'
- je .gotprefix
-.notdq:
- pop si
- push si
- call dns_resolv
- cmp word [si],'::'
- jne .noip
- and eax,eax
- jnz .gotprefix
-
-.noip:
- pop si
- xor eax,eax
- jmp .prefix_done
-
-.gotprefix:
- pop cx ; Adjust stack
- inc si ; Skip double colon
- inc si
-
-.prefix_done:
- stosd ; Save IP address prefix
- mov cx,FILENAME_MAX-5
-
-.mn_loop:
- lodsb
- cmp al,' ' ; If control or space, end
- jna .mn_end
- stosb
- loop .mn_loop
-.mn_end:
- inc cx ; At least one null byte
- xor ax,ax ; Zero-fill name
- rep stosb ; Doesn't do anything if CX=0
- pop di
- ret ; Done
-
-;
-; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
-; filename to the conventional representation. This is needed
-; for the BOOT_IMAGE= parameter for the kernel.
-;
-; NOTE: The output buffer needs to be able to hold an
-; expanded IP address.
-;
-; DS:SI -> input mangled file name
-; ES:DI -> output buffer
-;
-; On return, DI points to the first byte after the output name,
-; which is set to a null byte.
-;
-unmangle_name:
- push eax
- lodsd
- and eax,eax
- jz .noip
- cmp eax,-1
- jz .noip ; URL
- call gendotquad
- mov ax,'::'
- stosw
-.noip:
- call strcpy
- dec di ; Point to final null byte
- pop eax
- ret
;
; pxenv
@@ -1707,6 +367,7 @@ unmangle_name:
;
; While we're at it, save and restore all registers.
;
+ global pxenv
pxenv:
pushfd
pushad
@@ -1741,475 +402,49 @@ pxenv:
ret
; Must be after function def due to NASM bug
+ global PXEEntry
PXEEntry equ pxenv.jump+1
- section .bss
+ section .bss16
alignb 2
PXEStatus resb 2
- section .text
-
-;
-; getfssec: Get multiple clusters from a file, given the starting cluster.
-;
-; In this case, get multiple blocks from a specific TCP connection.
-;
-; On entry:
-; ES:BX -> Buffer
-; SI -> TFTP socket pointer
-; CX -> 512-byte block count; 0FFFFh = until end of file
-; On exit:
-; SI -> TFTP socket pointer (or 0 on EOF)
-; CF = 1 -> Hit EOF
-; ECX -> number of bytes actually read
-;
-getfssec:
- push eax
- push edi
- push bx
- push si
- push fs
- mov di,bx
- mov ax,pktbuf_seg
- mov fs,ax
-
- xor eax,eax
- movzx ecx,cx
- shl ecx,TFTP_BLOCKSIZE_LG2 ; Convert to bytes
- push ecx ; Initial request size
- jz .hit_eof ; Nothing to do?
-
-.need_more:
- call fill_buffer
- movzx eax,word [si+tftp_bytesleft]
- and ax,ax
- jz .hit_eof
-
- push ecx
- cmp ecx,eax
- jna .ok_size
- mov ecx,eax
-.ok_size:
- mov ax,cx ; EAX<31:16> == ECX<31:16> == 0
- mov bx,[si+tftp_dataptr]
- sub [si+tftp_bytesleft],cx
- xchg si,bx
- fs rep movsb ; Copy from packet buffer
- xchg si,bx
- mov [si+tftp_dataptr],bx
-
- pop ecx
- sub ecx,eax
- jnz .need_more
-
-.hit_eof:
- call fill_buffer
-
- pop eax ; Initial request amount
- xchg eax,ecx
- sub ecx,eax ; ... minus anything not gotten
-
- pop fs
- pop si
-
- ; Is there anything left of this?
- mov eax,[si+tftp_filesize]
- sub eax,[si+tftp_filepos]
- jnz .bytes_left
-
- cmp [si+tftp_bytesleft],ax ; AX == 0
- jne .bytes_left
-
- cmp byte [si+tftp_goteof],0
- je .done
- ; I'm 99% sure this can't happen, but...
- call fill_buffer ; Receive/ACK the EOF packet
-.done:
- ; The socket is closed and the buffer drained
- ; Close socket structure and re-init for next user
- call free_socket
- stc
- jmp .ret
-.bytes_left:
- clc
-.ret:
- pop bx
- pop edi
- pop eax
- ret
+ section .text16
;
-; Get a fresh packet if the buffer is drained, and we haven't hit
-; EOF yet. The buffer should be filled immediately after draining!
-;
-; expects fs -> pktbuf_seg and ds:si -> socket structure
-;
-fill_buffer:
- cmp word [si+tftp_bytesleft],0
- je .empty
- ret ; Otherwise, nothing to do
-
-.empty:
- push es
- pushad
- mov ax,ds
- mov es,ax
-
- ; Note: getting the EOF packet is not the same thing
- ; as tftp_filepos == tftp_filesize; if the EOF packet
- ; is empty the latter condition can be true without
- ; having gotten the official EOF.
- cmp byte [si+tftp_goteof],0
- jne .ret ; Already EOF
-
-%if GPXE
- cmp word [si+tftp_localport], -1
- jne .get_packet_tftp
- call get_packet_gpxe
- jmp .ret
-.get_packet_tftp:
-%endif ; GPXE
-
- ; TFTP code...
-.packet_loop:
- ; Start by ACKing the previous packet; this should cause the
- ; next packet to be sent.
- mov bx,TimeoutTable
-
-.send_ack: push bx ; <D> Retry pointer
- movzx cx,byte [bx] ; Timeout
-
- mov ax,[si+tftp_lastpkt]
- call ack_packet ; Send ACK
-
- ; We used to test the error code here, but sometimes
- ; PXE would return negative status even though we really
- ; did send the ACK. Now, just treat a failed send as
- ; a normally lost packet, and let it time out in due
- ; course of events.
-
-.send_ok: ; Now wait for packet.
- mov dx,[BIOS_timer] ; Get current time
-
-.wait_data: push cx ; <E> Timeout
- push dx ; <F> Old time
-
- mov bx,[si+tftp_pktbuf]
- mov [pxe_udp_read_pkt.buffer],bx
- mov [pxe_udp_read_pkt.buffer+2],fs
- mov [pxe_udp_read_pkt.buffersize],word PKTBUF_SIZE
- mov eax,[si+tftp_remoteip]
- mov [pxe_udp_read_pkt.sip],eax
- mov eax,[MyIP]
- mov [pxe_udp_read_pkt.dip],eax
- mov ax,[si+tftp_remoteport]
- mov [pxe_udp_read_pkt.rport],ax
- mov ax,[si+tftp_localport]
- mov [pxe_udp_read_pkt.lport],ax
- mov di,pxe_udp_read_pkt
- mov bx,PXENV_UDP_READ
- call pxenv
- jnc .recv_ok
-
- ; No packet, or receive failure
- mov dx,[BIOS_timer]
- pop ax ; <F> Old time
- pop cx ; <E> Timeout
- cmp ax,dx ; Same time -> don't advance timeout
- je .wait_data ; Same clock tick
- loop .wait_data ; Decrease timeout
-
- pop bx ; <D> Didn't get any, send another ACK
- inc bx
- cmp bx,TimeoutTableEnd
- jb .send_ack
- jmp kaboom ; Forget it...
-
-.recv_ok: pop dx ; <F>
- pop cx ; <E>
-
- cmp word [pxe_udp_read_pkt.buffersize],byte 4
- jb .wait_data ; Bad size for a DATA packet
-
- mov bx,[si+tftp_pktbuf]
- cmp word [fs:bx],TFTP_DATA ; Not a data packet?
- jne .wait_data ; Then wait for something else
-
- mov ax,[si+tftp_lastpkt]
- xchg ah,al ; Host byte order
- inc ax ; Which packet are we waiting for?
- xchg ah,al ; Network byte order
- cmp [fs:bx+2],ax
- je .right_packet
-
- ; Wrong packet, ACK the packet and then try again
- ; This is presumably because the ACK got lost,
- ; so the server just resent the previous packet
- mov ax,[fs:bx+2]
- call ack_packet
- jmp .send_ok ; Reset timeout
-
-.right_packet: ; It's the packet we want. We're also EOF if the
- ; size < blocksize
-
- pop cx ; <D> Don't need the retry count anymore
-
- mov [si+tftp_lastpkt],ax ; Update last packet number
-
- movzx ecx,word [pxe_udp_read_pkt.buffersize]
- sub cx,byte 4 ; Skip TFTP header
-
- ; Set pointer to data block
- lea ax,[bx+4] ; Data past TFTP header
- mov [si+tftp_dataptr],ax
-
- add [si+tftp_filepos],ecx
- mov [si+tftp_bytesleft],cx
-
- cmp cx,[si+tftp_blksize] ; Is it a full block?
- jb .last_block ; If not, it's EOF
-
-.ret:
- popad
- pop es
- ret
-
-
-.last_block: ; Last block - ACK packet immediately
- mov ax,[fs:bx+2]
- call ack_packet
-
- ; Make sure we know we are at end of file
- mov eax,[si+tftp_filepos]
- mov [si+tftp_filesize],eax
- mov byte [si+tftp_goteof],1
-
- jmp .ret
-
+; Invoke INT 1Ah on the PXE stack. This is used by the "Plan C" method
+; for finding the PXE entry point.
;
-; TimeoutTable: list of timeouts (in 18.2 Hz timer ticks)
-;
-; This is roughly an exponential backoff...
-;
- section .data
-TimeoutTable:
- db 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18
- db 21, 26, 31, 37, 44, 53, 64, 77, 92, 110, 132
- db 159, 191, 229, 255, 255, 255, 255
-TimeoutTableEnd equ $
-
- section .text
-;
-; ack_packet:
-;
-; Send ACK packet. This is a common operation and so is worth canning.
-;
-; Entry:
-; SI = TFTP block
-; AX = Packet # to ack (network byte order)
-; Exit:
-; All registers preserved
-;
-; This function uses the pxe_udp_write_pkt but not the packet_buf.
-;
-ack_packet:
- pushad
- mov [ack_packet_buf+2],ax ; Packet number to ack
- mov ax,[si]
- mov [pxe_udp_write_pkt.lport],ax
- mov ax,[si+tftp_remoteport]
- mov [pxe_udp_write_pkt.rport],ax
- mov eax,[si+tftp_remoteip]
- mov [pxe_udp_write_pkt.sip],eax
- xor eax,[MyIP]
- and eax,[Netmask]
- jz .nogw
- mov eax,[Gateway]
-.nogw:
- mov [pxe_udp_write_pkt.gip],eax
- mov [pxe_udp_write_pkt.buffer],word ack_packet_buf
- mov [pxe_udp_write_pkt.buffersize], word 4
- mov di,pxe_udp_write_pkt
- mov bx,PXENV_UDP_WRITE
- call pxenv
- popad
- ret
-
-%if GPXE
-;
-; Get a fresh packet from a gPXE socket; expects fs -> pktbuf_seg
-; and ds:si -> socket structure
-;
-; Assumes CS == DS == ES.
-;
-get_packet_gpxe:
- mov di,gpxe_file_read
-
- mov ax,[si+tftp_remoteport] ; gPXE filehandle
- mov [di+2],ax
- mov ax,[si+tftp_pktbuf]
- mov [di+6],ax
- mov [si+tftp_dataptr],ax
- mov [di+8],fs
-
-.again:
- mov word [di+4],PKTBUF_SIZE
- mov bx,PXENV_FILE_READ
- call pxenv
- jnc .ok ; Got data or EOF
- cmp word [di],PXENV_STATUS_TFTP_OPEN ; == EWOULDBLOCK
- je .again
- jmp kaboom ; Otherwise error...
-
-.ok:
- movzx eax,word [di+4] ; Bytes read
- mov [si+tftp_bytesleft],ax ; Bytes in buffer
- add [si+tftp_filepos],eax ; Position in file
-
- and ax,ax ; EOF?
- mov eax,[si+tftp_filepos]
-
- jnz .got_stuff
-
- ; We got EOF here, make sure the upper layers know
- mov [si+tftp_filesize],eax
-
-.got_stuff:
- ; If we're done here, close the file
- cmp [si+tftp_filesize],eax
- ja .done ; Not EOF, there is still data...
-
- ; Reuse the previous [es:di] structure since the
- ; relevant fields are all the same
- mov byte [si+tftp_goteof],1
-
- mov bx,PXENV_FILE_CLOSE
- call pxenv
- ; Ignore return...
-.done:
+ global pxe_int1a
+pxe_int1a:
+%if USE_PXE_PROVIDED_STACK == 0
+ mov [cs:PXEStack],sp
+ mov [cs:PXEStack+2],ss
+ lss sp,[cs:InitStack]
+%endif
+ int 1Ah ; May trash registers
+%if USE_PXE_PROVIDED_STACK == 0
+ lss sp,[cs:PXEStack]
+%endif
ret
-%endif ; GPXE
;
-; unload_pxe:
-;
-; This function unloads the PXE and UNDI stacks and unclaims
-; the memory.
+; Special unload for gPXE: this switches the InitStack from
+; gPXE to the ROM PXE stack.
;
-reset_pxe:
- or byte [KeepPXE],1
- ; Fall through
-
-unload_pxe:
- push ds
- push es
-
- mov ax,cs
- mov ds,ax
- mov es,ax
-
- cmp byte [KeepPXE],0 ; Should we keep PXE around?
- jne do_reset_pxe
-
- mov si,new_api_unload
- cmp byte [APIVer+1],2 ; Major API version >= 2?
- jae .new_api
- mov si,old_api_unload
-.new_api:
-
-.call_loop: xor ax,ax
- lodsb
- and ax,ax
- jz .call_done
- xchg bx,ax
- mov di,pxe_unload_stack_pkt
- push di
- xor ax,ax
- mov cx,pxe_unload_stack_pkt_len >> 1
- rep stosw
- pop di
- call pxenv
- jc .cant_free
- mov ax,word [pxe_unload_stack_pkt.status]
- cmp ax,PXENV_STATUS_SUCCESS
- jne .cant_free
- jmp .call_loop
-
-.call_done:
- mov bx,0FF00h
-
- mov dx,[RealBaseMem]
- cmp dx,[BIOS_fbm] ; Sanity check
- jna .cant_free
- inc bx
-
- ; Check that PXE actually unhooked the INT 1Ah chain
- movzx eax,word [4*0x1a]
- movzx ecx,word [4*0x1a+2]
- shl ecx,4
- add eax,ecx
- shr eax,10
- cmp ax,dx ; Not in range
- jae .ok
- cmp ax,[BIOS_fbm]
- jae .cant_free
- ; inc bx
-
-.ok:
- mov [BIOS_fbm],dx
-.pop_ret:
- pop es
- pop ds
- ret
-
-.cant_free:
- mov si,cant_free_msg
- call writestr_early
- push ax
- xchg bx,ax
- call writehex4
- mov al,'-'
- call writechr
- pop ax
- call writehex4
- mov al,'-'
- call writechr
- mov eax,[4*0x1a]
- call writehex8
- call crlf
- jmp .pop_ret
-
- ; We want to keep PXE around, but still we should reset
- ; it to the standard bootup configuration
-do_reset_pxe:
- TRACER 'A'
-
- mov bx,PXENV_UDP_CLOSE
- mov di,pxe_udp_close_pkt
- call pxenv
-
- TRACER 'B'
-
%if GPXE
- test byte [GPXEFuncs],80h ; gPXE special unload?
- jz .plain
-
- TRACER 'C'
-
+ global gpxe_unload
+gpxe_unload:
mov bx,PXENV_FILE_EXIT_HOOK
mov di,pxe_file_exit_hook
call pxenv
jc .plain
- TRACER 'D'
-
; Now we actually need to exit back to gPXE, which will
; give control back to us on the *new* "original stack"...
pushfd
- pushad
push ds
- push fs
- push gs
+ push es
mov [PXEStack],sp
mov [PXEStack+2],ss
lss sp,[InitStack]
@@ -2224,8 +459,6 @@ do_reset_pxe:
.resume:
cli
- TRACER 'E'
-
; gPXE will have a stack frame looking much like our
; InitStack, except it has a magic cookie at the top,
; and the segment registers are in reverse order.
@@ -2241,629 +474,47 @@ do_reset_pxe:
mov [cs:InitStack],sp
mov [cs:InitStack+2],ss
lss sp,[cs:PXEStack]
- pop gs
- pop fs
+ pop es
pop ds
- popad
popfd
-%endif ; GPXE
.plain:
- TRACER 'F'
-
-;
-; Look to see if we are on an EFI CSM system. Some EFI
-; CSM systems put the BEV stack in low memory, which means
-; a return to the PXE stack will crash the system. However,
-; INT 18h works reliably, so in that case hack the stack and
-; point the "return address" to an INT 18h instruction.
-;
-; Hack the stack instead of the much simpler "just invoke INT 18h
-; if we want to reset", so that chainloading other NBPs will work.
-;
-efi_csm_workaround:
- les bp,[InitStack] ; ES:BP -> original stack
- les bx,[es:bp+44] ; ES:BX -> Return address
- cmp word [es:bx],18CDh ; Already pointing to INT 18h?
- je .skip
-
- ; Search memory from E0000 to FFFFF for a $EFI structure
- mov bx,0E000h
-.scan_mem:
- mov es,bx
- cmp dword [es:0],'IFE$' ; $EFI is byte-reversed...
- jne .not_here
- ;
- ; Verify the table. We don't check the checksum because
- ; it seems some CSMs leave it at zero.
- ;
- movzx cx,byte [es:5] ; Table length
- cmp cx,83 ; 83 bytes is the current length...
- jae .found_it
-
-.not_here:
- inc bx
- jnz .scan_mem
- jmp .skip ; No $EFI structure found
-
- ;
- ; Found a $EFI structure. Move down the original stack
- ; and put an INT 18h instruction there instead.
- ;
-.found_it:
-%if USE_PXE_PROVIDED_STACK
- mov cx,efi_csm_hack_size
- mov si,sp
- sub sp,cx
- mov di,sp
- mov ax,ss
- mov es,ax
- sub [InitStack],cx
- sub [BaseStack],cx
-%else
- les si,[InitStack]
- lea di,[si-efi_csm_hack_size]
- mov [InitStack],di
-%endif
- lea cx,[bp+52] ; End of the stack we care about
- sub cx,si
- es rep movsb
- mov [es:di-8],di ; Clobber the return address
- mov [es:di-6],es
- mov si,efi_csm_hack
- mov cx,efi_csm_hack_size
- rep movsb
-
-.skip:
- TRACER 'G'
-
-.done:
- pop es
- pop ds
ret
-
- section .data
- alignz 4
-efi_csm_hack:
- int 18h
- jmp 0F000h:0FFF0h
- hlt
-efi_csm_hack_size equ $-efi_csm_hack
-
-
-
-%if GPXE
+ section .data16
alignz 4
pxe_file_exit_hook:
.status: dw 0
-.offset: dw do_reset_pxe.resume
+.offset: dw gpxe_unload.resume
.seg: dw 0
%endif
- section .text
-
-;
-; gendotquad
-;
-; Take an IP address (in network byte order) in EAX and
-; output a dotted quad string to ES:DI.
-; DI points to terminal null at end of string on exit.
-;
-gendotquad:
- push eax
- push cx
- mov cx,4
-.genchar:
- push eax
- cmp al,10 ; < 10?
- jb .lt10 ; If so, skip first 2 digits
-
- cmp al,100 ; < 100
- jb .lt100 ; If so, skip first digit
-
- aam 100
- ; Now AH = 100-digit; AL = remainder
- add ah,'0'
- mov [es:di],ah
- inc di
-
-.lt100:
- aam 10
- ; Now AH = 10-digit; AL = remainder
- add ah,'0'
- mov [es:di],ah
- inc di
-
-.lt10:
- add al,'0'
- stosb
- mov al,'.'
- stosb
- pop eax
- ror eax,8 ; Move next char into LSB
- loop .genchar
- dec di
- mov [es:di], byte 0
- pop cx
- pop eax
- ret
-;
-; uchexbytes/lchexbytes
-;
-; Take a number of bytes in memory and convert to upper/lower-case
-; hexadecimal
-;
-; Input:
-; DS:SI = input bytes
-; ES:DI = output buffer
-; CX = number of bytes
-; Output:
-; DS:SI = first byte after
-; ES:DI = first byte after
-; CX = 0
-;
-; Trashes AX, DX
-;
-
-lchexbytes:
- mov dl,'a'-'9'-1
- jmp xchexbytes
-uchexbytes:
- mov dl,'A'-'9'-1
-xchexbytes:
-.loop:
- lodsb
- mov ah,al
- shr al,4
- call .outchar
- mov al,ah
- call .outchar
- loop .loop
- ret
-.outchar:
- and al,0Fh
- add al,'0'
- cmp al,'9'
- jna .done
- add al,dl
-.done:
- stosb
- ret
-
-;
-; pxe_get_cached_info
-;
-; Get a DHCP packet from the PXE stack into the trackbuf.
-; Leaves the upper half of the trackbuf untouched.
-;
-; Input:
-; DL = packet type
-; Output:
-; CX = buffer size
-;
-; Assumes CS == DS == ES.
-;
-pxe_get_cached_info:
- pushad
- mov al,' '
- call writechr
- mov al,dl
- call writehex2
- mov di,pxe_bootp_query_pkt
- push di
- xor ax,ax
- stosw ; Status
- movzx ax,dl
- stosw ; Packet type
- mov ax,trackbufsize/2
- stosw ; Buffer size
- mov ax,trackbuf
- stosw ; Buffer offset
- xor ax,ax
- stosw ; Buffer segment
-
- pop di ; DI -> parameter set
- mov bx,PXENV_GET_CACHED_INFO
- call pxenv
- jc .err
-
- popad
- mov cx,[pxe_bootp_query_pkt.buffersize]
- ret
-
-.err:
- mov si,err_pxefailed
- call writestr_early
- call writehex4
- call crlf
- jmp kaboom
-
- section .data
-get_packet_msg db 'Getting cached packet', 0
-
- section .text
-;
-; ip_ok
-;
-; Tests an IP address in EAX for validity; return with ZF=1 for bad.
-; We used to refuse class E, but class E addresses are likely to become
-; assignable unicast addresses in the near future.
-;
-ip_ok:
- push ax
- cmp eax,-1 ; Refuse the all-ones address
- jz .out
- and al,al ; Refuse network zero
- jz .out
- cmp al,127 ; Refuse loopback
- jz .out
- and al,0F0h
- cmp al,224 ; Refuse class D
-.out:
- pop ax
- ret
-
-;
-; parse_dhcp
-;
-; Parse a DHCP packet. This includes dealing with "overloaded"
-; option fields (see RFC 2132, section 9.3)
-;
-; This should fill in the following global variables, if the
-; information is present:
-;
-; MyIP - client IP address
-; ServerIP - boot server IP address
-; Netmask - network mask
-; Gateway - default gateway router IP
-; BootFile - boot file name
-; DNSServers - DNS server IPs
-; LocalDomain - Local domain name
-; MACLen, MAC - Client identifier, if MACLen == 0
-;
-; This assumes the DHCP packet is in "trackbuf" and the length
-; of the packet in in CX on entry.
-;
-
-parse_dhcp:
- mov byte [OverLoad],0 ; Assume no overload
- mov eax, [trackbuf+bootp.yip]
- call ip_ok
- jz .noyip
- mov [MyIP], eax
-.noyip:
- mov eax, [trackbuf+bootp.sip]
- and eax, eax
- call ip_ok
- jz .nosip
- mov [ServerIP], eax
-.nosip:
- sub cx, bootp.options
- jbe .nooptions
- mov si, trackbuf+bootp.option_magic
- lodsd
- cmp eax, BOOTP_OPTION_MAGIC
- jne .nooptions
- call parse_dhcp_options
-.nooptions:
- mov si, trackbuf+bootp.bootfile
- test byte [OverLoad],1
- jz .nofileoverload
- mov cx,128
- call parse_dhcp_options
- jmp short .parsed_file
-.nofileoverload:
- cmp byte [si], 0
- jz .parsed_file ; No bootfile name
- mov di,BootFile
- mov cx,32
- rep movsd
- xor al,al
- stosb ; Null-terminate
-.parsed_file:
- mov si, trackbuf+bootp.sname
- test byte [OverLoad],2
- jz .nosnameoverload
- mov cx,64
- call parse_dhcp_options
-.nosnameoverload:
- ret
-
-;
-; Parse a sequence of DHCP options, pointed to by DS:SI; the field
-; size is CX -- some DHCP servers leave option fields unterminated
-; in violation of the spec.
-;
-; For parse_some_dhcp_options, DH contains the minimum value for
-; the option to recognize -- this is used to restrict parsing to
-; PXELINUX-specific options only.
-;
-parse_dhcp_options:
- xor dx,dx
-
-parse_some_dhcp_options:
-.loop:
- and cx,cx
- jz .done
-
- lodsb
- dec cx
- jz .done ; Last byte; must be PAD, END or malformed
- cmp al, 0 ; PAD option
- je .loop
- cmp al,255 ; END option
- je .done
-
- ; Anything else will have a length field
- mov dl,al ; DL <- option number
- xor ax,ax
- lodsb ; AX <- option length
- dec cx
- sub cx,ax ; Decrement bytes left counter
- jb .done ; Malformed option: length > field size
-
- cmp dl,dh ; Is the option value valid?
- jb .opt_done
-
- mov bx,dhcp_option_list
-.find_option:
- cmp bx,dhcp_option_list_end
- jae .opt_done
- cmp dl,[bx]
- je .found_option
- add bx,3
- jmp .find_option
-.found_option:
- pushad
- call [bx+1]
- popad
-
-; Fall through
- ; Unknown option. Skip to the next one.
-.opt_done:
- add si,ax
- jmp .loop
-.done:
- ret
-
- section .data
-dhcp_option_list:
- section .text
-
-%macro dopt 2
- section .data
- db %1
- dw dopt_%2
- section .text
-dopt_%2:
-%endmacro
-
-;
-; Parse individual DHCP options. SI points to the option data and
-; AX to the option length. DL contains the option number.
-; All registers are saved around the routine.
-;
- dopt 1, subnet_mask
- mov ebx,[si]
- mov [Netmask],ebx
- ret
-
- dopt 3, router
- mov ebx,[si]
- mov [Gateway],ebx
- ret
-
- dopt 6, dns_servers
- mov cx,ax
- shr cx,2
- cmp cl,DNS_MAX_SERVERS
- jna .oklen
- mov cl,DNS_MAX_SERVERS
-.oklen:
- mov di,DNSServers
- rep movsd
- mov [LastDNSServer],di
- ret
-
- dopt 15, local_domain
- mov bx,si
- add bx,ax
- xor ax,ax
- xchg [bx],al ; Zero-terminate option
- mov di,LocalDomain
- call dns_mangle ; Convert to DNS label set
- mov [bx],al ; Restore ending byte
- ret
-
- dopt 43, vendor_encaps
- mov dh,208 ; Only recognize PXELINUX options
- mov cx,ax ; Length of option = max bytes to parse
- call parse_some_dhcp_options ; Parse recursive structure
- ret
-
- dopt 52, option_overload
- mov bl,[si]
- mov [OverLoad],bl
- ret
-
- dopt 54, server
- mov eax,[si]
- cmp dword [ServerIP],0
- jne .skip ; Already have a next server IP
- call ip_ok
- jz .skip
- mov [ServerIP],eax
-.skip: ret
-
- dopt 61, client_identifier
- cmp ax,MAC_MAX ; Too long?
- ja .skip
- cmp ax,2 ; Too short?
- jb .skip
- cmp [MACLen],ah ; Only do this if MACLen == 0
- jne .skip
- push ax
- lodsb ; Client identifier type
- cmp al,[MACType]
- pop ax
- jne .skip ; Client identifier is not a MAC
- dec ax
- mov [MACLen],al
- mov di,MAC
- jmp dhcp_copyoption
-.skip: ret
-
- dopt 67, bootfile_name
- mov di,BootFile
- jmp dhcp_copyoption
-
- dopt 97, uuid_client_identifier
- cmp ax,17 ; type byte + 16 bytes UUID
- jne .skip
- mov dl,[si] ; Must have type 0 == UUID
- or dl,[HaveUUID] ; Capture only the first instance
- jnz .skip
- mov byte [HaveUUID],1 ; Got UUID
- mov di,UUIDType
- jmp dhcp_copyoption
-.skip: ret
-
- dopt 209, pxelinux_configfile
- mov di,ConfigName
- or byte [DHCPMagic],2 ; Got config file
- jmp dhcp_copyoption
-
- dopt 210, pxelinux_pathprefix
- mov di,PathPrefix
- or byte [DHCPMagic],4 ; Got path prefix
- jmp dhcp_copyoption
-
- dopt 211, pxelinux_reboottime
- cmp al,4
- jne .done
- mov ebx,[si]
- xchg bl,bh ; Convert to host byte order
- rol ebx,16
- xchg bl,bh
- mov [RebootTime],ebx
- or byte [DHCPMagic],8 ; Got RebootTime
-.done: ret
-
- ; Common code for copying an option verbatim
- ; Copies the option into ES:DI and null-terminates it.
- ; Returns with AX=0 and SI past the option.
-dhcp_copyoption:
- xchg cx,ax ; CX <- option length
- rep movsb
- xchg cx,ax ; AX <- 0
- stosb ; Null-terminate
- ret
-
- section .data
-dhcp_option_list_end:
- section .text
-
- section .data
-HaveUUID db 0
-uuid_dashes db 4,2,2,2,6,0 ; Bytes per UUID dashed section
- section .text
-
-;
-; genipopt
-;
-; Generate an ip=<client-ip>:<boot-server-ip>:<gw-ip>:<netmask>
-; option into IPOption based on a DHCP packet in trackbuf.
-; Assumes CS == DS == ES.
-;
-genipopt:
- pushad
- mov di,IPOption
- mov eax,'ip='
- stosd
- dec di
- mov eax,[MyIP]
- call gendotquad
- mov al,':'
- stosb
- mov eax,[ServerIP]
- call gendotquad
- mov al,':'
- stosb
- mov eax,[Gateway]
- call gendotquad
- mov al,':'
- stosb
- mov eax,[Netmask]
- call gendotquad ; Zero-terminates its output
- popad
- ret
+ section .text16
; -----------------------------------------------------------------------------
; Common modules
; -----------------------------------------------------------------------------
-%include "getc.inc" ; getc et al
-%include "conio.inc" ; Console I/O
+%include "common.inc" ; Universal modules
%include "writestr.inc" ; String output
writestr_early equ writestr
%include "writehex.inc" ; Hexadecimal output
-%include "configinit.inc" ; Initialize configuration
-%include "parseconfig.inc" ; High-level config file handling
-%include "parsecmd.inc" ; Low-level config file handling
-%include "bcopy32.inc" ; 32-bit bcopy
-%include "loadhigh.inc" ; Load a file into high memory
-%include "font.inc" ; VGA font stuff
-%include "graphics.inc" ; VGA graphics
-%include "highmem.inc" ; High memory sizing
-%include "strcpy.inc" ; strcpy()
%include "rawcon.inc" ; Console I/O w/o using the console functions
-%include "dnsresolv.inc" ; DNS resolver
-%include "idle.inc" ; Idle handling
-%include "pxeidle.inc" ; PXE-specific idle mechanism
-%include "adv.inc" ; Auxillary Data Vector
; -----------------------------------------------------------------------------
; Begin data section
; -----------------------------------------------------------------------------
- section .data
+ section .data16
copyright_str db ' Copyright (C) 1994-'
asciidec YEAR
db ' H. Peter Anvin et al', CR, LF, 0
err_bootfailed db CR, LF, 'Boot failed: press a key to retry, or wait for reset...', CR, LF, 0
bailmsg equ err_bootfailed
-err_nopxe db "No !PXE or PXENV+ API found; we're dead...", CR, LF, 0
-err_pxefailed db 'PXE API call failed, error ', 0
-err_udpinit db 'Failed to initialize UDP stack', CR, LF, 0
-err_noconfig db 'Unable to locate configuration file', CR, LF, 0
-err_damage db 'TFTP server sent an incomprehesible reply', CR, LF, 0
-found_pxenv db 'Found PXENV+ structure', CR, LF, 0
-apiver_str db 'PXE API version is ',0
-pxeentry_msg db '!PXE entry point found (we hope) at ', 0
-pxenventry_msg db 'PXENV+ entry point found (we hope) at ', 0
-viaplan_msg db ' via plan '
-plan db 'A', CR, LF, 0
-trymempxe_msg db 'Scanning memory for !PXE structure... ', 0
-trymempxenv_msg db 'Scanning memory for PXENV+ structure... ', 0
-undi_data_msg db 'UNDI data segment at ',0
-undi_code_msg db 'UNDI code segment at ',0
-len_msg db ' len ', 0
-cant_free_msg db 'Failed to free base memory, error ', 0
-notfound_msg db 'not found', CR, LF, 0
-myipaddr_msg db 'My IP address seems to be ',0
-tftpprefix_msg db 'TFTP prefix: ', 0
localboot_msg db 'Booting from local disk...', CR, LF, 0
-trying_msg db 'Trying to load: ', 0
-default_str db 'default', 0
syslinux_banner db CR, LF, 'PXELINUX ', VERSION_STR, ' ', DATE_STR, ' ', 0
-cfgprefix db 'pxelinux.cfg/' ; No final null!
-cfgprefix_len equ ($-cfgprefix)
-; This one we make ourselves
-bootif_str db 'BOOTIF='
-bootif_str_len equ $-bootif_str
;
; Config file keyword table
;
@@ -2871,7 +522,7 @@ bootif_str_len equ $-bootif_str
;
; Extensions to search for (in *forward* order).
-; (.bs and .bss are disabled for PXELINUX, since they are not supported)
+; (.bs and .bss16 are disabled for PXELINUX, since they are not supported)
;
alignz 4
exten_table: db '.cbt' ; COMBOOT (specific)
@@ -2882,139 +533,20 @@ exten_table_end:
dd 0, 0 ; Need 8 null bytes here
;
-; PXE unload sequences
-;
-new_api_unload:
- db PXENV_UDP_CLOSE
- db PXENV_UNDI_SHUTDOWN
- db PXENV_UNLOAD_STACK
- db PXENV_STOP_UNDI
- db 0
-old_api_unload:
- db PXENV_UDP_CLOSE
- db PXENV_UNDI_SHUTDOWN
- db PXENV_UNLOAD_STACK
- db PXENV_UNDI_CLEANUP
- db 0
-
-;
-; PXE query packets partially filled in
-;
- section .bss
-pxe_bootp_query_pkt:
-.status: resw 1 ; Status
-.packettype: resw 1 ; Boot server packet type
-.buffersize: resw 1 ; Packet size
-.buffer: resw 2 ; seg:off of buffer
-.bufferlimit: resw 1 ; Unused
-
- section .data
-pxe_udp_open_pkt:
-.status: dw 0 ; Status
-.sip: dd 0 ; Source (our) IP
-
-pxe_udp_close_pkt:
-.status: dw 0 ; Status
-
-pxe_udp_write_pkt:
-.status: dw 0 ; Status
-.sip: dd 0 ; Server IP
-.gip: dd 0 ; Gateway IP
-.lport: dw 0 ; Local port
-.rport: dw 0 ; Remote port
-.buffersize: dw 0 ; Size of packet
-.buffer: dw 0, 0 ; seg:off of buffer
-
-pxe_udp_read_pkt:
-.status: dw 0 ; Status
-.sip: dd 0 ; Source IP
-.dip: dd 0 ; Destination (our) IP
-.rport: dw 0 ; Remote port
-.lport: dw 0 ; Local port
-.buffersize: dw 0 ; Max packet size
-.buffer: dw 0, 0 ; seg:off of buffer
-
-%if GPXE
-
-gpxe_file_api_check:
-.status: dw 0 ; Status
-.size: dw 20 ; Size in bytes
-.magic: dd 0x91d447b2 ; Magic number
-.provider: dd 0
-.apimask: dd 0
-.flags: dd 0
-
-gpxe_file_open:
-.status: dw 0 ; Status
-.filehandle: dw 0 ; FileHandle
-.filename: dd 0 ; seg:off of FileName
-.reserved: dd 0
-
-gpxe_get_file_size:
-.status: dw 0 ; Status
-.filehandle: dw 0 ; FileHandle
-.filesize: dd 0 ; FileSize
-
-gpxe_file_read:
-.status: dw 0 ; Status
-.filehandle: dw 0 ; FileHandle
-.buffersize: dw 0 ; BufferSize
-.buffer: dd 0 ; seg:off of buffer
-
-%endif ; GPXE
-
-;
; Misc initialized (data) variables
;
+ section .data16
+
alignz 4
-BaseStack dd StackBuf ; ESP of base stack
+ global BaseStack, KeepPXE
+BaseStack dd StackTop ; ESP of base stack
dw 0 ; SS of base stack
-NextSocket dw 49152 ; Counter for allocating socket numbers
KeepPXE db 0 ; Should PXE be kept around?
;
-; TFTP commands
-;
-tftp_tail db 'octet', 0 ; Octet mode
-tsize_str db 'tsize' ,0 ; Request size
-tsize_len equ ($-tsize_str)
- db '0', 0
-blksize_str db 'blksize', 0 ; Request large blocks
-blksize_len equ ($-blksize_str)
- asciidec TFTP_LARGEBLK
- db 0
-tftp_tail_len equ ($-tftp_tail)
-
- alignz 2
-;
-; Options negotiation parsing table (string pointer, string len, offset
-; into socket structure)
-;
-tftp_opt_table:
- dw tsize_str, tsize_len, tftp_filesize
- dw blksize_str, blksize_len, tftp_blksize
-tftp_opts equ ($-tftp_opt_table)/6
-
-;
-; Error packet to return on TFTP protocol error
-; Most of our errors are OACK parsing errors, so use that error code
-;
-tftp_proto_err dw TFTP_ERROR ; ERROR packet
- dw TFTP_EOPTNEG ; ERROR 8: OACK error
- db 'TFTP protocol error', 0 ; Error message
-tftp_proto_err_len equ ($-tftp_proto_err)
-
- alignz 4
-ack_packet_buf: dw TFTP_ACK, 0 ; TFTP ACK packet
-
-;
; IP information (initialized to "unknown" values)
-MyIP dd 0 ; My IP address
-ServerIP dd 0 ; IP address of boot server
-Netmask dd 0 ; Netmask of this subnet
-Gateway dd 0 ; Default router
-ServerPort dw TFTP_PORT ; TFTP server port
-
+ global MyIP
+MyIP dd 0 ; My IP address
;
; Variables that are uninitialized in SYSLINUX but initialized here
;
diff --git a/core/rllpack.c b/core/rllpack.c
new file mode 100644
index 00000000..bb9f046c
--- /dev/null
+++ b/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;
+}
diff --git a/core/rllpack.inc b/core/rllpack.inc
deleted file mode 100644
index c3bca696..00000000
--- a/core/rllpack.inc
+++ /dev/null
@@ -1,164 +0,0 @@
-; -*- fundamental -*- ---------------------------------------------------
-;
-; 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., 53 Temple Place Ste 330,
-; Boston MA 02111-1307, 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.
-;
-
- section .text
-
-;
-; rllpack:
-; Pack ECX bytes from ESI into EDI.
-; Returns updated ESI and EDI.
-;
-rllpack:
- push word .pmentry
- call simple_pm_call
- ret
-
- bits 32
-.pmentry:
- push ecx
- push ebx
- push edx
-.startseq:
- xor eax,eax ; Zero byte
- xor ebx,ebx ; Run length zero
- dec edi
- mov edx,edi ; Pointer to header byte
- mov [edi],al ; Create header byte
- jcxz .done ; If done, this was the terminator
-.stdbyte:
- lodsb
- dec edi
- mov [edi],al
- dec ecx
- cmp ah,al
- je .same
-.diff:
- mov ah,al
- xor ebx,ebx
-.plainbyte:
- inc ebx
- inc byte [edx]
- jcxz .startseq
- jns .stdbyte
- jmp .startseq
-.same:
- cmp bl,2
- jb .plainbyte
- ; 3 bytes or more in a row, time to convert sequence
- sub [edx],bl
- jnz .normal
- inc edi ; We killed a whole stretch,
- ; drop start byte
-.normal:
- inc ebx
- add edi,ebx ; Remove the stored run bytes
-.getrun:
- jcxz .nomatch
- lodsb
- cmp al,ah
- jne .nomatch
- cmp bx,(256-224)*256-1 ; Maximum run size
- jae .nomatch
- inc ebx
- dec ecx
- jmp .getrun
-.nomatch:
- cmp bx,224-126
- jae .twobyte
-.onebyte:
- add bl,126
- dec edi
- mov [edi],bl
- jmp .storebyte
-.twobyte:
- add bh,224
- sub edi,2
- mov [edi],bx
-.storebyte:
- dec edi
- mov [edi],ah
- dec esi ; Reload subsequent byte
- jmp .startseq
-.done:
- pop edx
- pop ebx
- pop ecx
- ret
-
- bits 16
-;
-; rllunpack:
-; Unpack bytes from ESI into EDI
-; On return ESI, EDI are updated and
-; ECX contains number of bytes output.
-;
-rllunpack:
- push word .pmentry
- call simple_pm_call
- ret
-
- bits 32
-.pmentry:
- push edi
- xor ecx,ecx
-.header:
- dec esi
- mov cl,[esi]
- jcxz .done
- cmp cl,129
- jae .isrun
- ; Not a run
-.copy:
- dec esi
- mov al,[esi]
- stosb
- loop .copy
- jmp .header
-.isrun:
- cmp cl,224
- jae .longrun
- sub cl,126
-.dorun:
- dec esi
- mov al,[esi]
- rep stosb
- jmp .header
-.longrun:
- sub cl,224
- mov ch,cl
- dec esi
- mov cl,[esi]
- jmp .dorun
-.done:
- pop ecx
- sub ecx,edi
- neg ecx
- ret
-
- bits 16
diff --git a/core/runkernel.inc b/core/runkernel.inc
index e738706f..74f23c45 100644
--- a/core/runkernel.inc
+++ b/core/runkernel.inc
@@ -58,7 +58,7 @@ is_linux_kernel:
mov cx,8000h >> SECTOR_SHIFT ; Half a moby (32K)
xor bx,bx
pop si ; <A> file pointer
- call getfssec
+ pm_call getfssec
cmp cx,1024
jb kernel_corrupt
cmp word [es:bs_bootsign],0AA55h
@@ -262,7 +262,7 @@ read_kernel:
mov ecx,8000h ; 32K
sub ecx,esi ; Number of bytes to copy
add esi,(real_mode_seg << 4) ; Pointer to source
- mov edi,100000h ; Copy to address 100000h
+ mov edi,free_high_memory ; Copy to free high memory
call bcopy ; Transfer to high memory
@@ -417,6 +417,7 @@ setup_move:
push ds ; We need DS == ES == CS here
pop es
+ mov edx,100000h
test byte [LoadFlags],LOAD_HIGH
jnz .loading_high
@@ -428,20 +429,19 @@ setup_move:
movzx eax,word [CmdLineEnd]
stosd
inc cx
+ mov edx,10000h ; Revised target address
+ mov bx,9000h ; Revised real mode segment
- mov eax,10000h ; Target address of low kernel
+.loading_high:
+ mov eax,edx ; Target address of kernel
stosd
- mov eax,100000h ; Where currently loaded
+ mov eax,free_high_memory ; Where currently loaded
stosd
neg eax
add eax,[KernelEnd]
stosd
inc cx
- mov bx,9000h ; Revised real mode segment
-
-.loading_high:
-
cmp word [InitRDPtr],0 ; Did we have an initrd?
je .no_initrd
@@ -546,7 +546,7 @@ parse_load_initrd:
push di
mov di,InitRD ; Target buffer for mangled name
- call mangle_name
+ pm_call mangle_name
pop di
call loadinitrd
@@ -593,11 +593,11 @@ loadinitrd:
push edi
mov si,InitRD
mov di,InitRDCName
- call unmangle_name ; Create human-readable name
+ pm_call unmangle_name ; Create human-readable name
sub di,InitRDCName
mov [InitRDCNameLen],di
mov di,InitRD
- call searchdir ; Look for it in directory
+ pm_call searchdir ; Look for it in directory
pop edi
jz .notthere
@@ -637,7 +637,7 @@ writestr_qchk:
jz writestr
ret
- section .data
+ section .data16
crlfloading_msg db CR, LF
loading_msg db 'Loading ', 0
dotdot_msg db '.'
@@ -670,7 +670,7 @@ str_initrd equ $+1 ; Pointer to "initrd=" in memory
%endif
db 0
- section .bss
+ section .bss16
alignb 4
MyHighMemSize resd 1 ; Possibly adjusted highmem size
RamdiskMax resd 1 ; Highest address for ramdisk
diff --git a/core/serirq.inc b/core/serirq.inc
index b7d79e0f..47ccd50f 100644
--- a/core/serirq.inc
+++ b/core/serirq.inc
@@ -18,26 +18,26 @@
;; We don't know what IRQ, if any, we have, so map all of them...
;;
- section .text
+ section .text16
bits 16
align 8
- section .bss
+ section .bss16
alignb 8
%assign n 0
%rep 16
- section .text
+ section .text16
serstub_irq %+ n :
push dword [cs:oldirq %+ n]
jmp short irq_common
- section .bss
+ section .bss16
oldirq %+ n resd 1
%assign n n+1
%endrep
- section .text
+ section .text16
irq_common:
pushf
push ax
@@ -82,19 +82,19 @@ irq_common:
pop es
jmp .done
- section .data
+ section .bss16
;
; SerialIRQPort will generally track SerialPort, but will be 0 when an
; IRQ service is not installed.
;
-SerialIRQPort dw 0 ; Serial port w IRQ service
-SerialHead dw 0 ; Head of serial port rx buffer
-SerialTail dw 0 ; Tail of serial port rx buffer
+SerialIRQPort resw 1 ; Serial port w IRQ service
+SerialHead resw 1 ; Head of serial port rx buffer
+SerialTail resw 1 ; Tail of serial port rx buffer
- section .bss
+ section .bss16
IRQMask resw 1 ; PIC IRQ mask status
- section .text
+ section .text16
sirq_install:
pushad
@@ -216,4 +216,4 @@ sirq_cleanup:
popad
ret
- section .text
+ section .text16
diff --git a/core/stack.inc b/core/stack.inc
index f670dec0..3a4b60b3 100644
--- a/core/stack.inc
+++ b/core/stack.inc
@@ -1,6 +1,7 @@
; -----------------------------------------------------------------------
;
; Copyright 2005-2008 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
@@ -29,16 +30,11 @@
xor %1,%1
mov ds,%1
mov es,%1
-%if IS_SYSLINUX || IS_EXTLINUX
- mov ss,%1 ; Just in case...
- mov sp,StackBuf-2*5 ; Reset stack
-%elif IS_PXELINUX
+%if IS_PXELINUX
lss esp,[BaseStack]
-%elif IS_ISOLINUX
- mov ss,%1
- mov sp,StackBuf-2*2
%else
- NEED TO KNOW HOW TO RESET STACK
+ mov ss,%1
+ mov esp,StackTop
%endif
sti
cld
diff --git a/core/strcpy.inc b/core/strcpy.inc
index 2bafa7fe..9762cbbf 100644
--- a/core/strcpy.inc
+++ b/core/strcpy.inc
@@ -2,7 +2,7 @@
; strcpy: Copy DS:SI -> ES:DI up to and including a null byte;
; on exit SI and DI point to the byte *after* the null byte
;
- section .text
+ section .text16
strcpy: push ax
.loop: lodsb
diff --git a/core/strecpy.inc b/core/strecpy.inc
index 1fc53e96..bfcddc1a 100644
--- a/core/strecpy.inc
+++ b/core/strecpy.inc
@@ -5,7 +5,7 @@
; target buffer; return with CF=1 if target buffer overflows;
; the output is still zero-terminated.
;
- section .text
+ section .text16
strecpy:
push ax
diff --git a/core/syslinux.ld b/core/syslinux.ld
index c1da230e..c2e49a27 100644
--- a/core/syslinux.ld
+++ b/core/syslinux.ld
@@ -20,10 +20,17 @@ OUTPUT_ARCH(i386)
EXTERN(_start)
ENTRY(_start)
-STACK_LEN = 4096;
+STACK16_LEN = 4096;
+STACK32_LEN = 65536;
SECTIONS
{
+ /* Prefix structure for the compression program */
+ . = 0;
+ .prefix : {
+ *(.prefix)
+ }
+
/* "Early" sections (before the load) */
. = 0x0800;
@@ -35,15 +42,16 @@ SECTIONS
__earlybss_len = __earlybss_end - __earlybss_start;
__earlybss_dwords = (__earlybss_len + 3) >> 2;
- .bss : {
- __bss_start = .;
- *(.bss)
- *(.bss2)
- __bss_end = .;
+ . = ALIGN(4);
+ .bss16 : {
+ __bss16_start = .;
+ *(.bss16)
+ __bss16_end = .;
}
- __bss_len = __bss_end - __bss_start;
- __bss_dwords = (__bss_len + 3) >> 2;
+ __bss16_len = __bss16_end - __bss16_start;
+ __bss16_dwords = (__bss16_len + 3) >> 2;
+ . = ALIGN(4);
.config : AT (__config_lma) {
__config_start = .;
*(.config)
@@ -52,7 +60,9 @@ SECTIONS
__config_len = __config_end - __config_start;
__config_dwords = (__config_len + 3) >> 2;
- . = ALIGN(16);
+ /* Generated and/or copied code */
+
+ . = ALIGN(128); /* Minimum separation from mutable data */
.replacestub : AT (__replacestub_lma) {
__replacestub_start = .;
*(.replacestub)
@@ -61,29 +71,62 @@ SECTIONS
__replacestub_len = __replacestub_end - __replacestub_start;
__replacestub_dwords = (__replacestub_len + 3) >> 2;
- /* Stack */
+ . = ALIGN(16);
+ __gentextnr_lma = .;
+ .gentextnr : AT(__gentextnr_lma) {
+ __gentextnr_start = .;
+ *(.gentextnr)
+ __gentextnr_end = .;
+ }
+ __gentextnr_len = __gentextnr_end - __gentextnr_start;
+ __gentextnr_dwords = (__gentextnr_len + 3) >> 2;
- STACK_BASE = 0x7c00 - STACK_LEN;
- . = STACK_BASE;
- .stack : AT(STACK_BASE) {
- __stack_start = .;
- . += STACK_LEN;
- __stack_end = .;
+ /* 16-bit stack */
+
+ STACK16_BASE = 0x7c00 - STACK16_LEN;
+ . = STACK16_BASE;
+ .stack16 : AT(STACK16_BASE) {
+ __stack16_start = .;
+ . += STACK16_LEN;
+ __stack16_end = .;
}
- __stack_len = __stack_end - __stack_start;
- __stack_dwords = (__stack_len + 3) >> 2;
+ __stack16_len = __stack16_end - __stack16_start;
+ __stack16_dwords = (__stack16_len + 3) >> 2;
/* Initialized sections */
. = 0x7c00;
- .text : {
+ .init : {
FILL(0x90909090)
- __text_start = .;
- *(.text)
- __text_end = .;
+ __init_start = .;
+ *(.init)
+ __init_end = .;
+ }
+ __init_len = __init_end - __init_start;
+ __init_dwords = (__init_len + 3) >> 2;
+
+ .text16 : {
+ FILL(0x90909090)
+ __text16_start = .;
+ *(.text16)
+ __text16_end = .;
+ }
+ __text16_len = __text16_end - __text16_start;
+ __text16_dwords = (__text16_len + 3) >> 2;
+
+ /*
+ * .textnr is used for 32-bit code that is used on the code
+ * path to initialize the .text segment
+ */
+ . = ALIGN(16);
+ .textnr : {
+ FILL(0x90909090)
+ __textnr_start = .;
+ *(.textnr)
+ __textnr_end = .;
}
- __text_len = __text_end - __text_start;
- __text_dwords = (__text_len + 3) >> 2;
+ __textnr_len = __textnr_end - __textnr_start;
+ __textnr_dwords = (__textnr_len + 3) >> 2;
. = ALIGN(16);
.bcopyxx : {
@@ -96,13 +139,13 @@ SECTIONS
__bcopyxx_dwords = (__bcopyxx_len + 3) >> 2;
. = ALIGN(4);
- .data : {
- __data_start = .;
- *(.data)
- __data_end = .;
+ .data16 : {
+ __data16_start = .;
+ *(.data16)
+ __data16_end = .;
}
- __data_len = __data_end - __data_start;
- __data_dwords = (__data_len + 3) >> 2;
+ __data16_len = __data16_end - __data16_start;
+ __data16_dwords = (__data16_len + 3) >> 2;
. = ALIGN(4);
__config_lma = .;
@@ -112,10 +155,15 @@ SECTIONS
__replacestub_lma = .;
. += SIZEOF(.replacestub);
- /* ADV, must be the last intialized section */
+ /* The 32-bit code loads above the non-progbits sections */
+
+ . = ALIGN(16);
+ __pm_code_lma = .;
+
+ __high_clear_start = .;
. = ALIGN(512);
- .adv : {
+ .adv (NOLOAD) : {
__adv_start = .;
*(.adv)
__adv_end = .;
@@ -125,7 +173,8 @@ SECTIONS
/* Late uninitialized sections */
- .uibss : {
+ . = ALIGN(4);
+ .uibss (NOLOAD) : {
__uibss_start = .;
*(.uibss)
__uibss_end = .;
@@ -133,18 +182,165 @@ SECTIONS
__uibss_len = __uibss_end - __uibss_start;
__uibss_dwords = (__uibss_len + 3) >> 2;
- .bss1 : {
- __bss1_start = .;
- *(.bss1)
- __bss1_end = .;
+ _end16 = .;
+ __assert_end16 = ASSERT(_end16 <= 0x10000, "64K overflow");
+
+ /*
+ * The auxilliary data segment is allowed to spill out of the
+ * low 64K.
+ */
+
+ . = ALIGN(16);
+ .auxseg (NOLOAD) : {
+ __auxseg_start = .;
+ *(.auxseg)
+ __auxseg_end = .;
+ }
+ __auxseg_len = __auxseg_end - __auxseg_start;
+ __auxseg_dwords = (__auxseg_len + 3) >> 2;
+ aux_seg = __auxseg_start >> 4;
+
+ /*
+ * Used to allocate lowmem buffers from 32-bit code
+ */
+ .lowmem (NOLOAD) : {
+ __lowmem_start = .;
+ *(.lowmem)
+ __lowmem_end = .;
}
- __bss1_len = __bss1_end - __bss1_start;
- __bss1_dwords = (__bss1_len + 3) >> 2;
+ __lowmem_len = __lowmem_end - __lowmem_start;
+ __lowmem_dwords = (__lowmem_len + 3) >> 2;
+
+ __high_clear_end = .;
+
+ __high_clear_len = __high_clear_end - __high_clear_start;
+ __high_clear_dwords = (__high_clear_len + 3) >> 2;
- . = ASSERT(__bss1_end <= 0x10000, "64K overflow");
+
+ __assert_high = ASSERT(__high_clear_end <= core_xfer_buf,
+ "auxseg/lowmem region collides with xfer_buf_seg");
+
+ /*
+ * 32-bit code. This is a hack for the moment due to the
+ * real-mode segments also allocated.
+ */
. = 0x100000;
- .com32 : {
- *(.com32)
+
+ __pm_code_start = .;
+
+ __text_vma = .;
+ __text_lma = __pm_code_lma;
+ .text : AT(__text_lma) {
+ FILL(0x90909090)
+ __text_start = .;
+ *(.text)
+ *(.text.*)
+ __text_end = .;
+ }
+
+ . = ALIGN(16);
+
+ __rodata_vma = .;
+ __rodata_lma = __rodata_vma + __text_lma - __text_vma;
+ .rodata : AT(__rodata_lma) {
+ __rodata_start = .;
+ *(.rodata)
+ *(.rodata.*)
+ __rodata_end = .;
+ }
+
+ . = ALIGN(4);
+
+ __ctors_vma = .;
+ __ctors_lma = __ctors_vma + __text_lma - __text_vma;
+ .ctors : AT(__ctors_lma) {
+ __ctors_start = .;
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ __ctors_end = .;
+ }
+
+ __dtors_vma = .;
+ __dtors_lma = __dtors_vma + __text_lma - __text_vma;
+ .dtors : AT(__dtors_lma) {
+ __dtors_start = .;
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ __dtors_end = .;
+ }
+
+ . = ALIGN(4);
+
+ __dynlink_vma = .;
+ __dynlink_lma = __dynlink_vma + __text_lma - __text_vma;
+ .dynlink : AT(__dynlink_lma) {
+ __dynlink_start = .;
+ *(.dynlink)
+ __dynlink_end = .;
+ }
+
+ . = ALIGN(4);
+
+ __got_vma = .;
+ __got_lma = __got_vma + __text_lma - __text_vma;
+ .got : AT(__got_lma) {
+ __got_start = .;
+ KEEP (*(.got.plt))
+ KEEP (*(.got))
+ __got_end = .;
+ }
+
+ . = ALIGN(16);
+
+ __data_vma = .;
+ __data_lma = __data_vma + __text_lma - __text_vma;
+ .data : AT(__data_lma) {
+ __data_start = .;
+ *(.data)
+ *(.data.*)
+ __data_end = .;
+ }
+
+ __pm_code_end = .;
+ __pm_code_len = __pm_code_end - __pm_code_start;
+ __pm_code_dwords = (__pm_code_len + 3) >> 2;
+
+ . = ALIGN(128);
+
+ __bss_vma = .;
+ __bss_lma = .; /* Dummy */
+ .bss (NOLOAD) : AT (__bss_lma) {
+ __bss_start = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ __bss_end = .;
+ }
+ __bss_len = __bss_end - __bss_start;
+ __bss_dwords = (__bss_len + 3) >> 2;
+
+ . = ALIGN(65536);
+
+ /* XXX: This stack should be unified with the COM32 stack */
+ __stack_vma = .;
+ __stack_lma = .; /* Dummy */
+ .stack (NOLOAD) : AT(__stack_lma) {
+ __stack_start = .;
+ . += STACK32_LEN;
+ __stack_end = .;
+ }
+ __stack_len = __stack_end - __stack_start;
+ __stack_dwords = (__stack_len + 3) >> 2;
+
+ _end = .;
+
+ /* COM32R and kernels are loaded after our own PM code */
+ . = ALIGN(65536);
+ free_high_memory = .;
+
+ /* Stuff we don't need... */
+ /DISCARD/ : {
+ *(.eh_frame)
}
}
diff --git a/core/timer.inc b/core/timer.inc
new file mode 100644
index 00000000..095e92ed
--- /dev/null
+++ b/core/timer.inc
@@ -0,0 +1,46 @@
+;; -----------------------------------------------------------------------
+;;
+;; 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.
+;;
+;; -----------------------------------------------------------------------
+
+;;
+;; timer.inc
+;;
+;; Very simple counting timer
+;;
+;; This lets us have a simple incrementing variable without worrying
+;; about the BIOS_timer variable wrapping around at "midnight" and other
+;; weird things.
+;;
+
+ section .text16
+
+timer_init:
+ ; Hook INT 1Ch
+ mov eax,[BIOS_timer_hook]
+ mov [BIOS_timer_next],eax
+ mov dword [BIOS_timer_hook],timer_irq
+ ret
+
+timer_cleanup:
+ ; Unhook INT 1Ch
+ mov eax,[BIOS_timer_next]
+ mov [BIOS_timer_hook],eax
+ ret
+
+timer_irq:
+ inc dword [cs:__jiffies]
+ jmp 0:0
+BIOS_timer_next equ $-4
+
+ section .bss16
+ alignb 4
+ global __jiffies
+__jiffies resd 1 ; The actual timer variable
diff --git a/core/ui.inc b/core/ui.inc
index 348527ac..ec9190a9 100644
--- a/core/ui.inc
+++ b/core/ui.inc
@@ -45,6 +45,9 @@ no_config_file:
.no_bootonce:
+ ; *** TEST HACK ***
+ pm_call hello
+
;
; Check whether or not we are supposed to display the boot prompt.
;
@@ -162,7 +165,7 @@ display_labels:
push cx ; save command line size
mov edi,VKernelBuf
- call rllunpack
+ pm_call rllunpack
; ESI updated on return
sub di,cx ; Return to beginning of buf
@@ -234,7 +237,7 @@ show_help: ; AX = func key # (0 = F1, 9 = F10, 11 = F12)
xchg di,ax
cmp byte [di+NULLOFFSET],NULLFILE
je short fk_nofile ; Undefined F-key
- call open
+ call core_open
jz short fk_nofile ; File not found
call crlf
call get_msg_file
@@ -307,11 +310,11 @@ auto_boot:
rep movsd
jmp short load_kernel
- section .data
+ section .data16
no_default_msg db 'No DEFAULT or UI configuration directive found!'
db CR, LF, 0
- section .text
+ section .text16
;
; Jump here when the command line is completed
@@ -330,7 +333,7 @@ load_kernel: ; Load the kernel now
mov si,command_line
mov di,KernelName
push si
- call mangle_name
+ pm_call mangle_name
pop si
;
; Fast-forward to first option (we start over from the beginning, since
@@ -366,7 +369,7 @@ vk_check:
jbe .not_vk
mov edi,VKernelBuf
- call rllunpack
+ pm_call rllunpack
; ESI updated on return
sub di,cx ; Return to beginning of buf
@@ -460,7 +463,7 @@ get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/e
mov bx,exten_table
.search_loop: push bx
mov di,KernelName ; Search on disk
- call searchdir
+ pm_call searchdir
pop bx
jnz kernel_good
mov eax,[bx] ; Try a different extension
@@ -484,7 +487,7 @@ bad_kernel:
mov si,KernelName
mov di,KernelCName
push di
- call unmangle_name ; Get human form
+ pm_call unmangle_name ; Get human form
mov si,err_notfound ; Complain about missing kernel
call writestr
pop si ; KernelCName
@@ -541,11 +544,11 @@ getchar_timeout:
call reset_idle
.loop:
- push word [BIOS_timer]
+ push word [__jiffies]
call pollchar
jnz .got_char
pop ax
- cmp ax,[BIOS_timer] ; Has the timer advanced?
+ cmp ax,[__jiffies] ; Has the timer advanced?
je .loop
dec dword [ThisKbdTo]
@@ -586,12 +589,12 @@ getchar_timeout:
;
; Anything else is assumed to be a Linux kernel.
;
- section .bss
+ section .bss16
alignb 4
Kernel_EAX resd 1
Kernel_SI resw 1
- section .text
+ section .text16
kernel_good_saved:
; Alternate entry point for which the return from
; searchdir is stored in memory. This is used for
@@ -613,7 +616,7 @@ kernel_good:
mov si,KernelName
mov di,KernelCName
- call unmangle_name
+ pm_call unmangle_name
sub di,KernelCName
mov [KernelCNameLen],di
@@ -697,7 +700,7 @@ is_bss_sector equ is_bad_image
is_disk_image equ is_bad_image
%endif
- section .data
+ section .data16
boot_prompt db 'boot: ', 0
wipe_char db BS, ' ', BS, 0
err_badimage db 'Invalid image type for this media type!', CR, LF, 0
@@ -717,7 +720,7 @@ kerneltype_table:
dw is_com32_image ; VK_COM32
dw is_config_file ; VK_CONFIG
- section .bss
+ section .bss16
alignb 4
ThisKbdTo resd 1 ; Temporary holder for KbdTimeout
ThisTotalTo resd 1 ; Temporary holder for TotalTimeout
@@ -727,7 +730,7 @@ KbdFlags resb 1 ; Check for keyboard escapes
FuncFlag resb 1 ; Escape sequences received from keyboard
KernelType resb 1 ; Kernel type, from vkernel, if known
- section .text
+ section .text16
;
; Linux kernel loading code is common.
;
diff --git a/core/writedec.inc b/core/writedec.inc
index 10bf7bae..bfac0997 100644
--- a/core/writedec.inc
+++ b/core/writedec.inc
@@ -16,7 +16,7 @@
;; Write decimal numbers to the console
;;
- section .text
+ section .text16
;
; writedec[bwl]: Write an unsigned decimal number in (AL, AX, EAX)
; to the console
diff --git a/core/writehex.inc b/core/writehex.inc
index 1dbe4ab3..e2bf86b4 100644
--- a/core/writehex.inc
+++ b/core/writehex.inc
@@ -16,7 +16,6 @@
;; Write hexadecimal numbers to the console
;;
- section .text
;
; writehex[248]: Write a hex number in (AL, AX, EAX) to the console
;
diff --git a/core/writestr.inc b/core/writestr.inc
index 4adc6bf4..9c11b320 100644
--- a/core/writestr.inc
+++ b/core/writestr.inc
@@ -16,7 +16,6 @@
;; Code to write a simple string.
;;
- section .text
;
; crlf: Print a newline
;
diff --git a/doc/comboot.txt b/doc/comboot.txt
index b3d8e648..fb954038 100644
--- a/doc/comboot.txt
+++ b/doc/comboot.txt
@@ -51,25 +51,28 @@ program), or execute INT 20h or INT 21h AH=00h or INT 21h AH=4Ch.
If compatiblity with Syslinux 1.xx is desired, use INT 20h.
- ++++ COM32 file format ++++
+ ++++ COM32R file format ++++
-A COM32 file is a raw binary file containing 32-bit code. It should
-be linked to run at address 0x101000, and should not contain any
-segment references. It will be run in flat-memory 32-bit protected
+A COM32R file is a raw binary file containing 32-bit code. It should
+be self-relocating, as it will be loaded by the Syslinux core at any
+4K aligned address. It will be run in flat-memory 32-bit protected
mode. Under Syslinux, it will be run in CPL 0, however, since it may
be possible to create a COM32 execution engine that would run under
something like Linux DOSEMU, it is recommended that the code does not
assume CPL 0 unless absolutely necessary.
-It is highly recommended that every COM32 program begins with the byte
-sequence B8 FF 4C CD 21 (mov eax,21cd4cffh) as a magic number.
+A COM32R program must start with the byte sequence B8 FE 4C CD 21 (mov
+eax,21cd4cfeh) as a magic number.
-A COM32 file should have extension ".c32".
+The COM32R format replaces the earlier COM32 format, which was linked
+to a fixed address (0x101000).
+
+A COM32R file should have extension ".c32".
On startup, CS will be set up as a flat 32-bit code segment, and DS ==
ES == SS will be set up as the equivalent flat 32-bit data segment.
FS and GS are reserved for future use and are currently initialized to
-zero. A COM32 image should not assume any particular values of
+zero. A COM32R image should not assume any particular values of
segment selectors.
ESP is set up at the end of available memory and also serves as
diff --git a/dos/Makefile b/dos/Makefile
index 9d8ce33c..0bd7d41e 100644
--- a/dos/Makefile
+++ b/dos/Makefile
@@ -17,8 +17,10 @@
topdir = ..
include $(topdir)/MCONFIG.embedded
+CFLAGS += -D__MSDOS__
# CFLAGS += -DDEBUG
-LDFLAGS = -T com16.ld
+
+LDFLAGS = -T dosexe.ld
OPTFLAGS = -g
INCLUDES = -include code16.h -nostdinc -iwithprefix include \
-I. -I.. -I../libfat -I ../libinstaller
@@ -29,7 +31,7 @@ SRCS = syslinux.c \
../libinstaller/ldlinux_bin.c \
../libinstaller/mbr_bin.c \
$(wildcard ../libfat/*.c)
-OBJS = crt0.o $(patsubst %.c,%.o,$(notdir $(SRCS)))
+OBJS = header.o crt0.o $(patsubst %.c,%.o,$(notdir $(SRCS)))
LIBOBJS = int2526.o conio.o memcpy.o memset.o skipatou.o atou.o \
malloc.o free.o \
argv.o printf.o __divdi3.o __udivmoddi4.o
@@ -50,8 +52,8 @@ spotless: clean
installer:
-syslinux.elf: $(OBJS) libcom.a com16.ld
- $(LD) $(LDFLAGS) -o $@ $(filter-out %.ld,$^)
+syslinux.elf: $(OBJS) dosexe.ld libcom.a
+ $(LD) $(LDFLAGS) -o $@ $(OBJS) libcom.a
libcom.a: $(LIBOBJS)
-rm -f $@
@@ -60,9 +62,11 @@ libcom.a: $(LIBOBJS)
syslinux.com: syslinux.elf
$(OBJCOPY) -O binary $< $@
+ $(UPX) --lzma --ultra-brute $@ || \
+ $(UPX) --ultra-brute $@ || \
+ true
%.com: %.asm
- ( $(NASM) -M -DDEPEND $(NASMOPT) -o $@ -M $< && echo '' ) > .$@.d; true
- $(NASM) $(NASMOPT) -f bin -o $@ -l $*.lst $<
+ $(NASM) $(NASMOPT) -f bin -o $@ -MP -MD .$@.d -l $*.lst $<
-include .*.d *.tmp
diff --git a/dos/argv.c b/dos/argv.c
index 42e8657d..056aae59 100644
--- a/dos/argv.c
+++ b/dos/argv.c
@@ -38,8 +38,8 @@
#define ALIGN_UP(p,t) ((t *)(((uintptr_t)(p) + (sizeof(t)-1)) & ~(sizeof(t)-1)))
-extern char _end[]; /* Symbol created by linker */
-void *__mem_end = &_end; /* Global variable for use by malloc() */
+extern char __heap_start[];
+void *__mem_end = &__heap_start; /* Global variable for use by malloc() */
int __parse_argv(char ***argv, const char *str)
{
diff --git a/dos/com16.ld b/dos/com16.ld
deleted file mode 100644
index 5f82b73a..00000000
--- a/dos/com16.ld
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Linker script for COM16 binaries
- */
-
-/* Script for -z combreloc: combine and sort reloc sections */
-OUTPUT_FORMAT("elf32-i386", "elf32-i386",
- "elf32-i386")
-OUTPUT_ARCH(i386)
-EXTERN(_start)
-ENTRY(_start)
-SECTIONS
-{
- /* Read-only sections, merged into text segment: */
- . = 0x100;
- PROVIDE (__executable_start = .);
-
- .init :
- {
- KEEP (*(.init))
- } =0x90909090
- .text :
- {
- *(.text .stub .text.* .gnu.linkonce.t.*)
- /* .gnu.warning sections are handled specially by elf32.em. */
- *(.gnu.warning)
- } =0x90909090
- .fini :
- {
- KEEP (*(.fini))
- } =0x90909090
- PROVIDE (__etext = .);
- PROVIDE (_etext = .);
- PROVIDE (etext = .);
- .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
- .rodata1 : { *(.rodata1) }
-
- /* Ensure the __preinit_array_start label is properly aligned. We
- could instead move the label definition inside the section, but
- the linker would then create the section even if it turns out to
- be empty, which isn't pretty. */
- . = ALIGN(4);
- PROVIDE (__preinit_array_start = .);
- .preinit_array : { *(.preinit_array) }
- PROVIDE (__preinit_array_end = .);
- PROVIDE (__init_array_start = .);
- .init_array : { *(.init_array) }
- PROVIDE (__init_array_end = .);
- PROVIDE (__fini_array_start = .);
- .fini_array : { *(.fini_array) }
- PROVIDE (__fini_array_end = .);
- PROVIDE (__ctors_start = .);
- .ctors :
- {
- KEEP (*(SORT(.ctors.*)))
- KEEP (*(.ctors))
- }
- PROVIDE (__ctors_end = .);
- PROVIDE (__dtors_start = .);
- .dtors :
- {
- KEEP (*(SORT(.dtors.*)))
- KEEP (*(.dtors))
- }
- PROVIDE (__dtors_end = .);
-
- /* Adjust the address for the data segment. Avoid mixing code and
- data within same 128-byte chunk. */
- . = ALIGN(128);
-
- .data :
- {
- *(.data .data.* .gnu.linkonce.d.*)
- SORT(CONSTRUCTORS)
- }
- .data1 : { *(.data1) }
- _edata = .;
- PROVIDE (edata = .);
- __bss_start = .;
- .bss :
- {
- *(.dynbss)
- *(.bss .bss.* .gnu.linkonce.b.*)
- *(COMMON)
- /* Align here to ensure that the .bss section occupies space up to
- _end. Align after .bss to ensure correct alignment even if the
- .bss section disappears because there are no input sections. */
- . = ALIGN(32 / 8);
- }
- . = ALIGN(32 / 8);
- _end = .;
- PROVIDE (end = .);
-
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
- /* DWARF debug sections.
- Symbols in the DWARF debugging sections are relative to the beginning
- of the section so we begin them at 0. */
- /* DWARF 1 */
- .debug 0 : { *(.debug) }
- .line 0 : { *(.line) }
- /* GNU DWARF 1 extensions */
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- /* DWARF 1.1 and DWARF 2 */
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- /* DWARF 2 */
- .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- /* SGI/MIPS DWARF 2 extensions */
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
- /DISCARD/ : {
- *(.note.GNU-stack)
- *(.eh_frame)
- }
-}
diff --git a/dos/crt0.S b/dos/crt0.S
index 62ab80ff..3be57125 100644
--- a/dos/crt0.S
+++ b/dos/crt0.S
@@ -4,27 +4,38 @@
# error "This file assumes -mregparm=3 -DREGPARM=3"
#endif
- .section ".init","ax"
+ .section ".text","ax"
.globl _start
.type _start,@function
_start:
# Align the stack and make sure the high half is zero
andl $0xfff8,%esp
+ # DS, ES points to the PSP at this point
+ pushw %es # Save PSP pointer
+ movw %cs,%ax
+ movw %ax,%ds
+ movw %ax,%es
+
# Clear the .bss
cld
xorl %eax,%eax
movw $__bss_start,%di
- movw $_end+3,%cx
+ movw $__bss_end+3,%cx
subw %di,%cx
shrw $2,%cx
rep ; stosl
+ # Copy the command line into our own segment
+ popw %fs # FS -> PSP
+ movw $_cmdline,%di
+ movzbw %fs:0x80,%cx
+ movw $0x81,%si
+ fs ; rep ; movsb
+ # Already zero-terminated since we're writing into clean bss
+
# Compute argc and argv (assumes REGPARM)
- xorl %edx,%edx
- movzbw 0x80,%bx
- movb %dl,0x81(%bx) # Zero-terminate string
- movb $0x81,%dl
+ movl $_cmdline,%edx
pushl %eax # Make space for argv
movl %esp,%eax
calll __parse_argv
@@ -51,3 +62,9 @@ exit:
1: hlt
jmp 1b
.size exit,.-exit
+
+ .section ".bss","aw"
+ .balign 4
+_cmdline:
+ .space 128
+ .size _cmdline,.-_cmdline
diff --git a/dos/dosexe.ld b/dos/dosexe.ld
new file mode 100644
index 00000000..4612b30a
--- /dev/null
+++ b/dos/dosexe.ld
@@ -0,0 +1,131 @@
+/*
+ * Linker script for an MS-DOS EXE binary; this hard-codes a simple
+ * MZ header without relocations.
+ *
+ * For documentation on the MS-DOS MZ EXE format, see:
+ * http://www.delorie.com/djgpp/doc/exe/
+ */
+
+
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386",
+ "elf32-i386")
+OUTPUT_ARCH(i386)
+EXTERN(_start)
+ENTRY(_start)
+
+SECTIONS
+{
+ . = 0;
+ /* EXE header, from header.S */
+ .header : {
+ *(.header)
+ } =0
+
+ . = ALIGN(16);
+ __header_size = .;
+ __payload_lma = .;
+
+ . = 0;
+ .payload : AT (__payload_lma) {
+ __payload_start = .;
+ ldlinux_bin.o(.data)
+ __payload_end = .;
+ }
+ __payload_len = __payload_end - __payload_start;
+ __payload_dwords = __payload_len >> 2;
+
+ . = ALIGN(16);
+ __text_lma = __payload_lma + .;
+ __payload_sseg = (__payload_lma - __text_lma) >> 4;
+ _exe_text_seg = (__text_lma - __header_size) >> 4;
+
+ . = 0;
+ .text : AT (__text_lma) {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ *(.gnu.warning)
+ } =0x90909090
+ _etext = .;
+
+ . = ALIGN(16);
+ __rodata_vma = .;
+ .rodata : AT (__rodata_vma + __text_lma) {
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ }
+
+ /* Adjust the address for the data segment. Avoid mixing code and
+ data within same 128-byte chunk. */
+ . = ALIGN(128);
+ __data_vma = .;
+ .data : AT (__data_vma + __text_lma) {
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ _edata = .;
+
+ _exe_edata_low = ((_edata + __text_lma) & 511);
+ _exe_edata_blocks = ((_edata + __text_lma) + 511) >> 9;
+
+ .bss (NOLOAD) : {
+ __bss_start = .;
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ __bss_end = .;
+ }
+
+ . = ALIGN(16);
+ .heap (NOLOAD) : {
+ __heap_start = .;
+ *(.heap)
+ __heap_end = .;
+ }
+
+ . = ALIGN(16);
+ .stack (NOLOAD) : {
+ __stack_start = .;
+ *(.stack)
+ __stack_end = .;
+ }
+ . = ALIGN(16);
+ _end = .;
+
+ _exe_bss_paras = (_end - __bss_start) >> 4;
+
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /DISCARD/ : { *(.note.GNU-stack) }
+}
diff --git a/dos/header.S b/dos/header.S
new file mode 100644
index 00000000..e7504471
--- /dev/null
+++ b/dos/header.S
@@ -0,0 +1,46 @@
+STACK_SIZE = 8192
+HEAP_SIZE = 16384
+
+ .section ".header","a"
+ .balign 512
+__header_start:
+ .short 0x5a4d
+ .short _exe_edata_low
+ .short _exe_edata_blocks
+ .short 0 /* Relocation count */
+ .short (__header_end - __header_start) >> 4
+ .short _exe_bss_paras
+ .short _exe_bss_paras
+ .short _exe_text_seg /* SP */
+ .short __stack_end
+ .short 0 /* Checksum */
+ .short _start
+ .short _exe_text_seg /* CS */
+ .short __reloc
+ .short 0 /* Overlay number */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+ .long 0 /* Pointer to Windows PE header */
+__reloc:
+ .balign 512
+__header_end:
+
+ .section ".heap","aw"
+ .space HEAP_SIZE
+
+ .section ".stack","aw"
+ .space STACK_SIZE
diff --git a/dos/malloc.c b/dos/malloc.c
index 3cfcbb2c..55c78c4c 100644
--- a/dos/malloc.c
+++ b/dos/malloc.c
@@ -5,6 +5,7 @@
*/
#include <stdlib.h>
+#include <string.h>
#include "malloc.h"
struct free_arena_header __malloc_head = {
@@ -18,29 +19,16 @@ struct free_arena_header __malloc_head = {
&__malloc_head
};
-/* This is extern so it can be overridden by the user application */
-const size_t __stack_size = 4096;
-
-static inline size_t sp(void)
-{
- uint32_t sp;
- asm volatile ("movl %%esp,%0":"=rm" (sp));
- return sp;
-}
-
-extern void *__mem_end;
+extern void *__mem_end; /* In argv.c */
void __init_memory_arena(void)
{
+ extern char __heap_end[];
struct free_arena_header *fp;
- size_t start, total_space;
- start = (size_t) ARENA_ALIGN_UP(__mem_end);
- total_space = sp() - start;
-
- fp = (struct free_arena_header *)start;
+ fp = (struct free_arena_header *)__mem_end;
fp->a.type = ARENA_TYPE_FREE;
- fp->a.size = total_space - __stack_size;
+ fp->a.size = __heap_end - (char *)__mem_end;
/* Insert into chains */
fp->a.next = fp->a.prev = &__malloc_head;
@@ -111,3 +99,13 @@ void *malloc(size_t size)
/* Nothing found... need to request a block from the kernel */
return NULL; /* No kernel to get stuff from */
}
+
+void *calloc(size_t nmemb, size_t size)
+{
+ void *p;
+ size *= nmemb;
+ p = malloc(size);
+ if (p)
+ memset(p, 0, size);
+ return p;
+}
diff --git a/dos/stdlib.h b/dos/stdlib.h
index e0597ce8..71af6907 100644
--- a/dos/stdlib.h
+++ b/dos/stdlib.h
@@ -7,6 +7,7 @@ typedef unsigned int size_t;
void __attribute__ ((noreturn)) exit(int);
void *malloc(size_t);
+void *calloc(size_t, size_t);
void free(void *);
#endif
diff --git a/dos/syslinux.c b/dos/syslinux.c
index 650c48f6..61020a1f 100644
--- a/dos/syslinux.c
+++ b/dos/syslinux.c
@@ -121,6 +121,33 @@ int rename(const char *oldname, const char *newname)
return 0;
}
+extern const char __payload_sseg[];
+uint16_t ldlinux_seg;
+
+ssize_t write_ldlinux(int fd)
+{
+ uint32_t offset = 0;
+ uint16_t rv;
+ uint8_t err;
+
+ while (offset < syslinux_ldlinux_len) {
+ uint32_t chunk = syslinux_ldlinux_len - offset;
+ if (chunk > 32768)
+ chunk = 32768;
+ asm volatile ("pushw %%ds ; "
+ "movw %6,%%ds ; "
+ "int $0x21 ; "
+ "popw %%ds ; " "setc %0":"=bcdm" (err), "=a"(rv)
+ :"a"(0x4000), "b"(fd), "c"(chunk), "d"(offset & 15),
+ "SD"((uint16_t) (ldlinux_seg + (offset >> 4))));
+ if (err || rv == 0)
+ die("file write error");
+ offset += rv;
+ }
+
+ return offset;
+}
+
ssize_t write_file(int fd, const void *buf, size_t count)
{
uint16_t rv;
@@ -130,9 +157,8 @@ ssize_t write_file(int fd, const void *buf, size_t count)
dprintf("write_file(%d,%p,%u)\n", fd, buf, count);
while (count) {
- rv = 0x4000;
- asm volatile ("int $0x21 ; setc %0":"=abcdm" (err), "+a"(rv)
- :"b"(fd), "c"(count), "d"(buf));
+ asm volatile ("int $0x21 ; setc %0":"=bcdm" (err), "=a"(rv)
+ :"a"(0x4000), "b"(fd), "c"(count), "d"(buf));
if (err || rv == 0)
die("file write error");
@@ -513,7 +539,7 @@ struct mbr_entry {
static void adjust_mbr(int device, int writembr, int set_active)
{
- static unsigned char sectbuf[512];
+ static unsigned char sectbuf[SECTOR_SIZE];
int i;
if (!writembr && !set_active)
@@ -555,13 +581,15 @@ static void adjust_mbr(int device, int writembr, int set_active)
int main(int argc, char *argv[])
{
- static unsigned char sectbuf[512];
+ static unsigned char sectbuf[SECTOR_SIZE];
int dev_fd, fd;
static char ldlinux_name[] = "@:\\ldlinux.sys";
char **argp, *opt;
int force = 0; /* -f (force) option */
struct libfat_filesystem *fs;
- libfat_sector_t s, *secp, sectors[65]; /* 65 is maximum possible */
+ libfat_sector_t s, *secp;
+ libfat_sector_t *sectors;
+ int ldlinux_sectors;
int32_t ldlinux_cluster;
int nsectors;
const char *device = NULL, *bootsecfile = NULL;
@@ -572,6 +600,9 @@ int main(int argc, char *argv[])
const char *subdir = NULL;
int stupid = 0;
int raid_mode = 0;
+ int patch_sectors;
+
+ ldlinux_seg = (size_t) __payload_sseg + data_segment();
dprintf("argv = %p\n", argv);
for (i = 0; i <= argc; i++)
@@ -651,9 +682,9 @@ int main(int argc, char *argv[])
ldlinux_name[0] = dev_fd | 0x40;
- set_attributes(ldlinux_name, 0x00);
- fd = creat(ldlinux_name, 0);
- write_file(fd, syslinux_ldlinux, syslinux_ldlinux_len);
+ set_attributes(ldlinux_name, 0);
+ fd = creat(ldlinux_name, 0); /* SYSTEM HIDDEN READONLY */
+ write_ldlinux(fd);
close(fd);
set_attributes(ldlinux_name, 0x07); /* SYSTEM HIDDEN READONLY */
@@ -663,13 +694,15 @@ int main(int argc, char *argv[])
* this is supposed to be a simple, privileged version
* of the installer.
*/
+ ldlinux_sectors = (syslinux_ldlinux_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
+ sectors = calloc(ldlinux_sectors, sizeof *sectors);
lock_device(2);
fs = libfat_open(libfat_xpread, dev_fd);
ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL);
secp = sectors;
nsectors = 0;
s = libfat_clustertosector(fs, ldlinux_cluster);
- while (s && nsectors < 65) {
+ while (s && nsectors < ldlinux_sectors) {
*secp++ = s;
nsectors++;
s = libfat_nextsector(fs, s);
@@ -722,13 +755,24 @@ int main(int argc, char *argv[])
/*
* Patch ldlinux.sys and the boot sector
*/
- syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ i = syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ patch_sectors = (i + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
/*
- * Write the now-patched first sector of ldlinux.sys
+ * Overwrite the now-patched ldlinux.sys
*/
/* lock_device(3); -- doesn't seem to be needed */
- write_device(dev_fd, syslinux_ldlinux, 1, sectors[0]);
+ for (i = 0; i < patch_sectors; i++) {
+ uint16_t si, di, cx;
+ si = 0;
+ di = (size_t) sectbuf;
+ cx = SECTOR_SIZE >> 2;
+ asm volatile ("movw %3,%%fs ; fs ; rep ; movsl":"+S" (si), "+D"(di),
+ "+c"(cx)
+ :"abd"((uint16_t)
+ (ldlinux_seg + (i << (SECTOR_SHIFT - 4)))));
+ write_device(dev_fd, sectbuf, 1, sectors[i]);
+ }
/*
* Muck with the MBR, if desired, while we hold the lock
@@ -749,7 +793,7 @@ int main(int argc, char *argv[])
if (bootsecfile) {
unlock_device(0);
fd = creat(bootsecfile, 0x20); /* ARCHIVE */
- write_file(fd, sectbuf, 512);
+ write_file(fd, sectbuf, SECTOR_SIZE);
close(fd);
} else {
write_device(dev_fd, sectbuf, 1, 0);
diff --git a/extlinux/btrfs.h b/extlinux/btrfs.h
new file mode 100644
index 00000000..39a861a5
--- /dev/null
+++ b/extlinux/btrfs.h
@@ -0,0 +1,22 @@
+#ifndef _BTRFS_H_
+#define _BTRFS_H_
+
+#define BTRFS_SUPER_MAGIC 0x9123683E
+#define BTRFS_SUPER_INFO_OFFSET (64 * 1024)
+#define BTRFS_SUPER_INFO_SIZE 4096
+#define BTRFS_MAGIC "_BHRfS_M"
+#define BTRFS_CSUM_SIZE 32
+#define BTRFS_FSID_SIZE 16
+
+struct btrfs_super_block {
+ unsigned char csum[BTRFS_CSUM_SIZE];
+ /* the first 3 fields must match struct btrfs_header */
+ unsigned char fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
+ u64 bytenr; /* this block number */
+ u64 flags;
+
+ /* allowed to be different from the btrfs_header from here own down */
+ u64 magic;
+} __attribute__ ((__packed__));
+
+#endif
diff --git a/extlinux/main.c b/extlinux/main.c
index 19748c8d..7eb59dae 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -1,6 +1,7 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 1998-2008 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
@@ -13,7 +14,7 @@
/*
* extlinux.c
*
- * Install the extlinux boot block on an ext2/3 filesystem
+ * Install the extlinux boot block on an ext2/3/4 and btrfs filesystem
*/
#define _GNU_SOURCE /* Enable everything */
@@ -28,6 +29,7 @@ typedef uint64_t u64;
#ifndef __KLIBC__
#include <mntent.h>
#endif
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
@@ -45,6 +47,7 @@ typedef uint64_t u64;
#undef statfs
#include "ext2_fs.h"
+#include "btrfs.h"
#include "../version.h"
#include "syslxint.h"
@@ -55,6 +58,10 @@ typedef uint64_t u64;
#endif
/* Global option handling */
+/* Global fs_type for handling ext2/3/4 vs btrfs */
+#define EXT2 1
+#define BTRFS 2
+int fs_type;
const char *program;
@@ -63,10 +70,12 @@ struct my_options {
unsigned int sectors;
unsigned int heads;
int raid_mode;
+ int stupid_mode;
int reset_adv;
const char *set_once;
} opt = {
-.sectors = 0,.heads = 0,.raid_mode = 0,.reset_adv = 0,.set_once = NULL,};
+.sectors = 0,.heads = 0,.raid_mode = 0,.stupid_mode = 0,.reset_adv =
+ 0,.set_once = NULL,};
static void __attribute__ ((noreturn)) usage(int rv)
{
@@ -77,6 +86,7 @@ static void __attribute__ ((noreturn)) usage(int rv)
" --zip -z Force zipdrive geometry (-H 64 -S 32)\n"
" --sectors=# -S Force the number of sectors per track\n"
" --heads=# -H Force number of heads\n"
+ " --stupid -s Slow, safe and stupid mode\n"
" --raid -r Fall back to the next device on boot failure\n"
" --once=... -o Execute a command once upon boot\n"
" --clear-once -O Clear the boot-once command\n"
@@ -104,6 +114,7 @@ static const struct option long_options[] = {
{"update", 0, NULL, 'U'},
{"zipdrive", 0, NULL, 'z'},
{"sectors", 1, NULL, 'S'},
+ {"stupid", 0, NULL, 's'},
{"heads", 1, NULL, 'H'},
{"raid-mode", 0, NULL, 'r'},
{"version", 0, NULL, 'v'},
@@ -121,61 +132,13 @@ static const char short_options[] = "iUuzS:H:rvho:O";
# define BLKGETSIZE64 _IOR(0x12,114,size_t)
#endif
-#define LDLINUX_MAGIC 0x3eb202fe
-
-enum bs_offsets {
- bsJump = 0x00,
- bsOemName = 0x03,
- bsBytesPerSec = 0x0b,
- bsSecPerClust = 0x0d,
- bsResSectors = 0x0e,
- bsFATs = 0x10,
- bsRootDirEnts = 0x11,
- bsSectors = 0x13,
- bsMedia = 0x15,
- bsFATsecs = 0x16,
- bsSecPerTrack = 0x18,
- bsHeads = 0x1a,
- bsHiddenSecs = 0x1c,
- bsHugeSectors = 0x20,
-
- /* FAT12/16 only */
- bs16DriveNumber = 0x24,
- bs16Reserved1 = 0x25,
- bs16BootSignature = 0x26,
- bs16VolumeID = 0x27,
- bs16VolumeLabel = 0x2b,
- bs16FileSysType = 0x36,
- bs16Code = 0x3e,
-
- /* FAT32 only */
- bs32FATSz32 = 36,
- bs32ExtFlags = 40,
- bs32FSVer = 42,
- bs32RootClus = 44,
- bs32FSInfo = 48,
- bs32BkBootSec = 50,
- bs32Reserved = 52,
- bs32DriveNumber = 64,
- bs32Reserved1 = 65,
- bs32BootSignature = 66,
- bs32VolumeID = 67,
- bs32VolumeLabel = 71,
- bs32FileSysType = 82,
- bs32Code = 90,
-
- bsSignature = 0x1fe
-};
-
-#define bsHead bsJump
-#define bsHeadLen (bsOemName-bsHead)
-#define bsCode bs32Code /* The common safe choice */
-#define bsCodeLen (bsSignature-bs32Code)
-
#ifndef EXT2_SUPER_OFFSET
#define EXT2_SUPER_OFFSET 1024
#endif
+/* the btrfs partition first 64K blank area is used to store boot sector and
+ boot image, the boot sector is from 0~512, the boot image starts at 2K */
+#define BTRFS_EXTLINUX_OFFSET (2*1024)
/*
* Boot block
*/
@@ -388,22 +351,28 @@ int get_geometry(int devfd, uint64_t totalbytes, struct hd_geometry *geo)
* Query the device geometry and put it into the boot sector.
* Map the file and put the map in the boot sector and file.
* Stick the "current directory" inode number into the file.
+ *
+ * Returns the number of modified bytes in the boot file.
*/
-void patch_file_and_bootblock(int fd, int dirfd, int devfd)
+int patch_file_and_bootblock(int fd, int dirfd, int devfd)
{
struct stat dirst;
struct hd_geometry geo;
uint32_t *sectp;
uint64_t totalbytes, totalsectors;
int nsect;
- unsigned char *p, *patcharea;
- int i, dw;
+ uint32_t *wp;
+ struct boot_sector *bs;
+ struct patch_area *patcharea;
+ int i, dw, nptrs;
uint32_t csum;
+ int secptroffset;
- if (fstat(dirfd, &dirst)) {
- perror("fstat dirfd");
- exit(255); /* This should never happen */
- }
+ if (fs_type == EXT2)
+ if (fstat(dirfd, &dirst)) {
+ perror("fstat dirfd");
+ exit(255); /* This should never happen */
+ }
totalbytes = get_size(devfd);
get_geometry(devfd, totalbytes, &geo);
@@ -418,26 +387,28 @@ void patch_file_and_bootblock(int fd, int dirfd, int devfd)
early bootstrap share code with the FAT version. */
dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors);
+ bs = (struct boot_sector *)boot_block;
+
totalsectors = totalbytes >> SECTOR_SHIFT;
if (totalsectors >= 65536) {
- set_16(boot_block + bsSectors, 0);
+ set_16(&bs->bsSectors, 0);
} else {
- set_16(boot_block + bsSectors, totalsectors);
+ set_16(&bs->bsSectors, totalsectors);
}
- set_32(boot_block + bsHugeSectors, totalsectors);
+ set_32(&bs->bsHugeSectors, totalsectors);
- set_16(boot_block + bsBytesPerSec, SECTOR_SIZE);
- set_16(boot_block + bsSecPerTrack, geo.sectors);
- set_16(boot_block + bsHeads, geo.heads);
- set_32(boot_block + bsHiddenSecs, geo.start);
+ set_16(&bs->bsBytesPerSec, SECTOR_SIZE);
+ set_16(&bs->bsSecPerTrack, geo.sectors);
+ set_16(&bs->bsHeads, geo.heads);
+ set_32(&bs->bsHiddenSecs, geo.start);
/* If we're in RAID mode then patch the appropriate instruction;
either way write the proper boot signature */
- i = get_16(boot_block + 0x1FE);
+ i = get_16(&bs->bsSignature);
if (opt.raid_mode)
- set_16(boot_block + i, 0x18CD); /* INT 18h */
+ set_16((uint16_t *) (boot_block + i), 0x18CD); /* INT 18h */
- set_16(boot_block + 0x1FE, 0xAA55);
+ set_16(&bs->bsSignature, 0xAA55);
/* Construct the boot file */
@@ -445,43 +416,54 @@ void patch_file_and_bootblock(int fd, int dirfd, int devfd)
nsect = (boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
nsect += 2; /* Two sectors for the ADV */
sectp = alloca(sizeof(uint32_t) * nsect);
- if (sectmap(fd, sectp, nsect)) {
- perror("bmap");
- exit(1);
+ if (fs_type == EXT2) {
+ if (sectmap(fd, sectp, nsect)) {
+ perror("bmap");
+ exit(1);
+ }
+ } else if (fs_type == BTRFS) {
+ int i;
+
+ for (i = 0; i < nsect; i++)
+ *(sectp + i) = BTRFS_EXTLINUX_OFFSET/SECTOR_SIZE + i;
}
/* First sector need pointer in boot sector */
- set_32(boot_block + 0x1F8, *sectp++);
- nsect--;
+ set_32(&bs->NextSector, *sectp++);
+ /* Stupid mode? */
+ if (opt.stupid_mode)
+ set_16(&bs->MaxTransfer, 1);
/* Search for LDLINUX_MAGIC to find the patch area */
- for (p = boot_image; get_32(p) != LDLINUX_MAGIC; p += 4) ;
- patcharea = p + 8;
+ for (wp = (uint32_t *) boot_image; get_32(wp) != LDLINUX_MAGIC; wp++) ;
+ patcharea = (struct patch_area *)wp;
/* Set up the totals */
dw = boot_image_len >> 2; /* COMPLETE dwords, excluding ADV */
- set_16(patcharea, dw);
- set_16(patcharea + 2, nsect); /* Not including the first sector, but
- including the ADV */
- set_32(patcharea + 8, dirst.st_ino); /* "Current" directory */
+ set_16(&patcharea->data_sectors, nsect - 2); /* -2 for the ADVs */
+ set_16(&patcharea->adv_sectors, 2);
+ set_32(&patcharea->dwords, dw);
+ set_32(&patcharea->currentdir, dirst.st_ino);
/* Set the sector pointers */
- p = patcharea + 12;
+ secptroffset = get_16(&patcharea->secptroffset);
+ wp = (uint32_t *) ((char *)boot_image + secptroffset);
+ nptrs = get_16(&patcharea->secptrcnt);
- memset(p, 0, 64 * 4);
- while (nsect--) {
- set_32(p, *sectp++);
- p += 4;
- }
+ memset(wp, 0, nptrs * 4);
+ while (nsect--)
+ set_32(wp++, *sectp++);
/* Now produce a checksum */
- set_32(patcharea + 4, 0);
+ set_32(&patcharea->checksum, 0);
csum = LDLINUX_MAGIC;
- for (i = 0, p = boot_image; i < dw; i++, p += 4)
- csum -= get_32(p); /* Negative checksum */
+ for (i = 0, wp = (uint32_t *) boot_image; i < dw; i++, wp++)
+ csum -= get_32(wp); /* Negative checksum */
+
+ set_32(&patcharea->checksum, csum);
- set_32(patcharea + 4, csum);
+ return secptroffset + nptrs*4;
}
/*
@@ -489,13 +471,21 @@ void patch_file_and_bootblock(int fd, int dirfd, int devfd)
* Returns -1 on fatal errors, 0 if ADV is okay, and 1 if no valid
* ADV was found.
*/
-int read_adv(const char *path)
+int read_adv(const char *path, int devfd)
{
char *file;
int fd = -1;
struct stat st;
int err = 0;
+ if (fs_type == BTRFS) { /* btrfs "extlinux.sys" is in 64k blank area */
+ if (xpread(devfd, syslinux_adv, 2 * ADV_SIZE,
+ BTRFS_EXTLINUX_OFFSET + boot_image_len) != 2 * ADV_SIZE) {
+ perror("writing adv");
+ return 1;
+ }
+ return 0;
+ }
asprintf(&file, "%s%sextlinux.sys",
path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
@@ -539,7 +529,7 @@ int read_adv(const char *path)
/*
* Update the ADV in an existing installation.
*/
-int write_adv(const char *path)
+int write_adv(const char *path, int devfd)
{
unsigned char advtmp[2 * ADV_SIZE];
char *file;
@@ -548,6 +538,14 @@ int write_adv(const char *path)
int err = 0;
int flags, nflags;
+ if (fs_type == BTRFS) { /* btrfs "extlinux.sys" is in 64k blank area */
+ if (xpwrite(devfd, syslinux_adv, 2 * ADV_SIZE,
+ BTRFS_EXTLINUX_OFFSET + boot_image_len) != 2 * ADV_SIZE) {
+ perror("writing adv");
+ return 1;
+ }
+ return 0;
+ }
asprintf(&file, "%s%sextlinux.sys",
path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
@@ -645,17 +643,30 @@ int modify_adv(void)
int install_bootblock(int fd, const char *device)
{
struct ext2_super_block sb;
+ struct btrfs_super_block sb2;
+ bool ok = false;
- if (xpread(fd, &sb, sizeof sb, EXT2_SUPER_OFFSET) != sizeof sb) {
- perror("reading superblock");
- return 1;
+ if (fs_type == EXT2) {
+ if (xpread(fd, &sb, sizeof sb, EXT2_SUPER_OFFSET) != sizeof sb) {
+ perror("reading superblock");
+ return 1;
+ }
+ if (sb.s_magic == EXT2_SUPER_MAGIC)
+ ok = true;
+ } else if (fs_type == BTRFS) {
+ if (xpread(fd, &sb2, sizeof sb2, BTRFS_SUPER_INFO_OFFSET)
+ != sizeof sb2) {
+ perror("reading superblock");
+ return 1;
+ }
+ if (sb2.magic == *(u64 *)BTRFS_MAGIC)
+ ok = true;
}
-
- if (sb.s_magic != EXT2_SUPER_MAGIC) {
- fprintf(stderr, "no ext2/ext3 superblock found on %s\n", device);
+ if (!ok) {
+ fprintf(stderr, "no ext2/3/4 or btrfs superblock found on %s\n",
+ device);
return 1;
}
-
if (xpwrite(fd, boot_block, boot_block_len, 0) != boot_block_len) {
perror("writing bootblock");
return 1;
@@ -664,11 +675,12 @@ int install_bootblock(int fd, const char *device)
return 0;
}
-int install_file(const char *path, int devfd, struct stat *rst)
+int ext2_install_file(const char *path, int devfd, struct stat *rst)
{
char *file;
int fd = -1, dirfd = -1, flags;
struct stat st;
+ int modbytes;
asprintf(&file, "%s%sextlinux.sys",
path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
@@ -717,11 +729,11 @@ int install_file(const char *path, int devfd, struct stat *rst)
}
/* Map the file, and patch the initial sector accordingly */
- patch_file_and_bootblock(fd, dirfd, devfd);
+ modbytes = patch_file_and_bootblock(fd, dirfd, devfd);
- /* Write the first sector again - this relies on the file being
+ /* Write the patch area again - this relies on the file being
overwritten in place! */
- if (xpwrite(fd, boot_image, SECTOR_SIZE, 0) != SECTOR_SIZE) {
+ if (xpwrite(fd, boot_image, modbytes, 0) != modbytes) {
fprintf(stderr, "%s: write failure on %s\n", program, file);
goto bail;
}
@@ -754,6 +766,40 @@ bail:
return 1;
}
+/* btrfs has to install the extlinux.sys in the first 64K blank area, which
+ is not managered by btrfs tree, so actually this is not installed as files.
+ since the cow feature of btrfs will move the extlinux.sys every where */
+int btrfs_install_file(const char *path, int devfd, struct stat *rst)
+{
+ patch_file_and_bootblock(-1, -1, devfd);
+ if (xpwrite(devfd, boot_image, boot_image_len, BTRFS_EXTLINUX_OFFSET)
+ != boot_image_len) {
+ perror("writing bootblock");
+ return 1;
+ }
+ printf("write boot_image to 0x%x\n", BTRFS_EXTLINUX_OFFSET);
+ if (xpwrite(devfd, syslinux_adv, 2 * ADV_SIZE,
+ BTRFS_EXTLINUX_OFFSET + boot_image_len) != 2 * ADV_SIZE) {
+ perror("writing adv");
+ return 1;
+ }
+ printf("write adv to 0x%x\n", BTRFS_EXTLINUX_OFFSET + boot_image_len);
+ if (stat(path, rst)) {
+ perror(path);
+ return 1;
+ }
+ return 0;
+}
+
+int install_file(const char *path, int devfd, struct stat *rst)
+{
+ if (fs_type == EXT2)
+ return ext2_install_file(path, devfd, rst);
+ else if (fs_type == BTRFS)
+ return btrfs_install_file(path, devfd, rst);
+ return 1;
+}
+
/* EXTLINUX installs the string 'EXTLINUX' at offset 3 in the boot
sector; this is consistent with FAT filesystems. */
int already_installed(int devfd)
@@ -778,10 +824,13 @@ static void device_cleanup(void)
static int validate_device(const char *path, int devfd)
{
struct stat pst, dst;
+ struct statfs sfs;
- if (stat(path, &pst) || fstat(devfd, &dst))
+ if (stat(path, &pst) || fstat(devfd, &dst) || statfs(path, &sfs))
return -1;
-
+ /* btrfs st_dev is not matched with mnt st_rdev, it is a known issue */
+ if (fs_type == BTRFS && sfs.f_type == BTRFS_SUPER_MAGIC)
+ return 0;
return (pst.st_dev == dst.st_rdev) ? 0 : -1;
}
@@ -792,17 +841,35 @@ static const char *find_device(const char *mtab_file, dev_t dev)
struct stat dst;
FILE *mtab;
const char *devname = NULL;
+ bool done;
mtab = setmntent(mtab_file, "r");
if (!mtab)
return NULL;
+ done = false;
while ((mnt = getmntent(mtab))) {
- if ((!strcmp(mnt->mnt_type, "ext2") ||
- !strcmp(mnt->mnt_type, "ext3")) &&
- !stat(mnt->mnt_fsname, &dst) && dst.st_rdev == dev) {
- devname = strdup(mnt->mnt_fsname);
- break;
+ /* btrfs st_dev is not matched with mnt st_rdev, it is a known issue */
+ switch (fs_type) {
+ case BTRFS:
+ if (!strcmp(mnt->mnt_type, "btrfs") &&
+ !stat(mnt->mnt_dir, &dst) &&
+ dst.st_dev == dev)
+ done = true;
+ break;
+ case EXT2:
+ if ((!strcmp(mnt->mnt_type, "ext2") ||
+ !strcmp(mnt->mnt_type, "ext3") ||
+ !strcmp(mnt->mnt_type, "ext4")) &&
+ !stat(mnt->mnt_fsname, &dst) &&
+ dst.st_rdev == dev) {
+ done = true;
+ break;
+ }
+ }
+ if (done) {
+ devname = strdup(mnt->mnt_fsname);
+ break;
}
}
endmntent(mtab);
@@ -811,30 +878,20 @@ static const char *find_device(const char *mtab_file, dev_t dev)
}
#endif
-int install_loader(const char *path, int update_only)
+static const char *get_devname(const char *path)
{
- struct stat st, fst;
- int devfd, rv;
const char *devname = NULL;
+ struct stat st;
struct statfs sfs;
if (stat(path, &st) || !S_ISDIR(st.st_mode)) {
fprintf(stderr, "%s: Not a directory: %s\n", program, path);
- return 1;
+ return devname;
}
-
if (statfs(path, &sfs)) {
fprintf(stderr, "%s: statfs %s: %s\n", program, path, strerror(errno));
- return 1;
+ return devname;
}
-
- if (sfs.f_type != EXT2_SUPER_MAGIC) {
- fprintf(stderr, "%s: not an ext2/ext3 filesystem: %s\n", program, path);
- return 1;
- }
-
- devfd = -1;
-
#ifdef __KLIBC__
/* klibc doesn't have getmntent and friends; instead, just create
@@ -844,7 +901,7 @@ int install_loader(const char *path, int update_only)
if (mknod(devname_buf, S_IFBLK | 0600, st.st_dev)) {
fprintf(stderr, "%s: cannot create device %s\n", program, devname);
- return 1;
+ return devname;
}
atexit(device_cleanup); /* unlink the device node on exit */
@@ -859,46 +916,99 @@ int install_loader(const char *path, int update_only)
}
if (!devname) {
fprintf(stderr, "%s: cannot find device for path %s\n", program, path);
- return 1;
+ return devname;
}
fprintf(stderr, "%s is device %s\n", path, devname);
#endif
+ return devname;
+}
+
+static int open_device(const char *path, struct stat *st, const char **_devname)
+{
+ int devfd;
+ const char *devname = NULL;
+ struct statfs sfs;
+
+ if (st)
+ if (stat(path, st) || !S_ISDIR(st->st_mode)) {
+ fprintf(stderr, "%s: Not a directory: %s\n", program, path);
+ return -1;
+ }
+
+ if (statfs(path, &sfs)) {
+ fprintf(stderr, "%s: statfs %s: %s\n", program, path, strerror(errno));
+ return -1;
+ }
+ if (sfs.f_type == EXT2_SUPER_MAGIC)
+ fs_type = EXT2;
+ else if (sfs.f_type == BTRFS_SUPER_MAGIC)
+ fs_type = BTRFS;
+
+ if (!fs_type) {
+ fprintf(stderr, "%s: not an ext2/3/4 or btrfs filesystem: %s\n",
+ program, path);
+ return -1;
+ }
+
+ devfd = -1;
+ devname = get_devname(path);
+ if (_devname)
+ *_devname = devname;
if ((devfd = open(devname, O_RDWR | O_SYNC)) < 0) {
fprintf(stderr, "%s: cannot open device %s\n", program, devname);
- return 1;
+ return -1;
}
/* Verify that the device we opened is the device intended */
if (validate_device(path, devfd)) {
fprintf(stderr, "%s: path %s doesn't match device %s\n",
program, path, devname);
- return 1;
+ close(devfd);
+ return -1;
}
+ return devfd;
+}
+
+int install_loader(const char *path, int update_only)
+{
+ struct stat st, fst;
+ int devfd, rv;
+ const char *devname;
+
+ devfd = open_device(path, &st, &devname);
+ if (devfd < 0)
+ return 1;
if (update_only && !already_installed(devfd)) {
fprintf(stderr, "%s: no previous extlinux boot sector found\n",
program);
+ close(devfd);
return 1;
}
/* Read a pre-existing ADV, if already installed */
if (opt.reset_adv)
syslinux_reset_adv(syslinux_adv);
- else if (read_adv(path) < 0)
+ else if (read_adv(path, devfd) < 0) {
+ close(devfd);
return 1;
-
- if (modify_adv() < 0)
+ }
+ if (modify_adv() < 0) {
+ close(devfd);
return 1;
+ }
/* Install extlinux.sys */
- if (install_file(path, devfd, &fst))
+ if (install_file(path, devfd, &fst)) {
+ close(devfd);
return 1;
-
+ }
if (fst.st_dev != st.st_dev) {
fprintf(stderr, "%s: file system changed under us - aborting!\n",
program);
+ close(devfd);
return 1;
}
@@ -915,17 +1025,27 @@ int install_loader(const char *path, int update_only)
*/
int modify_existing_adv(const char *path)
{
+ int devfd;
+
+ devfd = open_device(path, NULL, NULL);
+ if (devfd < 0)
+ return 1;
+
if (opt.reset_adv)
syslinux_reset_adv(syslinux_adv);
- else if (read_adv(path) < 0)
+ else if (read_adv(path, devfd) < 0) {
+ close(devfd);
return 1;
-
- if (modify_adv() < 0)
+ }
+ if (modify_adv() < 0) {
+ close(devfd);
return 1;
-
- if (write_adv(path) < 0)
+ }
+ if (write_adv(path, devfd) < 0) {
+ close(devfd);
return 1;
-
+ }
+ close(devfd);
return 0;
}
@@ -965,6 +1085,9 @@ int main(int argc, char *argv[])
case 'r':
opt.raid_mode = 1;
break;
+ case 's':
+ opt.stupid_mode = 1;
+ break;
case 'i':
update_only = 0;
break;
diff --git a/libinstaller/bin2c.pl b/libinstaller/bin2c.pl
index 5a60ca9e..07c11ddb 100755
--- a/libinstaller/bin2c.pl
+++ b/libinstaller/bin2c.pl
@@ -69,10 +69,10 @@ if ($align != 0) {
}
}
-printf "\n};\n\nunsigned int %s_len = %u;\n", $table_name, $total_len;
+printf "\n};\n\nconst unsigned int %s_len = %u;\n", $table_name, $total_len;
@st = stat STDIN;
-printf "\nint %s_mtime = %d;\n", $table_name, $st[9];
+printf "\nconst int %s_mtime = %d;\n", $table_name, $st[9];
exit 0;
diff --git a/libinstaller/setadv.c b/libinstaller/setadv.c
index 32ad1654..d18ac927 100644
--- a/libinstaller/setadv.c
+++ b/libinstaller/setadv.c
@@ -36,14 +36,14 @@ static void cleanup_adv(unsigned char *advbuf)
uint32_t csum;
/* Make sure both copies agree, and update the checksum */
- set_32(advbuf, ADV_MAGIC1);
+ set_32((uint32_t *) advbuf, ADV_MAGIC1);
csum = ADV_MAGIC2;
for (i = 8; i < ADV_SIZE - 4; i += 4)
- csum -= get_32(advbuf + i);
+ csum -= get_32((uint32_t *) (advbuf + i));
- set_32(advbuf + 4, csum);
- set_32(advbuf + ADV_SIZE - 4, ADV_MAGIC3);
+ set_32((uint32_t *) (advbuf + 4), csum);
+ set_32((uint32_t *) (advbuf + ADV_SIZE - 4), ADV_MAGIC3);
memcpy(advbuf + ADV_SIZE, advbuf, ADV_SIZE);
}
@@ -130,12 +130,13 @@ static int adv_consistent(const unsigned char *p)
int i;
uint32_t csum;
- if (get_32(p) != ADV_MAGIC1 || get_32(p + ADV_SIZE - 4) != ADV_MAGIC3)
+ if (get_32((uint32_t *) p) != ADV_MAGIC1 ||
+ get_32((uint32_t *) (p + ADV_SIZE - 4)) != ADV_MAGIC3)
return 0;
csum = 0;
for (i = 4; i < ADV_SIZE - 4; i += 4)
- csum += get_32(p + i);
+ csum += get_32((uint32_t *) (p + i));
return csum == ADV_MAGIC2;
}
diff --git a/libinstaller/syslinux.h b/libinstaller/syslinux.h
index f8f25190..8ed1edbe 100644
--- a/libinstaller/syslinux.h
+++ b/libinstaller/syslinux.h
@@ -18,16 +18,20 @@
/* The standard boot sector and ldlinux image */
extern unsigned char syslinux_bootsect[];
-extern unsigned int syslinux_bootsect_len;
-extern int syslinux_bootsect_mtime;
+extern const unsigned int syslinux_bootsect_len;
+extern const int syslinux_bootsect_mtime;
extern unsigned char syslinux_ldlinux[];
-extern unsigned int syslinux_ldlinux_len;
-extern int syslinux_ldlinux_mtime;
+extern const unsigned int syslinux_ldlinux_len;
+extern const int syslinux_ldlinux_mtime;
extern unsigned char syslinux_mbr[];
-extern unsigned int syslinux_mbr_len;
-extern int syslinux_mbr_mtime;
+extern const unsigned int syslinux_mbr_len;
+extern const int syslinux_mbr_mtime;
+
+/* Sector size assumptions... */
+#define SECTOR_SHIFT 9
+#define SECTOR_SIZE (1 << SECTOR_SHIFT)
/* This takes a boot sector and merges in the syslinux fields */
void syslinux_make_bootsect(void *);
diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h
index 208d78ca..336e6f00 100644
--- a/libinstaller/syslxint.h
+++ b/libinstaller/syslxint.h
@@ -18,57 +18,134 @@
/*
* Access functions for littleendian numbers, possibly misaligned.
*/
-static inline uint8_t get_8(const unsigned char *p)
+static inline uint8_t get_8(const uint8_t * p)
{
- return *(const uint8_t *)p;
+ return *p;
}
-static inline uint16_t get_16(const unsigned char *p)
+static inline uint16_t get_16(const uint16_t * p)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
- return *(const uint16_t *)p;
+ return *p;
#else
- return (uint16_t) p[0] + ((uint16_t) p[1] << 8);
+ const uint8_t *pp = (const uint8_t *)p;
+ return (uint16_t) pp[0] + ((uint16_t) pp[1] << 8);
#endif
}
-static inline uint32_t get_32(const unsigned char *p)
+static inline uint32_t get_32(const uint32_t * p)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
- return *(const uint32_t *)p;
+ return *p;
#else
- return (uint32_t) p[0] + ((uint32_t) p[1] << 8) +
- ((uint32_t) p[2] << 16) + ((uint32_t) p[3] << 24);
+ const uint8_t *pp = (const uint8_t *)p;
+ return (uint32_t) pp[0] + ((uint32_t) pp[1] << 8) +
+ ((uint32_t) pp[2] << 16) + ((uint32_t) pp[3] << 24);
#endif
}
-static inline void set_16(unsigned char *p, uint16_t v)
+static inline void set_8(uint8_t * p, uint8_t v)
+{
+ *p = v;
+}
+
+static inline void set_16(uint16_t * p, uint16_t v)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
*(uint16_t *) p = v;
#else
- p[0] = (v & 0xff);
- p[1] = ((v >> 8) & 0xff);
+ uint8_t *pp = (uint8_t *) p;
+ pp[0] = (v & 0xff);
+ pp[1] = ((v >> 8) & 0xff);
#endif
}
-static inline void set_32(unsigned char *p, uint32_t v)
+static inline void set_32(uint32_t * p, uint32_t v)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
*(uint32_t *) p = v;
#else
- p[0] = (v & 0xff);
- p[1] = ((v >> 8) & 0xff);
- p[2] = ((v >> 16) & 0xff);
- p[3] = ((v >> 24) & 0xff);
+ uint8_t *pp = (uint8_t *) p;
+ pp[0] = (v & 0xff);
+ pp[1] = ((v >> 8) & 0xff);
+ pp[2] = ((v >> 16) & 0xff);
+ pp[3] = ((v >> 24) & 0xff);
#endif
}
-#define SECTOR_SHIFT 9 /* 512-byte sectors */
-#define SECTOR_SIZE (1 << SECTOR_SHIFT)
+#define LDLINUX_MAGIC 0x3eb202fe
+
+/* Patch area for disk-based installers */
+struct patch_area {
+ uint32_t magic; /* LDLINUX_MAGIC */
+ uint32_t instance; /* Per-version value */
+ uint16_t data_sectors;
+ uint16_t adv_sectors;
+ uint32_t dwords;
+ uint32_t checksum;
+ uint32_t currentdir;
+ uint16_t secptroffset;
+ uint16_t secptrcnt;
+};
+
+ /* FAT bootsector format, also used by other disk-based derivatives */
+struct boot_sector {
+ uint8_t bsJump[3];
+ char bsOemName[8];
+ uint16_t bsBytesPerSec;
+ uint8_t bsSecPerClust;
+ uint16_t bsResSectors;
+ uint8_t bsFATs;
+ uint16_t bsRootDirEnts;
+ uint16_t bsSectors;
+ uint8_t bsMedia;
+ uint16_t bsFATsecs;
+ uint16_t bsSecPerTrack;
+ uint16_t bsHeads;
+ uint32_t bsHiddenSecs;
+ uint32_t bsHugeSectors;
+
+ union {
+ struct {
+ uint8_t DriveNumber;
+ uint8_t Reserved1;
+ uint8_t BootSignature;
+ uint32_t VolumeID;
+ char VolumeLabel[11];
+ char FileSysType[8];
+ uint8_t Code[442];
+ } __attribute__ ((packed)) bs16;
+ struct {
+ uint32_t FATSz32;
+ uint16_t ExtFlags;
+ uint16_t FSVer;
+ uint32_t RootClus;
+ uint16_t FSInfo;
+ uint16_t BkBootSec;
+ uint8_t Reserved0[12];
+ uint8_t DriveNumber;
+ uint8_t Reserved1;
+ uint8_t BootSignature;
+ uint32_t VolumeID;
+ char VolumeLabel[11];
+ char FileSysType[8];
+ uint8_t Code[414];
+ } __attribute__ ((packed)) bs32;
+ } __attribute__ ((packed));
+
+ uint32_t NextSector; /* Pointer to the first unused sector */
+ uint16_t MaxTransfer; /* Max sectors per transfer */
+ uint16_t bsSignature;
+} __attribute__ ((packed));
+
+#define bsHead bsJump
+#define bsHeadLen offsetof(struct boot_sector, bsOemName)
+#define bsCode bs32.Code /* The common safe choice */
+#define bsCodeLen (offsetof(struct boot_sector, bsSignature) - \
+ offsetof(struct boot_sector, bsCode))
#endif /* SYSLXINT_H */
diff --git a/libinstaller/syslxmod.c b/libinstaller/syslxmod.c
index 8d793a5c..88de375f 100644
--- a/libinstaller/syslxmod.c
+++ b/libinstaller/syslxmod.c
@@ -1,6 +1,7 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 1998-2008 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
@@ -22,117 +23,16 @@
#include <stddef.h>
#include "syslinux.h"
+#include "syslxint.h"
-#define LDLINUX_MAGIC 0x3eb202fe
-
-enum bs_offsets {
- bsJump = 0x00,
- bsOemName = 0x03,
- bsBytesPerSec = 0x0b,
- bsSecPerClust = 0x0d,
- bsResSectors = 0x0e,
- bsFATs = 0x10,
- bsRootDirEnts = 0x11,
- bsSectors = 0x13,
- bsMedia = 0x15,
- bsFATsecs = 0x16,
- bsSecPerTrack = 0x18,
- bsHeads = 0x1a,
- bsHiddenSecs = 0x1c,
- bsHugeSectors = 0x20,
-
- /* FAT12/16 only */
- bs16DriveNumber = 0x24,
- bs16Reserved1 = 0x25,
- bs16BootSignature = 0x26,
- bs16VolumeID = 0x27,
- bs16VolumeLabel = 0x2b,
- bs16FileSysType = 0x36,
- bs16Code = 0x3e,
-
- /* FAT32 only */
- bs32FATSz32 = 36,
- bs32ExtFlags = 40,
- bs32FSVer = 42,
- bs32RootClus = 44,
- bs32FSInfo = 48,
- bs32BkBootSec = 50,
- bs32Reserved = 52,
- bs32DriveNumber = 64,
- bs32Reserved1 = 65,
- bs32BootSignature = 66,
- bs32VolumeID = 67,
- bs32VolumeLabel = 71,
- bs32FileSysType = 82,
- bs32Code = 90,
-
- bsSignature = 0x1fe
-};
-
-#define bsHead bsJump
-#define bsHeadLen (bsOemName-bsHead)
-#define bsCode bs32Code /* The common safe choice */
-#define bsCodeLen (bsSignature-bs32Code)
-
-/*
- * Access functions for littleendian numbers, possibly misaligned.
- */
-static inline uint8_t get_8(const unsigned char *p)
-{
- return *(const uint8_t *)p;
-}
-
-static inline uint16_t get_16(const unsigned char *p)
-{
-#if defined(__i386__) || defined(__x86_64__)
- /* Littleendian and unaligned-capable */
- return *(const uint16_t *)p;
-#else
- return (uint16_t) p[0] + ((uint16_t) p[1] << 8);
-#endif
-}
-
-static inline uint32_t get_32(const unsigned char *p)
-{
-#if defined(__i386__) || defined(__x86_64__)
- /* Littleendian and unaligned-capable */
- return *(const uint32_t *)p;
-#else
- return (uint32_t) p[0] + ((uint32_t) p[1] << 8) +
- ((uint32_t) p[2] << 16) + ((uint32_t) p[3] << 24);
-#endif
-}
-
-static inline void set_16(unsigned char *p, uint16_t v)
-{
-#if defined(__i386__) || defined(__x86_64__)
- /* Littleendian and unaligned-capable */
- *(uint16_t *) p = v;
-#else
- p[0] = (v & 0xff);
- p[1] = ((v >> 8) & 0xff);
-#endif
-}
-
-static inline void set_32(unsigned char *p, uint32_t v)
-{
-#if defined(__i386__) || defined(__x86_64__)
- /* Littleendian and unaligned-capable */
- *(uint32_t *) p = v;
-#else
- p[0] = (v & 0xff);
- p[1] = ((v >> 8) & 0xff);
- p[2] = ((v >> 16) & 0xff);
- p[3] = ((v >> 24) & 0xff);
-#endif
-}
+#define sbs ((struct boot_sector *)syslinux_bootsect)
void syslinux_make_bootsect(void *bs)
{
- unsigned char *bootsect = bs;
+ struct boot_sector *bootsect = bs;
- memcpy(bootsect + bsHead, syslinux_bootsect + bsHead, bsHeadLen);
- memcpy(bootsect + bsCode, syslinux_bootsect + bsCode, bsCodeLen);
+ memcpy(&bootsect->bsHead, &sbs->bsHead, bsHeadLen);
+ memcpy(&bootsect->bsCode, &sbs->bsCode, bsCodeLen);
}
/*
@@ -146,96 +46,194 @@ const char *syslinux_check_bootsect(const void *bs)
long long sectors, fatsectors, dsectors;
long long clusters;
int rootdirents, clustersize;
- const unsigned char *sectbuf = bs;
+ const struct boot_sector *sectbuf = bs;
veryold = 0;
/* Must be 0xF0 or 0xF8..0xFF */
- if (get_8(sectbuf + bsMedia) != 0xF0 && get_8(sectbuf + bsMedia) < 0xF8)
- goto invalid;
-
- sectorsize = get_16(sectbuf + bsBytesPerSec);
- if (sectorsize == 512) ; /* ok */
- else if (sectorsize == 1024 || sectorsize == 2048 || sectorsize == 4096)
- return "only 512-byte sectors are supported";
+ if (get_8(&sectbuf->bsMedia) != 0xF0 && get_8(&sectbuf->bsMedia) < 0xF8)
+ return "invalid media signature (not a FAT filesystem?)";
+
+ sectorsize = get_16(&sectbuf->bsBytesPerSec);
+ if (sectorsize == SECTOR_SIZE)
+ ; /* ok */
+ else if (sectorsize >= 512 && sectorsize <= 4096 &&
+ (sectorsize & (sectorsize - 1)) == 0)
+ return "unsupported sectors size";
else
- goto invalid;
+ return "impossible sector size";
- clustersize = get_8(sectbuf + bsSecPerClust);
+ clustersize = get_8(&sectbuf->bsSecPerClust);
if (clustersize == 0 || (clustersize & (clustersize - 1)))
- goto invalid; /* Must be nonzero and a power of 2 */
+ return "impossible cluster size";
- sectors = get_16(sectbuf + bsSectors);
- sectors = sectors ? sectors : get_32(sectbuf + bsHugeSectors);
+ sectors = get_16(&sectbuf->bsSectors);
+ sectors = sectors ? sectors : get_32(&sectbuf->bsHugeSectors);
- dsectors = sectors - get_16(sectbuf + bsResSectors);
+ dsectors = sectors - get_16(&sectbuf->bsResSectors);
- fatsectors = get_16(sectbuf + bsFATsecs);
- fatsectors = fatsectors ? fatsectors : get_32(sectbuf + bs32FATSz32);
- fatsectors *= get_8(sectbuf + bsFATs);
+ fatsectors = get_16(&sectbuf->bsFATsecs);
+ fatsectors = fatsectors ? fatsectors : get_32(&sectbuf->bs32.FATSz32);
+ fatsectors *= get_8(&sectbuf->bsFATs);
dsectors -= fatsectors;
- rootdirents = get_16(sectbuf + bsRootDirEnts);
+ rootdirents = get_16(&sectbuf->bsRootDirEnts);
dsectors -= (rootdirents + sectorsize / 32 - 1) / sectorsize;
- if (dsectors < 0 || fatsectors == 0)
- goto invalid;
+ if (dsectors < 0)
+ return "negative number of data sectors";
+
+ if (fatsectors == 0)
+ return "zero FAT sectors";
clusters = dsectors / clustersize;
if (clusters < 0xFFF5) {
/* FAT12 or FAT16 */
- if (!get_16(sectbuf + bsFATsecs))
- goto invalid;
+ if (!get_16(&sectbuf->bsFATsecs))
+ return "zero FAT sectors (FAT12/16)";
- if (get_8(sectbuf + bs16BootSignature) == 0x29) {
- if (!memcmp(sectbuf + bs16FileSysType, "FAT12 ", 8)) {
+ if (get_8(&sectbuf->bs16.BootSignature) == 0x29) {
+ if (!memcmp(&sectbuf->bs16.FileSysType, "FAT12 ", 8)) {
if (clusters >= 0xFF5)
return "more than 4084 clusters but claims FAT12";
- } else if (!memcmp(sectbuf + bs16FileSysType, "FAT16 ", 8)) {
+ } else if (!memcmp(&sectbuf->bs16.FileSysType, "FAT16 ", 8)) {
if (clusters < 0xFF5)
return "less than 4084 clusters but claims FAT16";
- } else if (memcmp(sectbuf + bs16FileSysType, "FAT ", 8)) {
+ } else if (!memcmp(&sectbuf->bs16.FileSysType, "FAT32 ", 8)) {
+ return "less than 65525 clusters but claims FAT32";
+ } else if (memcmp(&sectbuf->bs16.FileSysType, "FAT ", 8)) {
static char fserr[] =
"filesystem type \"????????\" not supported";
- memcpy(fserr + 17, sectbuf + bs16FileSysType, 8);
+ memcpy(fserr + 17, &sectbuf->bs16.FileSysType, 8);
return fserr;
}
}
} else if (clusters < 0x0FFFFFF5) {
- /* FAT32 */
- /* Moving the FileSysType and BootSignature was a lovely stroke of M$ idiocy */
- if (get_8(sectbuf + bs32BootSignature) != 0x29 ||
- memcmp(sectbuf + bs32FileSysType, "FAT32 ", 8))
- goto invalid;
+ /*
+ * FAT32...
+ *
+ * Moving the FileSysType and BootSignature was a lovely stroke
+ * of M$ idiocy...
+ */
+ if (get_8(&sectbuf->bs32.BootSignature) != 0x29 ||
+ memcmp(&sectbuf->bs32.FileSysType, "FAT32 ", 8))
+ return "missing FAT32 signature";
} else {
- goto invalid;
+ return "impossibly large number of clusters";
}
return NULL;
+}
+
+/*
+ * Special handling for the MS-DOS derivative: syslinux_ldlinux
+ * is a "far" object...
+ */
+#ifdef __MSDOS__
+
+#define __noinline __attribute__((noinline))
-invalid:
- return "this doesn't look like a valid FAT filesystem";
+extern uint16_t ldlinux_seg; /* Defined in dos/syslinux.c */
+
+static inline __attribute__ ((const))
+uint16_t ds(void)
+{
+ uint16_t v;
+asm("movw %%ds,%0":"=rm"(v));
+ return v;
}
+static inline void *set_fs(const void *p)
+{
+ uint16_t seg;
+
+ seg = ldlinux_seg + ((size_t) p >> 4);
+ asm volatile ("movw %0,%%fs"::"rm" (seg));
+ return (void *)((size_t) p & 0xf);
+}
+
+#if 0 /* unused */
+static __noinline uint8_t get_8_sl(const uint8_t * p)
+{
+ uint8_t v;
+
+ p = set_fs(p);
+ asm volatile ("movb %%fs:%1,%0":"=q" (v):"m"(*p));
+ return v;
+}
+#endif
+
+static __noinline uint16_t get_16_sl(const uint16_t * p)
+{
+ uint16_t v;
+
+ p = set_fs(p);
+ asm volatile ("movw %%fs:%1,%0":"=r" (v):"m"(*p));
+ return v;
+}
+
+static __noinline uint32_t get_32_sl(const uint32_t * p)
+{
+ uint32_t v;
+
+ p = set_fs(p);
+ asm volatile ("movl %%fs:%1,%0":"=r" (v):"m"(*p));
+ return v;
+}
+
+#if 0 /* unused */
+static __noinline void set_8_sl(uint8_t * p, uint8_t v)
+{
+ p = set_fs(p);
+ asm volatile ("movb %1,%%fs:%0":"=m" (*p):"qi"(v));
+}
+#endif
+
+static __noinline void set_16_sl(uint16_t * p, uint16_t v)
+{
+ p = set_fs(p);
+ asm volatile ("movw %1,%%fs:%0":"=m" (*p):"ri"(v));
+}
+
+static __noinline void set_32_sl(uint32_t * p, uint32_t v)
+{
+ p = set_fs(p);
+ asm volatile ("movl %1,%%fs:%0":"=m" (*p):"ri"(v));
+}
+
+#else
+
+/* Sane system ... */
+#define get_8_sl(x) get_8(x)
+#define get_16_sl(x) get_16(x)
+#define get_32_sl(x) get_32(x)
+#define set_8_sl(x,y) set_8(x,y)
+#define set_16_sl(x,y) set_16(x,y)
+#define set_32_sl(x,y) set_32(x,y)
+
+#endif
+
/*
- * This patches the boot sector and the first sector of ldlinux.sys
+ * This patches the boot sector and the beginning of ldlinux.sys
* based on an ldlinux.sys sector map passed in. Typically this is
* handled by writing ldlinux.sys, mapping it, and then overwrite it
* with the patched version. If this isn't safe to do because of
* an OS which does block reallocation, then overwrite it with
* direct access since the location is known.
*
- * Return 0 if successful, otherwise -1.
+ * Returns the number of modified bytes in ldlinux.sys if successful,
+ * otherwise -1.
*/
int syslinux_patch(const uint32_t * sectors, int nsectors,
int stupid, int raid_mode)
{
- unsigned char *patcharea, *p;
+ struct patch_area *patcharea;
+ uint32_t *wp;
int nsect = (syslinux_ldlinux_len + 511) >> 9;
uint32_t csum;
- int i, dw;
+ int i, dw, nptrs, rv;
if (nsectors < nsect)
return -1;
@@ -243,44 +241,51 @@ int syslinux_patch(const uint32_t * sectors, int nsectors,
/* Patch in options, as appropriate */
if (stupid) {
/* Access only one sector at a time */
- set_16(syslinux_bootsect + 0x1FC, 1);
+ set_16(&sbs->MaxTransfer, 1);
}
- i = get_16(syslinux_bootsect + 0x1FE);
+ i = get_16(&sbs->bsSignature);
if (raid_mode)
- set_16(syslinux_bootsect + i, 0x18CD); /* INT 18h */
- set_16(syslinux_bootsect + 0x1FE, 0xAA55);
+ set_16((uint16_t *) ((char *)sbs + i), 0x18CD); /* INT 18h */
+ set_16(&sbs->bsSignature, 0xAA55);
/* First sector need pointer in boot sector */
- set_32(syslinux_bootsect + 0x1F8, *sectors++);
- nsect--;
+ set_32(&sbs->NextSector, *sectors++);
/* Search for LDLINUX_MAGIC to find the patch area */
- for (p = syslinux_ldlinux; get_32(p) != LDLINUX_MAGIC; p += 4) ;
- patcharea = p + 8;
+ for (wp = (uint32_t *) syslinux_ldlinux; get_32_sl(wp) != LDLINUX_MAGIC;
+ wp++) ;
+ patcharea = (struct patch_area *)wp;
/* Set up the totals */
- dw = syslinux_ldlinux_len >> 2; /* COMPLETE dwords! */
- set_16(patcharea, dw);
- set_16(patcharea + 2, nsect); /* Does not include the first sector! */
+ dw = syslinux_ldlinux_len >> 2; /* COMPLETE dwords, excluding ADV */
+ set_16_sl(&patcharea->data_sectors, nsect); /* Not including ADVs */
+ set_16_sl(&patcharea->adv_sectors, 0); /* ADVs not supported yet */
+ set_32_sl(&patcharea->dwords, dw);
+ set_32_sl(&patcharea->currentdir, 0);
/* Set the sector pointers */
- p = patcharea + 8;
+ wp = (uint32_t *) ((char *)syslinux_ldlinux +
+ get_16_sl(&patcharea->secptroffset));
+ nptrs = get_16_sl(&patcharea->secptrcnt);
- memset(p, 0, 64 * 4);
while (nsect--) {
- set_32(p, *sectors++);
- p += 4;
+ set_32_sl(wp++, *sectors++);
+ nptrs--;
}
+ while (nptrs--)
+ set_32_sl(wp++, 0);
+
+ rv = (char *)wp - (char *)syslinux_ldlinux;
/* Now produce a checksum */
- set_32(patcharea + 4, 0);
+ set_32_sl(&patcharea->checksum, 0);
csum = LDLINUX_MAGIC;
- for (i = 0, p = syslinux_ldlinux; i < dw; i++, p += 4)
- csum -= get_32(p); /* Negative checksum */
+ for (i = 0, wp = (uint32_t *) syslinux_ldlinux; i < dw; i++, wp++)
+ csum -= get_32_sl(wp); /* Negative checksum */
- set_32(patcharea + 4, csum);
+ set_32_sl(&patcharea->checksum, csum);
- return 0;
+ return rv;
}
diff --git a/linux/syslinux.c b/linux/syslinux.c
index 01207490..02323771 100644
--- a/linux/syslinux.c
+++ b/linux/syslinux.c
@@ -48,10 +48,12 @@
#include <sys/ioctl.h>
#include <linux/fs.h> /* FIGETBSZ, FIBMAP */
-#include <linux/msdos_fs.h> /* FAT_IOCTL_SET_ATTRIBUTES, SECTOR_* */
+#include <linux/msdos_fs.h> /* FAT_IOCTL_SET_ATTRIBUTES */
#ifndef FAT_IOCTL_SET_ATTRIBUTES
# define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, uint32_t)
#endif
+#undef SECTOR_SIZE
+#undef SECTOR_SHIFT
#include <paths.h>
#ifndef _PATH_MOUNT
@@ -175,7 +177,7 @@ int make_block_map(uint32_t * sectors, int len, int dev_fd, int fd)
if (ioctl(fd, FIGETBSZ, &blocksize) < 0)
die("ioctl FIGETBSZ failed");
- blocksize >>= SECTOR_BITS; /* sectors/block */
+ blocksize >>= SECTOR_SHIFT; /* sectors/block */
nblock = 0;
while (len > 0) {
@@ -189,7 +191,7 @@ int make_block_map(uint32_t * sectors, int len, int dev_fd, int fd)
*sectors++ = (block * blocksize) + i;
nsectors++;
- len -= (1 << SECTOR_BITS);
+ len -= (1 << SECTOR_SHIFT);
}
}
@@ -327,10 +329,13 @@ int main(int argc, char *argv[])
char mntname[128];
char *ldlinux_name, **argp, *opt;
const char *subdir = NULL;
- uint32_t sectors[65]; /* 65 is maximum possible */
+ uint32_t *sectors;
+ int ldlinux_sectors;
int nsectors = 0;
const char *errmsg;
int mnt_cookie;
+ int patch_sectors;
+ int i;
int force = 0; /* -f (force) option */
int stupid = 0; /* -s (stupid) option */
@@ -515,6 +520,8 @@ int main(int argc, char *argv[])
/*
* Create a block map.
*/
+ ldlinux_sectors = (syslinux_ldlinux_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
+ sectors = calloc(ldlinux_sectors, sizeof *sectors);
nsectors = make_block_map(sectors, syslinux_ldlinux_len, dev_fd, fd);
close(fd);
@@ -531,13 +538,16 @@ umount:
/*
* Patch ldlinux.sys and the boot sector
*/
- syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ i = syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ patch_sectors = (i + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
/*
- * Write the now-patched first sector of ldlinux.sys
+ * Write the now-patched first sectors of ldlinux.sys
*/
- xpwrite(dev_fd, syslinux_ldlinux, SECTOR_SIZE,
- filesystem_offset + ((off_t) sectors[0] << SECTOR_BITS));
+ for (i = 0; i < patch_sectors; i++) {
+ xpwrite(dev_fd, syslinux_ldlinux + i * SECTOR_SIZE, SECTOR_SIZE,
+ filesystem_offset + ((off_t) sectors[i] << SECTOR_SHIFT));
+ }
/*
* To finish up, write the boot sector
diff --git a/lzo/.gitignore b/lzo/.gitignore
new file mode 100644
index 00000000..04202daf
--- /dev/null
+++ b/lzo/.gitignore
@@ -0,0 +1 @@
+/prepcore
diff --git a/lzo/LZO.TXT b/lzo/LZO.TXT
new file mode 100644
index 00000000..addf4303
--- /dev/null
+++ b/lzo/LZO.TXT
@@ -0,0 +1,291 @@
+
+ ============================================================================
+ LZO -- a real-time data compression library
+ ============================================================================
+
+ Author : Markus Franz Xaver Johannes Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ Version : 2.03
+ Date : 30 Apr 2008
+
+
+ Abstract
+ --------
+ LZO is a portable lossless data compression library written in ANSI C.
+ It offers pretty fast compression and very fast decompression.
+ Decompression requires no memory.
+
+ In addition there are slower compression levels achieving a quite
+ competitive compression ratio while still decompressing at
+ this very high speed.
+
+ The LZO algorithms and implementations are copyrighted OpenSource
+ distributed under the GNU General Public License.
+
+
+ Introduction
+ ------------
+ LZO is a data compression library which is suitable for data
+ de-/compression in real-time. This means it favours speed
+ over compression ratio.
+
+ The acronym LZO is standing for Lempel-Ziv-Oberhumer.
+
+ LZO is written in ANSI C. Both the source code and the compressed
+ data format are designed to be portable across platforms.
+
+ LZO implements a number of algorithms with the following features:
+
+ - Decompression is simple and *very* fast.
+ - Requires no memory for decompression.
+ - Compression is pretty fast.
+ - Requires 64 kB of memory for compression.
+ - Allows you to dial up extra compression at a speed cost in the
+ compressor. The speed of the decompressor is not reduced.
+ - Includes compression levels for generating pre-compressed
+ data which achieve a quite competitive compression ratio.
+ - There is also a compression level which needs only 8 kB for compression.
+ - Algorithm is thread safe.
+ - Algorithm is lossless.
+
+ LZO supports overlapping compression and in-place decompression.
+
+
+ Design criteria
+ ---------------
+ LZO was designed with speed in mind. Decompressor speed has been
+ favoured over compressor speed. Real-time decompression should be
+ possible for virtually any application. The implementation of the
+ LZO1X decompressor in optimized i386 assembler code runs about at
+ the third of the speed of a memcpy() - and even faster for many files.
+
+ In fact I first wrote the decompressor of each algorithm thereby
+ defining the compressed data format, verified it with manually
+ created test data and at last added the compressor.
+
+
+ Performance
+ -----------
+ To keep you interested, here is an overview of the average results
+ when compressing the Calgary Corpus test suite with a blocksize
+ of 256 kB, originally done on an ancient Intel Pentium 133.
+
+ The naming convention of the various algorithms goes LZOxx-N, where N is
+ the compression level. Range 1-9 indicates the fast standard levels using
+ 64 kB memory for compression. Level 99 offers better compression at the
+ cost of more memory (256 kB), and is still reasonably fast.
+ Level 999 achieves nearly optimal compression - but it is slow
+ and uses much memory, and is mainly intended for generating
+ pre-compressed data.
+
+ The C version of LZO1X-1 is about 4-5 times faster than the fastest
+ zlib compression level, and it also outperforms other algorithms
+ like LZRW1-A and LZV in both compression ratio and compression speed
+ and decompression speed.
+
+ +------------------------------------------------------------------------+
+ | Algorithm Length CxB ComLen %Remn Bits Com K/s Dec K/s |
+ | --------- ------ --- ------ ----- ---- ------- ------- |
+ | |
+ | memcpy() 224401 1 224401 100.0 8.00 60956.83 59124.58 |
+ | |
+ | LZO1-1 224401 1 117362 53.1 4.25 4665.24 13341.98 |
+ | LZO1-99 224401 1 101560 46.7 3.73 1373.29 13823.40 |
+ | |
+ | LZO1A-1 224401 1 115174 51.7 4.14 4937.83 14410.35 |
+ | LZO1A-99 224401 1 99958 45.5 3.64 1362.72 14734.17 |
+ | |
+ | LZO1B-1 224401 1 109590 49.6 3.97 4565.53 15438.34 |
+ | LZO1B-2 224401 1 106235 48.4 3.88 4297.33 15492.79 |
+ | LZO1B-3 224401 1 104395 47.8 3.83 4018.21 15373.52 |
+ | LZO1B-4 224401 1 104828 47.4 3.79 3024.48 15100.11 |
+ | LZO1B-5 224401 1 102724 46.7 3.73 2827.82 15427.62 |
+ | LZO1B-6 224401 1 101210 46.0 3.68 2615.96 15325.68 |
+ | LZO1B-7 224401 1 101388 46.0 3.68 2430.89 15361.47 |
+ | LZO1B-8 224401 1 99453 45.2 3.62 2183.87 15402.77 |
+ | LZO1B-9 224401 1 99118 45.0 3.60 1677.06 15069.60 |
+ | LZO1B-99 224401 1 95399 43.6 3.48 1286.87 15656.11 |
+ | LZO1B-999 224401 1 83934 39.1 3.13 232.40 16445.05 |
+ | |
+ | LZO1C-1 224401 1 111735 50.4 4.03 4883.08 15570.91 |
+ | LZO1C-2 224401 1 108652 49.3 3.94 4424.24 15733.14 |
+ | LZO1C-3 224401 1 106810 48.7 3.89 4127.65 15645.69 |
+ | LZO1C-4 224401 1 105717 47.7 3.82 3007.92 15346.44 |
+ | LZO1C-5 224401 1 103605 47.0 3.76 2829.15 15153.88 |
+ | LZO1C-6 224401 1 102585 46.5 3.72 2631.37 15257.58 |
+ | LZO1C-7 224401 1 101937 46.2 3.70 2378.57 15492.49 |
+ | LZO1C-8 224401 1 100779 45.6 3.65 2171.93 15386.07 |
+ | LZO1C-9 224401 1 100255 45.4 3.63 1691.44 15194.68 |
+ | LZO1C-99 224401 1 97252 44.1 3.53 1462.88 15341.37 |
+ | LZO1C-999 224401 1 87740 40.2 3.21 306.44 16411.94 |
+ | |
+ | LZO1F-1 224401 1 113412 50.8 4.07 4755.97 16074.12 |
+ | LZO1F-999 224401 1 89599 40.3 3.23 280.68 16553.90 |
+ | |
+ | LZO1X-1(11) 224401 1 118810 52.6 4.21 4544.42 15879.04 |
+ | LZO1X-1(12) 224401 1 113675 50.6 4.05 4411.15 15721.59 |
+ | LZO1X-1 224401 1 109323 49.4 3.95 4991.76 15584.89 |
+ | LZO1X-1(15) 224401 1 108500 49.1 3.93 5077.50 15744.56 |
+ | LZO1X-999 224401 1 82854 38.0 3.04 135.77 16548.48 |
+ | |
+ | LZO1Y-1 224401 1 110820 49.8 3.98 4952.52 15638.82 |
+ | LZO1Y-999 224401 1 83614 38.2 3.05 135.07 16385.40 |
+ | |
+ | LZO1Z-999 224401 1 83034 38.0 3.04 133.31 10553.74 |
+ | |
+ | LZO2A-999 224401 1 87880 40.0 3.20 301.21 8115.75 |
+ +------------------------------------------------------------------------+
+
+ Notes:
+ - CxB is the number of blocks
+ - K/s is the speed measured in 1000 uncompressed bytes per second
+ - the assembler decompressors are even faster
+
+
+ Short documentation
+ -------------------
+ LZO is a block compression algorithm - it compresses and decompresses
+ a block of data. Block size must be the same for compression
+ and decompression.
+
+ LZO compresses a block of data into matches (a sliding dictionary)
+ and runs of non-matching literals. LZO takes care about long matches
+ and long literal runs so that it produces good results on highly
+ redundant data and deals acceptably with non-compressible data.
+
+ When dealing with uncompressible data, LZO expands the input
+ block by a maximum of 16 bytes per 1024 bytes input.
+
+ I have verified LZO using such tools as valgrind and other memory checkers.
+ And in addition to compressing gigabytes of files when tuning some parameters
+ I have also consulted various `lint' programs to spot potential portability
+ problems. LZO is free of any known bugs.
+
+
+ The algorithms
+ --------------
+ There are too many algorithms implemented. But I want to support
+ unlimited backward compatibility, so I will not reduce the LZO
+ distribution in the future.
+
+ As the many object files are mostly independent of each other, the
+ size overhead for an executable statically linked with the LZO library
+ is usually pretty low (just a few kB) because the linker will only add
+ the modules that you are actually using.
+
+ I first published LZO1 and LZO1A in the Internet newsgroups
+ comp.compression and comp.compression.research in March 1996.
+ They are mainly included for compatibility reasons. The LZO2A
+ decompressor is too slow, and there is no fast compressor anyway.
+
+ My experiments have shown that LZO1B is good with a large blocksize
+ or with very redundant data, LZO1F is good with a small blocksize or
+ with binary data and that LZO1X is often the best choice of all.
+ LZO1Y and LZO1Z are almost identical to LZO1X - they can achieve a
+ better compression ratio on some files.
+ Beware, your mileage may vary.
+
+
+ Usage of the library
+ --------------------
+ Despite of its size, the basic usage of LZO is really very simple.
+
+ Let's assume you want to compress some data with LZO1X-1:
+ A) compression
+ * include <lzo/lzo1x.h>
+ call lzo_init()
+ compress your data with lzo1x_1_compress()
+ * link your application with the LZO library
+ B) decompression
+ * include <lzo/lzo1x.h>
+ call lzo_init()
+ decompress your data with lzo1x_decompress()
+ * link your application with the LZO library
+
+ The program examples/simple.c shows a fully working example.
+ See also LZO.FAQ for more information.
+
+
+ Building LZO
+ ------------
+ As LZO uses Autoconf+Automake+Libtool the building process under
+ UNIX systems should be very unproblematic. Shared libraries are
+ supported on many architectures as well.
+ For detailed instructions see the file INSTALL.
+
+ Please note that due to the design of the ELF executable format
+ the performance of a shared library on i386 systems (e.g. Linux)
+ is a little bit slower, so you may want to link your applications
+ with the static version (liblzo2.a) anyway.
+
+ For building under DOS, Win16, Win32, OS/2 and other systems
+ take a look at the file B/00readme.txt.
+
+ In case of troubles (like decompression data errors) try recompiling
+ everything without optimizations - LZO may break the optimizer
+ of your compiler. See the file BUGS.
+
+ LZO is written in ANSI C. In particular this means:
+ - your compiler must understand prototypes
+ - your compiler must understand prototypes in function pointers
+ - your compiler must correctly promote integrals ("value-preserving")
+ - your preprocessor must implement #elif, #error and stringizing
+ - you must have a conforming and correct <limits.h> header
+ - you must have <stddef.h>, <string.h> and other ANSI C headers
+ - you should have size_t and ptrdiff_t
+
+
+ Portability
+ -----------
+ I have built and tested LZO successfully on a variety of platforms
+ including DOS (16 + 32 bit), Windows 3.x (16-bit), Win32, Win64,
+ Linux, *BSD, HP-UX and many more.
+
+ LZO is also reported to work under AIX, ConvexOS, IRIX, MacOS, PalmOS (Pilot),
+ PSX (Sony Playstation), Solaris, SunOS, TOS (Atari ST) and VxWorks.
+ Furthermore it is said that its performance on a Cray is superior
+ to all other machines...
+
+ And I think it would be much fun to translate the decompressors
+ to Z-80 or 6502 assembly.
+
+
+ The future
+ ----------
+ Here is what I'm planning for the next months. No promises, though...
+
+ - interfaces to .NET and Mono
+ - interfaces to Perl, Java, Python, Delphi, Visual Basic, ...
+ - improve documentation and API reference
+
+
+ Some comments about the source code
+ -----------------------------------
+ Be warned: the main source code in the `src' directory is a
+ real pain to understand as I've experimented with hundreds of slightly
+ different versions. It contains many #if and some gotos, and
+ is *completely optimized for speed* and not for readability.
+ Code sharing of the different algorithms is implemented by stressing
+ the preprocessor - this can be really confusing. Lots of marcos and
+ assertions don't make things better.
+
+ Nevertheless LZO compiles very quietly on a variety of
+ compilers with the highest warning levels turned on, even
+ in C++ mode.
+
+
+ Copyright
+ ---------
+ LZO is Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007, 2008 Markus Franz Xaver Johannes Oberhumer
+
+ LZO is distributed under the terms of the GNU General Public License (GPL).
+ See the file COPYING.
+
+ Special licenses for commercial and other applications which
+ are not willing to accept the GNU General Public License
+ are available by contacting the author.
+
+
+
diff --git a/lzo/Makefile b/lzo/Makefile
new file mode 100644
index 00000000..d88279dd
--- /dev/null
+++ b/lzo/Makefile
@@ -0,0 +1,39 @@
+## -*- makefile -*- ------------------------------------------------------
+##
+## Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
+##
+## 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., 53 Temple Place Ste 330,
+## Boston MA 02111-1307, USA; either version 2 of the License, or
+## (at your option) any later version; incorporated herein by reference.
+##
+## -----------------------------------------------------------------------
+
+topdir = ..
+include $(topdir)/MCONFIG.build
+
+INCLUDES += -I./include
+
+LIBOBJS = $(patsubst %.c,%.o,$(wildcard src/*.c))
+LIB = lzo.a
+BINS = prepcore
+
+all : $(BINS)
+
+$(LIB) : $(LIBOBJS)
+ rm -f $@
+ $(AR) cq $@ $^
+ $(RANLIB) $@
+
+prepcore : prepcore.o $(LIB)
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+tidy dist clean spotless:
+ rm -f $(BINS)
+ rm -f *.o *.a .*.d
+ rm -f */*.o */*.a */.*.d
+
+installer:
+
+-include .*.d */.*.d
diff --git a/lzo/include/lzo/lzo1.h b/lzo/include/lzo/lzo1.h
new file mode 100644
index 00000000..480053aa
--- /dev/null
+++ b/lzo/include/lzo/lzo1.h
@@ -0,0 +1,96 @@
+/* lzo1.h -- public interface of the LZO1 compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZO1_H_INCLUDED
+#define __LZO1_H_INCLUDED
+
+#ifndef __LZOCONF_H_INCLUDED
+#include "lzoconf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1_MEM_COMPRESS ((lzo_uint32) (8192L * lzo_sizeof_dict_t))
+#define LZO1_MEM_DECOMPRESS (0)
+
+
+LZO_EXTERN(int)
+lzo1_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+LZO_EXTERN(int)
+lzo1_decompress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+/***********************************************************************
+// better compression ratio at the cost of more memory and time
+************************************************************************/
+
+#define LZO1_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1_99_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzo1a.h b/lzo/include/lzo/lzo1a.h
new file mode 100644
index 00000000..a24eecaa
--- /dev/null
+++ b/lzo/include/lzo/lzo1a.h
@@ -0,0 +1,96 @@
+/* lzo1a.h -- public interface of the LZO1A compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZO1A_H_INCLUDED
+#define __LZO1A_H_INCLUDED
+
+#ifndef __LZOCONF_H_INCLUDED
+#include "lzoconf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1A_MEM_COMPRESS ((lzo_uint32) (8192L * lzo_sizeof_dict_t))
+#define LZO1A_MEM_DECOMPRESS (0)
+
+
+LZO_EXTERN(int)
+lzo1a_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+LZO_EXTERN(int)
+lzo1a_decompress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+/***********************************************************************
+// better compression ratio at the cost of more memory and time
+************************************************************************/
+
+#define LZO1A_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1a_99_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzo1b.h b/lzo/include/lzo/lzo1b.h
new file mode 100644
index 00000000..48dea08f
--- /dev/null
+++ b/lzo/include/lzo/lzo1b.h
@@ -0,0 +1,160 @@
+/* lzo1b.h -- public interface of the LZO1B compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZO1B_H_INCLUDED
+#define __LZO1B_H_INCLUDED
+
+#ifndef __LZOCONF_H_INCLUDED
+#include "lzoconf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1B_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+#define LZO1B_MEM_DECOMPRESS (0)
+
+
+/* compression levels */
+#define LZO1B_BEST_SPEED 1
+#define LZO1B_BEST_COMPRESSION 9
+#define LZO1B_DEFAULT_COMPRESSION (-1) /* fastest by default */
+
+
+LZO_EXTERN(int)
+lzo1b_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem,
+ int compression_level );
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1b_decompress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1b_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_EXTERN(int)
+lzo1b_1_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1b_2_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1b_3_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1b_4_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1b_5_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1b_6_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1b_7_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1b_8_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1b_9_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+// better compression ratio at the cost of more memory and time
+************************************************************************/
+
+#define LZO1B_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1b_99_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+#define LZO1B_999_MEM_COMPRESS ((lzo_uint32) (3 * 65536L * sizeof(lzo_xint)))
+
+LZO_EXTERN(int)
+lzo1b_999_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzo1c.h b/lzo/include/lzo/lzo1c.h
new file mode 100644
index 00000000..c0a865e8
--- /dev/null
+++ b/lzo/include/lzo/lzo1c.h
@@ -0,0 +1,160 @@
+/* lzo1c.h -- public interface of the LZO1C compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZO1C_H_INCLUDED
+#define __LZO1C_H_INCLUDED
+
+#ifndef __LZOCONF_H_INCLUDED
+#include "lzoconf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1C_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+#define LZO1C_MEM_DECOMPRESS (0)
+
+
+/* compression levels */
+#define LZO1C_BEST_SPEED 1
+#define LZO1C_BEST_COMPRESSION 9
+#define LZO1C_DEFAULT_COMPRESSION (-1) /* fastest by default */
+
+
+LZO_EXTERN(int)
+lzo1c_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem,
+ int compression_level );
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1c_decompress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1c_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_EXTERN(int)
+lzo1c_1_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1c_2_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1c_3_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1c_4_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1c_5_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1c_6_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1c_7_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1c_8_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+LZO_EXTERN(int)
+lzo1c_9_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+// better compression ratio at the cost of more memory and time
+************************************************************************/
+
+#define LZO1C_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1c_99_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+#define LZO1C_999_MEM_COMPRESS ((lzo_uint32) (5 * 16384L * sizeof(short)))
+
+LZO_EXTERN(int)
+lzo1c_999_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzo1f.h b/lzo/include/lzo/lzo1f.h
new file mode 100644
index 00000000..f5bd2325
--- /dev/null
+++ b/lzo/include/lzo/lzo1f.h
@@ -0,0 +1,108 @@
+/* lzo1f.h -- public interface of the LZO1F compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZO1F_H_INCLUDED
+#define __LZO1F_H_INCLUDED
+
+#ifndef __LZOCONF_H_INCLUDED
+#include "lzoconf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1F_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+#define LZO1F_MEM_DECOMPRESS (0)
+
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1f_decompress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1f_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_EXTERN(int)
+lzo1f_1_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+// better compression ratio at the cost of more memory and time
+************************************************************************/
+
+#define LZO1F_999_MEM_COMPRESS ((lzo_uint32) (5 * 16384L * sizeof(short)))
+
+LZO_EXTERN(int)
+lzo1f_999_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzo1x.h b/lzo/include/lzo/lzo1x.h
new file mode 100644
index 00000000..5b7cad74
--- /dev/null
+++ b/lzo/include/lzo/lzo1x.h
@@ -0,0 +1,177 @@
+/* lzo1x.h -- public interface of the LZO1X compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZO1X_H_INCLUDED
+#define __LZO1X_H_INCLUDED
+
+#ifndef __LZOCONF_H_INCLUDED
+#include "lzoconf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
+#define LZO1X_MEM_DECOMPRESS (0)
+#define LZO1X_MEM_OPTIMIZE (0)
+
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+// special compressor versions
+************************************************************************/
+
+/* this version needs only 8 kB work memory */
+#define LZO1X_1_11_MEM_COMPRESS ((lzo_uint32) (2048L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_11_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/* this version needs 16 kB work memory */
+#define LZO1X_1_12_MEM_COMPRESS ((lzo_uint32) (4096L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_12_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/* use this version if you need a little more compression speed */
+#define LZO1X_1_15_MEM_COMPRESS ((lzo_uint32) (32768L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_15_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+// better compression ratio at the cost of more memory and time
+************************************************************************/
+
+#define LZO1X_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short)))
+
+LZO_EXTERN(int)
+lzo1x_999_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_EXTERN(int)
+lzo1x_999_compress_dict ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len );
+
+LZO_EXTERN(int)
+lzo1x_999_compress_level ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len,
+ lzo_callback_p cb,
+ int compression_level );
+
+LZO_EXTERN(int)
+lzo1x_decompress_dict_safe ( const lzo_bytep in, lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem /* NOT USED */,
+ const lzo_bytep dict, lzo_uint dict_len );
+
+
+/***********************************************************************
+// optimize a compressed data block
+************************************************************************/
+
+LZO_EXTERN(int)
+lzo1x_optimize ( lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzo1y.h b/lzo/include/lzo/lzo1y.h
new file mode 100644
index 00000000..7a7f1175
--- /dev/null
+++ b/lzo/include/lzo/lzo1y.h
@@ -0,0 +1,145 @@
+/* lzo1y.h -- public interface of the LZO1Y compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZO1Y_H_INCLUDED
+#define __LZO1Y_H_INCLUDED
+
+#ifndef __LZOCONF_H_INCLUDED
+#include "lzoconf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1Y_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+#define LZO1Y_MEM_DECOMPRESS (0)
+#define LZO1Y_MEM_OPTIMIZE (0)
+
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1y_decompress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1y_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_EXTERN(int)
+lzo1y_1_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+// better compression ratio at the cost of more memory and time
+************************************************************************/
+
+#define LZO1Y_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short)))
+
+LZO_EXTERN(int)
+lzo1y_999_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_EXTERN(int)
+lzo1y_999_compress_dict ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len );
+
+LZO_EXTERN(int)
+lzo1y_999_compress_level ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len,
+ lzo_callback_p cb,
+ int compression_level );
+
+LZO_EXTERN(int)
+lzo1y_decompress_dict_safe ( const lzo_bytep in, lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem /* NOT USED */,
+ const lzo_bytep dict, lzo_uint dict_len );
+
+
+/***********************************************************************
+// optimize a compressed data block
+************************************************************************/
+
+LZO_EXTERN(int)
+lzo1y_optimize ( lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzo1z.h b/lzo/include/lzo/lzo1z.h
new file mode 100644
index 00000000..d341c0c3
--- /dev/null
+++ b/lzo/include/lzo/lzo1z.h
@@ -0,0 +1,150 @@
+/* lzo1z.h -- public interface of the LZO1Z compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZO1Z_H_INCLUDED
+#define __LZO1Z_H_INCLUDED
+
+#ifndef __LZOCONF_H_INCLUDED
+#include "lzoconf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1Z_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+#define LZO1Z_MEM_DECOMPRESS (0)
+#define LZO1Z_MEM_OPTIMIZE (0)
+
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1z_decompress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1z_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#if 0
+/* not yet implemented */
+LZO_EXTERN(int)
+lzo1z_1_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+#endif
+
+
+/***********************************************************************
+// better compression ratio at the cost of more memory and time
+************************************************************************/
+
+#define LZO1Z_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short)))
+
+LZO_EXTERN(int)
+lzo1z_999_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_EXTERN(int)
+lzo1z_999_compress_dict ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len );
+
+LZO_EXTERN(int)
+lzo1z_999_compress_level ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len,
+ lzo_callback_p cb,
+ int compression_level );
+
+LZO_EXTERN(int)
+lzo1z_decompress_dict_safe ( const lzo_bytep in, lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem /* NOT USED */,
+ const lzo_bytep dict, lzo_uint dict_len );
+
+
+/***********************************************************************
+// optimize a compressed data block
+************************************************************************/
+
+#if 0
+/* not yet implemented */
+LZO_EXTERN(int)
+lzo1z_optimize ( lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+#endif
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzo2a.h b/lzo/include/lzo/lzo2a.h
new file mode 100644
index 00000000..c566241e
--- /dev/null
+++ b/lzo/include/lzo/lzo2a.h
@@ -0,0 +1,92 @@
+/* lzo2a.h -- public interface of the LZO2A compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZO2A_H_INCLUDED
+#define __LZO2A_H_INCLUDED
+
+#ifndef __LZOCONF_H_INCLUDED
+#include "lzoconf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#define LZO2A_MEM_DECOMPRESS (0)
+
+/* decompression */
+LZO_EXTERN(int)
+lzo2a_decompress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo2a_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+/***********************************************************************
+// better compression ratio at the cost of more memory and time
+************************************************************************/
+
+#define LZO2A_999_MEM_COMPRESS ((lzo_uint32) (8 * 16384L * sizeof(short)))
+
+LZO_EXTERN(int)
+lzo2a_999_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzo_asm.h b/lzo/include/lzo/lzo_asm.h
new file mode 100644
index 00000000..23563a6d
--- /dev/null
+++ b/lzo/include/lzo/lzo_asm.h
@@ -0,0 +1,139 @@
+/* lzo_asm.h -- assembler prototypes for the LZO data compression library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZO_ASM_H_INCLUDED
+#define __LZO_ASM_H_INCLUDED
+
+#ifndef __LZOCONF_H_INCLUDED
+#include "lzoconf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+// assembly decompressors
+************************************************************************/
+
+LZO_EXTERN(int) lzo1c_decompress_asm
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+LZO_EXTERN(int) lzo1c_decompress_asm_safe
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+
+LZO_EXTERN(int) lzo1f_decompress_asm_fast
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+LZO_EXTERN(int) lzo1f_decompress_asm_fast_safe
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+
+LZO_EXTERN(int) lzo1x_decompress_asm
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+LZO_EXTERN(int) lzo1x_decompress_asm_safe
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+LZO_EXTERN(int) lzo1x_decompress_asm_fast
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+LZO_EXTERN(int) lzo1x_decompress_asm_fast_safe
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+
+LZO_EXTERN(int) lzo1y_decompress_asm
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+LZO_EXTERN(int) lzo1y_decompress_asm_safe
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+LZO_EXTERN(int) lzo1y_decompress_asm_fast
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+LZO_EXTERN(int) lzo1y_decompress_asm_fast_safe
+ (const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem);
+
+
+/***********************************************************************
+// checksum and misc functions
+************************************************************************/
+
+#if 0
+
+LZO_EXTERN(lzo_uint32)
+lzo_crc32_asm(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len,
+ const lzo_uint32p _crc_table);
+
+LZO_EXTERN(lzo_uint32)
+lzo_crc32_asm_small(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len);
+
+LZO_EXTERN(int)
+lzo_cpuid_asm(lzo_uint32p /* lzo_uint32 info[16] */ );
+
+LZO_EXTERN(lzo_uint32)
+lzo_rdtsc_asm(lzo_uint32p /* lzo_uint32 ticks[2] */ );
+
+#endif
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzoconf.h b/lzo/include/lzo/lzoconf.h
new file mode 100644
index 00000000..cc437f1e
--- /dev/null
+++ b/lzo/include/lzo/lzoconf.h
@@ -0,0 +1,417 @@
+/* lzoconf.h -- configuration for the LZO real-time data compression library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZOCONF_H_INCLUDED
+#define __LZOCONF_H_INCLUDED
+
+#define LZO_VERSION 0x2030
+#define LZO_VERSION_STRING "2.03"
+#define LZO_VERSION_DATE "Apr 30 2008"
+
+/* internal Autoconf configuration file - only used when building LZO */
+#if defined(LZO_HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <limits.h>
+#include <stddef.h>
+
+
+/***********************************************************************
+// LZO requires a conforming <limits.h>
+************************************************************************/
+
+#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
+# error "invalid CHAR_BIT"
+#endif
+#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
+# error "check your compiler installation"
+#endif
+#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1)
+# error "your limits.h macros are broken"
+#endif
+
+/* get OS and architecture defines */
+#ifndef __LZODEFS_H_INCLUDED
+#include "lzodefs.h"
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+// some core defines
+************************************************************************/
+
+#if !defined(LZO_UINT32_C)
+# if (UINT_MAX < LZO_0xffffffffL)
+# define LZO_UINT32_C(c) c ## UL
+# else
+# define LZO_UINT32_C(c) ((c) + 0U)
+# endif
+#endif
+
+/* memory checkers */
+#if !defined(__LZO_CHECKER)
+# if defined(__BOUNDS_CHECKING_ON)
+# define __LZO_CHECKER 1
+# elif defined(__CHECKER__)
+# define __LZO_CHECKER 1
+# elif defined(__INSURE__)
+# define __LZO_CHECKER 1
+# elif defined(__PURIFY__)
+# define __LZO_CHECKER 1
+# endif
+#endif
+
+
+/***********************************************************************
+// integral and pointer types
+************************************************************************/
+
+/* lzo_uint should match size_t */
+#if !defined(LZO_UINT_MAX)
+# if defined(LZO_ABI_LLP64) /* WIN64 */
+# if defined(LZO_OS_WIN64)
+ typedef unsigned __int64 lzo_uint;
+ typedef __int64 lzo_int;
+# else
+ typedef unsigned long long lzo_uint;
+ typedef long long lzo_int;
+# endif
+# define LZO_UINT_MAX 0xffffffffffffffffull
+# define LZO_INT_MAX 9223372036854775807LL
+# define LZO_INT_MIN (-1LL - LZO_INT_MAX)
+# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */
+ typedef unsigned int lzo_uint;
+ typedef int lzo_int;
+# define LZO_UINT_MAX UINT_MAX
+# define LZO_INT_MAX INT_MAX
+# define LZO_INT_MIN INT_MIN
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+ typedef unsigned long lzo_uint;
+ typedef long lzo_int;
+# define LZO_UINT_MAX ULONG_MAX
+# define LZO_INT_MAX LONG_MAX
+# define LZO_INT_MIN LONG_MIN
+# else
+# error "lzo_uint"
+# endif
+#endif
+
+/* Integral types with 32 bits or more. */
+#if !defined(LZO_UINT32_MAX)
+# if (UINT_MAX >= LZO_0xffffffffL)
+ typedef unsigned int lzo_uint32;
+ typedef int lzo_int32;
+# define LZO_UINT32_MAX UINT_MAX
+# define LZO_INT32_MAX INT_MAX
+# define LZO_INT32_MIN INT_MIN
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+ typedef unsigned long lzo_uint32;
+ typedef long lzo_int32;
+# define LZO_UINT32_MAX ULONG_MAX
+# define LZO_INT32_MAX LONG_MAX
+# define LZO_INT32_MIN LONG_MIN
+# else
+# error "lzo_uint32"
+# endif
+#endif
+
+/* The larger type of lzo_uint and lzo_uint32. */
+#if (LZO_UINT_MAX >= LZO_UINT32_MAX)
+# define lzo_xint lzo_uint
+#else
+# define lzo_xint lzo_uint32
+#endif
+
+/* Memory model that allows to access memory at offsets of lzo_uint. */
+#if !defined(__LZO_MMODEL)
+# if (LZO_UINT_MAX <= UINT_MAX)
+# define __LZO_MMODEL
+# elif defined(LZO_HAVE_MM_HUGE_PTR)
+# define __LZO_MMODEL_HUGE 1
+# define __LZO_MMODEL __huge
+# else
+# define __LZO_MMODEL
+# endif
+#endif
+
+/* no typedef here because of const-pointer issues */
+#define lzo_bytep unsigned char __LZO_MMODEL *
+#define lzo_charp char __LZO_MMODEL *
+#define lzo_voidp void __LZO_MMODEL *
+#define lzo_shortp short __LZO_MMODEL *
+#define lzo_ushortp unsigned short __LZO_MMODEL *
+#define lzo_uint32p lzo_uint32 __LZO_MMODEL *
+#define lzo_int32p lzo_int32 __LZO_MMODEL *
+#define lzo_uintp lzo_uint __LZO_MMODEL *
+#define lzo_intp lzo_int __LZO_MMODEL *
+#define lzo_xintp lzo_xint __LZO_MMODEL *
+#define lzo_voidpp lzo_voidp __LZO_MMODEL *
+#define lzo_bytepp lzo_bytep __LZO_MMODEL *
+/* deprecated - use `lzo_bytep' instead of `lzo_byte *' */
+#define lzo_byte unsigned char __LZO_MMODEL
+
+typedef int lzo_bool;
+
+
+/***********************************************************************
+// function types
+************************************************************************/
+
+/* name mangling */
+#if !defined(__LZO_EXTERN_C)
+# ifdef __cplusplus
+# define __LZO_EXTERN_C extern "C"
+# else
+# define __LZO_EXTERN_C extern
+# endif
+#endif
+
+/* calling convention */
+#if !defined(__LZO_CDECL)
+# define __LZO_CDECL __lzo_cdecl
+#endif
+
+/* DLL export information */
+#if !defined(__LZO_EXPORT1)
+# define __LZO_EXPORT1
+#endif
+#if !defined(__LZO_EXPORT2)
+# define __LZO_EXPORT2
+#endif
+
+/* __cdecl calling convention for public C and assembly functions */
+#if !defined(LZO_PUBLIC)
+# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL
+#endif
+#if !defined(LZO_EXTERN)
+# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype)
+#endif
+#if !defined(LZO_PRIVATE)
+# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL
+#endif
+
+/* function types */
+typedef int
+(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len );
+
+typedef int
+(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len );
+
+
+/* Callback interface. Currently only the progress indicator ("nprogress")
+ * is used, but this may change in a future release. */
+
+struct lzo_callback_t;
+typedef struct lzo_callback_t lzo_callback_t;
+#define lzo_callback_p lzo_callback_t __LZO_MMODEL *
+
+/* malloc & free function types */
+typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t)
+ (lzo_callback_p self, lzo_uint items, lzo_uint size);
+typedef void (__LZO_CDECL *lzo_free_func_t)
+ (lzo_callback_p self, lzo_voidp ptr);
+
+/* a progress indicator callback function */
+typedef void (__LZO_CDECL *lzo_progress_func_t)
+ (lzo_callback_p, lzo_uint, lzo_uint, int);
+
+struct lzo_callback_t
+{
+ /* custom allocators (set to 0 to disable) */
+ lzo_alloc_func_t nalloc; /* [not used right now] */
+ lzo_free_func_t nfree; /* [not used right now] */
+
+ /* a progress indicator callback function (set to 0 to disable) */
+ lzo_progress_func_t nprogress;
+
+ /* NOTE: the first parameter "self" of the nalloc/nfree/nprogress
+ * callbacks points back to this struct, so you are free to store
+ * some extra info in the following variables. */
+ lzo_voidp user1;
+ lzo_xint user2;
+ lzo_xint user3;
+};
+
+
+/***********************************************************************
+// error codes and prototypes
+************************************************************************/
+
+/* Error codes for the compression/decompression functions. Negative
+ * values are errors, positive values will be used for special but
+ * normal events.
+ */
+#define LZO_E_OK 0
+#define LZO_E_ERROR (-1)
+#define LZO_E_OUT_OF_MEMORY (-2) /* [not used right now] */
+#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */
+#define LZO_E_INPUT_OVERRUN (-4)
+#define LZO_E_OUTPUT_OVERRUN (-5)
+#define LZO_E_LOOKBEHIND_OVERRUN (-6)
+#define LZO_E_EOF_NOT_FOUND (-7)
+#define LZO_E_INPUT_NOT_CONSUMED (-8)
+#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
+
+
+#ifndef lzo_sizeof_dict_t
+# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep))
+#endif
+
+/* lzo_init() should be the first function you call.
+ * Check the return code !
+ *
+ * lzo_init() is a macro to allow checking that the library and the
+ * compiler's view of various types are consistent.
+ */
+#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
+ (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\
+ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
+ (int)sizeof(lzo_callback_t))
+LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int);
+
+/* version functions (useful for shared libraries) */
+LZO_EXTERN(unsigned) lzo_version(void);
+LZO_EXTERN(const char *) lzo_version_string(void);
+LZO_EXTERN(const char *) lzo_version_date(void);
+LZO_EXTERN(const lzo_charp) _lzo_version_string(void);
+LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
+
+/* string functions */
+LZO_EXTERN(int)
+lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memset(lzo_voidp _s, int _c, lzo_uint _len);
+
+/* checksum functions */
+LZO_EXTERN(lzo_uint32)
+lzo_adler32(lzo_uint32 _adler, const lzo_bytep _buf, lzo_uint _len);
+LZO_EXTERN(lzo_uint32)
+lzo_crc32(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len);
+LZO_EXTERN(const lzo_uint32p)
+lzo_get_crc32_table(void);
+
+/* misc. */
+LZO_EXTERN(int) _lzo_config_check(void);
+typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u;
+typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u;
+typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t;
+
+/* align a char pointer on a boundary that is a multiple of `size' */
+LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size);
+#define LZO_PTR_ALIGN_UP(_ptr,_size) \
+ ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size)))
+
+
+/***********************************************************************
+// deprecated macros - only for backward compatibility with LZO v1.xx
+************************************************************************/
+
+#if defined(LZO_CFG_COMPAT)
+
+#define __LZOCONF_H 1
+
+#if defined(LZO_ARCH_I086)
+# define __LZO_i386 1
+#elif defined(LZO_ARCH_I386)
+# define __LZO_i386 1
+#endif
+
+#if defined(LZO_OS_DOS16)
+# define __LZO_DOS 1
+# define __LZO_DOS16 1
+#elif defined(LZO_OS_DOS32)
+# define __LZO_DOS 1
+#elif defined(LZO_OS_WIN16)
+# define __LZO_WIN 1
+# define __LZO_WIN16 1
+#elif defined(LZO_OS_WIN32)
+# define __LZO_WIN 1
+#endif
+
+#define __LZO_CMODEL
+#define __LZO_DMODEL
+#define __LZO_ENTRY __LZO_CDECL
+#define LZO_EXTERN_CDECL LZO_EXTERN
+#define LZO_ALIGN LZO_PTR_ALIGN_UP
+
+#define lzo_compress_asm_t lzo_compress_t
+#define lzo_decompress_asm_t lzo_decompress_t
+
+#endif /* LZO_CFG_COMPAT */
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzodefs.h b/lzo/include/lzo/lzodefs.h
new file mode 100644
index 00000000..18056372
--- /dev/null
+++ b/lzo/include/lzo/lzodefs.h
@@ -0,0 +1,1807 @@
+/* lzodefs.h -- architecture, OS and compiler specific defines
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZODEFS_H_INCLUDED
+#define __LZODEFS_H_INCLUDED 1
+
+#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
+# define __CYGWIN__ __CYGWIN32__
+#endif
+#if defined(__IBMCPP__) && !defined(__IBMC__)
+# define __IBMC__ __IBMCPP__
+#endif
+#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER)
+# define __INTEL_COMPILER __ICL
+#endif
+#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE)
+# define _ALL_SOURCE 1
+#endif
+#if defined(__mips__) && defined(__R5900__)
+# if !defined(__LONG_MAX__)
+# define __LONG_MAX__ 9223372036854775807L
+# endif
+#endif
+#if defined(__INTEL_COMPILER) && defined(__linux__)
+# pragma warning(disable: 193)
+#endif
+#if defined(__KEIL__) && defined(__C166__)
+# pragma warning disable = 322
+#elif 0 && defined(__C251__)
+# pragma warning disable = 322
+#endif
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
+# if (_MSC_VER >= 1300)
+# pragma warning(disable: 4668)
+# endif
+#endif
+#if 0 && defined(__WATCOMC__)
+# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060)
+# pragma warning 203 9
+# endif
+#endif
+#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__)
+# pragma option -h
+#endif
+#if 0
+#define LZO_0xffffL 0xfffful
+#define LZO_0xffffffffL 0xfffffffful
+#else
+#define LZO_0xffffL 65535ul
+#define LZO_0xffffffffL 4294967295ul
+#endif
+#if (LZO_0xffffL == LZO_0xffffffffL)
+# error "your preprocessor is broken 1"
+#endif
+#if (16ul * 16384ul != 262144ul)
+# error "your preprocessor is broken 2"
+#endif
+#if 0
+#if (32767 >= 4294967295ul)
+# error "your preprocessor is broken 3"
+#endif
+#if (65535u >= 4294967295ul)
+# error "your preprocessor is broken 4"
+#endif
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__)
+# if !defined(MSDOS)
+# define MSDOS 1
+# endif
+# if !defined(_MSDOS)
+# define _MSDOS 1
+# endif
+#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX)
+# if (__VERSION == 520) && (MB_LEN_MAX == 1)
+# if !defined(__AZTEC_C__)
+# define __AZTEC_C__ __VERSION
+# endif
+# if !defined(__DOS__)
+# define __DOS__ 1
+# endif
+# endif
+#endif
+#endif
+#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL)
+# define ptrdiff_t long
+# define _PTRDIFF_T_DEFINED
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+# undef __LZO_RENAME_A
+# undef __LZO_RENAME_B
+# if defined(__AZTEC_C__) && defined(__DOS__)
+# define __LZO_RENAME_A 1
+# elif defined(_MSC_VER) && defined(MSDOS)
+# if (_MSC_VER < 600)
+# define __LZO_RENAME_A 1
+# elif (_MSC_VER < 700)
+# define __LZO_RENAME_B 1
+# endif
+# elif defined(__TSC__) && defined(__OS2__)
+# define __LZO_RENAME_A 1
+# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410)
+# define __LZO_RENAME_A 1
+# elif defined(__PACIFIC__) && defined(DOS)
+# if !defined(__far)
+# define __far far
+# endif
+# if !defined(__near)
+# define __near near
+# endif
+# endif
+# if defined(__LZO_RENAME_A)
+# if !defined(__cdecl)
+# define __cdecl cdecl
+# endif
+# if !defined(__far)
+# define __far far
+# endif
+# if !defined(__huge)
+# define __huge huge
+# endif
+# if !defined(__near)
+# define __near near
+# endif
+# if !defined(__pascal)
+# define __pascal pascal
+# endif
+# if !defined(__huge)
+# define __huge huge
+# endif
+# elif defined(__LZO_RENAME_B)
+# if !defined(__cdecl)
+# define __cdecl _cdecl
+# endif
+# if !defined(__far)
+# define __far _far
+# endif
+# if !defined(__huge)
+# define __huge _huge
+# endif
+# if !defined(__near)
+# define __near _near
+# endif
+# if !defined(__pascal)
+# define __pascal _pascal
+# endif
+# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+# if !defined(__cdecl)
+# define __cdecl cdecl
+# endif
+# if !defined(__pascal)
+# define __pascal pascal
+# endif
+# endif
+# undef __LZO_RENAME_A
+# undef __LZO_RENAME_B
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#if defined(__AZTEC_C__) && defined(__DOS__)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+#elif defined(_MSC_VER) && defined(MSDOS)
+# if (_MSC_VER < 600)
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+# endif
+# if (_MSC_VER < 700)
+# define LZO_BROKEN_INTEGRAL_PROMOTION 1
+# define LZO_BROKEN_SIZEOF 1
+# endif
+#elif defined(__PACIFIC__) && defined(DOS)
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#elif defined(__TURBOC__) && defined(__MSDOS__)
+# if (__TURBOC__ < 0x0150)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+# define LZO_BROKEN_INTEGRAL_PROMOTION 1
+# endif
+# if (__TURBOC__ < 0x0200)
+# define LZO_BROKEN_SIZEOF 1
+# endif
+# if (__TURBOC__ < 0x0400) && defined(__cplusplus)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+# endif
+#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+# define LZO_BROKEN_SIZEOF 1
+#endif
+#endif
+#if defined(__WATCOMC__) && (__WATCOMC__ < 900)
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#endif
+#if defined(_CRAY) && defined(_CRAY1)
+# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1
+#endif
+#define LZO_PP_STRINGIZE(x) #x
+#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x)
+#define LZO_PP_CONCAT2(a,b) a ## b
+#define LZO_PP_CONCAT3(a,b,c) a ## b ## c
+#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d
+#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b)
+#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c)
+#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d)
+#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e)
+#if 1
+#define LZO_CPP_STRINGIZE(x) #x
+#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x)
+#define LZO_CPP_CONCAT2(a,b) a ## b
+#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c
+#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d
+#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b)
+#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c)
+#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d)
+#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e)
+#endif
+#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o))
+#if 1 && defined(__cplusplus)
+# if !defined(__STDC_CONSTANT_MACROS)
+# define __STDC_CONSTANT_MACROS 1
+# endif
+# if !defined(__STDC_LIMIT_MACROS)
+# define __STDC_LIMIT_MACROS 1
+# endif
+#endif
+#if defined(__cplusplus)
+# define LZO_EXTERN_C extern "C"
+#else
+# define LZO_EXTERN_C extern
+#endif
+#if !defined(__LZO_OS_OVERRIDE)
+#if defined(LZO_OS_FREESTANDING)
+# define LZO_INFO_OS "freestanding"
+#elif defined(LZO_OS_EMBEDDED)
+# define LZO_INFO_OS "embedded"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+# define LZO_OS_EMBEDDED 1
+# define LZO_INFO_OS "embedded"
+#elif defined(__CYGWIN__) && defined(__GNUC__)
+# define LZO_OS_CYGWIN 1
+# define LZO_INFO_OS "cygwin"
+#elif defined(__EMX__) && defined(__GNUC__)
+# define LZO_OS_EMX 1
+# define LZO_INFO_OS "emx"
+#elif defined(__BEOS__)
+# define LZO_OS_BEOS 1
+# define LZO_INFO_OS "beos"
+#elif defined(__Lynx__)
+# define LZO_OS_LYNXOS 1
+# define LZO_INFO_OS "lynxos"
+#elif defined(__OS400__)
+# define LZO_OS_OS400 1
+# define LZO_INFO_OS "os400"
+#elif defined(__QNX__)
+# define LZO_OS_QNX 1
+# define LZO_INFO_OS "qnx"
+#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460)
+# define LZO_OS_DOS32 1
+# define LZO_INFO_OS "dos32"
+#elif defined(__BORLANDC__) && defined(__DPMI16__)
+# define LZO_OS_DOS16 1
+# define LZO_INFO_OS "dos16"
+#elif defined(__ZTC__) && defined(DOS386)
+# define LZO_OS_DOS32 1
+# define LZO_INFO_OS "dos32"
+#elif defined(__OS2__) || defined(__OS2V2__)
+# if (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_OS216 1
+# define LZO_INFO_OS "os216"
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_OS_OS2 1
+# define LZO_INFO_OS "os2"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64)
+# define LZO_OS_WIN64 1
+# define LZO_INFO_OS "win64"
+#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+#elif defined(__MWERKS__) && defined(__INTEL__)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows)
+# if (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_WIN16 1
+# define LZO_INFO_OS "win16"
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS))
+# if (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_DOS16 1
+# define LZO_INFO_OS "dos16"
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_OS_DOS32 1
+# define LZO_INFO_OS "dos32"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__WATCOMC__)
+# if defined(__NT__) && (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_DOS16 1
+# define LZO_INFO_OS "dos16"
+# elif defined(__NT__) && (__WATCOMC__ < 1100)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+# elif defined(__linux__) || defined(__LINUX__)
+# define LZO_OS_POSIX 1
+# define LZO_INFO_OS "posix"
+# else
+# error "please specify a target using the -bt compiler option"
+# endif
+#elif defined(__palmos__)
+# define LZO_OS_PALMOS 1
+# define LZO_INFO_OS "palmos"
+#elif defined(__TOS__) || defined(__atarist__)
+# define LZO_OS_TOS 1
+# define LZO_INFO_OS "tos"
+#elif defined(macintosh) && !defined(__ppc__)
+# define LZO_OS_MACCLASSIC 1
+# define LZO_INFO_OS "macclassic"
+#elif defined(__VMS)
+# define LZO_OS_VMS 1
+# define LZO_INFO_OS "vms"
+#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+# define LZO_OS_CONSOLE 1
+# define LZO_OS_CONSOLE_PS2 1
+# define LZO_INFO_OS "console"
+# define LZO_INFO_OS_CONSOLE "ps2"
+#elif (defined(__mips__) && defined(__psp__))
+# define LZO_OS_CONSOLE 1
+# define LZO_OS_CONSOLE_PSP 1
+# define LZO_INFO_OS "console"
+# define LZO_INFO_OS_CONSOLE "psp"
+#else
+# define LZO_OS_POSIX 1
+# define LZO_INFO_OS "posix"
+#endif
+#if (LZO_OS_POSIX)
+# if defined(_AIX) || defined(__AIX__) || defined(__aix__)
+# define LZO_OS_POSIX_AIX 1
+# define LZO_INFO_OS_POSIX "aix"
+# elif defined(__FreeBSD__)
+# define LZO_OS_POSIX_FREEBSD 1
+# define LZO_INFO_OS_POSIX "freebsd"
+# elif defined(__hpux__) || defined(__hpux)
+# define LZO_OS_POSIX_HPUX 1
+# define LZO_INFO_OS_POSIX "hpux"
+# elif defined(__INTERIX)
+# define LZO_OS_POSIX_INTERIX 1
+# define LZO_INFO_OS_POSIX "interix"
+# elif defined(__IRIX__) || defined(__irix__)
+# define LZO_OS_POSIX_IRIX 1
+# define LZO_INFO_OS_POSIX "irix"
+# elif defined(__linux__) || defined(__linux) || defined(__LINUX__)
+# define LZO_OS_POSIX_LINUX 1
+# define LZO_INFO_OS_POSIX "linux"
+# elif defined(__APPLE__) || defined(__MACOS__)
+# define LZO_OS_POSIX_MACOSX 1
+# define LZO_INFO_OS_POSIX "macosx"
+# elif defined(__minix__) || defined(__minix)
+# define LZO_OS_POSIX_MINIX 1
+# define LZO_INFO_OS_POSIX "minix"
+# elif defined(__NetBSD__)
+# define LZO_OS_POSIX_NETBSD 1
+# define LZO_INFO_OS_POSIX "netbsd"
+# elif defined(__OpenBSD__)
+# define LZO_OS_POSIX_OPENBSD 1
+# define LZO_INFO_OS_POSIX "openbsd"
+# elif defined(__osf__)
+# define LZO_OS_POSIX_OSF 1
+# define LZO_INFO_OS_POSIX "osf"
+# elif defined(__solaris__) || defined(__sun)
+# if defined(__SVR4) || defined(__svr4__)
+# define LZO_OS_POSIX_SOLARIS 1
+# define LZO_INFO_OS_POSIX "solaris"
+# else
+# define LZO_OS_POSIX_SUNOS 1
+# define LZO_INFO_OS_POSIX "sunos"
+# endif
+# elif defined(__ultrix__) || defined(__ultrix)
+# define LZO_OS_POSIX_ULTRIX 1
+# define LZO_INFO_OS_POSIX "ultrix"
+# elif defined(_UNICOS)
+# define LZO_OS_POSIX_UNICOS 1
+# define LZO_INFO_OS_POSIX "unicos"
+# else
+# define LZO_OS_POSIX_UNKNOWN 1
+# define LZO_INFO_OS_POSIX "unknown"
+# endif
+#endif
+#endif
+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+# if (UINT_MAX != LZO_0xffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (UINT_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__)
+# define LZO_CC_CILLY 1
+# define LZO_INFO_CC "Cilly"
+# if defined(__CILLY__)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__)
+# else
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__)
+# define LZO_CC_SDCC 1
+# define LZO_INFO_CC "sdcc"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC)
+#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__)
+# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__)
+# define LZO_INFO_CC "Pathscale C"
+# define LZO_INFO_CCVER __PATHSCALE__
+#elif defined(__INTEL_COMPILER)
+# define LZO_CC_INTELC 1
+# define LZO_INFO_CC "Intel C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER)
+# if defined(_WIN32) || defined(_WIN64)
+# define LZO_CC_SYNTAX_MSC 1
+# else
+# define LZO_CC_SYNTAX_GNUC 1
+# endif
+#elif defined(__POCC__) && defined(_WIN32)
+# define LZO_CC_PELLESC 1
+# define LZO_INFO_CC "Pelles C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__)
+#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__)
+# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# else
+# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# endif
+# define LZO_INFO_CC "llvm-gcc"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(__GNUC__) && defined(__VERSION__)
+# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# elif defined(__GNUC_MINOR__)
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# else
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L)
+# endif
+# define LZO_INFO_CC "gcc"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(__ACK__) && defined(_ACK)
+# define LZO_CC_ACK 1
+# define LZO_INFO_CC "Amsterdam Compiler Kit C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__AZTEC_C__)
+# define LZO_CC_AZTECC 1
+# define LZO_INFO_CC "Aztec C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__)
+#elif defined(__BORLANDC__)
+# define LZO_CC_BORLANDC 1
+# define LZO_INFO_CC "Borland C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__)
+#elif defined(_CRAYC) && defined(_RELEASE)
+# define LZO_CC_CRAYC 1
+# define LZO_INFO_CC "Cray C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE)
+#elif defined(__DMC__) && defined(__SC__)
+# define LZO_CC_DMC 1
+# define LZO_INFO_CC "Digital Mars C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__)
+#elif defined(__DECC)
+# define LZO_CC_DECC 1
+# define LZO_INFO_CC "DEC C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC)
+#elif defined(__HIGHC__)
+# define LZO_CC_HIGHC 1
+# define LZO_INFO_CC "MetaWare High C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__IAR_SYSTEMS_ICC__)
+# define LZO_CC_IARC 1
+# define LZO_INFO_CC "IAR C"
+# if defined(__VER__)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__)
+# else
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(__IBMC__)
+# define LZO_CC_IBMC 1
+# define LZO_INFO_CC "IBM C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__)
+#elif defined(__KEIL__) && defined(__C166__)
+# define LZO_CC_KEILC 1
+# define LZO_INFO_CC "Keil C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__)
+#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL)
+# define LZO_CC_LCCWIN32 1
+# define LZO_INFO_CC "lcc-win32"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__LCC__)
+# define LZO_CC_LCC 1
+# define LZO_INFO_CC "lcc"
+# if defined(__LCC_VERSION__)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__)
+# else
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(_MSC_VER)
+# define LZO_CC_MSC 1
+# define LZO_INFO_CC "Microsoft C"
+# if defined(_MSC_FULL_VER)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER)
+# else
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER)
+# endif
+#elif defined(__MWERKS__)
+# define LZO_CC_MWERKS 1
+# define LZO_INFO_CC "Metrowerks C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__)
+#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386)
+# define LZO_CC_NDPC 1
+# define LZO_INFO_CC "Microway NDP C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__PACIFIC__)
+# define LZO_CC_PACIFICC 1
+# define LZO_INFO_CC "Pacific C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__)
+#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__))
+# define LZO_CC_PGI 1
+# define LZO_INFO_CC "Portland Group PGI C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__PUREC__) && defined(__TOS__)
+# define LZO_CC_PUREC 1
+# define LZO_INFO_CC "Pure C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__)
+#elif defined(__SC__) && defined(__ZTC__)
+# define LZO_CC_SYMANTECC 1
+# define LZO_INFO_CC "Symantec C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__)
+#elif defined(__SUNPRO_C)
+# define LZO_INFO_CC "SunPro C"
+# if ((__SUNPRO_C)+0 > 0)
+# define LZO_CC_SUNPROC __SUNPRO_C
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C)
+# else
+# define LZO_CC_SUNPROC 1
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(__SUNPRO_CC)
+# define LZO_INFO_CC "SunPro C"
+# if ((__SUNPRO_CC)+0 > 0)
+# define LZO_CC_SUNPROC __SUNPRO_CC
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC)
+# else
+# define LZO_CC_SUNPROC 1
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(__TINYC__)
+# define LZO_CC_TINYC 1
+# define LZO_INFO_CC "Tiny C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__)
+#elif defined(__TSC__)
+# define LZO_CC_TOPSPEEDC 1
+# define LZO_INFO_CC "TopSpeed C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__)
+#elif defined(__WATCOMC__)
+# define LZO_CC_WATCOMC 1
+# define LZO_INFO_CC "Watcom C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__)
+#elif defined(__TURBOC__)
+# define LZO_CC_TURBOC 1
+# define LZO_INFO_CC "Turbo C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__)
+#elif defined(__ZTC__)
+# define LZO_CC_ZORTECHC 1
+# define LZO_INFO_CC "Zortech C"
+# if (__ZTC__ == 0x310)
+# define LZO_INFO_CCVER "0x310"
+# else
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__)
+# endif
+#else
+# define LZO_CC_UNKNOWN 1
+# define LZO_INFO_CC "unknown"
+# define LZO_INFO_CCVER "unknown"
+#endif
+#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)
+# error "LZO_CC_MSC: _MSC_FULL_VER is not defined"
+#endif
+#if !defined(__LZO_ARCH_OVERRIDE) && !defined(LZO_ARCH_GENERIC) && defined(_CRAY)
+# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY)
+# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E)
+# define LZO_ARCH_CRAY_MPP 1
+# elif defined(_CRAY1)
+# define LZO_ARCH_CRAY_PVP 1
+# endif
+# endif
+#endif
+#if !defined(__LZO_ARCH_OVERRIDE)
+#if defined(LZO_ARCH_GENERIC)
+# define LZO_INFO_ARCH "generic"
+#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+# define LZO_ARCH_I086 1
+# define LZO_ARCH_IA16 1
+# define LZO_INFO_ARCH "i086"
+#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
+# define LZO_ARCH_ALPHA 1
+# define LZO_INFO_ARCH "alpha"
+#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E))
+# define LZO_ARCH_ALPHA 1
+# define LZO_INFO_ARCH "alpha"
+#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
+# define LZO_ARCH_AMD64 1
+# define LZO_INFO_ARCH "amd64"
+#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB))
+# define LZO_ARCH_ARM 1
+# define LZO_ARCH_ARM_THUMB 1
+# define LZO_INFO_ARCH "arm_thumb"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
+# define LZO_ARCH_ARM 1
+# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1)
+# define LZO_ARCH_ARM_THUMB 1
+# define LZO_INFO_ARCH "arm_thumb"
+# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2)
+# define LZO_INFO_ARCH "arm"
+# else
+# define LZO_INFO_ARCH "arm"
+# endif
+#elif defined(__arm__) || defined(_M_ARM)
+# define LZO_ARCH_ARM 1
+# define LZO_INFO_ARCH "arm"
+#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__)
+# define LZO_ARCH_AVR 1
+# define LZO_INFO_ARCH "avr"
+#elif defined(__bfin__)
+# define LZO_ARCH_BLACKFIN 1
+# define LZO_INFO_ARCH "blackfin"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__)
+# define LZO_ARCH_C166 1
+# define LZO_INFO_ARCH "c166"
+#elif defined(__cris__)
+# define LZO_ARCH_CRIS 1
+# define LZO_INFO_ARCH "cris"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__)
+# define LZO_ARCH_EZ80 1
+# define LZO_INFO_ARCH "ez80"
+#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+# define LZO_ARCH_H8300 1
+# define LZO_INFO_ARCH "h8300"
+#elif defined(__hppa__) || defined(__hppa)
+# define LZO_ARCH_HPPA 1
+# define LZO_INFO_ARCH "hppa"
+#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
+# define LZO_ARCH_I386 1
+# define LZO_ARCH_IA32 1
+# define LZO_INFO_ARCH "i386"
+#elif (LZO_CC_ZORTECHC && defined(__I86__))
+# define LZO_ARCH_I386 1
+# define LZO_ARCH_IA32 1
+# define LZO_INFO_ARCH "i386"
+#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386)
+# define LZO_ARCH_I386 1
+# define LZO_ARCH_IA32 1
+# define LZO_INFO_ARCH "i386"
+#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
+# define LZO_ARCH_IA64 1
+# define LZO_INFO_ARCH "ia64"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__)
+# define LZO_ARCH_M16C 1
+# define LZO_INFO_ARCH "m16c"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__)
+# define LZO_ARCH_M16C 1
+# define LZO_INFO_ARCH "m16c"
+#elif defined(__m32r__)
+# define LZO_ARCH_M32R 1
+# define LZO_INFO_ARCH "m32r"
+#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K)
+# define LZO_ARCH_M68K 1
+# define LZO_INFO_ARCH "m68k"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__)
+# define LZO_ARCH_MCS251 1
+# define LZO_INFO_ARCH "mcs251"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__)
+# define LZO_ARCH_MCS51 1
+# define LZO_INFO_ARCH "mcs51"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__)
+# define LZO_ARCH_MCS51 1
+# define LZO_INFO_ARCH "mcs51"
+#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
+# define LZO_ARCH_MIPS 1
+# define LZO_INFO_ARCH "mips"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__)
+# define LZO_ARCH_MSP430 1
+# define LZO_INFO_ARCH "msp430"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__)
+# define LZO_ARCH_MSP430 1
+# define LZO_INFO_ARCH "msp430"
+#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
+# define LZO_ARCH_POWERPC 1
+# define LZO_INFO_ARCH "powerpc"
+#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
+# define LZO_ARCH_S390 1
+# define LZO_INFO_ARCH "s390"
+#elif defined(__sh__) || defined(_M_SH)
+# define LZO_ARCH_SH 1
+# define LZO_INFO_ARCH "sh"
+#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
+# define LZO_ARCH_SPARC 1
+# define LZO_INFO_ARCH "sparc"
+#elif defined(__SPU__)
+# define LZO_ARCH_SPU 1
+# define LZO_INFO_ARCH "spu"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__z80)
+# define LZO_ARCH_Z80 1
+# define LZO_INFO_ARCH "z80"
+#elif (LZO_ARCH_CRAY_PVP)
+# if defined(_CRAYSV1)
+# define LZO_ARCH_CRAY_SV1 1
+# define LZO_INFO_ARCH "cray_sv1"
+# elif (_ADDR64)
+# define LZO_ARCH_CRAY_T90 1
+# define LZO_INFO_ARCH "cray_t90"
+# elif (_ADDR32)
+# define LZO_ARCH_CRAY_YMP 1
+# define LZO_INFO_ARCH "cray_ymp"
+# else
+# define LZO_ARCH_CRAY_XMP 1
+# define LZO_INFO_ARCH "cray_xmp"
+# endif
+#else
+# define LZO_ARCH_UNKNOWN 1
+# define LZO_INFO_ARCH "unknown"
+#endif
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2)
+# error "FIXME - missing define for CPU architecture"
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32)
+# error "FIXME - missing WIN32 define for CPU architecture"
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64)
+# error "FIXME - missing WIN64 define for CPU architecture"
+#endif
+#if (LZO_OS_OS216 || LZO_OS_WIN16)
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#elif 1 && (LZO_OS_DOS16 && defined(BLX286))
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#elif 1 && (LZO_OS_DOS16 && defined(DOSX286))
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__))
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#endif
+#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM)
+# error "this should not happen"
+#endif
+#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086)
+# error "this should not happen"
+#endif
+#if (LZO_ARCH_I086)
+# if (UINT_MAX != LZO_0xffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if (LZO_ARCH_I386)
+# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__)
+# error "this should not happen"
+# endif
+# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if !defined(__LZO_MM_OVERRIDE)
+#if (LZO_ARCH_I086)
+#if (UINT_MAX != LZO_0xffffL)
+# error "this should not happen"
+#endif
+#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM)
+# define LZO_MM_TINY 1
+#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM)
+# define LZO_MM_HUGE 1
+#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL)
+# define LZO_MM_SMALL 1
+#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM)
+# define LZO_MM_MEDIUM 1
+#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM)
+# define LZO_MM_COMPACT 1
+#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL)
+# define LZO_MM_LARGE 1
+#elif (LZO_CC_AZTECC)
+# if defined(_LARGE_CODE) && defined(_LARGE_DATA)
+# define LZO_MM_LARGE 1
+# elif defined(_LARGE_CODE)
+# define LZO_MM_MEDIUM 1
+# elif defined(_LARGE_DATA)
+# define LZO_MM_COMPACT 1
+# else
+# define LZO_MM_SMALL 1
+# endif
+#elif (LZO_CC_ZORTECHC && defined(__VCM__))
+# define LZO_MM_LARGE 1
+#else
+# error "unknown memory model"
+#endif
+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+#define LZO_HAVE_MM_HUGE_PTR 1
+#define LZO_HAVE_MM_HUGE_ARRAY 1
+#if (LZO_MM_TINY)
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#endif
+#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC)
+# undef LZO_HAVE_MM_HUGE_PTR
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#elif (LZO_CC_MSC && defined(_QC))
+# undef LZO_HAVE_MM_HUGE_ARRAY
+# if (_MSC_VER < 600)
+# undef LZO_HAVE_MM_HUGE_PTR
+# endif
+#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295))
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#endif
+#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR)
+# if (LZO_OS_DOS16)
+# error "this should not happen"
+# elif (LZO_CC_ZORTECHC)
+# else
+# error "this should not happen"
+# endif
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200))
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC)
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295))
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16)
+# define LZO_MM_AHSHIFT 12
+#elif (LZO_CC_WATCOMC)
+ extern unsigned char _HShift;
+# define LZO_MM_AHSHIFT ((unsigned) _HShift)
+#else
+# error "FIXME - implement LZO_MM_AHSHIFT"
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+#elif (LZO_ARCH_C166)
+#if !defined(__MODEL__)
+# error "FIXME - C166 __MODEL__"
+#elif ((__MODEL__) == 0)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 1)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define LZO_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define LZO_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define LZO_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define LZO_MM_XSMALL 1
+#else
+# error "FIXME - C166 __MODEL__"
+#endif
+#elif (LZO_ARCH_MCS251)
+#if !defined(__MODEL__)
+# error "FIXME - MCS251 __MODEL__"
+#elif ((__MODEL__) == 0)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define LZO_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define LZO_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define LZO_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define LZO_MM_XSMALL 1
+#else
+# error "FIXME - MCS251 __MODEL__"
+#endif
+#elif (LZO_ARCH_MCS51)
+#if !defined(__MODEL__)
+# error "FIXME - MCS51 __MODEL__"
+#elif ((__MODEL__) == 1)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define LZO_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define LZO_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define LZO_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define LZO_MM_XSMALL 1
+#else
+# error "FIXME - MCS51 __MODEL__"
+#endif
+#elif (LZO_ARCH_CRAY_PVP)
+# define LZO_MM_PVP 1
+#else
+# define LZO_MM_FLAT 1
+#endif
+#if (LZO_MM_COMPACT)
+# define LZO_INFO_MM "compact"
+#elif (LZO_MM_FLAT)
+# define LZO_INFO_MM "flat"
+#elif (LZO_MM_HUGE)
+# define LZO_INFO_MM "huge"
+#elif (LZO_MM_LARGE)
+# define LZO_INFO_MM "large"
+#elif (LZO_MM_MEDIUM)
+# define LZO_INFO_MM "medium"
+#elif (LZO_MM_PVP)
+# define LZO_INFO_MM "pvp"
+#elif (LZO_MM_SMALL)
+# define LZO_INFO_MM "small"
+#elif (LZO_MM_TINY)
+# define LZO_INFO_MM "tiny"
+#else
+# error "unknown memory model"
+#endif
+#endif
+#if defined(SIZEOF_SHORT)
+# define LZO_SIZEOF_SHORT (SIZEOF_SHORT)
+#endif
+#if defined(SIZEOF_INT)
+# define LZO_SIZEOF_INT (SIZEOF_INT)
+#endif
+#if defined(SIZEOF_LONG)
+# define LZO_SIZEOF_LONG (SIZEOF_LONG)
+#endif
+#if defined(SIZEOF_LONG_LONG)
+# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG)
+#endif
+#if defined(SIZEOF___INT16)
+# define LZO_SIZEOF___INT16 (SIZEOF___INT16)
+#endif
+#if defined(SIZEOF___INT32)
+# define LZO_SIZEOF___INT32 (SIZEOF___INT32)
+#endif
+#if defined(SIZEOF___INT64)
+# define LZO_SIZEOF___INT64 (SIZEOF___INT64)
+#endif
+#if defined(SIZEOF_VOID_P)
+# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P)
+#endif
+#if defined(SIZEOF_SIZE_T)
+# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T)
+#endif
+#if defined(SIZEOF_PTRDIFF_T)
+# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T)
+#endif
+#define __LZO_LSR(x,b) (((x)+0ul) >> (b))
+#if !defined(LZO_SIZEOF_SHORT)
+# if (LZO_ARCH_CRAY_PVP)
+# define LZO_SIZEOF_SHORT 8
+# elif (USHRT_MAX == LZO_0xffffL)
+# define LZO_SIZEOF_SHORT 2
+# elif (__LZO_LSR(USHRT_MAX,7) == 1)
+# define LZO_SIZEOF_SHORT 1
+# elif (__LZO_LSR(USHRT_MAX,15) == 1)
+# define LZO_SIZEOF_SHORT 2
+# elif (__LZO_LSR(USHRT_MAX,31) == 1)
+# define LZO_SIZEOF_SHORT 4
+# elif (__LZO_LSR(USHRT_MAX,63) == 1)
+# define LZO_SIZEOF_SHORT 8
+# elif (__LZO_LSR(USHRT_MAX,127) == 1)
+# define LZO_SIZEOF_SHORT 16
+# else
+# error "LZO_SIZEOF_SHORT"
+# endif
+#endif
+#if !defined(LZO_SIZEOF_INT)
+# if (LZO_ARCH_CRAY_PVP)
+# define LZO_SIZEOF_INT 8
+# elif (UINT_MAX == LZO_0xffffL)
+# define LZO_SIZEOF_INT 2
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_SIZEOF_INT 4
+# elif (__LZO_LSR(UINT_MAX,7) == 1)
+# define LZO_SIZEOF_INT 1
+# elif (__LZO_LSR(UINT_MAX,15) == 1)
+# define LZO_SIZEOF_INT 2
+# elif (__LZO_LSR(UINT_MAX,31) == 1)
+# define LZO_SIZEOF_INT 4
+# elif (__LZO_LSR(UINT_MAX,63) == 1)
+# define LZO_SIZEOF_INT 8
+# elif (__LZO_LSR(UINT_MAX,127) == 1)
+# define LZO_SIZEOF_INT 16
+# else
+# error "LZO_SIZEOF_INT"
+# endif
+#endif
+#if !defined(LZO_SIZEOF_LONG)
+# if (ULONG_MAX == LZO_0xffffffffL)
+# define LZO_SIZEOF_LONG 4
+# elif (__LZO_LSR(ULONG_MAX,7) == 1)
+# define LZO_SIZEOF_LONG 1
+# elif (__LZO_LSR(ULONG_MAX,15) == 1)
+# define LZO_SIZEOF_LONG 2
+# elif (__LZO_LSR(ULONG_MAX,31) == 1)
+# define LZO_SIZEOF_LONG 4
+# elif (__LZO_LSR(ULONG_MAX,63) == 1)
+# define LZO_SIZEOF_LONG 8
+# elif (__LZO_LSR(ULONG_MAX,127) == 1)
+# define LZO_SIZEOF_LONG 16
+# else
+# error "LZO_SIZEOF_LONG"
+# endif
+#endif
+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
+# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__)
+# if (LZO_CC_GNUC >= 0x030300ul)
+# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0)
+# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG
+# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1)
+# define LZO_SIZEOF_LONG_LONG 4
+# endif
+# endif
+# endif
+#endif
+#endif
+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
+#if (LZO_ARCH_I086 && LZO_CC_DMC)
+#elif (LZO_CC_CILLY) && defined(__GNUC__)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_OS_WIN64 || defined(_WIN64))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_ARCH_I386 && (LZO_CC_DMC))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700)))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__)))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC))
+# define LZO_SIZEOF___INT64 8
+#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520)))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100)))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2)
+#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define LZO_SIZEOF_LONG_LONG 8
+#endif
+#endif
+#endif
+#if defined(__cplusplus) && defined(LZO_CC_GNUC)
+# if (LZO_CC_GNUC < 0x020800ul)
+# undef LZO_SIZEOF_LONG_LONG
+# endif
+#endif
+#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
+# undef LZO_SIZEOF_LONG_LONG
+#endif
+#if !defined(LZO_SIZEOF_VOID_P)
+#if (LZO_ARCH_I086)
+# define __LZO_WORDSIZE 2
+# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM)
+# define LZO_SIZEOF_VOID_P 2
+# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE)
+# define LZO_SIZEOF_VOID_P 4
+# else
+# error "LZO_MM"
+# endif
+#elif (LZO_ARCH_AVR || LZO_ARCH_Z80)
+# define __LZO_WORDSIZE 1
+# define LZO_SIZEOF_VOID_P 2
+#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430)
+# define LZO_SIZEOF_VOID_P 2
+#elif (LZO_ARCH_H8300)
+# if defined(__NORMAL_MODE__)
+# define __LZO_WORDSIZE 4
+# define LZO_SIZEOF_VOID_P 2
+# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+# define __LZO_WORDSIZE 4
+# define LZO_SIZEOF_VOID_P 4
+# else
+# define __LZO_WORDSIZE 2
+# define LZO_SIZEOF_VOID_P 2
+# endif
+# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4)
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT
+# endif
+#elif (LZO_ARCH_M16C)
+# define __LZO_WORDSIZE 2
+# if defined(__m32c_cpu__) || defined(__m32cm_cpu__)
+# define LZO_SIZEOF_VOID_P 4
+# else
+# define LZO_SIZEOF_VOID_P 2
+# endif
+#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+# define __LZO_WORDSIZE 8
+# define LZO_SIZEOF_VOID_P 4
+#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
+# define __LZO_WORDSIZE 8
+# define LZO_SIZEOF_VOID_P 8
+#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+#elif (LZO_OS_OS400 || defined(__OS400__))
+# define __LZO_WORDSIZE LZO_SIZEOF_LONG
+# define LZO_SIZEOF_VOID_P 16
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+# define LZO_SIZEOF_VOID_P 8
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+#elif (LZO_ARCH_SPU)
+# if 0
+# define __LZO_WORDSIZE 16
+# endif
+# define LZO_SIZEOF_VOID_P 4
+#else
+# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
+#endif
+#endif
+#if !defined(LZO_WORDSIZE)
+# if defined(__LZO_WORDSIZE)
+# define LZO_WORDSIZE __LZO_WORDSIZE
+# else
+# define LZO_WORDSIZE LZO_SIZEOF_VOID_P
+# endif
+#endif
+#if !defined(LZO_SIZEOF_SIZE_T)
+#if (LZO_ARCH_I086 || LZO_ARCH_M16C)
+# define LZO_SIZEOF_SIZE_T 2
+#else
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P
+#endif
+#endif
+#if !defined(LZO_SIZEOF_PTRDIFF_T)
+#if (LZO_ARCH_I086)
+# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE)
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P
+# elif (LZO_MM_COMPACT || LZO_MM_LARGE)
+# if (LZO_CC_BORLANDC || LZO_CC_TURBOC)
+# define LZO_SIZEOF_PTRDIFF_T 4
+# else
+# define LZO_SIZEOF_PTRDIFF_T 2
+# endif
+# else
+# error "LZO_MM"
+# endif
+#else
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T
+#endif
+#endif
+#if defined(LZO_ABI_NEUTRAL_ENDIAN)
+# undef LZO_ABI_BIG_ENDIAN
+# undef LZO_ABI_LITTLE_ENDIAN
+#elif !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN)
+#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif (LZO_ARCH_M68K || LZO_ARCH_S390)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__)
+# if (__LITTLE_ENDIAN__ == 1)
+# define LZO_ABI_LITTLE_ENDIAN 1
+# else
+# define LZO_ABI_BIG_ENDIAN 1
+# endif
+#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#endif
+#endif
+#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN)
+# error "this should not happen"
+#endif
+#if defined(LZO_ABI_BIG_ENDIAN)
+# define LZO_INFO_ABI_ENDIAN "be"
+#elif defined(LZO_ABI_LITTLE_ENDIAN)
+# define LZO_INFO_ABI_ENDIAN "le"
+#elif defined(LZO_ABI_NEUTRAL_ENDIAN)
+# define LZO_INFO_ABI_ENDIAN "neutral"
+#endif
+#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
+# define LZO_ABI_I8LP16 1
+# define LZO_INFO_ABI_PM "i8lp16"
+#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
+# define LZO_ABI_ILP16 1
+# define LZO_INFO_ABI_PM "ilp16"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4)
+# define LZO_ABI_ILP32 1
+# define LZO_INFO_ABI_PM "ilp32"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8)
+# define LZO_ABI_LLP64 1
+# define LZO_INFO_ABI_PM "llp64"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
+# define LZO_ABI_LP64 1
+# define LZO_INFO_ABI_PM "lp64"
+#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
+# define LZO_ABI_ILP64 1
+# define LZO_INFO_ABI_PM "ilp64"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4)
+# define LZO_ABI_IP32L64 1
+# define LZO_INFO_ABI_PM "ip32l64"
+#endif
+#if !defined(__LZO_LIBC_OVERRIDE)
+#if defined(LZO_LIBC_NAKED)
+# define LZO_INFO_LIBC "naked"
+#elif defined(LZO_LIBC_FREESTANDING)
+# define LZO_INFO_LIBC "freestanding"
+#elif defined(LZO_LIBC_MOSTLY_FREESTANDING)
+# define LZO_INFO_LIBC "mfreestanding"
+#elif defined(LZO_LIBC_ISOC90)
+# define LZO_INFO_LIBC "isoc90"
+#elif defined(LZO_LIBC_ISOC99)
+# define LZO_INFO_LIBC "isoc99"
+#elif defined(__dietlibc__)
+# define LZO_LIBC_DIETLIBC 1
+# define LZO_INFO_LIBC "dietlibc"
+#elif defined(_NEWLIB_VERSION)
+# define LZO_LIBC_NEWLIB 1
+# define LZO_INFO_LIBC "newlib"
+#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__)
+# if defined(__UCLIBC_SUBLEVEL__)
+# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__)
+# else
+# define LZO_LIBC_UCLIBC 0x00090bL
+# endif
+# define LZO_INFO_LIBC "uclibc"
+#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__)
+# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100)
+# define LZO_INFO_LIBC "glibc"
+#elif (LZO_CC_MWERKS) && defined(__MSL__)
+# define LZO_LIBC_MSL __MSL__
+# define LZO_INFO_LIBC "msl"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+# define LZO_LIBC_ISOC90 1
+# define LZO_INFO_LIBC "isoc90"
+#else
+# define LZO_LIBC_DEFAULT 1
+# define LZO_INFO_LIBC "default"
+#endif
+#endif
+#if !defined(__lzo_gnuc_extension__)
+#if (LZO_CC_GNUC >= 0x020800ul)
+# define __lzo_gnuc_extension__ __extension__
+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_gnuc_extension__ __extension__
+#else
+# define __lzo_gnuc_extension__
+#endif
+#endif
+#if !defined(__lzo_ua_volatile)
+# define __lzo_ua_volatile volatile
+#endif
+#if !defined(__lzo_alignof)
+#if (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700))
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_alignof(e) __alignof(e)
+#endif
+#endif
+#if defined(__lzo_alignof)
+# define __lzo_HAVE_alignof 1
+#endif
+#if !defined(__lzo_constructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_constructor __attribute__((__constructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_constructor __attribute__((__constructor__))
+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_constructor __attribute__((__constructor__))
+#endif
+#endif
+#if defined(__lzo_constructor)
+# define __lzo_HAVE_constructor 1
+#endif
+#if !defined(__lzo_destructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_destructor __attribute__((__destructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_destructor __attribute__((__destructor__))
+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_destructor __attribute__((__destructor__))
+#endif
+#endif
+#if defined(__lzo_destructor)
+# define __lzo_HAVE_destructor 1
+#endif
+#if defined(__lzo_HAVE_destructor) && !defined(__lzo_HAVE_constructor)
+# error "this should not happen"
+#endif
+#if !defined(__lzo_inline)
+#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295))
+#elif defined(__cplusplus)
+# define __lzo_inline inline
+#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
+# define __lzo_inline __inline
+#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_inline __inline__
+#elif (LZO_CC_DMC)
+# define __lzo_inline __inline
+#elif (LZO_CC_INTELC)
+# define __lzo_inline __inline
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405))
+# define __lzo_inline __inline
+#elif (LZO_CC_MSC && (_MSC_VER >= 900))
+# define __lzo_inline __inline
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define __lzo_inline inline
+#endif
+#endif
+#if defined(__lzo_inline)
+# define __lzo_HAVE_inline 1
+#else
+# define __lzo_inline
+#endif
+#if !defined(__lzo_forceinline)
+#if (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
+# define __lzo_forceinline __forceinline
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+# define __lzo_forceinline __forceinline
+#endif
+#endif
+#if defined(__lzo_forceinline)
+# define __lzo_HAVE_forceinline 1
+#else
+# define __lzo_forceinline
+#endif
+#if !defined(__lzo_noinline)
+#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul)
+# define __lzo_noinline __attribute__((__noinline__,__used__))
+#elif (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC)
+# define __lzo_noinline __declspec(noinline)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_noinline __declspec(noinline)
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64))
+# if defined(__cplusplus)
+# else
+# define __lzo_noinline __declspec(noinline)
+# endif
+#endif
+#endif
+#if defined(__lzo_noinline)
+# define __lzo_HAVE_noinline 1
+#else
+# define __lzo_noinline
+#endif
+#if (defined(__lzo_HAVE_forceinline) || defined(__lzo_HAVE_noinline)) && !defined(__lzo_HAVE_inline)
+# error "this should not happen"
+#endif
+#if !defined(__lzo_noreturn)
+#if (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
+# define __lzo_noreturn __declspec(noreturn)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+# define __lzo_noreturn __declspec(noreturn)
+#endif
+#endif
+#if defined(__lzo_noreturn)
+# define __lzo_HAVE_noreturn 1
+#else
+# define __lzo_noreturn
+#endif
+#if !defined(__lzo_nothrow)
+#if (LZO_CC_GNUC >= 0x030300ul)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus)
+# define __lzo_nothrow __declspec(nothrow)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus)
+# define __lzo_nothrow __declspec(nothrow)
+#endif
+#endif
+#if defined(__lzo_nothrow)
+# define __lzo_HAVE_nothrow 1
+#else
+# define __lzo_nothrow
+#endif
+#if !defined(__lzo_restrict)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_LLVM)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_MSC && (_MSC_VER >= 1400))
+# define __lzo_restrict __restrict
+#endif
+#endif
+#if defined(__lzo_restrict)
+# define __lzo_HAVE_restrict 1
+#else
+# define __lzo_restrict
+#endif
+#if !defined(__lzo_likely) && !defined(__lzo_unlikely)
+#if (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#endif
+#endif
+#if defined(__lzo_likely)
+# define __lzo_HAVE_likely 1
+#else
+# define __lzo_likely(e) (e)
+#endif
+#if defined(__lzo_unlikely)
+# define __lzo_HAVE_unlikely 1
+#else
+# define __lzo_unlikely(e) (e)
+#endif
+#if !defined(LZO_UNUSED)
+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define LZO_UNUSED(var) ((void) &var)
+# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC)
+# define LZO_UNUSED(var) if (&var) ; else
+# elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNUSED(var) ((void) var)
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_UNUSED(var) if (&var) ; else
+# elif (LZO_CC_KEILC)
+# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];}
+# elif (LZO_CC_PACIFICC)
+# define LZO_UNUSED(var) ((void) sizeof(var))
+# elif (LZO_CC_WATCOMC) && defined(__cplusplus)
+# define LZO_UNUSED(var) ((void) var)
+# else
+# define LZO_UNUSED(var) ((void) &var)
+# endif
+#endif
+#if !defined(LZO_UNUSED_FUNC)
+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define LZO_UNUSED_FUNC(func) ((void) func)
+# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC)
+# define LZO_UNUSED_FUNC(func) if (func) ; else
+# elif (LZO_CC_LLVM)
+# define LZO_UNUSED_FUNC(func) ((void) &func)
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_UNUSED_FUNC(func) if (func) ; else
+# elif (LZO_CC_MSC)
+# define LZO_UNUSED_FUNC(func) ((void) &func)
+# elif (LZO_CC_KEILC || LZO_CC_PELLESC)
+# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];}
+# else
+# define LZO_UNUSED_FUNC(func) ((void) func)
+# endif
+#endif
+#if !defined(LZO_UNUSED_LABEL)
+# if (LZO_CC_WATCOMC) && defined(__cplusplus)
+# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
+# elif (LZO_CC_INTELC || LZO_CC_WATCOMC)
+# define LZO_UNUSED_LABEL(l) if (0) goto l
+# else
+# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
+# endif
+#endif
+#if !defined(LZO_DEFINE_UNINITIALIZED_VAR)
+# if 0
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var
+# elif 0 && (LZO_CC_GNUC)
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var
+# else
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init
+# endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER)
+# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)];
+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
+# else
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)];
+# endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT)
+# if (LZO_CC_AZTECC)
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];}
+# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# else
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];}
+# endif
+#endif
+#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+# define __lzo_cdecl __cdecl
+# define __lzo_cdecl_atexit
+# define __lzo_cdecl_main __cdecl
+# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+# define __lzo_cdecl_qsort __pascal
+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+# define __lzo_cdecl_qsort _stdcall
+# else
+# define __lzo_cdecl_qsort __cdecl
+# endif
+# elif (LZO_CC_WATCOMC)
+# define __lzo_cdecl __cdecl
+# else
+# define __lzo_cdecl __cdecl
+# define __lzo_cdecl_atexit __cdecl
+# define __lzo_cdecl_main __cdecl
+# define __lzo_cdecl_qsort __cdecl
+# endif
+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC)
+# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+# define __lzo_cdecl_sighandler __pascal
+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+# define __lzo_cdecl_sighandler _stdcall
+# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)
+# define __lzo_cdecl_sighandler __clrcall
+# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))
+# if defined(_DLL)
+# define __lzo_cdecl_sighandler _far _cdecl _loadds
+# elif defined(_MT)
+# define __lzo_cdecl_sighandler _far _cdecl
+# else
+# define __lzo_cdecl_sighandler _cdecl
+# endif
+# else
+# define __lzo_cdecl_sighandler __cdecl
+# endif
+#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC)
+# define __lzo_cdecl __cdecl
+#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC))
+# define __lzo_cdecl cdecl
+#endif
+#if !defined(__lzo_cdecl)
+# define __lzo_cdecl
+#endif
+#if !defined(__lzo_cdecl_atexit)
+# define __lzo_cdecl_atexit
+#endif
+#if !defined(__lzo_cdecl_main)
+# define __lzo_cdecl_main
+#endif
+#if !defined(__lzo_cdecl_qsort)
+# define __lzo_cdecl_qsort
+#endif
+#if !defined(__lzo_cdecl_sighandler)
+# define __lzo_cdecl_sighandler
+#endif
+#if !defined(__lzo_cdecl_va)
+# define __lzo_cdecl_va __lzo_cdecl
+#endif
+#if !defined(LZO_CFG_NO_WINDOWS_H)
+#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
+# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
+# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
+# else
+# define LZO_HAVE_WINDOWS_H 1
+# endif
+#endif
+#endif
+#if (LZO_ARCH_ALPHA)
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_AVOID_SHORT 1
+# define LZO_OPT_AVOID_USHORT 1
+#elif (LZO_ARCH_AMD64)
+# define LZO_OPT_AVOID_INT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# define LZO_OPT_UNALIGNED64 1
+#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB)
+#elif (LZO_ARCH_ARM)
+# define LZO_OPT_AVOID_SHORT 1
+# define LZO_OPT_AVOID_USHORT 1
+#elif (LZO_ARCH_CRIS)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+#elif (LZO_ARCH_I386)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+#elif (LZO_ARCH_IA64)
+# define LZO_OPT_AVOID_INT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_PREFER_POSTINC 1
+#elif (LZO_ARCH_M68K)
+# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_PREFER_PREDEC 1
+# if defined(__mc68020__) && !defined(__mcoldfire__)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# endif
+#elif (LZO_ARCH_MIPS)
+# define LZO_OPT_AVOID_UINT_INDEX 1
+#elif (LZO_ARCH_POWERPC)
+# define LZO_OPT_PREFER_PREINC 1
+# define LZO_OPT_PREFER_PREDEC 1
+# if defined(LZO_ABI_BIG_ENDIAN)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# endif
+#elif (LZO_ARCH_S390)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# if (LZO_SIZEOF_SIZE_T == 8)
+# define LZO_OPT_UNALIGNED64 1
+# endif
+#elif (LZO_ARCH_SH)
+# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_PREFER_PREDEC 1
+#endif
+#if !defined(LZO_CFG_NO_INLINE_ASM)
+#if defined(LZO_CC_LLVM)
+# define LZO_CFG_NO_INLINE_ASM 1
+#endif
+#endif
+#if !defined(LZO_CFG_NO_UNALIGNED)
+#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC)
+# define LZO_CFG_NO_UNALIGNED 1
+#endif
+#endif
+#if defined(LZO_CFG_NO_UNALIGNED)
+# undef LZO_OPT_UNALIGNED16
+# undef LZO_OPT_UNALIGNED32
+# undef LZO_OPT_UNALIGNED64
+#endif
+#if defined(LZO_CFG_NO_INLINE_ASM)
+#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+# define LZO_ASM_SYNTAX_MSC 1
+#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+#elif (LZO_ARCH_I386 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+# define LZO_ASM_SYNTAX_GNUC 1
+#elif (LZO_ARCH_AMD64 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+# define LZO_ASM_SYNTAX_GNUC 1
+#endif
+#if (LZO_ASM_SYNTAX_GNUC)
+#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul))
+# define __LZO_ASM_CLOBBER "ax"
+#elif (LZO_CC_INTELC)
+# define __LZO_ASM_CLOBBER "memory"
+#else
+# define __LZO_ASM_CLOBBER "cc", "memory"
+#endif
+#endif
+#if defined(__LZO_INFOSTR_MM)
+#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM))
+# define __LZO_INFOSTR_MM ""
+#elif defined(LZO_INFO_MM)
+# define __LZO_INFOSTR_MM "." LZO_INFO_MM
+#else
+# define __LZO_INFOSTR_MM ""
+#endif
+#if defined(__LZO_INFOSTR_PM)
+#elif defined(LZO_INFO_ABI_PM)
+# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM
+#else
+# define __LZO_INFOSTR_PM ""
+#endif
+#if defined(__LZO_INFOSTR_ENDIAN)
+#elif defined(LZO_INFO_ABI_ENDIAN)
+# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN
+#else
+# define __LZO_INFOSTR_ENDIAN ""
+#endif
+#if defined(__LZO_INFOSTR_OSNAME)
+#elif defined(LZO_INFO_OS_CONSOLE)
+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE
+#elif defined(LZO_INFO_OS_POSIX)
+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX
+#else
+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS
+#endif
+#if defined(__LZO_INFOSTR_LIBC)
+#elif defined(LZO_INFO_LIBC)
+# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC
+#else
+# define __LZO_INFOSTR_LIBC ""
+#endif
+#if defined(__LZO_INFOSTR_CCVER)
+#elif defined(LZO_INFO_CCVER)
+# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER
+#else
+# define __LZO_INFOSTR_CCVER ""
+#endif
+#define LZO_INFO_STRING \
+ LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \
+ " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER
+
+#endif /* already included */
+
+/* vim:set ts=4 et: */
diff --git a/lzo/include/lzo/lzoutil.h b/lzo/include/lzo/lzoutil.h
new file mode 100644
index 00000000..c8089843
--- /dev/null
+++ b/lzo/include/lzo/lzoutil.h
@@ -0,0 +1,73 @@
+/* lzoutil.h -- utilitiy functions for use by applications [DEPRECATED]
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZOUTIL_H_INCLUDED
+#define __LZOUTIL_H_INCLUDED
+
+#ifndef __LZOCONF_H_INCLUDED
+#include "lzoconf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+// LZO-v1 deprecated macros (which were used in the old example programs)
+// DO NOT USE
+************************************************************************/
+
+#define lzo_alloc(a,b) (malloc((a)*(b)))
+#define lzo_malloc(a) (malloc(a))
+#define lzo_free(a) (free(a))
+
+#define lzo_fread(f,b,s) (fread(b,1,s,f))
+#define lzo_fwrite(f,b,s) (fwrite(b,1,s,f))
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/lzo/prepcore.c b/lzo/prepcore.c
new file mode 100644
index 00000000..1d400670
--- /dev/null
+++ b/lzo/prepcore.c
@@ -0,0 +1,385 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ This file is based in part on:
+
+ precomp2.c -- example program: how to generate pre-compressed data
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+#include "lzo/lzoconf.h"
+#include "lzo/lzo1x.h"
+
+LZO_EXTERN(int)
+lzo1x_999_compress_internal(const lzo_bytep in, lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len,
+ lzo_callback_p cb,
+ int try_lazy,
+ lzo_uint good_length,
+ lzo_uint max_lazy,
+ lzo_uint nice_length,
+ lzo_uint max_chain, lzo_uint32 flags);
+
+LZO_EXTERN(int)
+lzo1y_999_compress_internal(const lzo_bytep in, lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len,
+ lzo_callback_p cb,
+ int try_lazy,
+ lzo_uint good_length,
+ lzo_uint max_lazy,
+ lzo_uint nice_length,
+ lzo_uint max_chain, lzo_uint32 flags);
+
+#define PARANOID 1
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef __GNUC__
+# define noreturn void __attribute__((noreturn))
+#else
+# define noreturn void
+#endif
+
+struct prefix {
+ uint32_t pfx_start;
+ uint32_t pfx_compressed;
+ uint32_t pfx_cdatalen;
+ uint32_t pfx_checksum;
+ uint32_t pfx_maxlma;
+};
+
+static inline uint32_t get_32(const uint32_t * p)
+{
+#if defined(__i386__) || defined(__x86_64__)
+ /* Littleendian and unaligned-capable */
+ return *p;
+#else
+ const uint8_t *pp = (const uint8_t *)p;
+ return (uint32_t) pp[0] + ((uint32_t) pp[1] << 8) +
+ ((uint32_t) pp[2] << 16) + ((uint32_t) pp[3] << 24);
+#endif
+}
+
+static inline void set_32(uint32_t * p, uint32_t v)
+{
+#if defined(__i386__) || defined(__x86_64__)
+ /* Littleendian and unaligned-capable */
+ *p = v;
+#else
+ uint8_t *pp = (uint8_t *) p;
+ pp[0] = (v & 0xff);
+ pp[1] = ((v >> 8) & 0xff);
+ pp[2] = ((v >> 16) & 0xff);
+ pp[3] = ((v >> 24) & 0xff);
+#endif
+}
+
+const char *progname = NULL;
+const char *in_name = NULL;
+const char *out_name = NULL;
+
+static noreturn error(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: ", progname);
+ if (in_name)
+ fprintf(stderr, "%s: ", in_name);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+
+ exit(1);
+}
+
+static void *xzalloc(size_t n)
+{
+ void *p = calloc(n, 1);
+ if (!p)
+ error("out of memory");
+ return p;
+}
+
+/*************************************************************************
+//
+**************************************************************************/
+
+int main(int argc, char *argv[])
+{
+ int r;
+ int lazy;
+ const int max_try_lazy = 5;
+ const lzo_uint big = 65536L; /* can result in very slow compression */
+ const lzo_uint32 flags = 0x1;
+
+ lzo_bytep in;
+ lzo_bytep infile;
+ lzo_uint in_len, infile_len, start, offset, soff;
+
+ lzo_bytep out;
+ lzo_uint out_bufsize;
+ lzo_uint out_len = 0;
+ lzo_uint outfile_len;
+
+ lzo_bytep test;
+
+ lzo_byte wrkmem[LZO1X_999_MEM_COMPRESS];
+
+ lzo_uint best_len;
+ int best_lazy = -1;
+
+ lzo_uint orig_len;
+ lzo_uint32 uncompressed_checksum;
+ lzo_uint32 compressed_checksum;
+
+ FILE *f;
+ long l;
+
+ struct prefix *prefix;
+
+ progname = argv[0];
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s file output-file\n", progname);
+ exit(1);
+ }
+ in_name = argv[1];
+ if (argc > 2)
+ out_name = argv[2];
+
+/*
+ * Step 1: initialize the LZO library
+ */
+ if (lzo_init() != LZO_E_OK)
+ error("internal error - lzo_init() failed!");
+
+/*
+ * Step 3: open the input file
+ */
+ f = fopen(in_name, "rb");
+ if (!f)
+ error("cannot open file: %s", strerror(errno));
+
+ fseek(f, 0, SEEK_END);
+ l = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ if (l <= 0) {
+ error("empty file", progname, in_name);
+ fclose(f);
+ exit(1);
+ }
+ infile_len = (lzo_uint) l;
+ out_bufsize = infile_len + infile_len / 16 + 64 + 3 + 2048;
+
+/*
+ * Step 4: allocate compression buffers and read the file
+ */
+ infile = xzalloc(infile_len);
+ out = xzalloc(out_bufsize);
+ infile_len = fread(infile, 1, infile_len, f);
+ fclose(f);
+
+/*
+ * Select the portion which is for compression...
+ */
+ prefix = (struct prefix *)infile;
+ start = get_32(&prefix->pfx_start);
+ offset = get_32(&prefix->pfx_compressed);
+ in = infile + offset;
+ in_len = infile_len - offset;
+ best_len = in_len;
+
+/*
+ * Step 5: compute a checksum of the uncompressed data
+ */
+ uncompressed_checksum = lzo_adler32(0, NULL, 0);
+ uncompressed_checksum = lzo_adler32(uncompressed_checksum, in, in_len);
+
+/*
+ * Step 6a: compress from `in' to `out' with LZO1X-999
+ */
+ for (lazy = 0; lazy <= max_try_lazy; lazy++) {
+ out_len = out_bufsize;
+ r = lzo1x_999_compress_internal(in, in_len, out, &out_len, wrkmem,
+ NULL, 0, 0,
+ lazy, big, big, big, big, flags);
+ if (r != LZO_E_OK)
+ /* this should NEVER happen */
+ error("internal error - compression failed: %d", r);
+
+ if (out_len < best_len) {
+ best_len = out_len;
+ best_lazy = lazy;
+ }
+ }
+
+/*
+ * Step 7: check if compressible
+ */
+ if (best_len >= in_len) {
+ fprintf(stderr, "%s: %s: this file contains incompressible data.",
+ progname, in_name);
+ /* do it anyway */
+ }
+
+/*
+ * Step 8: compress data again using the best compressor found
+ */
+ out_len = out_bufsize;
+ r = lzo1x_999_compress_internal(in, in_len, out, &out_len, wrkmem,
+ NULL, 0, 0,
+ best_lazy, big, big, big, big, flags);
+ assert(r == LZO_E_OK);
+ assert(out_len == best_len);
+
+/*
+ * Step 9: optimize compressed data (compressed data is in `out' buffer)
+ */
+#if 1
+ /* Optimization does not require any data in the buffer that will
+ * hold the uncompressed data. To prove this, we clear the buffer.
+ */
+ memset(in, 0, in_len);
+#endif
+
+ orig_len = in_len;
+ r = lzo1x_optimize(out, out_len, in, &orig_len, NULL);
+ if (r != LZO_E_OK || orig_len != in_len) {
+ /* this should NEVER happen */
+ error("internal error - optimization failed: %d", r);
+ }
+
+/*
+ * Step 10: compute a checksum of the compressed data
+ */
+ compressed_checksum = lzo_adler32(0, NULL, 0);
+ compressed_checksum = lzo_adler32(compressed_checksum, out, out_len);
+
+/*
+ * Step 11: write compressed data to a file
+ */
+ /* Make sure we have up to 2048 bytes of zero after the output */
+ memset(out + out_len, 0, 2048);
+
+ outfile_len = out_len;
+
+ soff = get_32(&prefix->pfx_cdatalen);
+ set_32((uint32_t *) (infile + soff), out_len);
+
+ soff = get_32(&prefix->pfx_checksum);
+ if (soff) {
+ /* ISOLINUX padding and checksumming */
+ uint32_t csum = 0;
+ unsigned int ptr;
+ outfile_len =
+ ((offset - start + out_len + 2047) & ~2047) - (offset - start);
+ for (ptr = 64; ptr < offset; ptr += 4)
+ csum += get_32((uint32_t *) (infile + ptr));
+ for (ptr = 0; ptr < outfile_len; ptr += 4)
+ csum += get_32((uint32_t *) (out + ptr));
+
+ set_32((uint32_t *) (infile + soff), offset - start + outfile_len);
+ set_32((uint32_t *) (infile + soff + 4), csum);
+ }
+
+ if (offset+outfile_len > get_32(&prefix->pfx_maxlma))
+ error("output too big (%lu, max %lu)",
+ (unsigned long)offset+outfile_len,
+ (unsigned long)get_32(&prefix->pfx_maxlma));
+
+ f = fopen(out_name, "wb");
+ if (!f)
+ error("cannot open output file %s: %s", out_name, strerror(errno));
+
+ if (fwrite(infile + start, 1, offset - start, f) != offset - start ||
+ fwrite(out, 1, outfile_len, f) != outfile_len || fclose(f))
+ error("write error");
+
+/*
+ * Step 12: verify decompression
+ */
+#ifdef PARANOID
+ orig_len = in_len * 2;
+ test = xzalloc(orig_len);
+ r = lzo1x_decompress_safe(out, out_len, test, &orig_len, NULL);
+
+ if (r != LZO_E_OK || orig_len != in_len) {
+ /* this should NEVER happen */
+ error("internal error - decompression failed: %d", r);
+ }
+
+ if (memcmp(test, in, in_len)) {
+ /* this should NEVER happen */
+ error("internal error - decompression data error");
+ }
+
+ /* Now you could also verify decompression under similar conditions as in
+ * your application, e.g. overlapping assembler decompression etc.
+ */
+
+ free(test);
+#endif
+
+ free(infile);
+ free(out);
+
+ return 0;
+}
diff --git a/lzo/src/compr1b.h b/lzo/src/compr1b.h
new file mode 100644
index 00000000..be0d2005
--- /dev/null
+++ b/lzo/src/compr1b.h
@@ -0,0 +1,81 @@
+/* compr1b.h --
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#define LZO_NEED_DICT_H
+#include "config1b.h"
+
+
+#if !defined(COMPRESS_ID)
+#define COMPRESS_ID LZO_CPP_ECONCAT2(DD_BITS,CLEVEL)
+#endif
+
+
+#include "lzo1b_c.ch"
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#define LZO_COMPRESS \
+ LZO_CPP_ECONCAT3(lzo1b_,COMPRESS_ID,_compress)
+
+#define LZO_COMPRESS_FUNC \
+ LZO_CPP_ECONCAT3(_lzo1b_,COMPRESS_ID,_compress_func)
+
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+const lzo_compress_t LZO_COMPRESS_FUNC = do_compress;
+
+LZO_PUBLIC(int)
+LZO_COMPRESS ( const lzo_bytep in, lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+{
+ return _lzo1b_do_compress(in,in_len,out,out_len,wrkmem,do_compress);
+}
+
+/*
+vi:ts=4:et
+*/
diff --git a/lzo/src/compr1c.h b/lzo/src/compr1c.h
new file mode 100644
index 00000000..8b29f9ae
--- /dev/null
+++ b/lzo/src/compr1c.h
@@ -0,0 +1,81 @@
+/* compr1c.h --
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#define LZO_NEED_DICT_H
+#include "config1c.h"
+
+
+#if !defined(COMPRESS_ID)
+#define COMPRESS_ID LZO_CPP_ECONCAT2(DD_BITS,CLEVEL)
+#endif
+
+
+#include "lzo1b_c.ch"
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#define LZO_COMPRESS \
+ LZO_CPP_ECONCAT3(lzo1c_,COMPRESS_ID,_compress)
+
+#define LZO_COMPRESS_FUNC \
+ LZO_CPP_ECONCAT3(_lzo1c_,COMPRESS_ID,_compress_func)
+
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+const lzo_compress_t LZO_COMPRESS_FUNC = do_compress;
+
+LZO_PUBLIC(int)
+LZO_COMPRESS ( const lzo_bytep in, lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+{
+ return _lzo1c_do_compress(in,in_len,out,out_len,wrkmem,do_compress);
+}
+
+/*
+vi:ts=4:et
+*/
diff --git a/lzo/src/config1x.h b/lzo/src/config1x.h
new file mode 100644
index 00000000..e123bf3d
--- /dev/null
+++ b/lzo/src/config1x.h
@@ -0,0 +1,118 @@
+/* config1x.h -- configuration for the LZO1X algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the library and is subject
+ to change.
+ */
+
+
+#ifndef __LZO_CONFIG1X_H
+#define __LZO_CONFIG1X_H
+
+#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z)
+# define LZO1X
+#endif
+
+#include "lzo_conf.h"
+#if !defined(__LZO_IN_MINILZO)
+#include "lzo/lzo1x.h"
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#define LZO_EOF_CODE
+#undef LZO_DETERMINISTIC
+
+#define M1_MAX_OFFSET 0x0400
+#ifndef M2_MAX_OFFSET
+#define M2_MAX_OFFSET 0x0800
+#endif
+#define M3_MAX_OFFSET 0x4000
+#define M4_MAX_OFFSET 0xbfff
+
+#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET)
+
+#define M1_MIN_LEN 2
+#define M1_MAX_LEN 2
+#define M2_MIN_LEN 3
+#ifndef M2_MAX_LEN
+#define M2_MAX_LEN 8
+#endif
+#define M3_MIN_LEN 3
+#define M3_MAX_LEN 33
+#define M4_MIN_LEN 3
+#define M4_MAX_LEN 9
+
+#define M1_MARKER 0
+#define M2_MARKER 64
+#define M3_MARKER 32
+#define M4_MARKER 16
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#ifndef MIN_LOOKAHEAD
+#define MIN_LOOKAHEAD (M2_MAX_LEN + 1)
+#endif
+
+#if defined(LZO_NEED_DICT_H)
+
+#ifndef LZO_HASH
+#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B
+#endif
+#define DL_MIN_LEN M2_MIN_LEN
+#include "lzo_dict.h"
+
+#endif
+
+
+
+#endif /* already included */
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo1_d.ch b/lzo/src/lzo1_d.ch
new file mode 100644
index 00000000..c1dad39f
--- /dev/null
+++ b/lzo/src/lzo1_d.ch
@@ -0,0 +1,155 @@
+/* lzo1_d.ch -- common decompression stuff
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+
+#if defined(LZO_TEST_OVERRUN)
+# if !defined(LZO_TEST_OVERRUN_INPUT)
+# define LZO_TEST_OVERRUN_INPUT 2
+# endif
+# if !defined(LZO_TEST_OVERRUN_OUTPUT)
+# define LZO_TEST_OVERRUN_OUTPUT 2
+# endif
+# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+# define LZO_TEST_OVERRUN_LOOKBEHIND
+# endif
+#endif
+
+
+/***********************************************************************
+// Overrun detection is internally handled by these macros:
+//
+// TEST_IP test input overrun at loop begin
+// NEED_IP test input overrun at every input byte
+//
+// TEST_OP test output overrun at loop begin
+// NEED_OP test output overrun at every output byte
+//
+// TEST_LB test match postion
+//
+// The fastest decompressor results when testing for no overruns
+// and using LZO_EOF_CODE.
+************************************************************************/
+
+#undef TEST_IP
+#undef TEST_OP
+#undef TEST_LB
+#undef TEST_LBO
+#undef NEED_IP
+#undef NEED_OP
+#undef HAVE_TEST_IP
+#undef HAVE_TEST_OP
+#undef HAVE_NEED_IP
+#undef HAVE_NEED_OP
+#undef HAVE_ANY_IP
+#undef HAVE_ANY_OP
+
+
+#if defined(LZO_TEST_OVERRUN_INPUT)
+# if (LZO_TEST_OVERRUN_INPUT >= 1)
+# define TEST_IP (ip < ip_end)
+# endif
+# if (LZO_TEST_OVERRUN_INPUT >= 2)
+# define NEED_IP(x) \
+ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_OVERRUN_OUTPUT)
+# if (LZO_TEST_OVERRUN_OUTPUT >= 1)
+# define TEST_OP (op <= op_end)
+# endif
+# if (LZO_TEST_OVERRUN_OUTPUT >= 2)
+# undef TEST_OP /* don't need both of the tests here */
+# define NEED_OP(x) \
+ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun
+# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun
+#else
+# define TEST_LB(m_pos) ((void) 0)
+# define TEST_LBO(m_pos,o) ((void) 0)
+#endif
+
+
+#if !defined(LZO_EOF_CODE) && !defined(TEST_IP)
+ /* if we have no EOF code, we have to test for the end of the input */
+# define TEST_IP (ip < ip_end)
+#endif
+
+
+#if defined(TEST_IP)
+# define HAVE_TEST_IP
+#else
+# define TEST_IP 1
+#endif
+#if defined(TEST_OP)
+# define HAVE_TEST_OP
+#else
+# define TEST_OP 1
+#endif
+
+#if defined(NEED_IP)
+# define HAVE_NEED_IP
+#else
+# define NEED_IP(x) ((void) 0)
+#endif
+#if defined(NEED_OP)
+# define HAVE_NEED_OP
+#else
+# define NEED_OP(x) ((void) 0)
+#endif
+
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
+# define HAVE_ANY_IP
+#endif
+#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP)
+# define HAVE_ANY_OP
+#endif
+
+
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo1x_1.c b/lzo/src/lzo1x_1.c
new file mode 100644
index 00000000..ac4b85cd
--- /dev/null
+++ b/lzo/src/lzo1x_1.c
@@ -0,0 +1,50 @@
+/* lzo1x_1.c -- LZO1X-1 compression
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#define LZO_NEED_DICT_H
+#define D_BITS 14
+#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
+#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
+
+#include "config1x.h"
+
+#define DO_COMPRESS lzo1x_1_compress
+
+#include "lzo1x_c.ch"
diff --git a/lzo/src/lzo1x_1k.c b/lzo/src/lzo1x_1k.c
new file mode 100644
index 00000000..e100ff19
--- /dev/null
+++ b/lzo/src/lzo1x_1k.c
@@ -0,0 +1,50 @@
+/* lzo1x_1k.c -- LZO1X-1(11) compression (needs only 8kB work memory)
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#define LZO_NEED_DICT_H
+#define D_BITS 11
+#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX2(p,3,5)) >> 5)
+#define D_INDEX2(d,p) d = d ^ D_MASK
+
+#include "config1x.h"
+
+#define DO_COMPRESS lzo1x_1_11_compress
+
+#include "lzo1x_c.ch"
diff --git a/lzo/src/lzo1x_1l.c b/lzo/src/lzo1x_1l.c
new file mode 100644
index 00000000..15718306
--- /dev/null
+++ b/lzo/src/lzo1x_1l.c
@@ -0,0 +1,50 @@
+/* lzo1x_1l.c -- LZO1X-1(12) compression
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#define LZO_NEED_DICT_H
+#define D_BITS 12
+#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX2(p,4,5)) >> 5)
+#define D_INDEX2(d,p) d = d ^ D_MASK
+
+#include "config1x.h"
+
+#define DO_COMPRESS lzo1x_1_12_compress
+
+#include "lzo1x_c.ch"
diff --git a/lzo/src/lzo1x_1o.c b/lzo/src/lzo1x_1o.c
new file mode 100644
index 00000000..979ca448
--- /dev/null
+++ b/lzo/src/lzo1x_1o.c
@@ -0,0 +1,50 @@
+/* lzo1x_1o.c -- LZO1X-1(15) compression
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#define LZO_NEED_DICT_H
+#define D_BITS 15
+#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
+#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
+
+#include "config1x.h"
+
+#define DO_COMPRESS lzo1x_1_15_compress
+
+#include "lzo1x_c.ch"
diff --git a/lzo/src/lzo1x_9x.c b/lzo/src/lzo1x_9x.c
new file mode 100644
index 00000000..b108bf8e
--- /dev/null
+++ b/lzo/src/lzo1x_9x.c
@@ -0,0 +1,881 @@
+/* lzo1x_9x.c -- implementation of the LZO1X-999 compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z)
+# define LZO1X
+#endif
+
+#if defined(LZO1X)
+# include "config1x.h"
+#elif defined(LZO1Y)
+# include "config1y.h"
+#elif defined(LZO1Z)
+# include "config1z.h"
+#else
+# error
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#define N M4_MAX_OFFSET /* size of ring buffer */
+#define THRESHOLD 1 /* lower limit for match length */
+#define F 2048 /* upper limit for match length */
+
+#define SWD_BEST_OFF (LZO_MAX3( M2_MAX_LEN, M3_MAX_LEN, M4_MAX_LEN ) + 1)
+
+#if defined(LZO1X)
+# define LZO_COMPRESS_T lzo1x_999_t
+# define lzo_swd_t lzo1x_999_swd_t
+#elif defined(LZO1Y)
+# define LZO_COMPRESS_T lzo1y_999_t
+# define lzo_swd_t lzo1y_999_swd_t
+# define lzo1x_999_compress_internal lzo1y_999_compress_internal
+# define lzo1x_999_compress_dict lzo1y_999_compress_dict
+# define lzo1x_999_compress_level lzo1y_999_compress_level
+# define lzo1x_999_compress lzo1y_999_compress
+#elif defined(LZO1Z)
+# define LZO_COMPRESS_T lzo1z_999_t
+# define lzo_swd_t lzo1z_999_swd_t
+# define lzo1x_999_compress_internal lzo1z_999_compress_internal
+# define lzo1x_999_compress_dict lzo1z_999_compress_dict
+# define lzo1x_999_compress_level lzo1z_999_compress_level
+# define lzo1x_999_compress lzo1z_999_compress
+#else
+# error
+#endif
+
+#if 0
+# define HEAD3(b,p) \
+ ((((((lzo_xint)b[p]<<3)^b[p+1])<<3)^b[p+2]) & (SWD_HSIZE-1))
+#endif
+#if 0 && defined(LZO_UNALIGNED_OK_4) && defined(LZO_ABI_LITTLE_ENDIAN)
+# define HEAD3(b,p) \
+ (((* (lzo_uint32p) &b[p]) ^ ((* (lzo_uint32p) &b[p])>>10)) & (SWD_HSIZE-1))
+#endif
+
+#include "lzo_mchw.ch"
+
+
+/* this is a public functions, but there is no prototype in a header file */
+LZO_EXTERN(int)
+lzo1x_999_compress_internal ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len,
+ lzo_callback_p cb,
+ int try_lazy,
+ lzo_uint good_length,
+ lzo_uint max_lazy,
+ lzo_uint nice_length,
+ lzo_uint max_chain,
+ lzo_uint32 flags );
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static lzo_bytep
+code_match ( LZO_COMPRESS_T *c, lzo_bytep op, lzo_uint m_len, lzo_uint m_off )
+{
+ lzo_uint x_len = m_len;
+ lzo_uint x_off = m_off;
+
+ c->match_bytes += (unsigned long) m_len;
+
+#if 0
+/*
+ static lzo_uint last_m_len = 0, last_m_off = 0;
+ static lzo_uint prev_m_off[4];
+ static int prev_m_off_ptr = 0;
+ int i;
+
+ //if (m_len >= 3 && m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
+ if (m_len >= 3 && m_len <= M2_MAX_LEN)
+ {
+ //if (m_len == last_m_len && m_off == last_m_off)
+ //printf("last_m_len + last_m_off\n");
+ //else
+ if (m_off == last_m_off)
+ printf("last_m_off\n");
+ else
+ {
+ for (i = 0; i < 4; i++)
+ if (m_off == prev_m_off[i])
+ printf("prev_m_off %d: %5ld\n",i,(long)m_off);
+ }
+ }
+ last_m_len = m_len;
+ last_m_off = prev_m_off[prev_m_off_ptr] = m_off;
+ prev_m_off_ptr = (prev_m_off_ptr + 1) & 3;
+*/
+#endif
+
+ assert(op > c->out);
+ if (m_len == 2)
+ {
+ assert(m_off <= M1_MAX_OFFSET);
+ assert(c->r1_lit > 0); assert(c->r1_lit < 4);
+ m_off -= 1;
+#if defined(LZO1Z)
+ *op++ = LZO_BYTE(M1_MARKER | (m_off >> 6));
+ *op++ = LZO_BYTE(m_off << 2);
+#else
+ *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2));
+ *op++ = LZO_BYTE(m_off >> 2);
+#endif
+ c->m1a_m++;
+ }
+#if defined(LZO1Z)
+ else if (m_len <= M2_MAX_LEN && (m_off <= M2_MAX_OFFSET || m_off == c->last_m_off))
+#else
+ else if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
+#endif
+ {
+ assert(m_len >= 3);
+#if defined(LZO1X)
+ m_off -= 1;
+ *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
+ *op++ = LZO_BYTE(m_off >> 3);
+ assert(op[-2] >= M2_MARKER);
+#elif defined(LZO1Y)
+ m_off -= 1;
+ *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2));
+ *op++ = LZO_BYTE(m_off >> 2);
+ assert(op[-2] >= M2_MARKER);
+#elif defined(LZO1Z)
+ if (m_off == c->last_m_off)
+ *op++ = LZO_BYTE(((m_len - 1) << 5) | (0x700 >> 6));
+ else
+ {
+ m_off -= 1;
+ *op++ = LZO_BYTE(((m_len - 1) << 5) | (m_off >> 6));
+ *op++ = LZO_BYTE(m_off << 2);
+ }
+#endif
+ c->m2_m++;
+ }
+ else if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET && c->r1_lit >= 4)
+ {
+ assert(m_len == 3);
+ assert(m_off > M2_MAX_OFFSET);
+ m_off -= 1 + M2_MAX_OFFSET;
+#if defined(LZO1Z)
+ *op++ = LZO_BYTE(M1_MARKER | (m_off >> 6));
+ *op++ = LZO_BYTE(m_off << 2);
+#else
+ *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2));
+ *op++ = LZO_BYTE(m_off >> 2);
+#endif
+ c->m1b_m++;
+ }
+ else if (m_off <= M3_MAX_OFFSET)
+ {
+ assert(m_len >= 3);
+ m_off -= 1;
+ if (m_len <= M3_MAX_LEN)
+ *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
+ else
+ {
+ m_len -= M3_MAX_LEN;
+ *op++ = M3_MARKER | 0;
+ while (m_len > 255)
+ {
+ m_len -= 255;
+ *op++ = 0;
+ }
+ assert(m_len > 0);
+ *op++ = LZO_BYTE(m_len);
+ }
+#if defined(LZO1Z)
+ *op++ = LZO_BYTE(m_off >> 6);
+ *op++ = LZO_BYTE(m_off << 2);
+#else
+ *op++ = LZO_BYTE(m_off << 2);
+ *op++ = LZO_BYTE(m_off >> 6);
+#endif
+ c->m3_m++;
+ }
+ else
+ {
+ lzo_uint k;
+
+ assert(m_len >= 3);
+ assert(m_off > 0x4000); assert(m_off <= 0xbfff);
+ m_off -= 0x4000;
+ k = (m_off & 0x4000) >> 11;
+ if (m_len <= M4_MAX_LEN)
+ *op++ = LZO_BYTE(M4_MARKER | k | (m_len - 2));
+ else
+ {
+ m_len -= M4_MAX_LEN;
+ *op++ = LZO_BYTE(M4_MARKER | k | 0);
+ while (m_len > 255)
+ {
+ m_len -= 255;
+ *op++ = 0;
+ }
+ assert(m_len > 0);
+ *op++ = LZO_BYTE(m_len);
+ }
+#if defined(LZO1Z)
+ *op++ = LZO_BYTE(m_off >> 6);
+ *op++ = LZO_BYTE(m_off << 2);
+#else
+ *op++ = LZO_BYTE(m_off << 2);
+ *op++ = LZO_BYTE(m_off >> 6);
+#endif
+ c->m4_m++;
+ }
+
+ c->last_m_len = x_len;
+ c->last_m_off = x_off;
+ return op;
+}
+
+
+static lzo_bytep
+STORE_RUN ( LZO_COMPRESS_T *c, lzo_bytep op, const lzo_bytep ii, lzo_uint t )
+{
+ c->lit_bytes += (unsigned long) t;
+
+ if (op == c->out && t <= 238)
+ {
+ *op++ = LZO_BYTE(17 + t);
+ }
+ else if (t <= 3)
+ {
+#if defined(LZO1Z)
+ op[-1] |= LZO_BYTE(t);
+#else
+ op[-2] |= LZO_BYTE(t);
+#endif
+ c->lit1_r++;
+ }
+ else if (t <= 18)
+ {
+ *op++ = LZO_BYTE(t - 3);
+ c->lit2_r++;
+ }
+ else
+ {
+ lzo_uint tt = t - 18;
+
+ *op++ = 0;
+ while (tt > 255)
+ {
+ tt -= 255;
+ *op++ = 0;
+ }
+ assert(tt > 0);
+ *op++ = LZO_BYTE(tt);
+ c->lit3_r++;
+ }
+ do *op++ = *ii++; while (--t > 0);
+
+ return op;
+}
+
+
+static lzo_bytep
+code_run ( LZO_COMPRESS_T *c, lzo_bytep op, const lzo_bytep ii,
+ lzo_uint lit, lzo_uint m_len )
+{
+ if (lit > 0)
+ {
+ assert(m_len >= 2);
+ op = STORE_RUN(c,op,ii,lit);
+ c->r1_m_len = m_len;
+ c->r1_lit = lit;
+ }
+ else
+ {
+ assert(m_len >= 3);
+ c->r1_m_len = 0;
+ c->r1_lit = 0;
+ }
+
+ return op;
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static int
+len_of_coded_match ( lzo_uint m_len, lzo_uint m_off, lzo_uint lit )
+{
+ int n = 4;
+
+ if (m_len < 2)
+ return -1;
+ if (m_len == 2)
+ return (m_off <= M1_MAX_OFFSET && lit > 0 && lit < 4) ? 2 : -1;
+ if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
+ return 2;
+ if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET && lit >= 4)
+ return 2;
+ if (m_off <= M3_MAX_OFFSET)
+ {
+ if (m_len <= M3_MAX_LEN)
+ return 3;
+ m_len -= M3_MAX_LEN;
+ while (m_len > 255)
+ {
+ m_len -= 255;
+ n++;
+ }
+ return n;
+ }
+ if (m_off <= M4_MAX_OFFSET)
+ {
+ if (m_len <= M4_MAX_LEN)
+ return 3;
+ m_len -= M4_MAX_LEN;
+ while (m_len > 255)
+ {
+ m_len -= 255;
+ n++;
+ }
+ return n;
+ }
+ return -1;
+}
+
+
+static lzo_int
+min_gain(lzo_uint ahead, lzo_uint lit1, lzo_uint lit2, int l1, int l2, int l3)
+{
+ lzo_int lazy_match_min_gain = 0;
+
+ assert (ahead >= 1);
+ lazy_match_min_gain += ahead;
+
+#if 0
+ if (l3 > 0)
+ lit2 -= ahead;
+#endif
+
+ if (lit1 <= 3)
+ lazy_match_min_gain += (lit2 <= 3) ? 0 : 2;
+ else if (lit1 <= 18)
+ lazy_match_min_gain += (lit2 <= 18) ? 0 : 1;
+
+ lazy_match_min_gain += (l2 - l1) * 2;
+ if (l3 > 0)
+ lazy_match_min_gain -= (ahead - l3) * 2;
+
+ if (lazy_match_min_gain < 0)
+ lazy_match_min_gain = 0;
+
+#if 0
+ if (l1 == 2)
+ if (lazy_match_min_gain == 0)
+ lazy_match_min_gain = 1;
+#endif
+
+ return lazy_match_min_gain;
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#if !defined(NDEBUG)
+static
+void assert_match( const lzo_swd_p swd, lzo_uint m_len, lzo_uint m_off )
+{
+ const LZO_COMPRESS_T *c = swd->c;
+ lzo_uint d_off;
+
+ assert(m_len >= 2);
+ if (m_off <= (lzo_uint) (c->bp - c->in))
+ {
+ assert(c->bp - m_off + m_len < c->ip);
+ assert(lzo_memcmp(c->bp, c->bp - m_off, m_len) == 0);
+ }
+ else
+ {
+ assert(swd->dict != NULL);
+ d_off = m_off - (lzo_uint) (c->bp - c->in);
+ assert(d_off <= swd->dict_len);
+ if (m_len > d_off)
+ {
+ assert(lzo_memcmp(c->bp, swd->dict_end - d_off, d_off) == 0);
+ assert(c->in + m_len - d_off < c->ip);
+ assert(lzo_memcmp(c->bp + d_off, c->in, m_len - d_off) == 0);
+ }
+ else
+ {
+ assert(lzo_memcmp(c->bp, swd->dict_end - d_off, m_len) == 0);
+ }
+ }
+}
+#else
+# define assert_match(a,b,c) ((void)0)
+#endif
+
+
+#if defined(SWD_BEST_OFF)
+
+static void
+better_match ( const lzo_swd_p swd, lzo_uint *m_len, lzo_uint *m_off )
+{
+#if defined(LZO1Z)
+ const LZO_COMPRESS_T *c = swd->c;
+#endif
+
+ if (*m_len <= M2_MIN_LEN)
+ return;
+#if defined(LZO1Z)
+ if (*m_off == c->last_m_off && *m_len <= M2_MAX_LEN)
+ return;
+#if 1
+ if (*m_len >= M2_MIN_LEN + 1 && *m_len <= M2_MAX_LEN + 1 &&
+ c->last_m_off && swd->best_off[*m_len-1] == c->last_m_off)
+ {
+ *m_len = *m_len - 1;
+ *m_off = swd->best_off[*m_len];
+ return;
+ }
+#endif
+#endif
+
+ if (*m_off <= M2_MAX_OFFSET)
+ return;
+
+#if 1
+ /* M3/M4 -> M2 */
+ if (*m_off > M2_MAX_OFFSET &&
+ *m_len >= M2_MIN_LEN + 1 && *m_len <= M2_MAX_LEN + 1 &&
+ swd->best_off[*m_len-1] && swd->best_off[*m_len-1] <= M2_MAX_OFFSET)
+ {
+ *m_len = *m_len - 1;
+ *m_off = swd->best_off[*m_len];
+ return;
+ }
+#endif
+
+#if 1
+ /* M4 -> M2 */
+ if (*m_off > M3_MAX_OFFSET &&
+ *m_len >= M4_MAX_LEN + 1 && *m_len <= M2_MAX_LEN + 2 &&
+ swd->best_off[*m_len-2] && swd->best_off[*m_len-2] <= M2_MAX_OFFSET)
+ {
+ *m_len = *m_len - 2;
+ *m_off = swd->best_off[*m_len];
+ return;
+ }
+#endif
+
+#if 1
+ /* M4 -> M3 */
+ if (*m_off > M3_MAX_OFFSET &&
+ *m_len >= M4_MAX_LEN + 1 && *m_len <= M3_MAX_LEN + 1 &&
+ swd->best_off[*m_len-1] && swd->best_off[*m_len-1] <= M3_MAX_OFFSET)
+ {
+ *m_len = *m_len - 1;
+ *m_off = swd->best_off[*m_len];
+ }
+#endif
+}
+
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_PUBLIC(int)
+lzo1x_999_compress_internal ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len,
+ lzo_callback_p cb,
+ int try_lazy,
+ lzo_uint good_length,
+ lzo_uint max_lazy,
+ lzo_uint nice_length,
+ lzo_uint max_chain,
+ lzo_uint32 flags )
+{
+ lzo_bytep op;
+ const lzo_bytep ii;
+ lzo_uint lit;
+ lzo_uint m_len, m_off;
+ LZO_COMPRESS_T cc;
+ LZO_COMPRESS_T * const c = &cc;
+ lzo_swd_p const swd = (lzo_swd_p) wrkmem;
+ int r;
+
+ /* sanity check */
+#if defined(LZO1X)
+ LZO_COMPILE_TIME_ASSERT(LZO1X_999_MEM_COMPRESS >= SIZEOF_LZO_SWD_T)
+#elif defined(LZO1Y)
+ LZO_COMPILE_TIME_ASSERT(LZO1Y_999_MEM_COMPRESS >= SIZEOF_LZO_SWD_T)
+#elif defined(LZO1Z)
+ LZO_COMPILE_TIME_ASSERT(LZO1Z_999_MEM_COMPRESS >= SIZEOF_LZO_SWD_T)
+#else
+# error
+#endif
+
+/* setup parameter defaults */
+ /* number of lazy match tries */
+ if (try_lazy < 0)
+ try_lazy = 1;
+ /* reduce lazy match search if we already have a match with this length */
+ if (good_length <= 0)
+ good_length = 32;
+ /* do not try a lazy match if we already have a match with this length */
+ if (max_lazy <= 0)
+ max_lazy = 32;
+ /* stop searching for longer matches than this one */
+ if (nice_length <= 0)
+ nice_length = 0;
+ /* don't search more positions than this */
+ if (max_chain <= 0)
+ max_chain = SWD_MAX_CHAIN;
+
+ c->init = 0;
+ c->ip = c->in = in;
+ c->in_end = in + in_len;
+ c->out = out;
+ c->cb = cb;
+ c->m1a_m = c->m1b_m = c->m2_m = c->m3_m = c->m4_m = 0;
+ c->lit1_r = c->lit2_r = c->lit3_r = 0;
+
+ op = out;
+ ii = c->ip; /* point to start of literal run */
+ lit = 0;
+ c->r1_lit = c->r1_m_len = 0;
+
+ r = init_match(c,swd,dict,dict_len,flags);
+ if (r != 0)
+ return r;
+ if (max_chain > 0)
+ swd->max_chain = max_chain;
+ if (nice_length > 0)
+ swd->nice_length = nice_length;
+
+ r = find_match(c,swd,0,0);
+ if (r != 0)
+ return r;
+ while (c->look > 0)
+ {
+ lzo_uint ahead;
+ lzo_uint max_ahead;
+ int l1, l2, l3;
+
+ c->codesize = pd(op, out);
+
+ m_len = c->m_len;
+ m_off = c->m_off;
+
+ assert(c->bp == c->ip - c->look);
+ assert(c->bp >= in);
+ if (lit == 0)
+ ii = c->bp;
+ assert(ii + lit == c->bp);
+ assert(swd->b_char == *(c->bp));
+
+ if ( m_len < 2 ||
+ (m_len == 2 && (m_off > M1_MAX_OFFSET || lit == 0 || lit >= 4)) ||
+#if 1
+ /* Do not accept this match for compressed-data compatibility
+ * with LZO v1.01 and before
+ * [ might be a problem for decompress() and optimize() ]
+ */
+ (m_len == 2 && op == out) ||
+#endif
+ (op == out && lit == 0))
+ {
+ /* a literal */
+ m_len = 0;
+ }
+ else if (m_len == M2_MIN_LEN)
+ {
+ /* compression ratio improves if we code a literal in some cases */
+ if (m_off > MX_MAX_OFFSET && lit >= 4)
+ m_len = 0;
+ }
+
+ if (m_len == 0)
+ {
+ /* a literal */
+ lit++;
+ swd->max_chain = max_chain;
+ r = find_match(c,swd,1,0);
+ assert(r == 0);
+ continue;
+ }
+
+ /* a match */
+#if defined(SWD_BEST_OFF)
+ if (swd->use_best_off)
+ better_match(swd,&m_len,&m_off);
+#endif
+ assert_match(swd,m_len,m_off);
+
+
+
+ /* shall we try a lazy match ? */
+ ahead = 0;
+ if (try_lazy <= 0 || m_len >= max_lazy)
+ {
+ /* no */
+ l1 = 0;
+ max_ahead = 0;
+ }
+ else
+ {
+ /* yes, try a lazy match */
+ l1 = len_of_coded_match(m_len,m_off,lit);
+ assert(l1 > 0);
+#if 1
+ max_ahead = LZO_MIN((lzo_uint)try_lazy, (lzo_uint)l1 - 1);
+#else
+ max_ahead = LZO_MIN3(try_lazy, l1, m_len - 1);
+#endif
+ }
+
+
+ while (ahead < max_ahead && c->look > m_len)
+ {
+ lzo_int lazy_match_min_gain;
+
+ if (m_len >= good_length)
+ swd->max_chain = max_chain >> 2;
+ else
+ swd->max_chain = max_chain;
+ r = find_match(c,swd,1,0);
+ ahead++;
+
+ assert(r == 0);
+ assert(c->look > 0);
+ assert(ii + lit + ahead == c->bp);
+
+#if defined(LZO1Z)
+ if (m_off == c->last_m_off && c->m_off != c->last_m_off)
+ if (m_len >= M2_MIN_LEN && m_len <= M2_MAX_LEN)
+ c->m_len = 0;
+#endif
+ if (c->m_len < m_len)
+ continue;
+#if 1
+ if (c->m_len == m_len && c->m_off >= m_off)
+ continue;
+#endif
+#if defined(SWD_BEST_OFF)
+ if (swd->use_best_off)
+ better_match(swd,&c->m_len,&c->m_off);
+#endif
+ l2 = len_of_coded_match(c->m_len,c->m_off,lit+ahead);
+ if (l2 < 0)
+ continue;
+#if 0
+ if (c->m_len == m_len && l2 >= l1)
+ continue;
+#endif
+
+
+#if 1
+ /* compressed-data compatibility [see above] */
+ l3 = (op == out) ? -1 : len_of_coded_match(ahead,m_off,lit);
+#else
+ l3 = len_of_coded_match(ahead,m_off,lit);
+#endif
+
+ lazy_match_min_gain = min_gain(ahead,lit,lit+ahead,l1,l2,l3);
+ if (c->m_len >= m_len + lazy_match_min_gain)
+ {
+ c->lazy++;
+ assert_match(swd,c->m_len,c->m_off);
+
+ if (l3 > 0)
+ {
+ /* code previous run */
+ op = code_run(c,op,ii,lit,ahead);
+ lit = 0;
+ /* code shortened match */
+ op = code_match(c,op,ahead,m_off);
+ }
+ else
+ {
+ lit += ahead;
+ assert(ii + lit == c->bp);
+ }
+ goto lazy_match_done;
+ }
+ }
+
+
+ assert(ii + lit + ahead == c->bp);
+
+ /* 1 - code run */
+ op = code_run(c,op,ii,lit,m_len);
+ lit = 0;
+
+ /* 2 - code match */
+ op = code_match(c,op,m_len,m_off);
+ swd->max_chain = max_chain;
+ r = find_match(c,swd,m_len,1+ahead);
+ assert(r == 0);
+
+lazy_match_done: ;
+ }
+
+
+ /* store final run */
+ if (lit > 0)
+ op = STORE_RUN(c,op,ii,lit);
+
+#if defined(LZO_EOF_CODE)
+ *op++ = M4_MARKER | 1;
+ *op++ = 0;
+ *op++ = 0;
+#endif
+
+ c->codesize = pd(op, out);
+ assert(c->textsize == in_len);
+
+ *out_len = pd(op, out);
+
+ if (c->cb && c->cb->nprogress)
+ (*c->cb->nprogress)(c->cb, c->textsize, c->codesize, 0);
+
+#if 0
+ printf("%ld %ld -> %ld %ld: %ld %ld %ld %ld %ld %ld: %ld %ld %ld %ld\n",
+ (long) c->textsize, (long) in_len, (long) c->codesize,
+ c->match_bytes, c->m1a_m, c->m1b_m, c->m2_m, c->m3_m, c->m4_m,
+ c->lit_bytes, c->lit1_r, c->lit2_r, c->lit3_r, c->lazy);
+#endif
+ assert(c->lit_bytes + c->match_bytes == in_len);
+
+ return LZO_E_OK;
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_PUBLIC(int)
+lzo1x_999_compress_level ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len,
+ lzo_callback_p cb,
+ int compression_level )
+{
+ static const struct
+ {
+ int try_lazy;
+ lzo_uint good_length;
+ lzo_uint max_lazy;
+ lzo_uint nice_length;
+ lzo_uint max_chain;
+ lzo_uint32 flags;
+ } c[9] = {
+ { 0, 0, 0, 8, 4, 0 }, /* faster compression */
+ { 0, 0, 0, 16, 8, 0 },
+ { 0, 0, 0, 32, 16, 0 },
+
+ { 1, 4, 4, 16, 16, 0 },
+ { 1, 8, 16, 32, 32, 0 },
+ { 1, 8, 16, 128, 128, 0 },
+
+ { 2, 8, 32, 128, 256, 0 },
+ { 2, 32, 128, F, 2048, 1 },
+ { 2, F, F, F, 4096, 1 } /* max. compression */
+ };
+
+ if (compression_level < 1 || compression_level > 9)
+ return LZO_E_ERROR;
+
+ compression_level -= 1;
+ return lzo1x_999_compress_internal(in, in_len, out, out_len, wrkmem,
+ dict, dict_len, cb,
+ c[compression_level].try_lazy,
+ c[compression_level].good_length,
+ c[compression_level].max_lazy,
+#if 0
+ c[compression_level].nice_length,
+#else
+ 0,
+#endif
+ c[compression_level].max_chain,
+ c[compression_level].flags);
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_PUBLIC(int)
+lzo1x_999_compress_dict ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len )
+{
+ return lzo1x_999_compress_level(in, in_len, out, out_len, wrkmem,
+ dict, dict_len, 0, 8);
+}
+
+LZO_PUBLIC(int)
+lzo1x_999_compress ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+{
+ return lzo1x_999_compress_level(in, in_len, out, out_len, wrkmem,
+ NULL, 0, (lzo_callback_p) 0, 8);
+}
+
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo1x_c.ch b/lzo/src/lzo1x_c.ch
new file mode 100644
index 00000000..08d615e2
--- /dev/null
+++ b/lzo/src/lzo1x_c.ch
@@ -0,0 +1,351 @@
+/* lzo1x_c.ch -- implementation of the LZO1[XY]-1 compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+
+/***********************************************************************
+// compress a block of data.
+************************************************************************/
+
+static __lzo_noinline lzo_uint
+do_compress ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+{
+ register const lzo_bytep ip;
+ lzo_bytep op;
+ const lzo_bytep const in_end = in + in_len;
+ const lzo_bytep const ip_end = in + in_len - M2_MAX_LEN - 5;
+ const lzo_bytep ii;
+ lzo_dict_p const dict = (lzo_dict_p) wrkmem;
+
+ op = out;
+ ip = in;
+ ii = ip;
+
+ ip += 4;
+ for (;;)
+ {
+ register const lzo_bytep m_pos;
+ lzo_uint m_off;
+ lzo_uint m_len;
+ lzo_uint dindex;
+
+ DINDEX1(dindex,ip);
+ GINDEX(m_pos,m_off,dict,dindex,in);
+ if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
+ goto literal;
+#if 1
+ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+ goto try_match;
+ DINDEX2(dindex,ip);
+#endif
+ GINDEX(m_pos,m_off,dict,dindex,in);
+ if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
+ goto literal;
+ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+ goto try_match;
+ goto literal;
+
+
+try_match:
+#if 1 && defined(LZO_UNALIGNED_OK_2)
+ if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip)
+#else
+ if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
+#endif
+ {
+ }
+ else
+ {
+ if __lzo_likely(m_pos[2] == ip[2])
+ {
+#if 0
+ if (m_off <= M2_MAX_OFFSET)
+ goto match;
+ if (lit <= 3)
+ goto match;
+ if (lit == 3) /* better compression, but slower */
+ {
+ assert(op - 2 > out); op[-2] |= LZO_BYTE(3);
+ *op++ = *ii++; *op++ = *ii++; *op++ = *ii++;
+ goto code_match;
+ }
+ if (m_pos[3] == ip[3])
+#endif
+ goto match;
+ }
+ else
+ {
+ /* still need a better way for finding M1 matches */
+#if 0
+ /* a M1 match */
+#if 0
+ if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3)
+#else
+ if (m_off <= M1_MAX_OFFSET && lit == 3)
+#endif
+ {
+ register lzo_uint t;
+
+ t = lit;
+ assert(op - 2 > out); op[-2] |= LZO_BYTE(t);
+ do *op++ = *ii++; while (--t > 0);
+ assert(ii == ip);
+ m_off -= 1;
+ *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2));
+ *op++ = LZO_BYTE(m_off >> 2);
+ ip += 2;
+ goto match_done;
+ }
+#endif
+ }
+ }
+
+
+ /* a literal */
+literal:
+ UPDATE_I(dict,0,dindex,ip,in);
+ ++ip;
+ if __lzo_unlikely(ip >= ip_end)
+ break;
+ continue;
+
+
+ /* a match */
+match:
+ UPDATE_I(dict,0,dindex,ip,in);
+ /* store current literal run */
+ if (pd(ip,ii) > 0)
+ {
+ register lzo_uint t = pd(ip,ii);
+
+ if (t <= 3)
+ {
+ assert(op - 2 > out);
+ op[-2] |= LZO_BYTE(t);
+ }
+ else if (t <= 18)
+ *op++ = LZO_BYTE(t - 3);
+ else
+ {
+ register lzo_uint tt = t - 18;
+
+ *op++ = 0;
+ while (tt > 255)
+ {
+ tt -= 255;
+ *op++ = 0;
+ }
+ assert(tt > 0);
+ *op++ = LZO_BYTE(tt);
+ }
+ do *op++ = *ii++; while (--t > 0);
+ }
+
+ /* code the match */
+ assert(ii == ip);
+ ip += 3;
+ if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ ||
+ m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++
+#ifdef LZO1Y
+ || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++
+ || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++
+#endif
+ )
+ {
+ --ip;
+ m_len = pd(ip, ii);
+ assert(m_len >= 3); assert(m_len <= M2_MAX_LEN);
+
+ if (m_off <= M2_MAX_OFFSET)
+ {
+ m_off -= 1;
+#if defined(LZO1X)
+ *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
+ *op++ = LZO_BYTE(m_off >> 3);
+#elif defined(LZO1Y)
+ *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2));
+ *op++ = LZO_BYTE(m_off >> 2);
+#endif
+ }
+ else if (m_off <= M3_MAX_OFFSET)
+ {
+ m_off -= 1;
+ *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
+ goto m3_m4_offset;
+ }
+ else
+#if defined(LZO1X)
+ {
+ m_off -= 0x4000;
+ assert(m_off > 0); assert(m_off <= 0x7fff);
+ *op++ = LZO_BYTE(M4_MARKER |
+ ((m_off & 0x4000) >> 11) | (m_len - 2));
+ goto m3_m4_offset;
+ }
+#elif defined(LZO1Y)
+ goto m4_match;
+#endif
+ }
+ else
+ {
+ {
+ const lzo_bytep end = in_end;
+ const lzo_bytep m = m_pos + M2_MAX_LEN + 1;
+ while (ip < end && *m == *ip)
+ m++, ip++;
+ m_len = pd(ip, ii);
+ }
+ assert(m_len > M2_MAX_LEN);
+
+ if (m_off <= M3_MAX_OFFSET)
+ {
+ m_off -= 1;
+ if (m_len <= 33)
+ *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
+ else
+ {
+ m_len -= 33;
+ *op++ = M3_MARKER | 0;
+ goto m3_m4_len;
+ }
+ }
+ else
+ {
+#if defined(LZO1Y)
+m4_match:
+#endif
+ m_off -= 0x4000;
+ assert(m_off > 0); assert(m_off <= 0x7fff);
+ if (m_len <= M4_MAX_LEN)
+ *op++ = LZO_BYTE(M4_MARKER |
+ ((m_off & 0x4000) >> 11) | (m_len - 2));
+ else
+ {
+ m_len -= M4_MAX_LEN;
+ *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11));
+m3_m4_len:
+ while (m_len > 255)
+ {
+ m_len -= 255;
+ *op++ = 0;
+ }
+ assert(m_len > 0);
+ *op++ = LZO_BYTE(m_len);
+ }
+ }
+
+m3_m4_offset:
+ *op++ = LZO_BYTE((m_off & 63) << 2);
+ *op++ = LZO_BYTE(m_off >> 6);
+ }
+
+#if 0
+match_done:
+#endif
+ ii = ip;
+ if __lzo_unlikely(ip >= ip_end)
+ break;
+ }
+
+ *out_len = pd(op, out);
+ return pd(in_end,ii);
+}
+
+
+/***********************************************************************
+// public entry point
+************************************************************************/
+
+LZO_PUBLIC(int)
+DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+{
+ lzo_bytep op = out;
+ lzo_uint t;
+
+ if __lzo_unlikely(in_len <= M2_MAX_LEN + 5)
+ t = in_len;
+ else
+ {
+ t = do_compress(in,in_len,op,out_len,wrkmem);
+ op += *out_len;
+ }
+
+ if (t > 0)
+ {
+ const lzo_bytep ii = in + in_len - t;
+
+ if (op == out && t <= 238)
+ *op++ = LZO_BYTE(17 + t);
+ else if (t <= 3)
+ op[-2] |= LZO_BYTE(t);
+ else if (t <= 18)
+ *op++ = LZO_BYTE(t - 3);
+ else
+ {
+ lzo_uint tt = t - 18;
+
+ *op++ = 0;
+ while (tt > 255)
+ {
+ tt -= 255;
+ *op++ = 0;
+ }
+ assert(tt > 0);
+ *op++ = LZO_BYTE(tt);
+ }
+ do *op++ = *ii++; while (--t > 0);
+ }
+
+ *op++ = M4_MARKER | 1;
+ *op++ = 0;
+ *op++ = 0;
+
+ *out_len = pd(op, out);
+ return LZO_E_OK;
+}
+
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo1x_d.ch b/lzo/src/lzo1x_d.ch
new file mode 100644
index 00000000..d068866b
--- /dev/null
+++ b/lzo/src/lzo1x_d.ch
@@ -0,0 +1,466 @@
+/* lzo1x_d.ch -- implementation of the LZO1X decompression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#include "lzo1_d.ch"
+
+
+#undef __COPY4
+#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
+
+#undef COPY4
+#if defined(LZO_UNALIGNED_OK_4)
+# define COPY4(dst,src) __COPY4(dst,src)
+#elif defined(LZO_ALIGNED_OK_4)
+# define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src))
+#endif
+
+
+/***********************************************************************
+// decompress a block of data.
+************************************************************************/
+
+#if defined(DO_DECOMPRESS)
+LZO_PUBLIC(int)
+DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+#endif
+{
+ register lzo_bytep op;
+ register const lzo_bytep ip;
+ register lzo_uint t;
+#if defined(COPY_DICT)
+ lzo_uint m_off;
+ const lzo_bytep dict_end;
+#else
+ register const lzo_bytep m_pos;
+#endif
+
+ const lzo_bytep const ip_end = in + in_len;
+#if defined(HAVE_ANY_OP)
+ lzo_bytep const op_end = out + *out_len;
+#endif
+#if defined(LZO1Z)
+ lzo_uint last_m_off = 0;
+#endif
+
+ LZO_UNUSED(wrkmem);
+
+#if defined(COPY_DICT)
+ if (dict)
+ {
+ if (dict_len > M4_MAX_OFFSET)
+ {
+ dict += dict_len - M4_MAX_OFFSET;
+ dict_len = M4_MAX_OFFSET;
+ }
+ dict_end = dict + dict_len;
+ }
+ else
+ {
+ dict_len = 0;
+ dict_end = NULL;
+ }
+#endif /* COPY_DICT */
+
+ *out_len = 0;
+
+ op = out;
+ ip = in;
+
+ if (*ip > 17)
+ {
+ t = *ip++ - 17;
+ if (t < 4)
+ goto match_next;
+ assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+ do *op++ = *ip++; while (--t > 0);
+ goto first_literal_run;
+ }
+
+ while (TEST_IP && TEST_OP)
+ {
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ /* a literal run */
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 15 + *ip++;
+ }
+ /* copy literals */
+ assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (PTR_ALIGNED2_4(op,ip))
+ {
+#endif
+ COPY4(op,ip);
+ op += 4; ip += 4;
+ if (--t > 0)
+ {
+ if (t >= 4)
+ {
+ do {
+ COPY4(op,ip);
+ op += 4; ip += 4; t -= 4;
+ } while (t >= 4);
+ if (t > 0) do *op++ = *ip++; while (--t > 0);
+ }
+ else
+ do *op++ = *ip++; while (--t > 0);
+ }
+#if !defined(LZO_UNALIGNED_OK_4)
+ }
+ else
+#endif
+#endif
+#if !defined(LZO_UNALIGNED_OK_4)
+ {
+ *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
+ do *op++ = *ip++; while (--t > 0);
+ }
+#endif
+
+
+first_literal_run:
+
+
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+#else
+ m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
+#endif
+ NEED_OP(3);
+ t = 3; COPY_DICT(t,m_off)
+#else /* !COPY_DICT */
+#if defined(LZO1Z)
+ t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+ m_pos = op - t;
+ last_m_off = t;
+#else
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+#endif
+ TEST_LB(m_pos); NEED_OP(3);
+ *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
+#endif /* COPY_DICT */
+ goto match_done;
+
+
+ /* handle matches */
+ do {
+match:
+ if (t >= 64) /* a M2 match */
+ {
+#if defined(COPY_DICT)
+#if defined(LZO1X)
+ m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
+ t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+ m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
+ t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+ m_off = t & 0x1f;
+ if (m_off >= 0x1c)
+ m_off = last_m_off;
+ else
+ {
+ m_off = 1 + (m_off << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+ }
+ t = (t >> 5) - 1;
+#endif
+#else /* !COPY_DICT */
+#if defined(LZO1X)
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 3;
+ m_pos -= *ip++ << 2;
+ t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+ {
+ lzo_uint off = t & 0x1f;
+ m_pos = op;
+ if (off >= 0x1c)
+ {
+ assert(last_m_off > 0);
+ m_pos -= last_m_off;
+ }
+ else
+ {
+ off = 1 + (off << 6) + (*ip++ >> 2);
+ m_pos -= off;
+ last_m_off = off;
+ }
+ }
+ t = (t >> 5) - 1;
+#endif
+ TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
+ goto copy_match;
+#endif /* COPY_DICT */
+ }
+ else if (t >= 32) /* a M3 match */
+ {
+ t &= 31;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+ }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+ last_m_off = m_off;
+#else
+ m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#else /* !COPY_DICT */
+#if defined(LZO1Z)
+ {
+ lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+ m_pos = op - off;
+ last_m_off = off;
+ }
+#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+ m_pos = op - 1;
+ m_pos -= (* (const lzo_ushortp) ip) >> 2;
+#else
+ m_pos = op - 1;
+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#endif /* COPY_DICT */
+ ip += 2;
+ }
+ else if (t >= 16) /* a M4 match */
+ {
+#if defined(COPY_DICT)
+ m_off = (t & 8) << 11;
+#else /* !COPY_DICT */
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+#endif /* COPY_DICT */
+ t &= 7;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 7 + *ip++;
+ }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off += (ip[0] << 6) + (ip[1] >> 2);
+#else
+ m_off += (ip[0] >> 2) + (ip[1] << 6);
+#endif
+ ip += 2;
+ if (m_off == 0)
+ goto eof_found;
+ m_off += 0x4000;
+#if defined(LZO1Z)
+ last_m_off = m_off;
+#endif
+#else /* !COPY_DICT */
+#if defined(LZO1Z)
+ m_pos -= (ip[0] << 6) + (ip[1] >> 2);
+#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+ m_pos -= (* (const lzo_ushortp) ip) >> 2;
+#else
+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+ ip += 2;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+#if defined(LZO1Z)
+ last_m_off = pd((const lzo_bytep)op, m_pos);
+#endif
+#endif /* COPY_DICT */
+ }
+ else /* a M1 match */
+ {
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = 1 + (t << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+#else
+ m_off = 1 + (t >> 2) + (*ip++ << 2);
+#endif
+ NEED_OP(2);
+ t = 2; COPY_DICT(t,m_off)
+#else /* !COPY_DICT */
+#if defined(LZO1Z)
+ t = 1 + (t << 6) + (*ip++ >> 2);
+ m_pos = op - t;
+ last_m_off = t;
+#else
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+#endif
+ TEST_LB(m_pos); NEED_OP(2);
+ *op++ = *m_pos++; *op++ = *m_pos;
+#endif /* COPY_DICT */
+ goto match_done;
+ }
+
+ /* copy match */
+#if defined(COPY_DICT)
+
+ NEED_OP(t+3-1);
+ t += 3-1; COPY_DICT(t,m_off)
+
+#else /* !COPY_DICT */
+
+ TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
+ {
+ assert((op - m_pos) >= 4); /* both pointers are aligned */
+#else
+ if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
+ {
+#endif
+ COPY4(op,m_pos);
+ op += 4; m_pos += 4; t -= 4 - (3 - 1);
+ do {
+ COPY4(op,m_pos);
+ op += 4; m_pos += 4; t -= 4;
+ } while (t >= 4);
+ if (t > 0) do *op++ = *m_pos++; while (--t > 0);
+ }
+ else
+#endif
+ {
+copy_match:
+ *op++ = *m_pos++; *op++ = *m_pos++;
+ do *op++ = *m_pos++; while (--t > 0);
+ }
+
+#endif /* COPY_DICT */
+
+match_done:
+#if defined(LZO1Z)
+ t = ip[-1] & 3;
+#else
+ t = ip[-2] & 3;
+#endif
+ if (t == 0)
+ break;
+
+ /* copy literals */
+match_next:
+ assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1);
+#if 0
+ do *op++ = *ip++; while (--t > 0);
+#else
+ *op++ = *ip++;
+ if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
+#endif
+ t = *ip++;
+ } while (TEST_IP && TEST_OP);
+ }
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
+ /* no EOF code was found */
+ *out_len = pd(op, out);
+ return LZO_E_EOF_NOT_FOUND;
+#endif
+
+eof_found:
+ assert(t == 1);
+ *out_len = pd(op, out);
+ return (ip == ip_end ? LZO_E_OK :
+ (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+
+
+#if defined(HAVE_NEED_IP)
+input_overrun:
+ *out_len = pd(op, out);
+ return LZO_E_INPUT_OVERRUN;
+#endif
+
+#if defined(HAVE_NEED_OP)
+output_overrun:
+ *out_len = pd(op, out);
+ return LZO_E_OUTPUT_OVERRUN;
+#endif
+
+#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+lookbehind_overrun:
+ *out_len = pd(op, out);
+ return LZO_E_LOOKBEHIND_OVERRUN;
+#endif
+}
+
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo1x_d1.c b/lzo/src/lzo1x_d1.c
new file mode 100644
index 00000000..5fbd9b2d
--- /dev/null
+++ b/lzo/src/lzo1x_d1.c
@@ -0,0 +1,46 @@
+/* lzo1x_d1.c -- LZO1X decompression
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#include "config1x.h"
+
+#undef LZO_TEST_OVERRUN
+#define DO_DECOMPRESS lzo1x_decompress
+
+#include "lzo1x_d.ch"
diff --git a/lzo/src/lzo1x_d2.c b/lzo/src/lzo1x_d2.c
new file mode 100644
index 00000000..f6c84cb6
--- /dev/null
+++ b/lzo/src/lzo1x_d2.c
@@ -0,0 +1,46 @@
+/* lzo1x_d2.c -- LZO1X decompression with overrun testing
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#include "config1x.h"
+
+#define LZO_TEST_OVERRUN
+#define DO_DECOMPRESS lzo1x_decompress_safe
+
+#include "lzo1x_d.ch"
diff --git a/lzo/src/lzo1x_d3.c b/lzo/src/lzo1x_d3.c
new file mode 100644
index 00000000..ffaa6802
--- /dev/null
+++ b/lzo/src/lzo1x_d3.c
@@ -0,0 +1,108 @@
+/* lzo1x_d3.c -- LZO1X decompression with preset dictionary
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#include "config1x.h"
+
+#define LZO_TEST_OVERRUN
+
+
+#define SLOW_MEMCPY(a,b,l) { do *a++ = *b++; while (--l > 0); }
+#define FAST_MEMCPY(a,b,l) { lzo_memcpy(a,b,l); a += l; }
+
+#if 1 && defined(FAST_MEMCPY)
+# define DICT_MEMMOVE(op,m_pos,m_len,m_off) \
+ if (m_off >= (m_len)) \
+ FAST_MEMCPY(op,m_pos,m_len) \
+ else \
+ SLOW_MEMCPY(op,m_pos,m_len)
+#else
+# define DICT_MEMMOVE(op,m_pos,m_len,m_off) \
+ SLOW_MEMCPY(op,m_pos,m_len)
+#endif
+
+#if !defined(FAST_MEMCPY)
+# define FAST_MEMCPY SLOW_MEMCPY
+#endif
+
+
+#define COPY_DICT_DICT(m_len,m_off) \
+ { \
+ register const lzo_bytep m_pos; \
+ m_off -= pd(op, out); assert(m_off > 0); \
+ if (m_off > dict_len) goto lookbehind_overrun; \
+ m_pos = dict_end - m_off; \
+ if (m_len > m_off) \
+ { \
+ m_len -= m_off; \
+ FAST_MEMCPY(op,m_pos,m_off) \
+ m_pos = out; \
+ SLOW_MEMCPY(op,m_pos,m_len) \
+ } \
+ else \
+ FAST_MEMCPY(op,m_pos,m_len) \
+ }
+
+#define COPY_DICT(m_len,m_off) \
+ assert(m_len >= 2); assert(m_off > 0); assert(op > out); \
+ if (m_off <= pd(op, out)) \
+ { \
+ register const lzo_bytep m_pos = op - m_off; \
+ DICT_MEMMOVE(op,m_pos,m_len,m_off) \
+ } \
+ else \
+ COPY_DICT_DICT(m_len,m_off)
+
+
+
+
+LZO_PUBLIC(int)
+lzo1x_decompress_dict_safe ( const lzo_bytep in, lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem /* NOT USED */,
+ const lzo_bytep dict, lzo_uint dict_len)
+
+
+#include "lzo1x_d.ch"
+
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo1x_o.c b/lzo/src/lzo1x_o.c
new file mode 100644
index 00000000..89cd1bc7
--- /dev/null
+++ b/lzo/src/lzo1x_o.c
@@ -0,0 +1,45 @@
+/* lzo1x_o.c -- LZO1X compressed data optimizer
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#include "config1x.h"
+
+#define DO_OPTIMIZE lzo1x_optimize
+
+#include "lzo1x_oo.ch"
diff --git a/lzo/src/lzo1x_oo.ch b/lzo/src/lzo1x_oo.ch
new file mode 100644
index 00000000..e978f399
--- /dev/null
+++ b/lzo/src/lzo1x_oo.ch
@@ -0,0 +1,366 @@
+/* lzo1x_oo.ch -- LZO1X compressed data optimizer
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#define TEST_IP (ip < ip_end)
+#define TEST_OP (op <= op_end)
+
+#define NO_LIT LZO_UINT_MAX
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static void copy2(lzo_bytep ip, const lzo_bytep m_pos, lzo_uint off)
+{
+ assert(off > 0);
+ ip[0] = m_pos[0];
+ if (off == 1)
+ ip[1] = m_pos[0];
+ else
+ ip[1] = m_pos[1];
+}
+
+
+static void copy3(lzo_bytep ip, const lzo_bytep m_pos, lzo_uint off)
+{
+ assert(off > 0);
+ ip[0] = m_pos[0];
+ if (off == 1)
+ {
+ ip[2] = ip[1] = m_pos[0];
+ }
+ else if (off == 2)
+ {
+ ip[1] = m_pos[1];
+ ip[2] = m_pos[0];
+ }
+ else
+ {
+ ip[1] = m_pos[1];
+ ip[2] = m_pos[2];
+ }
+}
+
+
+/***********************************************************************
+// optimize a block of data.
+************************************************************************/
+
+LZO_PUBLIC(int)
+DO_OPTIMIZE ( lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+{
+ lzo_bytep op;
+ lzo_bytep ip;
+ lzo_uint t;
+ lzo_bytep m_pos;
+ lzo_bytep const ip_end = in + in_len;
+ lzo_bytep const op_end = out + *out_len;
+ lzo_bytep litp = NULL;
+ lzo_uint lit = 0;
+ lzo_uint next_lit = NO_LIT;
+ lzo_uint nl;
+ unsigned long o_m1_a = 0, o_m1_b = 0, o_m2 = 0, o_m3_a = 0, o_m3_b = 0;
+
+ LZO_UNUSED(wrkmem);
+
+ *out_len = 0;
+
+ op = out;
+ ip = in;
+
+ assert(in_len >= 3);
+ if (*ip > 17)
+ {
+ t = *ip++ - 17;
+ if (t < 4)
+ goto match_next;
+ goto first_literal_run;
+ }
+ assert(*ip < 16 || (*ip == 17 && in_len == 3));
+
+ while (TEST_IP && TEST_OP)
+ {
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ /* a literal run */
+ litp = ip - 1;
+ if (t == 0)
+ {
+ t = 15;
+ while (*ip == 0)
+ t += 255, ip++;
+ t += *ip++;
+ }
+ lit = t + 3;
+ /* copy literals */
+copy_literal_run:
+ *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
+first_literal_run:
+ do *op++ = *ip++; while (--t > 0);
+
+
+ t = *ip++;
+
+ if (t >= 16)
+ goto match;
+#if defined(LZO1X)
+ m_pos = op - 1 - 0x800;
+#elif defined(LZO1Y)
+ m_pos = op - 1 - 0x400;
+#endif
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+ *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;
+ lit = 0;
+ goto match_done;
+
+
+ /* handle matches */
+ do {
+ if (t < 16) /* a M1 match */
+ {
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+
+ if (litp == NULL)
+ goto copy_m1;
+
+ /* assert that there was a match just before */
+ assert(lit >= 1 && lit <= 3);
+ assert(litp == ip - 2 - lit - 2);
+ assert((lzo_uint)(*litp & 3) == lit);
+ nl = ip[-2] & 3;
+ /* test if a match follows */
+ if (nl == 0 && lit == 1 && ip[0] >= 16)
+ {
+ next_lit = nl;
+ /* adjust length of previous short run */
+ lit += 2;
+ *litp = LZO_BYTE((*litp & ~3) | lit);
+ /* copy over the 2 literals that replace the match */
+ copy2(ip-2,m_pos,pd(op,m_pos));
+ o_m1_a++;
+ }
+ /* test if a literal run follows */
+ else if (nl == 0 && ip[0] < 16 && ip[0] != 0 &&
+ (lit + 2 + ip[0] < 16))
+ {
+ t = *ip++;
+ /* remove short run */
+ *litp &= ~3;
+ /* copy over the 2 literals that replace the match */
+ copy2(ip-3+1,m_pos,pd(op,m_pos));
+ /* move literals 1 byte ahead */
+ litp += 2;
+ if (lit > 0)
+ lzo_memmove(litp+1,litp,lit);
+ /* insert new length of long literal run */
+ lit += 2 + t + 3; assert(lit <= 18);
+ *litp = LZO_BYTE(lit - 3);
+
+ o_m1_b++;
+ *op++ = *m_pos++; *op++ = *m_pos++;
+ goto copy_literal_run;
+ }
+copy_m1:
+ *op++ = *m_pos++; *op++ = *m_pos++;
+ }
+ else
+ {
+match:
+ if (t >= 64) /* a M2 match */
+ {
+ m_pos = op - 1;
+#if defined(LZO1X)
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+ m_pos -= (t >> 2) & 3;
+ m_pos -= *ip++ << 2;
+ t = (t >> 4) - 3;
+#endif
+ if (litp == NULL)
+ goto copy_m;
+
+ nl = ip[-2] & 3;
+ /* test if in beetween two long literal runs */
+ if (t == 1 && lit > 3 && nl == 0 &&
+ ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16))
+ {
+ assert(*litp == lit - 3);
+ t = *ip++;
+ /* copy over the 3 literals that replace the match */
+ copy3(ip-1-2,m_pos,pd(op,m_pos));
+ /* set new length of previous literal run */
+ lit += 3 + t + 3; assert(lit <= 18);
+ *litp = LZO_BYTE(lit - 3);
+ o_m2++;
+ *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;
+ goto copy_literal_run;
+ }
+ }
+ else
+ {
+ if (t >= 32) /* a M3 match */
+ {
+ t &= 31;
+ if (t == 0)
+ {
+ t = 31;
+ while (*ip == 0)
+ t += 255, ip++;
+ t += *ip++;
+ }
+ m_pos = op - 1;
+ m_pos -= *ip++ >> 2;
+ m_pos -= *ip++ << 6;
+ }
+ else /* a M4 match */
+ {
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+ t &= 7;
+ if (t == 0)
+ {
+ t = 7;
+ while (*ip == 0)
+ t += 255, ip++;
+ t += *ip++;
+ }
+ m_pos -= *ip++ >> 2;
+ m_pos -= *ip++ << 6;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+ }
+ if (litp == NULL)
+ goto copy_m;
+
+ nl = ip[-2] & 3;
+ /* test if in beetween two matches */
+ if (t == 1 && lit == 0 && nl == 0 && ip[0] >= 16)
+ {
+ assert(litp == ip - 3 - lit - 2);
+ assert((lzo_uint)(*litp & 3) == lit);
+ next_lit = nl;
+ /* make a previous short run */
+ lit += 3;
+ *litp = LZO_BYTE((*litp & ~3) | lit);
+ /* copy over the 3 literals that replace the match */
+ copy3(ip-3,m_pos,pd(op,m_pos));
+ o_m3_a++;
+ }
+ /* test if a literal run follows */
+ else if (t == 1 && lit <= 3 && nl == 0 &&
+ ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16))
+ {
+ assert(litp == ip - 3 - lit - 2);
+ assert((lzo_uint)(*litp & 3) == lit);
+ t = *ip++;
+ /* remove short run */
+ *litp &= ~3;
+ /* copy over the 3 literals that replace the match */
+ copy3(ip-4+1,m_pos,pd(op,m_pos));
+ /* move literals 1 byte ahead */
+ litp += 2;
+ if (lit > 0)
+ lzo_memmove(litp+1,litp,lit);
+ /* insert new length of long literal run */
+ lit += 3 + t + 3; assert(lit <= 18);
+ *litp = LZO_BYTE(lit - 3);
+
+ o_m3_b++;
+ *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;
+ goto copy_literal_run;
+ }
+ }
+copy_m:
+ *op++ = *m_pos++; *op++ = *m_pos++;
+ do *op++ = *m_pos++; while (--t > 0);
+ }
+
+match_done:
+ if (next_lit == NO_LIT)
+ {
+ t = ip[-2] & 3;
+ lit = t;
+ litp = ip - 2;
+ }
+ else
+ t = next_lit;
+ assert(t <= 3);
+ next_lit = NO_LIT;
+ if (t == 0)
+ break;
+ /* copy literals */
+match_next:
+ do *op++ = *ip++; while (--t > 0);
+ t = *ip++;
+ } while (TEST_IP && TEST_OP);
+ }
+
+ /* no EOF code was found */
+ *out_len = pd(op, out);
+ return LZO_E_EOF_NOT_FOUND;
+
+eof_found:
+ assert(t == 1);
+#if 0
+ printf("optimize: %5lu %5lu %5lu %5lu %5lu\n",
+ o_m1_a, o_m1_b, o_m2, o_m3_a, o_m3_b);
+#endif
+ LZO_UNUSED(o_m1_a); LZO_UNUSED(o_m1_b); LZO_UNUSED(o_m2);
+ LZO_UNUSED(o_m3_a); LZO_UNUSED(o_m3_b);
+ *out_len = pd(op, out);
+ return (ip == ip_end ? LZO_E_OK :
+ (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+}
+
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo_conf.h b/lzo/src/lzo_conf.h
new file mode 100644
index 00000000..85e10808
--- /dev/null
+++ b/lzo/src/lzo_conf.h
@@ -0,0 +1,323 @@
+/* lzo_conf.h -- main internal configuration file for the the LZO library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the library and is subject
+ to change.
+ */
+
+
+#ifndef __LZO_CONF_H
+#define __LZO_CONF_H
+
+#if !defined(__LZO_IN_MINILZO)
+#if defined(LZO_CFG_FREESTANDING)
+# define LZO_LIBC_FREESTANDING 1
+# define LZO_OS_FREESTANDING 1
+# define ACC_LIBC_FREESTANDING 1
+# define ACC_OS_FREESTANDING 1
+#endif
+#if defined(LZO_CFG_NO_UNALIGNED)
+# define ACC_CFG_NO_UNALIGNED 1
+#endif
+#if defined(LZO_ARCH_GENERIC)
+# define ACC_ARCH_GENERIC 1
+#endif
+#if defined(LZO_ABI_NEUTRAL_ENDIAN)
+# define ACC_ABI_NEUTRAL_ENDIAN 1
+#endif
+#if defined(LZO_HAVE_CONFIG_H)
+# define ACC_CONFIG_NO_HEADER 1
+#endif
+#if defined(LZO_CFG_EXTRA_CONFIG_HEADER)
+# include LZO_CFG_EXTRA_CONFIG_HEADER
+#endif
+#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED)
+# error "include this file first"
+#endif
+#include "lzo/lzoconf.h"
+#endif
+
+#if (LZO_VERSION < 0x02000) || !defined(__LZOCONF_H_INCLUDED)
+# error "version mismatch"
+#endif
+
+
+/***********************************************************************
+// pragmas
+************************************************************************/
+
+#if (LZO_CC_BORLANDC && LZO_ARCH_I086)
+# pragma option -h /* enable fast huge pointers */
+#endif
+
+#if (LZO_CC_MSC && (_MSC_VER >= 1000))
+# pragma warning(disable: 4127 4701)
+#endif
+#if (LZO_CC_MSC && (_MSC_VER >= 1300))
+ /* avoid `-Wall' warnings in system header files */
+# pragma warning(disable: 4820)
+ /* avoid warnings about inlining */
+# pragma warning(disable: 4514 4710 4711)
+#endif
+
+#if (LZO_CC_SUNPROC)
+# pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED)
+# pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP)
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#if defined(__LZO_MMODEL_HUGE) && (!LZO_HAVE_MM_HUGE_PTR)
+# error "this should not happen - check defines for __huge"
+#endif
+
+#if defined(__LZO_IN_MINILZO) || defined(LZO_CFG_FREESTANDING)
+#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+# define ACC_WANT_ACC_INCD_H 1
+# define ACC_WANT_ACC_INCE_H 1
+# define ACC_WANT_ACC_INCI_H 1
+#elif 1
+# include <string.h>
+#else
+# define ACC_WANT_ACC_INCD_H 1
+#endif
+#include "miniacc.h"
+
+
+#if defined(LZO_CFG_FREESTANDING)
+# undef HAVE_MEMCMP
+# undef HAVE_MEMCPY
+# undef HAVE_MEMMOVE
+# undef HAVE_MEMSET
+#endif
+
+#if !defined(HAVE_MEMCMP)
+# undef memcmp
+# define memcmp(a,b,c) lzo_memcmp(a,b,c)
+#elif !defined(__LZO_MMODEL_HUGE)
+# define lzo_memcmp(a,b,c) memcmp(a,b,c)
+#endif
+#if !defined(HAVE_MEMCPY)
+# undef memcpy
+# define memcpy(a,b,c) lzo_memcpy(a,b,c)
+#elif !defined(__LZO_MMODEL_HUGE)
+# define lzo_memcpy(a,b,c) memcpy(a,b,c)
+#endif
+#if !defined(HAVE_MEMMOVE)
+# undef memmove
+# define memmove(a,b,c) lzo_memmove(a,b,c)
+#elif !defined(__LZO_MMODEL_HUGE)
+# define lzo_memmove(a,b,c) memmove(a,b,c)
+#endif
+#if !defined(HAVE_MEMSET)
+# undef memset
+# define memset(a,b,c) lzo_memset(a,b,c)
+#elif !defined(__LZO_MMODEL_HUGE)
+# define lzo_memset(a,b,c) memset(a,b,c)
+#endif
+
+
+#undef NDEBUG
+#if defined(LZO_CFG_FREESTANDING)
+# undef LZO_DEBUG
+# define NDEBUG 1
+# undef assert
+# define assert(e) ((void)0)
+#else
+# if !defined(LZO_DEBUG)
+# define NDEBUG 1
+# endif
+# include <assert.h>
+#endif
+
+#if 0 && defined(__BOUNDS_CHECKING_ON)
+# include <unchecked.h>
+#else
+# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt
+# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr)
+#endif
+
+#if !defined(__lzo_inline)
+# define __lzo_inline
+#endif
+#if !defined(__lzo_forceinline)
+# define __lzo_forceinline
+#endif
+#if !defined(__lzo_noinline)
+# define __lzo_noinline
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#if 1
+# define LZO_BYTE(x) ((unsigned char) (x))
+#else
+# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff))
+#endif
+
+#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b))
+#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b))
+#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c))
+#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c))
+
+#define lzo_sizeof(type) ((lzo_uint) (sizeof(type)))
+
+#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array))))
+
+/* this always fits into 16 bits */
+#define LZO_SIZE(bits) (1u << (bits))
+#define LZO_MASK(bits) (LZO_SIZE(bits) - 1)
+
+#define LZO_LSIZE(bits) (1ul << (bits))
+#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1)
+
+#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits))
+#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1)
+
+#if !defined(DMUL)
+#if 0
+ /* 32*32 multiplies may be faster than 64*64 on some 64-bit machines,
+ * but then we need extra casts from unsigned<->size_t */
+# define DMUL(a,b) ((lzo_xint) ((lzo_uint32)(a) * (lzo_uint32)(b)))
+#else
+# define DMUL(a,b) ((lzo_xint) ((a) * (b)))
+#endif
+#endif
+
+
+/***********************************************************************
+// compiler and architecture specific stuff
+************************************************************************/
+
+/* Some defines that indicate if memory can be accessed at unaligned
+ * memory addresses. You should also test that this is actually faster
+ * even if it is allowed by your system.
+ */
+
+#if 1 && !defined(LZO_CFG_NO_UNALIGNED)
+#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386)
+# if (LZO_SIZEOF_SHORT == 2)
+# define LZO_UNALIGNED_OK_2
+# endif
+# if (LZO_SIZEOF_INT == 4)
+# define LZO_UNALIGNED_OK_4
+# endif
+#endif
+#endif
+
+#if defined(LZO_UNALIGNED_OK_2)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(short) == 2)
+#endif
+#if defined(LZO_UNALIGNED_OK_4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4)
+#elif defined(LZO_ALIGNED_OK_4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4)
+#endif
+
+
+/* Fast memcpy that copies multiples of 8 byte chunks.
+ * len is the number of bytes.
+ * note: all parameters must be lvalues, len >= 8
+ * dest and src advance, len is undefined afterwards
+ */
+
+#define MEMCPY8_DS(dest,src,len) \
+ lzo_memcpy(dest,src,len); dest += len; src += len
+
+#define BZERO8_PTR(s,l,n) \
+ lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n))
+
+#define MEMCPY_DS(dest,src,len) \
+ do *dest++ = *src++; while (--len > 0)
+
+
+/***********************************************************************
+// some globals
+************************************************************************/
+
+__LZO_EXTERN_C int __lzo_init_done;
+__LZO_EXTERN_C const char __lzo_copyright[];
+LZO_EXTERN(const lzo_bytep) lzo_copyright(void);
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#include "lzo_ptr.h"
+
+
+/* Generate compressed data in a deterministic way.
+ * This is fully portable, and compression can be faster as well.
+ * A reason NOT to be deterministic is when the block size is
+ * very small (e.g. 8kB) or the dictionary is big, because
+ * then the initialization of the dictionary becomes a relevant
+ * magnitude for compression speed.
+ */
+#define LZO_DETERMINISTIC
+
+
+#define LZO_DICT_USE_PTR
+#if 0 && (LZO_ARCH_I086)
+# undef LZO_DICT_USE_PTR
+#endif
+
+#if defined(LZO_DICT_USE_PTR)
+# define lzo_dict_t const lzo_bytep
+# define lzo_dict_p lzo_dict_t __LZO_MMODEL *
+#else
+# define lzo_dict_t lzo_uint
+# define lzo_dict_p lzo_dict_t __LZO_MMODEL *
+#endif
+
+
+#endif /* already included */
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo_crc.c b/lzo/src/lzo_crc.c
new file mode 100644
index 00000000..83941ab2
--- /dev/null
+++ b/lzo/src/lzo_crc.c
@@ -0,0 +1,167 @@
+/* lzo_crc.c -- crc checksum for the the LZO library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#include "lzo_conf.h"
+
+
+/***********************************************************************
+// crc32 checksum
+// adapted from free code by Mark Adler <madler@alumni.caltech.edu>
+// see http://www.zlib.org/
+************************************************************************/
+
+static const lzo_uint32 lzo_crc32_table[256] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+
+
+LZO_PUBLIC(const lzo_uint32p)
+lzo_get_crc32_table(void)
+{
+ return lzo_crc32_table;
+}
+
+
+#if 1
+#define LZO_DO1(buf,i) \
+ crc = table[((int)crc ^ buf[i]) & 0xff] ^ (crc >> 8)
+#else
+#define LZO_DO1(buf,i) \
+ crc = table[(unsigned char)((unsigned char)crc ^ buf[i])] ^ (crc >> 8)
+#endif
+#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1);
+#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2);
+#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4);
+#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8);
+
+
+LZO_PUBLIC(lzo_uint32)
+lzo_crc32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len)
+{
+ lzo_uint32 crc;
+#undef table
+#if 1
+# define table lzo_crc32_table
+#else
+ const lzo_uint32 * table = lzo_crc32_table;
+#endif
+
+ if (buf == NULL)
+ return 0;
+
+ crc = (c & LZO_UINT32_C(0xffffffff)) ^ LZO_UINT32_C(0xffffffff);
+ if (len >= 16) do
+ {
+ LZO_DO16(buf,0);
+ buf += 16;
+ len -= 16;
+ } while (len >= 16);
+ if (len != 0) do
+ {
+ LZO_DO1(buf,0);
+ buf += 1;
+ len -= 1;
+ } while (len > 0);
+
+ return crc ^ LZO_UINT32_C(0xffffffff);
+#undef table
+}
+
+#undef LZO_DO1
+#undef LZO_DO2
+#undef LZO_DO4
+#undef LZO_DO8
+#undef LZO_DO16
+
+
+/*
+vi:ts=4:et
+*/
diff --git a/lzo/src/lzo_dict.h b/lzo/src/lzo_dict.h
new file mode 100644
index 00000000..043a1e2b
--- /dev/null
+++ b/lzo/src/lzo_dict.h
@@ -0,0 +1,316 @@
+/* lzo_dict.h -- dictionary definitions for the the LZO library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the library and is subject
+ to change.
+ */
+
+
+#ifndef __LZO_DICT_H
+#define __LZO_DICT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+/***********************************************************************
+// dictionary size
+************************************************************************/
+
+/* dictionary needed for compression */
+#if !defined(D_BITS) && defined(DBITS)
+# define D_BITS DBITS
+#endif
+#if !defined(D_BITS)
+# error "D_BITS is not defined"
+#endif
+#if (D_BITS < 16)
+# define D_SIZE LZO_SIZE(D_BITS)
+# define D_MASK LZO_MASK(D_BITS)
+#else
+# define D_SIZE LZO_USIZE(D_BITS)
+# define D_MASK LZO_UMASK(D_BITS)
+#endif
+#define D_HIGH ((D_MASK >> 1) + 1)
+
+
+/* dictionary depth */
+#if !defined(DD_BITS)
+# define DD_BITS 0
+#endif
+#define DD_SIZE LZO_SIZE(DD_BITS)
+#define DD_MASK LZO_MASK(DD_BITS)
+
+/* dictionary length */
+#if !defined(DL_BITS)
+# define DL_BITS (D_BITS - DD_BITS)
+#endif
+#if (DL_BITS < 16)
+# define DL_SIZE LZO_SIZE(DL_BITS)
+# define DL_MASK LZO_MASK(DL_BITS)
+#else
+# define DL_SIZE LZO_USIZE(DL_BITS)
+# define DL_MASK LZO_UMASK(DL_BITS)
+#endif
+
+
+#if (D_BITS != DL_BITS + DD_BITS)
+# error "D_BITS does not match"
+#endif
+#if (D_BITS < 8 || D_BITS > 18)
+# error "invalid D_BITS"
+#endif
+#if (DL_BITS < 8 || DL_BITS > 20)
+# error "invalid DL_BITS"
+#endif
+#if (DD_BITS < 0 || DD_BITS > 6)
+# error "invalid DD_BITS"
+#endif
+
+
+#if !defined(DL_MIN_LEN)
+# define DL_MIN_LEN 3
+#endif
+#if !defined(DL_SHIFT)
+# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN)
+#endif
+
+
+
+/***********************************************************************
+// dictionary access
+************************************************************************/
+
+#define LZO_HASH_GZIP 1
+#define LZO_HASH_GZIP_INCREMENTAL 2
+#define LZO_HASH_LZO_INCREMENTAL_A 3
+#define LZO_HASH_LZO_INCREMENTAL_B 4
+
+#if !defined(LZO_HASH)
+# error "choose a hashing strategy"
+#endif
+
+#undef DM
+#undef DX
+
+#if (DL_MIN_LEN == 3)
+# define _DV2_A(p,shift1,shift2) \
+ (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2])
+# define _DV2_B(p,shift1,shift2) \
+ (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0])
+# define _DV3_B(p,shift1,shift2,shift3) \
+ ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0])
+#elif (DL_MIN_LEN == 2)
+# define _DV2_A(p,shift1,shift2) \
+ (( (lzo_xint)(p[0]) << shift1) ^ p[1])
+# define _DV2_B(p,shift1,shift2) \
+ (( (lzo_xint)(p[1]) << shift1) ^ p[2])
+#else
+# error "invalid DL_MIN_LEN"
+#endif
+#define _DV_A(p,shift) _DV2_A(p,shift,shift)
+#define _DV_B(p,shift) _DV2_B(p,shift,shift)
+#define DA2(p,s1,s2) \
+ (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0])
+#define DS2(p,s1,s2) \
+ (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0])
+#define DX2(p,s1,s2) \
+ (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0])
+#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0])
+#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0])
+#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0])
+#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s)))
+#define DM(v) DMS(v,0)
+
+
+#if (LZO_HASH == LZO_HASH_GZIP)
+ /* hash function like in gzip/zlib (deflate) */
+# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT))
+
+#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL)
+ /* incremental hash like in gzip/zlib (deflate) */
+# define __LZO_HASH_INCREMENTAL
+# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT)
+# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2])
+# define _DINDEX(dv,p) (dv)
+# define DVAL_LOOKAHEAD DL_MIN_LEN
+
+#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A)
+ /* incremental LZO hash version A */
+# define __LZO_HASH_INCREMENTAL
+# define DVAL_FIRST(dv,p) dv = _DV_A((p),5)
+# define DVAL_NEXT(dv,p) \
+ dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2])
+# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5)
+# define DVAL_LOOKAHEAD DL_MIN_LEN
+
+#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B)
+ /* incremental LZO hash version B */
+# define __LZO_HASH_INCREMENTAL
+# define DVAL_FIRST(dv,p) dv = _DV_B((p),5)
+# define DVAL_NEXT(dv,p) \
+ dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5)))
+# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5)
+# define DVAL_LOOKAHEAD DL_MIN_LEN
+
+#else
+# error "choose a hashing strategy"
+#endif
+
+
+#ifndef DINDEX
+#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS)
+#endif
+#if !defined(DINDEX1) && defined(D_INDEX1)
+#define DINDEX1 D_INDEX1
+#endif
+#if !defined(DINDEX2) && defined(D_INDEX2)
+#define DINDEX2 D_INDEX2
+#endif
+
+
+
+#if !defined(__LZO_HASH_INCREMENTAL)
+# define DVAL_FIRST(dv,p) ((void) 0)
+# define DVAL_NEXT(dv,p) ((void) 0)
+# define DVAL_LOOKAHEAD 0
+#endif
+
+
+#if !defined(DVAL_ASSERT)
+#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG)
+static void DVAL_ASSERT(lzo_xint dv, const lzo_bytep p)
+{
+ lzo_xint df;
+ DVAL_FIRST(df,(p));
+ assert(DINDEX(dv,p) == DINDEX(df,p));
+}
+#else
+# define DVAL_ASSERT(dv,p) ((void) 0)
+#endif
+#endif
+
+
+
+/***********************************************************************
+// dictionary updating
+************************************************************************/
+
+#if defined(LZO_DICT_USE_PTR)
+# define DENTRY(p,in) (p)
+# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex]
+#else
+# define DENTRY(p,in) ((lzo_uint) ((p)-(in)))
+# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex]
+#endif
+
+
+#if (DD_BITS == 0)
+
+# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in)
+# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in)
+# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in)
+
+#else
+
+# define UPDATE_D(dict,drun,dv,p,in) \
+ dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK
+# define UPDATE_I(dict,drun,index,p,in) \
+ dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK
+# define UPDATE_P(ptr,drun,p,in) \
+ (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK
+
+#endif
+
+
+/***********************************************************************
+// test for a match
+************************************************************************/
+
+#if defined(LZO_DICT_USE_PTR)
+
+/* m_pos is either NULL or a valid pointer */
+#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
+ (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset)
+
+/* m_pos may point anywhere... */
+#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
+ (BOUNDS_CHECKING_OFF_IN_EXPR(( \
+ m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \
+ PTR_LT(m_pos,in) || \
+ (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) <= 0 || \
+ m_off > max_offset )))
+
+#else
+
+#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
+ (m_off == 0 || \
+ ((m_off = pd(ip, in) - m_off) > max_offset) || \
+ (m_pos = (ip) - (m_off), 0) )
+
+#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
+ (pd(ip, in) <= m_off || \
+ ((m_off = pd(ip, in) - m_off) > max_offset) || \
+ (m_pos = (ip) - (m_off), 0) )
+
+#endif
+
+
+#if defined(LZO_DETERMINISTIC)
+# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET
+#else
+# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET
+#endif
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo_dll.ch b/lzo/src/lzo_dll.ch
new file mode 100644
index 00000000..346cb275
--- /dev/null
+++ b/lzo/src/lzo_dll.ch
@@ -0,0 +1,64 @@
+/* lzo_dll.ch -- DLL initialization of the LZO library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/***********************************************************************
+// Windows 16 bit + Watcom C + DLL
+************************************************************************/
+
+#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD)
+
+/* don't pull in <windows.h> - we don't need it */
+#if 0
+BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment,
+ WORD wHeapSize, LPSTR lpszCmdLine )
+#else
+int __far __pascal LibMain ( int a, short b, short c, long d )
+#endif
+{
+ LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d);
+ return 1;
+}
+
+#endif
+
+
+/*
+vi:ts=4:et
+*/
diff --git a/lzo/src/lzo_init.c b/lzo/src/lzo_init.c
new file mode 100644
index 00000000..6977891d
--- /dev/null
+++ b/lzo/src/lzo_init.c
@@ -0,0 +1,176 @@
+/* lzo_init.c -- initialization of the LZO library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#include "lzo_conf.h"
+
+
+/***********************************************************************
+// Runtime check of the assumptions about the size of builtin types,
+// memory model, byte order and other low-level constructs.
+//
+// We are really paranoid here - LZO should either fail
+// at startup or not at all.
+//
+// Because of inlining much of these functions evaluates to nothing.
+//
+// And while many of the tests seem highly obvious and redundant they are
+// here to catch compiler/optimizer bugs. Yes, these do exist.
+************************************************************************/
+
+#if !defined(__LZO_IN_MINILZO)
+
+#define ACC_WANT_ACC_CHK_CH 1
+#undef ACCCHK_ASSERT
+#include "miniacc.h"
+
+ ACCCHK_ASSERT_IS_SIGNED_T(lzo_int)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint)
+
+ ACCCHK_ASSERT_IS_SIGNED_T(lzo_int32)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint32)
+ ACCCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0)
+ ACCCHK_ASSERT(sizeof(lzo_uint32) >= 4)
+
+#if !defined(__LZO_UINTPTR_T_IS_POINTER)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t)
+#endif
+ ACCCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
+
+ ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_xint)
+ ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint32))
+ ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint))
+ ACCCHK_ASSERT(sizeof(lzo_xint) == sizeof(lzo_uint32) || sizeof(lzo_xint) == sizeof(lzo_uint))
+
+#endif
+#undef ACCCHK_ASSERT
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_PUBLIC(int)
+_lzo_config_check(void)
+{
+ lzo_bool r = 1;
+ union { unsigned char c[2*sizeof(lzo_xint)]; lzo_xint l[2]; } u;
+ lzo_uintptr_t p;
+
+#if !defined(LZO_CFG_NO_CONFIG_CHECK)
+#if defined(LZO_ABI_BIG_ENDIAN)
+ u.l[0] = u.l[1] = 0; u.c[sizeof(lzo_xint) - 1] = 128;
+ r &= (u.l[0] == 128);
+#endif
+#if defined(LZO_ABI_LITTLE_ENDIAN)
+ u.l[0] = u.l[1] = 0; u.c[0] = 128;
+ r &= (u.l[0] == 128);
+#endif
+#if defined(LZO_UNALIGNED_OK_2)
+ p = (lzo_uintptr_t) (const lzo_voidp) &u.c[0];
+ u.l[0] = u.l[1] = 0;
+ r &= ((* (const lzo_ushortp) (p+1)) == 0);
+#endif
+#if defined(LZO_UNALIGNED_OK_4)
+ p = (lzo_uintptr_t) (const lzo_voidp) &u.c[0];
+ u.l[0] = u.l[1] = 0;
+ r &= ((* (const lzo_uint32p) (p+1)) == 0);
+#endif
+#endif
+
+ LZO_UNUSED(u); LZO_UNUSED(p);
+ return r == 1 ? LZO_E_OK : LZO_E_ERROR;
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+int __lzo_init_done = 0;
+
+LZO_PUBLIC(int)
+__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5,
+ int s6, int s7, int s8, int s9)
+{
+ int r;
+
+#if defined(__LZO_IN_MINILZO)
+#elif (LZO_CC_MSC && ((_MSC_VER) < 700))
+#else
+#define ACC_WANT_ACC_CHK_CH 1
+#undef ACCCHK_ASSERT
+#define ACCCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr)
+#include "miniacc.h"
+#endif
+#undef ACCCHK_ASSERT
+
+ __lzo_init_done = 1;
+
+ if (v == 0)
+ return LZO_E_ERROR;
+
+ r = (s1 == -1 || s1 == (int) sizeof(short)) &&
+ (s2 == -1 || s2 == (int) sizeof(int)) &&
+ (s3 == -1 || s3 == (int) sizeof(long)) &&
+ (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) &&
+ (s5 == -1 || s5 == (int) sizeof(lzo_uint)) &&
+ (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) &&
+ (s7 == -1 || s7 == (int) sizeof(char *)) &&
+ (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) &&
+ (s9 == -1 || s9 == (int) sizeof(lzo_callback_t));
+ if (!r)
+ return LZO_E_ERROR;
+
+ r = _lzo_config_check();
+ if (r != LZO_E_OK)
+ return r;
+
+ return r;
+}
+
+
+#if !defined(__LZO_IN_MINILZO)
+#include "lzo_dll.ch"
+#endif
+
+
+/*
+vi:ts=4:et
+*/
diff --git a/lzo/src/lzo_mchw.ch b/lzo/src/lzo_mchw.ch
new file mode 100644
index 00000000..a8c4fec5
--- /dev/null
+++ b/lzo/src/lzo_mchw.ch
@@ -0,0 +1,242 @@
+/* lzo_mchw.ch -- matching functions using a window
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+typedef struct
+{
+ int init;
+
+ lzo_uint look; /* bytes in lookahead buffer */
+
+ lzo_uint m_len;
+ lzo_uint m_off;
+
+ lzo_uint last_m_len;
+ lzo_uint last_m_off;
+
+ const lzo_bytep bp;
+ const lzo_bytep ip;
+ const lzo_bytep in;
+ const lzo_bytep in_end;
+ lzo_bytep out;
+
+ lzo_callback_p cb;
+
+ lzo_uint textsize; /* text size counter */
+ lzo_uint codesize; /* code size counter */
+ lzo_uint printcount; /* counter for reporting progress every 1K bytes */
+
+ /* some stats */
+ unsigned long lit_bytes;
+ unsigned long match_bytes;
+ unsigned long rep_bytes;
+ unsigned long lazy;
+
+#if defined(LZO1B)
+ lzo_uint r1_m_len;
+
+ /* some stats */
+ unsigned long r1_r, m3_r, m2_m, m3_m;
+#endif
+
+#if defined(LZO1C)
+ lzo_uint r1_m_len;
+ lzo_bytep m3;
+
+ /* some stats */
+ unsigned long r1_r, m3_r, m2_m, m3_m;
+#endif
+
+#if defined(LZO1F)
+ lzo_uint r1_lit;
+ lzo_uint r1_m_len;
+
+ /* some stats */
+ unsigned long r1_r, m2_m, m3_m;
+#endif
+
+#if defined(LZO1X) || defined(LZO1Y) || defined(LZO1Z)
+ lzo_uint r1_lit;
+ lzo_uint r1_m_len;
+
+ /* some stats */
+ unsigned long m1a_m, m1b_m, m2_m, m3_m, m4_m;
+ unsigned long lit1_r, lit2_r, lit3_r;
+#endif
+
+#if defined(LZO2A)
+ /* some stats */
+ unsigned long m1, m2, m3, m4;
+#endif
+}
+LZO_COMPRESS_T;
+
+
+#if (LZO_CC_BORLANDC && LZO_ARCH_I086) && (__BORLANDC__ < 0x0450)
+ /* work around a Borland C 3.1 bug */
+# define getbyte(c) ((c).ip < (c).in_end ? (c).ip +=1, (c).ip[-1] : (-1))
+#elif defined(__TURBOC__) && defined(__TOS__)
+ /* work around a bug in Turbo C / Pure C (Atari ST) */
+# define getbyte(c) ((c).ip < (c).in_end ? (int)(unsigned) *((c).ip)++ : (-1))
+#else
+# define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
+#endif
+
+#include "lzo_swd.ch"
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static int
+init_match ( LZO_COMPRESS_T *c, lzo_swd_p s,
+ const lzo_bytep dict, lzo_uint dict_len,
+ lzo_uint32 flags )
+{
+ int r;
+
+ assert(!c->init);
+ c->init = 1;
+
+ s->c = c;
+
+ c->last_m_len = c->last_m_off = 0;
+
+ c->textsize = c->codesize = c->printcount = 0;
+ c->lit_bytes = c->match_bytes = c->rep_bytes = 0;
+ c->lazy = 0;
+
+ r = swd_init(s,dict,dict_len);
+ if (r != 0)
+ return r;
+
+ s->use_best_off = (flags & 1) ? 1 : 0;
+ return r;
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static int
+find_match ( LZO_COMPRESS_T *c, lzo_swd_p s,
+ lzo_uint this_len, lzo_uint skip )
+{
+ assert(c->init);
+
+ if (skip > 0)
+ {
+ assert(this_len >= skip);
+ swd_accept(s, this_len - skip);
+ c->textsize += this_len - skip + 1;
+ }
+ else
+ {
+ assert(this_len <= 1);
+ c->textsize += this_len - skip;
+ }
+
+ s->m_len = 1;
+ s->m_len = THRESHOLD;
+#ifdef SWD_BEST_OFF
+ if (s->use_best_off)
+ lzo_memset(s->best_pos,0,sizeof(s->best_pos));
+#endif
+ swd_findbest(s);
+ c->m_len = s->m_len;
+ c->m_off = s->m_off;
+
+ swd_getbyte(s);
+
+ if (s->b_char < 0)
+ {
+ c->look = 0;
+ c->m_len = 0;
+ swd_exit(s);
+ }
+ else
+ {
+ c->look = s->look + 1;
+ }
+ c->bp = c->ip - c->look;
+
+#if 0
+ /* brute force match search */
+ if (c->m_len > THRESHOLD && c->m_len + 1 <= c->look)
+ {
+ const lzo_bytep ip = c->bp;
+ const lzo_bytep m = c->bp - c->m_off;
+ const lzo_bytep in = c->in;
+
+ if (ip - in > N)
+ in = ip - N;
+ for (;;)
+ {
+ while (*in != *ip)
+ in++;
+ if (in == ip)
+ break;
+ if (in != m)
+ if (lzo_memcmp(in,ip,c->m_len+1) == 0)
+ printf("%p %p %p %5d\n",in,ip,m,c->m_len);
+ in++;
+ }
+ }
+#endif
+
+ if (c->cb && c->cb->nprogress && c->textsize > c->printcount)
+ {
+ (*c->cb->nprogress)(c->cb, c->textsize, c->codesize, 0);
+ c->printcount += 1024;
+ }
+
+ return LZO_E_OK;
+}
+
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo_ptr.c b/lzo/src/lzo_ptr.c
new file mode 100644
index 00000000..064bddf1
--- /dev/null
+++ b/lzo/src/lzo_ptr.c
@@ -0,0 +1,92 @@
+/* lzo_ptr.c -- low-level pointer constructs
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#include "lzo_conf.h"
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_PUBLIC(lzo_uintptr_t)
+__lzo_ptr_linear(const lzo_voidp ptr)
+{
+ lzo_uintptr_t p;
+
+#if (LZO_ARCH_I086)
+ p = (((lzo_uintptr_t)(ACC_PTR_FP_SEG(ptr))) << (16 - ACC_MM_AHSHIFT)) + (ACC_PTR_FP_OFF(ptr));
+#elif (LZO_MM_PVP)
+ p = (lzo_uintptr_t) (ptr);
+ p = (p << 3) | (p >> 61);
+#else
+ p = (lzo_uintptr_t) PTR_LINEAR(ptr);
+#endif
+
+ return p;
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+LZO_PUBLIC(unsigned)
+__lzo_align_gap(const lzo_voidp ptr, lzo_uint size)
+{
+#if defined(__LZO_UINTPTR_T_IS_POINTER)
+ size_t n = (size_t) ptr;
+ n = (((n + size - 1) / size) * size) - n;
+#else
+ lzo_uintptr_t p, n;
+ p = __lzo_ptr_linear(ptr);
+ n = (((p + size - 1) / size) * size) - p;
+#endif
+
+ assert(size > 0);
+ assert((long)n >= 0);
+ assert(n <= size);
+ return (unsigned)n;
+}
+
+
+
+/*
+vi:ts=4:et
+*/
diff --git a/lzo/src/lzo_ptr.h b/lzo/src/lzo_ptr.h
new file mode 100644
index 00000000..e286a702
--- /dev/null
+++ b/lzo/src/lzo_ptr.h
@@ -0,0 +1,154 @@
+/* lzo_ptr.h -- low-level pointer constructs
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the library and is subject
+ to change.
+ */
+
+
+#ifndef __LZO_PTR_H
+#define __LZO_PTR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+// Integral types
+************************************************************************/
+
+#if !defined(lzo_uintptr_t)
+# if defined(__LZO_MMODEL_HUGE)
+# define lzo_uintptr_t unsigned long
+# else
+# define lzo_uintptr_t acc_uintptr_t
+# ifdef __ACC_INTPTR_T_IS_POINTER
+# define __LZO_UINTPTR_T_IS_POINTER 1
+# endif
+# endif
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Always use the safe (=integral) version for pointer-comparisions.
+ * The compiler should optimize away the additional casts anyway.
+ *
+ * Note that this only works if the representation and ordering
+ * of the pointer and the integral is the same (at bit level).
+ *
+ * Most 16-bit compilers have their own view about pointers -
+ * fortunately they don't care about comparing pointers
+ * that are pointing to Nirvana.
+ */
+
+#if (LZO_ARCH_I086)
+#define PTR(a) ((lzo_bytep) (a))
+/* only need the low bits of the pointer -> offset is ok */
+#define PTR_ALIGNED_4(a) ((ACC_PTR_FP_OFF(a) & 3) == 0)
+#define PTR_ALIGNED2_4(a,b) (((ACC_PTR_FP_OFF(a) | ACC_PTR_FP_OFF(b)) & 3) == 0)
+#elif (LZO_MM_PVP)
+#define PTR(a) ((lzo_bytep) (a))
+#define PTR_ALIGNED_8(a) ((((lzo_uintptr_t)(a)) >> 61) == 0)
+#define PTR_ALIGNED2_8(a,b) ((((lzo_uintptr_t)(a)|(lzo_uintptr_t)(b)) >> 61) == 0)
+#else
+#define PTR(a) ((lzo_uintptr_t) (a))
+#define PTR_LINEAR(a) PTR(a)
+#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0)
+#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0)
+#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0)
+#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0)
+#endif
+
+#define PTR_LT(a,b) (PTR(a) < PTR(b))
+#define PTR_GE(a,b) (PTR(a) >= PTR(b))
+#define PTR_DIFF(a,b) (PTR(a) - PTR(b))
+#define pd(a,b) ((lzo_uint) ((a)-(b)))
+
+
+LZO_EXTERN(lzo_uintptr_t)
+__lzo_ptr_linear(const lzo_voidp ptr);
+
+
+typedef union
+{
+ char a_char;
+ unsigned char a_uchar;
+ short a_short;
+ unsigned short a_ushort;
+ int a_int;
+ unsigned int a_uint;
+ long a_long;
+ unsigned long a_ulong;
+ lzo_int a_lzo_int;
+ lzo_uint a_lzo_uint;
+ lzo_int32 a_lzo_int32;
+ lzo_uint32 a_lzo_uint32;
+ ptrdiff_t a_ptrdiff_t;
+ lzo_uintptr_t a_lzo_uintptr_t;
+ lzo_voidp a_lzo_voidp;
+ void * a_void_p;
+ lzo_bytep a_lzo_bytep;
+ lzo_bytepp a_lzo_bytepp;
+ lzo_uintp a_lzo_uintp;
+ lzo_uint * a_lzo_uint_p;
+ lzo_uint32p a_lzo_uint32p;
+ lzo_uint32 * a_lzo_uint32_p;
+ unsigned char * a_uchar_p;
+ char * a_char_p;
+}
+lzo_full_align_t;
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo_str.c b/lzo/src/lzo_str.c
new file mode 100644
index 00000000..bf08960f
--- /dev/null
+++ b/lzo/src/lzo_str.c
@@ -0,0 +1,71 @@
+/* lzo_str.c -- string functions for the the LZO library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#include "lzo_conf.h"
+
+#undef lzo_memcmp
+#undef lzo_memcpy
+#undef lzo_memmove
+#undef lzo_memset
+
+
+/***********************************************************************
+// slow but portable <string.h> stuff, only used in assertions
+************************************************************************/
+
+#if !defined(__LZO_MMODEL_HUGE)
+# undef ACC_HAVE_MM_HUGE_PTR
+#endif
+#define acc_hsize_t lzo_uint
+#define acc_hvoid_p lzo_voidp
+#define acc_hbyte_p lzo_bytep
+#define ACCLIB_PUBLIC(r,f) LZO_PUBLIC(r) f
+#define acc_hmemcmp lzo_memcmp
+#define acc_hmemcpy lzo_memcpy
+#define acc_hmemmove lzo_memmove
+#define acc_hmemset lzo_memset
+#define ACC_WANT_ACCLIB_HMEMCPY 1
+#include "miniacc.h"
+#undef ACCLIB_PUBLIC
+
+
+/*
+vi:ts=4:et
+*/
diff --git a/lzo/src/lzo_swd.ch b/lzo/src/lzo_swd.ch
new file mode 100644
index 00000000..aa4b17c0
--- /dev/null
+++ b/lzo/src/lzo_swd.ch
@@ -0,0 +1,707 @@
+/* lzo_swd.ch -- sliding window dictionary
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#if (LZO_UINT_MAX < LZO_0xffffffffL)
+# error "LZO_UINT_MAX"
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#ifndef SWD_N
+# define SWD_N N
+#endif
+#ifndef SWD_F
+# define SWD_F F
+#endif
+#ifndef SWD_THRESHOLD
+# define SWD_THRESHOLD THRESHOLD
+#endif
+
+/* unsigned type for dictionary access - don't waste memory here */
+#if (0UL + SWD_N + SWD_F + SWD_F < 0UL + USHRT_MAX)
+ typedef unsigned short swd_uint;
+# define SWD_UINT_MAX USHRT_MAX
+#elif (0UL + SWD_N + SWD_F + SWD_F < 0UL + UINT_MAX)
+ typedef unsigned swd_uint;
+# define SWD_UINT_MAX UINT_MAX
+#else
+ typedef lzo_uint swd_uint;
+# define SWD_UINT_MAX LZO_UINT_MAX
+#endif
+#define swd_uintp swd_uint __LZO_MMODEL *
+#define SWD_UINT(x) ((swd_uint)(x))
+
+
+#ifndef SWD_HSIZE
+# define SWD_HSIZE 16384
+#endif
+#ifndef SWD_MAX_CHAIN
+# define SWD_MAX_CHAIN 2048
+#endif
+
+#if !defined(HEAD3)
+#if 1
+# define HEAD3(b,p) \
+ ((DMUL(0x9f5f,(((((lzo_xint)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
+#else
+# define HEAD3(b,p) \
+ ((DMUL(0x9f5f,(((((lzo_xint)b[p+2]<<5)^b[p+1])<<5)^b[p]))>>5) & (SWD_HSIZE-1))
+#endif
+#endif
+
+#if (SWD_THRESHOLD == 1) && !defined(HEAD2)
+# if 1 && defined(LZO_UNALIGNED_OK_2)
+# define HEAD2(b,p) (* (lzo_ushortp) &(b[p]))
+# else
+# define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
+# endif
+# define NIL2 SWD_UINT_MAX
+#endif
+
+
+typedef struct
+{
+/* public - "built-in" */
+ lzo_uint n;
+ lzo_uint f;
+ lzo_uint threshold;
+
+/* public - configuration */
+ lzo_uint max_chain;
+ lzo_uint nice_length;
+ lzo_bool use_best_off;
+ lzo_uint lazy_insert;
+
+/* public - output */
+ lzo_uint m_len;
+ lzo_uint m_off;
+ lzo_uint look;
+ int b_char;
+#if defined(SWD_BEST_OFF)
+ lzo_uint best_off[ SWD_BEST_OFF ];
+#endif
+
+/* semi public */
+ LZO_COMPRESS_T *c;
+ lzo_uint m_pos;
+#if defined(SWD_BEST_OFF)
+ lzo_uint best_pos[ SWD_BEST_OFF ];
+#endif
+
+/* private */
+ const lzo_bytep dict;
+ const lzo_bytep dict_end;
+ lzo_uint dict_len;
+
+/* private */
+ lzo_uint ip; /* input pointer (lookahead) */
+ lzo_uint bp; /* buffer pointer */
+ lzo_uint rp; /* remove pointer */
+ lzo_uint b_size;
+
+ lzo_bytep b_wrap;
+
+ lzo_uint node_count;
+ lzo_uint first_rp;
+
+#if defined(__LZO_MMODEL_HUGE)
+# define A(type, n) ((((n) * sizeof(type)) + 3UL) &~ 3UL)
+
+# define O_b(s) (0L)
+# define O_head3(s) (O_b(s) + A(char, 0UL + SWD_N + SWD_F + SWD_F))
+# define O_succ3(s) (O_head3(s) + A(swd_uint, 0UL + SWD_HSIZE))
+# define O_best3(s) (O_succ3(s) + A(swd_uint, 0UL + SWD_N + SWD_F))
+# define O_llen3(s) (O_best3(s) + A(swd_uint, 0UL + SWD_N + SWD_F))
+# ifdef HEAD2
+# define O_head2(s) (O_llen3(s) + A(swd_uint, 0UL + SWD_HSIZE))
+# define O_END(s) (O_head2(s) + A(swd_uint, 0UL + 65536L))
+# else
+# define O_END(s) (O_llen3(s) + A(swd_uint, 0UL + SWD_HSIZE))
+# endif
+
+# define S_DEF(s,type,off) ((type) ((lzo_bytep)s + 0L + sizeof(*s) + off))
+# define s_b(s) S_DEF(s, lzo_bytep, O_b(s))
+# define s_head3(s) S_DEF(s, swd_uintp, O_head3(s))
+# define s_succ3(s) S_DEF(s, swd_uintp, O_succ3(s))
+# define s_best3(s) S_DEF(s, swd_uintp, O_best3(s))
+# define s_llen3(s) S_DEF(s, swd_uintp, O_llen3(s))
+# ifdef HEAD2
+# define s_head2(s) S_DEF(s, swd_uintp, O_head2(s))
+# endif
+
+#elif defined(__LZO_CHECKER)
+ /* malloc arrays of the exact size to detect any overrun */
+ unsigned char *b;
+ swd_uint *head3;
+ swd_uint *succ3;
+ swd_uint *best3;
+ swd_uint *llen3;
+# ifdef HEAD2
+ swd_uint *head2;
+# endif
+
+#else
+ unsigned char b [ SWD_N + SWD_F + SWD_F ];
+ swd_uint head3 [ SWD_HSIZE ];
+ swd_uint succ3 [ SWD_N + SWD_F ];
+ swd_uint best3 [ SWD_N + SWD_F ];
+ swd_uint llen3 [ SWD_HSIZE ];
+# ifdef HEAD2
+ swd_uint head2 [ 65536L ];
+# endif
+#endif
+}
+lzo_swd_t;
+#define lzo_swd_p lzo_swd_t __LZO_MMODEL *
+
+
+#if defined(__LZO_MMODEL_HUGE)
+#define SIZEOF_LZO_SWD_T O_END(0)
+#else
+#define s_b(s) s->b
+#define s_head3(s) s->head3
+#define s_succ3(s) s->succ3
+#define s_best3(s) s->best3
+#define s_llen3(s) s->llen3
+#ifdef HEAD2
+#define s_head2(s) s->head2
+#endif
+#define SIZEOF_LZO_SWD_T (sizeof(lzo_swd_t))
+#endif
+
+
+/* Access macro for head3.
+ * head3[key] may be uninitialized, but then its value will never be used.
+ */
+#if defined(__LZO_CHECKER)
+# define s_get_head3(s,key) \
+ ((s->llen3[key] == 0) ? SWD_UINT_MAX : s_head3(s)[key])
+#else
+# define s_get_head3(s,key) s_head3(s)[key]
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static
+void swd_initdict(lzo_swd_p s, const lzo_bytep dict, lzo_uint dict_len)
+{
+ s->dict = s->dict_end = NULL;
+ s->dict_len = 0;
+
+ if (!dict || dict_len <= 0)
+ return;
+ if (dict_len > s->n)
+ {
+ dict += dict_len - s->n;
+ dict_len = s->n;
+ }
+
+ s->dict = dict;
+ s->dict_len = dict_len;
+ s->dict_end = dict + dict_len;
+ lzo_memcpy(s_b(s),dict,dict_len);
+ s->ip = dict_len;
+}
+
+
+static
+void swd_insertdict(lzo_swd_p s, lzo_uint node, lzo_uint len)
+{
+ lzo_uint key;
+
+ s->node_count = s->n - len;
+ s->first_rp = node;
+
+ while (len-- > 0)
+ {
+ key = HEAD3(s_b(s),node);
+ s_succ3(s)[node] = s_get_head3(s,key);
+ s_head3(s)[key] = SWD_UINT(node);
+ s_best3(s)[node] = SWD_UINT(s->f + 1);
+ s_llen3(s)[key]++;
+ assert(s_llen3(s)[key] <= SWD_N);
+
+#ifdef HEAD2
+ key = HEAD2(s_b(s),node);
+ s_head2(s)[key] = SWD_UINT(node);
+#endif
+
+ node++;
+ }
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static
+int swd_init(lzo_swd_p s, const lzo_bytep dict, lzo_uint dict_len)
+{
+ lzo_uint i = 0;
+ int c = 0;
+
+#if defined(__LZO_CHECKER)
+ s->b = malloc(SWD_N + SWD_F + SWD_F);
+ s->head3 = malloc(sizeof(swd_uint) * SWD_HSIZE);
+ s->succ3 = malloc(sizeof(swd_uint) * (SWD_N + SWD_F));
+ s->best3 = malloc(sizeof(swd_uint) * (SWD_N + SWD_F));
+ s->llen3 = malloc(sizeof(swd_uint) * SWD_HSIZE);
+#ifdef HEAD2
+ s->head2 = malloc(sizeof(swd_uint) * 65536L);
+#endif
+#endif
+
+ s->n = SWD_N;
+ s->f = SWD_F;
+ s->threshold = SWD_THRESHOLD;
+
+ /* defaults */
+ s->max_chain = SWD_MAX_CHAIN;
+ s->nice_length = SWD_F;
+ s->use_best_off = 0;
+ s->lazy_insert = 0;
+
+ s->b_size = s->n + s->f;
+#if 0
+ if (2 * s->f >= s->n || s->b_size + s->f >= SWD_UINT_MAX)
+ return LZO_E_ERROR;
+#else
+ LZO_COMPILE_TIME_ASSERT(!(0ul + 2 * SWD_F >= SWD_N))
+ LZO_COMPILE_TIME_ASSERT(!(0ul + SWD_N + SWD_F + SWD_F >= SWD_UINT_MAX))
+#endif
+ s->b_wrap = s_b(s) + s->b_size;
+ s->node_count = s->n;
+
+ lzo_memset(s_llen3(s), 0, sizeof(s_llen3(s)[0]) * (lzo_uint)SWD_HSIZE);
+#ifdef HEAD2
+#if 1
+ lzo_memset(s_head2(s), 0xff, sizeof(s_head2(s)[0]) * 65536L);
+ assert(s_head2(s)[0] == NIL2);
+#else
+ for (i = 0; i < 65536L; i++)
+ s_head2(s)[i] = NIL2;
+#endif
+#endif
+
+ s->ip = 0;
+ swd_initdict(s,dict,dict_len);
+ s->bp = s->ip;
+ s->first_rp = s->ip;
+
+ assert(s->ip + s->f <= s->b_size);
+#if 1
+ s->look = (lzo_uint) (s->c->in_end - s->c->ip);
+ if (s->look > 0)
+ {
+ if (s->look > s->f)
+ s->look = s->f;
+ lzo_memcpy(&s_b(s)[s->ip],s->c->ip,s->look);
+ s->c->ip += s->look;
+ s->ip += s->look;
+ }
+#else
+ s->look = 0;
+ while (s->look < s->f)
+ {
+ if ((c = getbyte(*(s->c))) < 0)
+ break;
+ s_b(s)[s->ip] = LZO_BYTE(c);
+ s->ip++;
+ s->look++;
+ }
+#endif
+ if (s->ip == s->b_size)
+ s->ip = 0;
+
+ if (s->look >= 2 && s->dict_len > 0)
+ swd_insertdict(s,0,s->dict_len);
+
+ s->rp = s->first_rp;
+ if (s->rp >= s->node_count)
+ s->rp -= s->node_count;
+ else
+ s->rp += s->b_size - s->node_count;
+
+#if defined(__LZO_CHECKER)
+ /* initialize memory for the first few HEAD3 (if s->ip is not far
+ * enough ahead to do this job for us). The value doesn't matter. */
+ if (s->look < 3)
+ lzo_memset(&s_b(s)[s->bp+s->look],0,3);
+#endif
+
+ LZO_UNUSED(i);
+ LZO_UNUSED(c);
+ return LZO_E_OK;
+}
+
+
+static
+void swd_exit(lzo_swd_p s)
+{
+#if defined(__LZO_CHECKER)
+ /* free in reverse order of allocations */
+#ifdef HEAD2
+ free(s->head2); s->head2 = NULL;
+#endif
+ free(s->llen3); s->llen3 = NULL;
+ free(s->best3); s->best3 = NULL;
+ free(s->succ3); s->succ3 = NULL;
+ free(s->head3); s->head3 = NULL;
+ free(s->b); s->b = NULL;
+#else
+ LZO_UNUSED(s);
+#endif
+}
+
+
+#define swd_pos2off(s,pos) \
+ (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static __lzo_inline
+void swd_getbyte(lzo_swd_p s)
+{
+ int c;
+
+ if ((c = getbyte(*(s->c))) < 0)
+ {
+ if (s->look > 0)
+ --s->look;
+#if defined(__LZO_CHECKER)
+ /* initialize memory - value doesn't matter */
+ s_b(s)[s->ip] = 0;
+ if (s->ip < s->f)
+ s->b_wrap[s->ip] = 0;
+#endif
+ }
+ else
+ {
+ s_b(s)[s->ip] = LZO_BYTE(c);
+ if (s->ip < s->f)
+ s->b_wrap[s->ip] = LZO_BYTE(c);
+ }
+ if (++s->ip == s->b_size)
+ s->ip = 0;
+ if (++s->bp == s->b_size)
+ s->bp = 0;
+ if (++s->rp == s->b_size)
+ s->rp = 0;
+}
+
+
+/***********************************************************************
+// remove node from lists
+************************************************************************/
+
+static __lzo_inline
+void swd_remove_node(lzo_swd_p s, lzo_uint node)
+{
+ if (s->node_count == 0)
+ {
+ lzo_uint key;
+
+#ifdef LZO_DEBUG
+ if (s->first_rp != LZO_UINT_MAX)
+ {
+ if (node != s->first_rp)
+ printf("Remove %5u: %5u %5u %5u %5u %6u %6u\n",
+ node, s->rp, s->ip, s->bp, s->first_rp,
+ s->ip - node, s->ip - s->bp);
+ assert(node == s->first_rp);
+ s->first_rp = LZO_UINT_MAX;
+ }
+#endif
+
+ key = HEAD3(s_b(s),node);
+ assert(s_llen3(s)[key] > 0);
+ --s_llen3(s)[key];
+
+#ifdef HEAD2
+ key = HEAD2(s_b(s),node);
+ assert(s_head2(s)[key] != NIL2);
+ if ((lzo_uint) s_head2(s)[key] == node)
+ s_head2(s)[key] = NIL2;
+#endif
+ }
+ else
+ --s->node_count;
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static
+void swd_accept(lzo_swd_p s, lzo_uint n)
+{
+ assert(n <= s->look);
+
+ while (n--)
+ {
+ lzo_uint key;
+
+ swd_remove_node(s,s->rp);
+
+ /* add bp into HEAD3 */
+ key = HEAD3(s_b(s),s->bp);
+ s_succ3(s)[s->bp] = s_get_head3(s,key);
+ s_head3(s)[key] = SWD_UINT(s->bp);
+ s_best3(s)[s->bp] = SWD_UINT(s->f + 1);
+ s_llen3(s)[key]++;
+ assert(s_llen3(s)[key] <= SWD_N);
+
+#ifdef HEAD2
+ /* add bp into HEAD2 */
+ key = HEAD2(s_b(s),s->bp);
+ s_head2(s)[key] = SWD_UINT(s->bp);
+#endif
+
+ swd_getbyte(s);
+ }
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static
+void swd_search(lzo_swd_p s, lzo_uint node, lzo_uint cnt)
+{
+ const lzo_bytep p1;
+ const lzo_bytep p2;
+ const lzo_bytep px;
+ lzo_uint m_len = s->m_len;
+ const lzo_bytep b = s_b(s);
+ const lzo_bytep bp = s_b(s) + s->bp;
+ const lzo_bytep bx = s_b(s) + s->bp + s->look;
+ unsigned char scan_end1;
+
+ assert(s->m_len > 0);
+
+ scan_end1 = bp[m_len - 1];
+ for ( ; cnt-- > 0; node = s_succ3(s)[node])
+ {
+ p1 = bp;
+ p2 = b + node;
+ px = bx;
+
+ assert(m_len < s->look);
+
+ if (
+#if 1
+ p2[m_len - 1] == scan_end1 &&
+ p2[m_len] == p1[m_len] &&
+#endif
+ p2[0] == p1[0] &&
+ p2[1] == p1[1])
+ {
+ lzo_uint i;
+ assert(lzo_memcmp(bp,&b[node],3) == 0);
+
+#if 0 && defined(LZO_UNALIGNED_OK_4)
+ p1 += 3; p2 += 3;
+ while (p1 < px && * (const lzo_uint32p) p1 == * (const lzo_uint32p) p2)
+ p1 += 4, p2 += 4;
+ while (p1 < px && *p1 == *p2)
+ p1 += 1, p2 += 1;
+#else
+ p1 += 2; p2 += 2;
+ do {} while (++p1 < px && *p1 == *++p2);
+#endif
+ i = pd(p1, bp);
+
+#ifdef LZO_DEBUG
+ if (lzo_memcmp(bp,&b[node],i) != 0)
+ printf("%5ld %5ld %02x%02x %02x%02x\n",
+ (long)s->bp, (long) node,
+ bp[0], bp[1], b[node], b[node+1]);
+#endif
+ assert(lzo_memcmp(bp,&b[node],i) == 0);
+
+#if defined(SWD_BEST_OFF)
+ if (i < SWD_BEST_OFF)
+ {
+ if (s->best_pos[i] == 0)
+ s->best_pos[i] = node + 1;
+ }
+#endif
+ if (i > m_len)
+ {
+ s->m_len = m_len = i;
+ s->m_pos = node;
+ if (m_len == s->look)
+ return;
+ if (m_len >= s->nice_length)
+ return;
+ if (m_len > (lzo_uint) s_best3(s)[node])
+ return;
+ scan_end1 = bp[m_len - 1];
+ }
+ }
+ }
+}
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#ifdef HEAD2
+
+static
+lzo_bool swd_search2(lzo_swd_p s)
+{
+ lzo_uint key;
+
+ assert(s->look >= 2);
+ assert(s->m_len > 0);
+
+ key = s_head2(s)[ HEAD2(s_b(s),s->bp) ];
+ if (key == NIL2)
+ return 0;
+#ifdef LZO_DEBUG
+ if (lzo_memcmp(&s_b(s)[s->bp],&s_b(s)[key],2) != 0)
+ printf("%5ld %5ld %02x%02x %02x%02x\n", (long)s->bp, (long)key,
+ s_b(s)[s->bp], s_b(s)[s->bp+1], s_b(s)[key], s_b(s)[key+1]);
+#endif
+ assert(lzo_memcmp(&s_b(s)[s->bp],&s_b(s)[key],2) == 0);
+#if defined(SWD_BEST_OFF)
+ if (s->best_pos[2] == 0)
+ s->best_pos[2] = key + 1;
+#endif
+
+ if (s->m_len < 2)
+ {
+ s->m_len = 2;
+ s->m_pos = key;
+ }
+ return 1;
+}
+
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+static
+void swd_findbest(lzo_swd_p s)
+{
+ lzo_uint key;
+ lzo_uint cnt, node;
+ lzo_uint len;
+
+ assert(s->m_len > 0);
+
+ /* get current head, add bp into HEAD3 */
+ key = HEAD3(s_b(s),s->bp);
+ node = s_succ3(s)[s->bp] = s_get_head3(s,key);
+ cnt = s_llen3(s)[key]++;
+ assert(s_llen3(s)[key] <= SWD_N + SWD_F);
+ if (cnt > s->max_chain && s->max_chain > 0)
+ cnt = s->max_chain;
+ s_head3(s)[key] = SWD_UINT(s->bp);
+
+ s->b_char = s_b(s)[s->bp];
+ len = s->m_len;
+ if (s->m_len >= s->look)
+ {
+ if (s->look == 0)
+ s->b_char = -1;
+ s->m_off = 0;
+ s_best3(s)[s->bp] = SWD_UINT(s->f + 1);
+ }
+ else
+ {
+#ifdef HEAD2
+ if (swd_search2(s))
+#endif
+ if (s->look >= 3)
+ swd_search(s,node,cnt);
+ if (s->m_len > len)
+ s->m_off = swd_pos2off(s,s->m_pos);
+ s_best3(s)[s->bp] = SWD_UINT(s->m_len);
+
+#if defined(SWD_BEST_OFF)
+ if (s->use_best_off)
+ {
+ int i;
+ for (i = 2; i < SWD_BEST_OFF; i++)
+ if (s->best_pos[i] > 0)
+ s->best_off[i] = swd_pos2off(s,s->best_pos[i]-1);
+ else
+ s->best_off[i] = 0;
+ }
+#endif
+ }
+
+ swd_remove_node(s,s->rp);
+
+#ifdef HEAD2
+ /* add bp into HEAD2 */
+ key = HEAD2(s_b(s),s->bp);
+ s_head2(s)[key] = SWD_UINT(s->bp);
+#endif
+}
+
+
+#undef HEAD3
+#undef HEAD2
+#undef s_get_head3
+
+
+/*
+vi:ts=4:et
+*/
+
diff --git a/lzo/src/lzo_util.c b/lzo/src/lzo_util.c
new file mode 100644
index 00000000..c3bfb407
--- /dev/null
+++ b/lzo/src/lzo_util.c
@@ -0,0 +1,165 @@
+/* lzo_util.c -- utilities for the LZO library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#include "lzo_conf.h"
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* If you use the LZO library in a product, I would appreciate that you
+ * keep this copyright string in the executable of your product.
+.*/
+
+const char __lzo_copyright[] =
+#if !defined(__LZO_IN_MINLZO)
+ /* save space as some people want a really small decompressor */
+ LZO_VERSION_STRING;
+#else
+ "\r\n\n"
+ "LZO data compression library.\n"
+ "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Markus Franz Xaver Johannes Oberhumer\n"
+ "<markus@oberhumer.com>\n"
+ "http://www.oberhumer.com $\n\n"
+ "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n"
+ "$Built: " __DATE__ " " __TIME__ " $\n"
+ "$Info: " LZO_INFO_STRING " $\n";
+#endif
+
+
+LZO_PUBLIC(const lzo_bytep)
+lzo_copyright(void)
+{
+#if (LZO_OS_DOS16 && LZO_CC_TURBOC)
+ return (lzo_voidp) __lzo_copyright;
+#else
+ return (const lzo_bytep) __lzo_copyright;
+#endif
+}
+
+LZO_PUBLIC(unsigned)
+lzo_version(void)
+{
+ return LZO_VERSION;
+}
+
+LZO_PUBLIC(const char *)
+lzo_version_string(void)
+{
+ return LZO_VERSION_STRING;
+}
+
+LZO_PUBLIC(const char *)
+lzo_version_date(void)
+{
+ return LZO_VERSION_DATE;
+}
+
+LZO_PUBLIC(const lzo_charp)
+_lzo_version_string(void)
+{
+ return LZO_VERSION_STRING;
+}
+
+LZO_PUBLIC(const lzo_charp)
+_lzo_version_date(void)
+{
+ return LZO_VERSION_DATE;
+}
+
+
+/***********************************************************************
+// adler32 checksum
+// adapted from free code by Mark Adler <madler@alumni.caltech.edu>
+// see http://www.zlib.org/
+************************************************************************/
+
+#define LZO_BASE 65521u /* largest prime smaller than 65536 */
+#define LZO_NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1
+#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1);
+#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2);
+#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4);
+#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8);
+
+LZO_PUBLIC(lzo_uint32)
+lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len)
+{
+ lzo_uint32 s1 = adler & 0xffff;
+ lzo_uint32 s2 = (adler >> 16) & 0xffff;
+ unsigned k;
+
+ if (buf == NULL)
+ return 1;
+
+ while (len > 0)
+ {
+ k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX;
+ len -= k;
+ if (k >= 16) do
+ {
+ LZO_DO16(buf,0);
+ buf += 16;
+ k -= 16;
+ } while (k >= 16);
+ if (k != 0) do
+ {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k > 0);
+ s1 %= LZO_BASE;
+ s2 %= LZO_BASE;
+ }
+ return (s2 << 16) | s1;
+}
+
+#undef LZO_DO1
+#undef LZO_DO2
+#undef LZO_DO4
+#undef LZO_DO8
+#undef LZO_DO16
+
+
+/*
+vi:ts=4:et
+*/
diff --git a/lzo/src/miniacc.h b/lzo/src/miniacc.h
new file mode 100644
index 00000000..315a20b2
--- /dev/null
+++ b/lzo/src/miniacc.h
@@ -0,0 +1,6553 @@
+/* ACC --- Automatic Compiler Configuration
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __ACC_H_INCLUDED
+#define __ACC_H_INCLUDED 1
+#define ACC_VERSION 20080430L
+#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
+# define __CYGWIN__ __CYGWIN32__
+#endif
+#if defined(__IBMCPP__) && !defined(__IBMC__)
+# define __IBMC__ __IBMCPP__
+#endif
+#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER)
+# define __INTEL_COMPILER __ICL
+#endif
+#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE)
+# define _ALL_SOURCE 1
+#endif
+#if defined(__mips__) && defined(__R5900__)
+# if !defined(__LONG_MAX__)
+# define __LONG_MAX__ 9223372036854775807L
+# endif
+#endif
+#if defined(__INTEL_COMPILER) && defined(__linux__)
+# pragma warning(disable: 193)
+#endif
+#if defined(__KEIL__) && defined(__C166__)
+# pragma warning disable = 322
+#elif 0 && defined(__C251__)
+# pragma warning disable = 322
+#endif
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
+# if (_MSC_VER >= 1300)
+# pragma warning(disable: 4668)
+# endif
+#endif
+#if defined(__POCC__) && defined(_WIN32)
+# if (__POCC__ >= 400)
+# pragma warn(disable: 2216)
+# endif
+#endif
+#if 0 && defined(__WATCOMC__)
+# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060)
+# pragma warning 203 9
+# endif
+#endif
+#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__)
+# pragma option -h
+#endif
+#if defined(ACC_CFG_NO_CONFIG_HEADER)
+#elif defined(ACC_CFG_CONFIG_HEADER)
+# include ACC_CFG_CONFIG_HEADER
+#else
+#endif
+#if defined(ACC_CFG_NO_LIMITS_H)
+#elif defined(ACC_LIBC_NAKED) || defined(ACC_BROKEN_LIMITS_H)
+#ifndef __ACC_FALLBACK_LIMITS_H_INCLUDED
+#define __ACC_FALLBACK_LIMITS_H_INCLUDED
+#undef CHAR_BIT
+#define CHAR_BIT 8
+#ifndef MB_LEN_MAX
+#define MB_LEN_MAX 1
+#endif
+#ifndef __SCHAR_MAX__
+#define __SCHAR_MAX__ 127
+#endif
+#ifndef __SHRT_MAX__
+#define __SHRT_MAX__ 32767
+#endif
+#ifndef __INT_MAX__
+#define __INT_MAX__ 2147483647
+#endif
+#ifndef __LONG_MAX__
+#if defined(__alpha__) || defined(_LP64) || defined(__MIPS_PSX2__)
+#define __LONG_MAX__ 9223372036854775807L
+#else
+#define __LONG_MAX__ 2147483647L
+#endif
+#endif
+#undef SCHAR_MIN
+#undef SCHAR_MAX
+#undef UCHAR_MAX
+#define SCHAR_MIN (-1 - SCHAR_MAX)
+#define SCHAR_MAX (__SCHAR_MAX__)
+#define UCHAR_MAX (SCHAR_MAX * 2 + 1)
+#undef SHRT_MIN
+#undef SHRT_MAX
+#undef USHRT_MAX
+#define SHRT_MIN (-1 - SHRT_MAX)
+#define SHRT_MAX (__SHRT_MAX__)
+#if ((__INT_MAX__) == (__SHRT_MAX__))
+#define USHRT_MAX (SHRT_MAX * 2U + 1U)
+#else
+#define USHRT_MAX (SHRT_MAX * 2 + 1)
+#endif
+#undef INT_MIN
+#undef INT_MAX
+#undef UINT_MAX
+#define INT_MIN (-1 - INT_MAX)
+#define INT_MAX (__INT_MAX__)
+#define UINT_MAX (INT_MAX * 2U + 1U)
+#undef LONG_MIN
+#undef LONG_MAX
+#undef ULONG_MAX
+#define LONG_MIN (-1L - LONG_MAX)
+#define LONG_MAX ((__LONG_MAX__) + 0L)
+#define ULONG_MAX (LONG_MAX * 2UL + 1UL)
+#undef CHAR_MIN
+#undef CHAR_MAX
+#if defined(__CHAR_UNSIGNED__) || defined(_CHAR_UNSIGNED)
+#define CHAR_MIN 0
+#define CHAR_MAX UCHAR_MAX
+#else
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+#endif
+#endif
+#else
+# include <limits.h>
+#endif
+#if 0
+#define ACC_0xffffL 0xfffful
+#define ACC_0xffffffffL 0xfffffffful
+#else
+#define ACC_0xffffL 65535ul
+#define ACC_0xffffffffL 4294967295ul
+#endif
+#if (ACC_0xffffL == ACC_0xffffffffL)
+# error "your preprocessor is broken 1"
+#endif
+#if (16ul * 16384ul != 262144ul)
+# error "your preprocessor is broken 2"
+#endif
+#if 0
+#if (32767 >= 4294967295ul)
+# error "your preprocessor is broken 3"
+#endif
+#if (65535u >= 4294967295ul)
+# error "your preprocessor is broken 4"
+#endif
+#endif
+#if (UINT_MAX == ACC_0xffffL)
+#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__)
+# if !defined(MSDOS)
+# define MSDOS 1
+# endif
+# if !defined(_MSDOS)
+# define _MSDOS 1
+# endif
+#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX)
+# if (__VERSION == 520) && (MB_LEN_MAX == 1)
+# if !defined(__AZTEC_C__)
+# define __AZTEC_C__ __VERSION
+# endif
+# if !defined(__DOS__)
+# define __DOS__ 1
+# endif
+# endif
+#endif
+#endif
+#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == ACC_0xffffL)
+# define ptrdiff_t long
+# define _PTRDIFF_T_DEFINED
+#endif
+#if (UINT_MAX == ACC_0xffffL)
+# undef __ACC_RENAME_A
+# undef __ACC_RENAME_B
+# if defined(__AZTEC_C__) && defined(__DOS__)
+# define __ACC_RENAME_A 1
+# elif defined(_MSC_VER) && defined(MSDOS)
+# if (_MSC_VER < 600)
+# define __ACC_RENAME_A 1
+# elif (_MSC_VER < 700)
+# define __ACC_RENAME_B 1
+# endif
+# elif defined(__TSC__) && defined(__OS2__)
+# define __ACC_RENAME_A 1
+# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410)
+# define __ACC_RENAME_A 1
+# elif defined(__PACIFIC__) && defined(DOS)
+# if !defined(__far)
+# define __far far
+# endif
+# if !defined(__near)
+# define __near near
+# endif
+# endif
+# if defined(__ACC_RENAME_A)
+# if !defined(__cdecl)
+# define __cdecl cdecl
+# endif
+# if !defined(__far)
+# define __far far
+# endif
+# if !defined(__huge)
+# define __huge huge
+# endif
+# if !defined(__near)
+# define __near near
+# endif
+# if !defined(__pascal)
+# define __pascal pascal
+# endif
+# if !defined(__huge)
+# define __huge huge
+# endif
+# elif defined(__ACC_RENAME_B)
+# if !defined(__cdecl)
+# define __cdecl _cdecl
+# endif
+# if !defined(__far)
+# define __far _far
+# endif
+# if !defined(__huge)
+# define __huge _huge
+# endif
+# if !defined(__near)
+# define __near _near
+# endif
+# if !defined(__pascal)
+# define __pascal _pascal
+# endif
+# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+# if !defined(__cdecl)
+# define __cdecl cdecl
+# endif
+# if !defined(__pascal)
+# define __pascal pascal
+# endif
+# endif
+# undef __ACC_RENAME_A
+# undef __ACC_RENAME_B
+#endif
+#if (UINT_MAX == ACC_0xffffL)
+#if defined(__AZTEC_C__) && defined(__DOS__)
+# define ACC_BROKEN_CDECL_ALT_SYNTAX 1
+#elif defined(_MSC_VER) && defined(MSDOS)
+# if (_MSC_VER < 600)
+# define ACC_BROKEN_INTEGRAL_CONSTANTS 1
+# endif
+# if (_MSC_VER < 700)
+# define ACC_BROKEN_INTEGRAL_PROMOTION 1
+# define ACC_BROKEN_SIZEOF 1
+# endif
+#elif defined(__PACIFIC__) && defined(DOS)
+# define ACC_BROKEN_INTEGRAL_CONSTANTS 1
+#elif defined(__TURBOC__) && defined(__MSDOS__)
+# if (__TURBOC__ < 0x0150)
+# define ACC_BROKEN_CDECL_ALT_SYNTAX 1
+# define ACC_BROKEN_INTEGRAL_CONSTANTS 1
+# define ACC_BROKEN_INTEGRAL_PROMOTION 1
+# endif
+# if (__TURBOC__ < 0x0200)
+# define ACC_BROKEN_SIZEOF 1
+# endif
+# if (__TURBOC__ < 0x0400) && defined(__cplusplus)
+# define ACC_BROKEN_CDECL_ALT_SYNTAX 1
+# endif
+#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+# define ACC_BROKEN_CDECL_ALT_SYNTAX 1
+# define ACC_BROKEN_SIZEOF 1
+#endif
+#endif
+#if defined(__WATCOMC__) && (__WATCOMC__ < 900)
+# define ACC_BROKEN_INTEGRAL_CONSTANTS 1
+#endif
+#if defined(_CRAY) && defined(_CRAY1)
+# define ACC_BROKEN_SIGNED_RIGHT_SHIFT 1
+#endif
+#define ACC_PP_STRINGIZE(x) #x
+#define ACC_PP_MACRO_EXPAND(x) ACC_PP_STRINGIZE(x)
+#define ACC_PP_CONCAT2(a,b) a ## b
+#define ACC_PP_CONCAT3(a,b,c) a ## b ## c
+#define ACC_PP_CONCAT4(a,b,c,d) a ## b ## c ## d
+#define ACC_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define ACC_PP_ECONCAT2(a,b) ACC_PP_CONCAT2(a,b)
+#define ACC_PP_ECONCAT3(a,b,c) ACC_PP_CONCAT3(a,b,c)
+#define ACC_PP_ECONCAT4(a,b,c,d) ACC_PP_CONCAT4(a,b,c,d)
+#define ACC_PP_ECONCAT5(a,b,c,d,e) ACC_PP_CONCAT5(a,b,c,d,e)
+#if 1
+#define ACC_CPP_STRINGIZE(x) #x
+#define ACC_CPP_MACRO_EXPAND(x) ACC_CPP_STRINGIZE(x)
+#define ACC_CPP_CONCAT2(a,b) a ## b
+#define ACC_CPP_CONCAT3(a,b,c) a ## b ## c
+#define ACC_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d
+#define ACC_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define ACC_CPP_ECONCAT2(a,b) ACC_CPP_CONCAT2(a,b)
+#define ACC_CPP_ECONCAT3(a,b,c) ACC_CPP_CONCAT3(a,b,c)
+#define ACC_CPP_ECONCAT4(a,b,c,d) ACC_CPP_CONCAT4(a,b,c,d)
+#define ACC_CPP_ECONCAT5(a,b,c,d,e) ACC_CPP_CONCAT5(a,b,c,d,e)
+#endif
+#define __ACC_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o))
+#if 1 && defined(__cplusplus)
+# if !defined(__STDC_CONSTANT_MACROS)
+# define __STDC_CONSTANT_MACROS 1
+# endif
+# if !defined(__STDC_LIMIT_MACROS)
+# define __STDC_LIMIT_MACROS 1
+# endif
+#endif
+#if defined(__cplusplus)
+# define ACC_EXTERN_C extern "C"
+#else
+# define ACC_EXTERN_C extern
+#endif
+#if !defined(__ACC_OS_OVERRIDE)
+#if defined(ACC_OS_FREESTANDING)
+# define ACC_INFO_OS "freestanding"
+#elif defined(ACC_OS_EMBEDDED)
+# define ACC_INFO_OS "embedded"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+# define ACC_OS_EMBEDDED 1
+# define ACC_INFO_OS "embedded"
+#elif defined(__CYGWIN__) && defined(__GNUC__)
+# define ACC_OS_CYGWIN 1
+# define ACC_INFO_OS "cygwin"
+#elif defined(__EMX__) && defined(__GNUC__)
+# define ACC_OS_EMX 1
+# define ACC_INFO_OS "emx"
+#elif defined(__BEOS__)
+# define ACC_OS_BEOS 1
+# define ACC_INFO_OS "beos"
+#elif defined(__Lynx__)
+# define ACC_OS_LYNXOS 1
+# define ACC_INFO_OS "lynxos"
+#elif defined(__OS400__)
+# define ACC_OS_OS400 1
+# define ACC_INFO_OS "os400"
+#elif defined(__QNX__)
+# define ACC_OS_QNX 1
+# define ACC_INFO_OS "qnx"
+#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460)
+# define ACC_OS_DOS32 1
+# define ACC_INFO_OS "dos32"
+#elif defined(__BORLANDC__) && defined(__DPMI16__)
+# define ACC_OS_DOS16 1
+# define ACC_INFO_OS "dos16"
+#elif defined(__ZTC__) && defined(DOS386)
+# define ACC_OS_DOS32 1
+# define ACC_INFO_OS "dos32"
+#elif defined(__OS2__) || defined(__OS2V2__)
+# if (UINT_MAX == ACC_0xffffL)
+# define ACC_OS_OS216 1
+# define ACC_INFO_OS "os216"
+# elif (UINT_MAX == ACC_0xffffffffL)
+# define ACC_OS_OS2 1
+# define ACC_INFO_OS "os2"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64)
+# define ACC_OS_WIN64 1
+# define ACC_INFO_OS "win64"
+#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__)
+# define ACC_OS_WIN32 1
+# define ACC_INFO_OS "win32"
+#elif defined(__MWERKS__) && defined(__INTEL__)
+# define ACC_OS_WIN32 1
+# define ACC_INFO_OS "win32"
+#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows)
+# if (UINT_MAX == ACC_0xffffL)
+# define ACC_OS_WIN16 1
+# define ACC_INFO_OS "win16"
+# elif (UINT_MAX == ACC_0xffffffffL)
+# define ACC_OS_WIN32 1
+# define ACC_INFO_OS "win32"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS))
+# if (UINT_MAX == ACC_0xffffL)
+# define ACC_OS_DOS16 1
+# define ACC_INFO_OS "dos16"
+# elif (UINT_MAX == ACC_0xffffffffL)
+# define ACC_OS_DOS32 1
+# define ACC_INFO_OS "dos32"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__WATCOMC__)
+# if defined(__NT__) && (UINT_MAX == ACC_0xffffL)
+# define ACC_OS_DOS16 1
+# define ACC_INFO_OS "dos16"
+# elif defined(__NT__) && (__WATCOMC__ < 1100)
+# define ACC_OS_WIN32 1
+# define ACC_INFO_OS "win32"
+# elif defined(__linux__) || defined(__LINUX__)
+# define ACC_OS_POSIX 1
+# define ACC_INFO_OS "posix"
+# else
+# error "please specify a target using the -bt compiler option"
+# endif
+#elif defined(__palmos__)
+# define ACC_OS_PALMOS 1
+# define ACC_INFO_OS "palmos"
+#elif defined(__TOS__) || defined(__atarist__)
+# define ACC_OS_TOS 1
+# define ACC_INFO_OS "tos"
+#elif defined(macintosh) && !defined(__ppc__)
+# define ACC_OS_MACCLASSIC 1
+# define ACC_INFO_OS "macclassic"
+#elif defined(__VMS)
+# define ACC_OS_VMS 1
+# define ACC_INFO_OS "vms"
+#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+# define ACC_OS_CONSOLE 1
+# define ACC_OS_CONSOLE_PS2 1
+# define ACC_INFO_OS "console"
+# define ACC_INFO_OS_CONSOLE "ps2"
+#elif (defined(__mips__) && defined(__psp__))
+# define ACC_OS_CONSOLE 1
+# define ACC_OS_CONSOLE_PSP 1
+# define ACC_INFO_OS "console"
+# define ACC_INFO_OS_CONSOLE "psp"
+#else
+# define ACC_OS_POSIX 1
+# define ACC_INFO_OS "posix"
+#endif
+#if (ACC_OS_POSIX)
+# if defined(_AIX) || defined(__AIX__) || defined(__aix__)
+# define ACC_OS_POSIX_AIX 1
+# define ACC_INFO_OS_POSIX "aix"
+# elif defined(__FreeBSD__)
+# define ACC_OS_POSIX_FREEBSD 1
+# define ACC_INFO_OS_POSIX "freebsd"
+# elif defined(__hpux__) || defined(__hpux)
+# define ACC_OS_POSIX_HPUX 1
+# define ACC_INFO_OS_POSIX "hpux"
+# elif defined(__INTERIX)
+# define ACC_OS_POSIX_INTERIX 1
+# define ACC_INFO_OS_POSIX "interix"
+# elif defined(__IRIX__) || defined(__irix__)
+# define ACC_OS_POSIX_IRIX 1
+# define ACC_INFO_OS_POSIX "irix"
+# elif defined(__linux__) || defined(__linux) || defined(__LINUX__)
+# define ACC_OS_POSIX_LINUX 1
+# define ACC_INFO_OS_POSIX "linux"
+# elif defined(__APPLE__) || defined(__MACOS__)
+# define ACC_OS_POSIX_MACOSX 1
+# define ACC_INFO_OS_POSIX "macosx"
+# elif defined(__minix__) || defined(__minix)
+# define ACC_OS_POSIX_MINIX 1
+# define ACC_INFO_OS_POSIX "minix"
+# elif defined(__NetBSD__)
+# define ACC_OS_POSIX_NETBSD 1
+# define ACC_INFO_OS_POSIX "netbsd"
+# elif defined(__OpenBSD__)
+# define ACC_OS_POSIX_OPENBSD 1
+# define ACC_INFO_OS_POSIX "openbsd"
+# elif defined(__osf__)
+# define ACC_OS_POSIX_OSF 1
+# define ACC_INFO_OS_POSIX "osf"
+# elif defined(__solaris__) || defined(__sun)
+# if defined(__SVR4) || defined(__svr4__)
+# define ACC_OS_POSIX_SOLARIS 1
+# define ACC_INFO_OS_POSIX "solaris"
+# else
+# define ACC_OS_POSIX_SUNOS 1
+# define ACC_INFO_OS_POSIX "sunos"
+# endif
+# elif defined(__ultrix__) || defined(__ultrix)
+# define ACC_OS_POSIX_ULTRIX 1
+# define ACC_INFO_OS_POSIX "ultrix"
+# elif defined(_UNICOS)
+# define ACC_OS_POSIX_UNICOS 1
+# define ACC_INFO_OS_POSIX "unicos"
+# else
+# define ACC_OS_POSIX_UNKNOWN 1
+# define ACC_INFO_OS_POSIX "unknown"
+# endif
+#endif
+#endif
+#if (ACC_OS_DOS16 || ACC_OS_OS216 || ACC_OS_WIN16)
+# if (UINT_MAX != ACC_0xffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != ACC_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if (ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_WIN32 || ACC_OS_WIN64)
+# if (UINT_MAX != ACC_0xffffffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != ACC_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__)
+# define ACC_CC_CILLY 1
+# define ACC_INFO_CC "Cilly"
+# if defined(__CILLY__)
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__CILLY__)
+# else
+# define ACC_INFO_CCVER "unknown"
+# endif
+#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__)
+# define ACC_CC_SDCC 1
+# define ACC_INFO_CC "sdcc"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(SDCC)
+#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__)
+# define ACC_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__)
+# define ACC_INFO_CC "Pathscale C"
+# define ACC_INFO_CCVER __PATHSCALE__
+#elif defined(__INTEL_COMPILER)
+# define ACC_CC_INTELC 1
+# define ACC_INFO_CC "Intel C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__INTEL_COMPILER)
+# if defined(_WIN32) || defined(_WIN64)
+# define ACC_CC_SYNTAX_MSC 1
+# else
+# define ACC_CC_SYNTAX_GNUC 1
+# endif
+#elif defined(__POCC__) && defined(_WIN32)
+# define ACC_CC_PELLESC 1
+# define ACC_INFO_CC "Pelles C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__POCC__)
+#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__)
+# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+# define ACC_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# else
+# define ACC_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# endif
+# define ACC_INFO_CC "llvm-gcc"
+# define ACC_INFO_CCVER __VERSION__
+#elif defined(__GNUC__) && defined(__VERSION__)
+# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+# define ACC_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# elif defined(__GNUC_MINOR__)
+# define ACC_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# else
+# define ACC_CC_GNUC (__GNUC__ * 0x10000L)
+# endif
+# define ACC_INFO_CC "gcc"
+# define ACC_INFO_CCVER __VERSION__
+#elif defined(__ACK__) && defined(_ACK)
+# define ACC_CC_ACK 1
+# define ACC_INFO_CC "Amsterdam Compiler Kit C"
+# define ACC_INFO_CCVER "unknown"
+#elif defined(__AZTEC_C__)
+# define ACC_CC_AZTECC 1
+# define ACC_INFO_CC "Aztec C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__AZTEC_C__)
+#elif defined(__BORLANDC__)
+# define ACC_CC_BORLANDC 1
+# define ACC_INFO_CC "Borland C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__BORLANDC__)
+#elif defined(_CRAYC) && defined(_RELEASE)
+# define ACC_CC_CRAYC 1
+# define ACC_INFO_CC "Cray C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(_RELEASE)
+#elif defined(__DMC__) && defined(__SC__)
+# define ACC_CC_DMC 1
+# define ACC_INFO_CC "Digital Mars C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__DMC__)
+#elif defined(__DECC)
+# define ACC_CC_DECC 1
+# define ACC_INFO_CC "DEC C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__DECC)
+#elif defined(__HIGHC__)
+# define ACC_CC_HIGHC 1
+# define ACC_INFO_CC "MetaWare High C"
+# define ACC_INFO_CCVER "unknown"
+#elif defined(__IAR_SYSTEMS_ICC__)
+# define ACC_CC_IARC 1
+# define ACC_INFO_CC "IAR C"
+# if defined(__VER__)
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__VER__)
+# else
+# define ACC_INFO_CCVER "unknown"
+# endif
+#elif defined(__IBMC__)
+# define ACC_CC_IBMC 1
+# define ACC_INFO_CC "IBM C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__IBMC__)
+#elif defined(__KEIL__) && defined(__C166__)
+# define ACC_CC_KEILC 1
+# define ACC_INFO_CC "Keil C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__C166__)
+#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL)
+# define ACC_CC_LCCWIN32 1
+# define ACC_INFO_CC "lcc-win32"
+# define ACC_INFO_CCVER "unknown"
+#elif defined(__LCC__)
+# define ACC_CC_LCC 1
+# define ACC_INFO_CC "lcc"
+# if defined(__LCC_VERSION__)
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__LCC_VERSION__)
+# else
+# define ACC_INFO_CCVER "unknown"
+# endif
+#elif defined(_MSC_VER)
+# define ACC_CC_MSC 1
+# define ACC_INFO_CC "Microsoft C"
+# if defined(_MSC_FULL_VER)
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(_MSC_VER) "." ACC_PP_MACRO_EXPAND(_MSC_FULL_VER)
+# else
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(_MSC_VER)
+# endif
+#elif defined(__MWERKS__)
+# define ACC_CC_MWERKS 1
+# define ACC_INFO_CC "Metrowerks C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__MWERKS__)
+#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386)
+# define ACC_CC_NDPC 1
+# define ACC_INFO_CC "Microway NDP C"
+# define ACC_INFO_CCVER "unknown"
+#elif defined(__PACIFIC__)
+# define ACC_CC_PACIFICC 1
+# define ACC_INFO_CC "Pacific C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__PACIFIC__)
+#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__))
+# define ACC_CC_PGI 1
+# define ACC_INFO_CC "Portland Group PGI C"
+# define ACC_INFO_CCVER "unknown"
+#elif defined(__PUREC__) && defined(__TOS__)
+# define ACC_CC_PUREC 1
+# define ACC_INFO_CC "Pure C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__PUREC__)
+#elif defined(__SC__) && defined(__ZTC__)
+# define ACC_CC_SYMANTECC 1
+# define ACC_INFO_CC "Symantec C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__SC__)
+#elif defined(__SUNPRO_C)
+# define ACC_INFO_CC "SunPro C"
+# if ((__SUNPRO_C)+0 > 0)
+# define ACC_CC_SUNPROC __SUNPRO_C
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__SUNPRO_C)
+# else
+# define ACC_CC_SUNPROC 1
+# define ACC_INFO_CCVER "unknown"
+# endif
+#elif defined(__SUNPRO_CC)
+# define ACC_INFO_CC "SunPro C"
+# if ((__SUNPRO_CC)+0 > 0)
+# define ACC_CC_SUNPROC __SUNPRO_CC
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__SUNPRO_CC)
+# else
+# define ACC_CC_SUNPROC 1
+# define ACC_INFO_CCVER "unknown"
+# endif
+#elif defined(__TINYC__)
+# define ACC_CC_TINYC 1
+# define ACC_INFO_CC "Tiny C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__TINYC__)
+#elif defined(__TSC__)
+# define ACC_CC_TOPSPEEDC 1
+# define ACC_INFO_CC "TopSpeed C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__TSC__)
+#elif defined(__WATCOMC__)
+# define ACC_CC_WATCOMC 1
+# define ACC_INFO_CC "Watcom C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__WATCOMC__)
+#elif defined(__TURBOC__)
+# define ACC_CC_TURBOC 1
+# define ACC_INFO_CC "Turbo C"
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__TURBOC__)
+#elif defined(__ZTC__)
+# define ACC_CC_ZORTECHC 1
+# define ACC_INFO_CC "Zortech C"
+# if (__ZTC__ == 0x310)
+# define ACC_INFO_CCVER "0x310"
+# else
+# define ACC_INFO_CCVER ACC_PP_MACRO_EXPAND(__ZTC__)
+# endif
+#else
+# define ACC_CC_UNKNOWN 1
+# define ACC_INFO_CC "unknown"
+# define ACC_INFO_CCVER "unknown"
+#endif
+#if 0 && (ACC_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)
+# error "ACC_CC_MSC: _MSC_FULL_VER is not defined"
+#endif
+#if !defined(__ACC_ARCH_OVERRIDE) && !defined(ACC_ARCH_GENERIC) && defined(_CRAY)
+# if (UINT_MAX > ACC_0xffffffffL) && defined(_CRAY)
+# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E)
+# define ACC_ARCH_CRAY_MPP 1
+# elif defined(_CRAY1)
+# define ACC_ARCH_CRAY_PVP 1
+# endif
+# endif
+#endif
+#if !defined(__ACC_ARCH_OVERRIDE)
+#if defined(ACC_ARCH_GENERIC)
+# define ACC_INFO_ARCH "generic"
+#elif (ACC_OS_DOS16 || ACC_OS_OS216 || ACC_OS_WIN16)
+# define ACC_ARCH_I086 1
+# define ACC_ARCH_IA16 1
+# define ACC_INFO_ARCH "i086"
+#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
+# define ACC_ARCH_ALPHA 1
+# define ACC_INFO_ARCH "alpha"
+#elif (ACC_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E))
+# define ACC_ARCH_ALPHA 1
+# define ACC_INFO_ARCH "alpha"
+#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
+# define ACC_ARCH_AMD64 1
+# define ACC_INFO_ARCH "amd64"
+#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB))
+# define ACC_ARCH_ARM 1
+# define ACC_ARCH_ARM_THUMB 1
+# define ACC_INFO_ARCH "arm_thumb"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
+# define ACC_ARCH_ARM 1
+# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1)
+# define ACC_ARCH_ARM_THUMB 1
+# define ACC_INFO_ARCH "arm_thumb"
+# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2)
+# define ACC_INFO_ARCH "arm"
+# else
+# define ACC_INFO_ARCH "arm"
+# endif
+#elif defined(__arm__) || defined(_M_ARM)
+# define ACC_ARCH_ARM 1
+# define ACC_INFO_ARCH "arm"
+#elif (UINT_MAX <= ACC_0xffffL) && defined(__AVR__)
+# define ACC_ARCH_AVR 1
+# define ACC_INFO_ARCH "avr"
+#elif defined(__bfin__)
+# define ACC_ARCH_BLACKFIN 1
+# define ACC_INFO_ARCH "blackfin"
+#elif (UINT_MAX == ACC_0xffffL) && defined(__C166__)
+# define ACC_ARCH_C166 1
+# define ACC_INFO_ARCH "c166"
+#elif defined(__cris__)
+# define ACC_ARCH_CRIS 1
+# define ACC_INFO_ARCH "cris"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__)
+# define ACC_ARCH_EZ80 1
+# define ACC_INFO_ARCH "ez80"
+#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+# define ACC_ARCH_H8300 1
+# define ACC_INFO_ARCH "h8300"
+#elif defined(__hppa__) || defined(__hppa)
+# define ACC_ARCH_HPPA 1
+# define ACC_INFO_ARCH "hppa"
+#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
+# define ACC_ARCH_I386 1
+# define ACC_ARCH_IA32 1
+# define ACC_INFO_ARCH "i386"
+#elif (ACC_CC_ZORTECHC && defined(__I86__))
+# define ACC_ARCH_I386 1
+# define ACC_ARCH_IA32 1
+# define ACC_INFO_ARCH "i386"
+#elif (ACC_OS_DOS32 && ACC_CC_HIGHC) && defined(_I386)
+# define ACC_ARCH_I386 1
+# define ACC_ARCH_IA32 1
+# define ACC_INFO_ARCH "i386"
+#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
+# define ACC_ARCH_IA64 1
+# define ACC_INFO_ARCH "ia64"
+#elif (UINT_MAX == ACC_0xffffL) && defined(__m32c__)
+# define ACC_ARCH_M16C 1
+# define ACC_INFO_ARCH "m16c"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__)
+# define ACC_ARCH_M16C 1
+# define ACC_INFO_ARCH "m16c"
+#elif defined(__m32r__)
+# define ACC_ARCH_M32R 1
+# define ACC_INFO_ARCH "m32r"
+#elif (ACC_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K)
+# define ACC_ARCH_M68K 1
+# define ACC_INFO_ARCH "m68k"
+#elif (UINT_MAX == ACC_0xffffL) && defined(__C251__)
+# define ACC_ARCH_MCS251 1
+# define ACC_INFO_ARCH "mcs251"
+#elif (UINT_MAX == ACC_0xffffL) && defined(__C51__)
+# define ACC_ARCH_MCS51 1
+# define ACC_INFO_ARCH "mcs51"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__)
+# define ACC_ARCH_MCS51 1
+# define ACC_INFO_ARCH "mcs51"
+#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
+# define ACC_ARCH_MIPS 1
+# define ACC_INFO_ARCH "mips"
+#elif (UINT_MAX == ACC_0xffffL) && defined(__MSP430__)
+# define ACC_ARCH_MSP430 1
+# define ACC_INFO_ARCH "msp430"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__)
+# define ACC_ARCH_MSP430 1
+# define ACC_INFO_ARCH "msp430"
+#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
+# define ACC_ARCH_POWERPC 1
+# define ACC_INFO_ARCH "powerpc"
+#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
+# define ACC_ARCH_S390 1
+# define ACC_INFO_ARCH "s390"
+#elif defined(__sh__) || defined(_M_SH)
+# define ACC_ARCH_SH 1
+# define ACC_INFO_ARCH "sh"
+#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
+# define ACC_ARCH_SPARC 1
+# define ACC_INFO_ARCH "sparc"
+#elif defined(__SPU__)
+# define ACC_ARCH_SPU 1
+# define ACC_INFO_ARCH "spu"
+#elif (UINT_MAX == ACC_0xffffL) && defined(__z80)
+# define ACC_ARCH_Z80 1
+# define ACC_INFO_ARCH "z80"
+#elif (ACC_ARCH_CRAY_PVP)
+# if defined(_CRAYSV1)
+# define ACC_ARCH_CRAY_SV1 1
+# define ACC_INFO_ARCH "cray_sv1"
+# elif (_ADDR64)
+# define ACC_ARCH_CRAY_T90 1
+# define ACC_INFO_ARCH "cray_t90"
+# elif (_ADDR32)
+# define ACC_ARCH_CRAY_YMP 1
+# define ACC_INFO_ARCH "cray_ymp"
+# else
+# define ACC_ARCH_CRAY_XMP 1
+# define ACC_INFO_ARCH "cray_xmp"
+# endif
+#else
+# define ACC_ARCH_UNKNOWN 1
+# define ACC_INFO_ARCH "unknown"
+#endif
+#endif
+#if 1 && (ACC_ARCH_UNKNOWN) && (ACC_OS_DOS32 || ACC_OS_OS2)
+# error "FIXME - missing define for CPU architecture"
+#endif
+#if 1 && (ACC_ARCH_UNKNOWN) && (ACC_OS_WIN32)
+# error "FIXME - missing WIN32 define for CPU architecture"
+#endif
+#if 1 && (ACC_ARCH_UNKNOWN) && (ACC_OS_WIN64)
+# error "FIXME - missing WIN64 define for CPU architecture"
+#endif
+#if (ACC_OS_OS216 || ACC_OS_WIN16)
+# define ACC_ARCH_I086PM 1
+# define ACC_ARCH_IA16PM 1
+#elif 1 && (ACC_OS_DOS16 && defined(BLX286))
+# define ACC_ARCH_I086PM 1
+# define ACC_ARCH_IA16PM 1
+#elif 1 && (ACC_OS_DOS16 && defined(DOSX286))
+# define ACC_ARCH_I086PM 1
+# define ACC_ARCH_IA16PM 1
+#elif 1 && (ACC_OS_DOS16 && ACC_CC_BORLANDC && defined(__DPMI16__))
+# define ACC_ARCH_I086PM 1
+# define ACC_ARCH_IA16PM 1
+#endif
+#if defined(ACC_ARCH_ARM_THUMB) && !defined(ACC_ARCH_ARM)
+# error "this should not happen"
+#endif
+#if defined(ACC_ARCH_I086PM) && !defined(ACC_ARCH_I086)
+# error "this should not happen"
+#endif
+#if (ACC_ARCH_I086)
+# if (UINT_MAX != ACC_0xffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != ACC_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if (ACC_ARCH_I386)
+# if (UINT_MAX != ACC_0xffffL) && defined(__i386_int16__)
+# error "this should not happen"
+# endif
+# if (UINT_MAX != ACC_0xffffffffL) && !defined(__i386_int16__)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != ACC_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if !defined(__ACC_MM_OVERRIDE)
+#if (ACC_ARCH_I086)
+#if (UINT_MAX != ACC_0xffffL)
+# error "this should not happen"
+#endif
+#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM)
+# define ACC_MM_TINY 1
+#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM)
+# define ACC_MM_HUGE 1
+#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL)
+# define ACC_MM_SMALL 1
+#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM)
+# define ACC_MM_MEDIUM 1
+#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM)
+# define ACC_MM_COMPACT 1
+#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL)
+# define ACC_MM_LARGE 1
+#elif (ACC_CC_AZTECC)
+# if defined(_LARGE_CODE) && defined(_LARGE_DATA)
+# define ACC_MM_LARGE 1
+# elif defined(_LARGE_CODE)
+# define ACC_MM_MEDIUM 1
+# elif defined(_LARGE_DATA)
+# define ACC_MM_COMPACT 1
+# else
+# define ACC_MM_SMALL 1
+# endif
+#elif (ACC_CC_ZORTECHC && defined(__VCM__))
+# define ACC_MM_LARGE 1
+#else
+# error "unknown memory model"
+#endif
+#if (ACC_OS_DOS16 || ACC_OS_OS216 || ACC_OS_WIN16)
+#define ACC_HAVE_MM_HUGE_PTR 1
+#define ACC_HAVE_MM_HUGE_ARRAY 1
+#if (ACC_MM_TINY)
+# undef ACC_HAVE_MM_HUGE_ARRAY
+#endif
+#if (ACC_CC_AZTECC || ACC_CC_PACIFICC || ACC_CC_ZORTECHC)
+# undef ACC_HAVE_MM_HUGE_PTR
+# undef ACC_HAVE_MM_HUGE_ARRAY
+#elif (ACC_CC_DMC || ACC_CC_SYMANTECC)
+# undef ACC_HAVE_MM_HUGE_ARRAY
+#elif (ACC_CC_MSC && defined(_QC))
+# undef ACC_HAVE_MM_HUGE_ARRAY
+# if (_MSC_VER < 600)
+# undef ACC_HAVE_MM_HUGE_PTR
+# endif
+#elif (ACC_CC_TURBOC && (__TURBOC__ < 0x0295))
+# undef ACC_HAVE_MM_HUGE_ARRAY
+#endif
+#if (ACC_ARCH_I086PM) && !defined(ACC_HAVE_MM_HUGE_PTR)
+# if (ACC_OS_DOS16)
+# error "this should not happen"
+# elif (ACC_CC_ZORTECHC)
+# else
+# error "this should not happen"
+# endif
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0200))
+ extern void __near __cdecl _AHSHIFT(void);
+# define ACC_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (ACC_CC_DMC || ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)
+ extern void __near __cdecl _AHSHIFT(void);
+# define ACC_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (ACC_CC_MSC || ACC_CC_TOPSPEEDC)
+ extern void __near __cdecl _AHSHIFT(void);
+# define ACC_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (ACC_CC_TURBOC && (__TURBOC__ >= 0x0295))
+ extern void __near __cdecl _AHSHIFT(void);
+# define ACC_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif ((ACC_CC_AZTECC || ACC_CC_PACIFICC || ACC_CC_TURBOC) && ACC_OS_DOS16)
+# define ACC_MM_AHSHIFT 12
+#elif (ACC_CC_WATCOMC)
+ extern unsigned char _HShift;
+# define ACC_MM_AHSHIFT ((unsigned) _HShift)
+#else
+# error "FIXME - implement ACC_MM_AHSHIFT"
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+#elif (ACC_ARCH_C166)
+#if !defined(__MODEL__)
+# error "FIXME - C166 __MODEL__"
+#elif ((__MODEL__) == 0)
+# define ACC_MM_SMALL 1
+#elif ((__MODEL__) == 1)
+# define ACC_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define ACC_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define ACC_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define ACC_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define ACC_MM_XSMALL 1
+#else
+# error "FIXME - C166 __MODEL__"
+#endif
+#elif (ACC_ARCH_MCS251)
+#if !defined(__MODEL__)
+# error "FIXME - MCS251 __MODEL__"
+#elif ((__MODEL__) == 0)
+# define ACC_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define ACC_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define ACC_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define ACC_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define ACC_MM_XSMALL 1
+#else
+# error "FIXME - MCS251 __MODEL__"
+#endif
+#elif (ACC_ARCH_MCS51)
+#if !defined(__MODEL__)
+# error "FIXME - MCS51 __MODEL__"
+#elif ((__MODEL__) == 1)
+# define ACC_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define ACC_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define ACC_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define ACC_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define ACC_MM_XSMALL 1
+#else
+# error "FIXME - MCS51 __MODEL__"
+#endif
+#elif (ACC_ARCH_CRAY_PVP)
+# define ACC_MM_PVP 1
+#else
+# define ACC_MM_FLAT 1
+#endif
+#if (ACC_MM_COMPACT)
+# define ACC_INFO_MM "compact"
+#elif (ACC_MM_FLAT)
+# define ACC_INFO_MM "flat"
+#elif (ACC_MM_HUGE)
+# define ACC_INFO_MM "huge"
+#elif (ACC_MM_LARGE)
+# define ACC_INFO_MM "large"
+#elif (ACC_MM_MEDIUM)
+# define ACC_INFO_MM "medium"
+#elif (ACC_MM_PVP)
+# define ACC_INFO_MM "pvp"
+#elif (ACC_MM_SMALL)
+# define ACC_INFO_MM "small"
+#elif (ACC_MM_TINY)
+# define ACC_INFO_MM "tiny"
+#else
+# error "unknown memory model"
+#endif
+#endif
+#if defined(SIZEOF_SHORT)
+# define ACC_SIZEOF_SHORT (SIZEOF_SHORT)
+#endif
+#if defined(SIZEOF_INT)
+# define ACC_SIZEOF_INT (SIZEOF_INT)
+#endif
+#if defined(SIZEOF_LONG)
+# define ACC_SIZEOF_LONG (SIZEOF_LONG)
+#endif
+#if defined(SIZEOF_LONG_LONG)
+# define ACC_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG)
+#endif
+#if defined(SIZEOF___INT16)
+# define ACC_SIZEOF___INT16 (SIZEOF___INT16)
+#endif
+#if defined(SIZEOF___INT32)
+# define ACC_SIZEOF___INT32 (SIZEOF___INT32)
+#endif
+#if defined(SIZEOF___INT64)
+# define ACC_SIZEOF___INT64 (SIZEOF___INT64)
+#endif
+#if defined(SIZEOF_VOID_P)
+# define ACC_SIZEOF_VOID_P (SIZEOF_VOID_P)
+#endif
+#if defined(SIZEOF_SIZE_T)
+# define ACC_SIZEOF_SIZE_T (SIZEOF_SIZE_T)
+#endif
+#if defined(SIZEOF_PTRDIFF_T)
+# define ACC_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T)
+#endif
+#define __ACC_LSR(x,b) (((x)+0ul) >> (b))
+#if !defined(ACC_SIZEOF_SHORT)
+# if (ACC_ARCH_CRAY_PVP)
+# define ACC_SIZEOF_SHORT 8
+# elif (USHRT_MAX == ACC_0xffffL)
+# define ACC_SIZEOF_SHORT 2
+# elif (__ACC_LSR(USHRT_MAX,7) == 1)
+# define ACC_SIZEOF_SHORT 1
+# elif (__ACC_LSR(USHRT_MAX,15) == 1)
+# define ACC_SIZEOF_SHORT 2
+# elif (__ACC_LSR(USHRT_MAX,31) == 1)
+# define ACC_SIZEOF_SHORT 4
+# elif (__ACC_LSR(USHRT_MAX,63) == 1)
+# define ACC_SIZEOF_SHORT 8
+# elif (__ACC_LSR(USHRT_MAX,127) == 1)
+# define ACC_SIZEOF_SHORT 16
+# else
+# error "ACC_SIZEOF_SHORT"
+# endif
+#endif
+#if !defined(ACC_SIZEOF_INT)
+# if (ACC_ARCH_CRAY_PVP)
+# define ACC_SIZEOF_INT 8
+# elif (UINT_MAX == ACC_0xffffL)
+# define ACC_SIZEOF_INT 2
+# elif (UINT_MAX == ACC_0xffffffffL)
+# define ACC_SIZEOF_INT 4
+# elif (__ACC_LSR(UINT_MAX,7) == 1)
+# define ACC_SIZEOF_INT 1
+# elif (__ACC_LSR(UINT_MAX,15) == 1)
+# define ACC_SIZEOF_INT 2
+# elif (__ACC_LSR(UINT_MAX,31) == 1)
+# define ACC_SIZEOF_INT 4
+# elif (__ACC_LSR(UINT_MAX,63) == 1)
+# define ACC_SIZEOF_INT 8
+# elif (__ACC_LSR(UINT_MAX,127) == 1)
+# define ACC_SIZEOF_INT 16
+# else
+# error "ACC_SIZEOF_INT"
+# endif
+#endif
+#if !defined(ACC_SIZEOF_LONG)
+# if (ULONG_MAX == ACC_0xffffffffL)
+# define ACC_SIZEOF_LONG 4
+# elif (__ACC_LSR(ULONG_MAX,7) == 1)
+# define ACC_SIZEOF_LONG 1
+# elif (__ACC_LSR(ULONG_MAX,15) == 1)
+# define ACC_SIZEOF_LONG 2
+# elif (__ACC_LSR(ULONG_MAX,31) == 1)
+# define ACC_SIZEOF_LONG 4
+# elif (__ACC_LSR(ULONG_MAX,63) == 1)
+# define ACC_SIZEOF_LONG 8
+# elif (__ACC_LSR(ULONG_MAX,127) == 1)
+# define ACC_SIZEOF_LONG 16
+# else
+# error "ACC_SIZEOF_LONG"
+# endif
+#endif
+#if !defined(ACC_SIZEOF_LONG_LONG) && !defined(ACC_SIZEOF___INT64)
+#if (ACC_SIZEOF_LONG > 0 && ACC_SIZEOF_LONG < 8)
+# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__)
+# if (ACC_CC_GNUC >= 0x030300ul)
+# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0)
+# define ACC_SIZEOF_LONG_LONG ACC_SIZEOF_LONG
+# elif (__ACC_LSR(__LONG_LONG_MAX__,30) == 1)
+# define ACC_SIZEOF_LONG_LONG 4
+# endif
+# endif
+# endif
+#endif
+#endif
+#if !defined(ACC_SIZEOF_LONG_LONG) && !defined(ACC_SIZEOF___INT64)
+#if (ACC_SIZEOF_LONG > 0 && ACC_SIZEOF_LONG < 8)
+#if (ACC_ARCH_I086 && ACC_CC_DMC)
+#elif (ACC_CC_CILLY) && defined(__GNUC__)
+# define ACC_SIZEOF_LONG_LONG 8
+#elif (ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define ACC_SIZEOF_LONG_LONG 8
+#elif ((ACC_OS_WIN32 || ACC_OS_WIN64 || defined(_WIN32)) && ACC_CC_MSC && (_MSC_VER >= 1400))
+# define ACC_SIZEOF_LONG_LONG 8
+#elif (ACC_OS_WIN64 || defined(_WIN64))
+# define ACC_SIZEOF___INT64 8
+#elif (ACC_ARCH_I386 && (ACC_CC_DMC))
+# define ACC_SIZEOF_LONG_LONG 8
+#elif (ACC_ARCH_I386 && (ACC_CC_SYMANTECC && (__SC__ >= 0x700)))
+# define ACC_SIZEOF_LONG_LONG 8
+#elif (ACC_ARCH_I386 && (ACC_CC_INTELC && defined(__linux__)))
+# define ACC_SIZEOF_LONG_LONG 8
+#elif (ACC_ARCH_I386 && (ACC_CC_MWERKS || ACC_CC_PELLESC || ACC_CC_PGI || ACC_CC_SUNPROC))
+# define ACC_SIZEOF_LONG_LONG 8
+#elif (ACC_ARCH_I386 && (ACC_CC_INTELC || ACC_CC_MSC))
+# define ACC_SIZEOF___INT64 8
+#elif ((ACC_OS_WIN32 || defined(_WIN32)) && (ACC_CC_MSC))
+# define ACC_SIZEOF___INT64 8
+#elif (ACC_ARCH_I386 && (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0520)))
+# define ACC_SIZEOF___INT64 8
+#elif (ACC_ARCH_I386 && (ACC_CC_WATCOMC && (__WATCOMC__ >= 1100)))
+# define ACC_SIZEOF___INT64 8
+#elif (ACC_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64))
+# define ACC_SIZEOF___INT64 8
+#elif (ACC_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+# define ACC_SIZEOF_LONG_LONG 8
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+# define ACC_SIZEOF_LONG_LONG 8
+#elif (ACC_CC_SDCC) && (ACC_SIZEOF_INT == 2)
+#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define ACC_SIZEOF_LONG_LONG 8
+#endif
+#endif
+#endif
+#if defined(__cplusplus) && defined(ACC_CC_GNUC)
+# if (ACC_CC_GNUC < 0x020800ul)
+# undef ACC_SIZEOF_LONG_LONG
+# endif
+#endif
+#if defined(ACC_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
+# undef ACC_SIZEOF_LONG_LONG
+#endif
+#if !defined(ACC_SIZEOF_VOID_P)
+#if (ACC_ARCH_I086)
+# define __ACC_WORDSIZE 2
+# if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM)
+# define ACC_SIZEOF_VOID_P 2
+# elif (ACC_MM_COMPACT || ACC_MM_LARGE || ACC_MM_HUGE)
+# define ACC_SIZEOF_VOID_P 4
+# else
+# error "ACC_MM"
+# endif
+#elif (ACC_ARCH_AVR || ACC_ARCH_Z80)
+# define __ACC_WORDSIZE 1
+# define ACC_SIZEOF_VOID_P 2
+#elif (ACC_ARCH_C166 || ACC_ARCH_MCS51 || ACC_ARCH_MCS251 || ACC_ARCH_MSP430)
+# define ACC_SIZEOF_VOID_P 2
+#elif (ACC_ARCH_H8300)
+# if defined(__NORMAL_MODE__)
+# define __ACC_WORDSIZE 4
+# define ACC_SIZEOF_VOID_P 2
+# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+# define __ACC_WORDSIZE 4
+# define ACC_SIZEOF_VOID_P 4
+# else
+# define __ACC_WORDSIZE 2
+# define ACC_SIZEOF_VOID_P 2
+# endif
+# if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x040000ul)) && (ACC_SIZEOF_INT == 4)
+# define ACC_SIZEOF_SIZE_T ACC_SIZEOF_INT
+# define ACC_SIZEOF_PTRDIFF_T ACC_SIZEOF_INT
+# endif
+#elif (ACC_ARCH_M16C)
+# define __ACC_WORDSIZE 2
+# if defined(__m32c_cpu__) || defined(__m32cm_cpu__)
+# define ACC_SIZEOF_VOID_P 4
+# else
+# define ACC_SIZEOF_VOID_P 2
+# endif
+#elif (ACC_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+# define __ACC_WORDSIZE 8
+# define ACC_SIZEOF_VOID_P 4
+#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
+# define __ACC_WORDSIZE 8
+# define ACC_SIZEOF_VOID_P 8
+#elif (ACC_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+# define ACC_SIZEOF_VOID_P ACC_SIZEOF_LONG
+# define ACC_SIZEOF_SIZE_T ACC_SIZEOF_LONG
+# define ACC_SIZEOF_PTRDIFF_T ACC_SIZEOF_LONG
+#elif (ACC_OS_OS400 || defined(__OS400__))
+# define __ACC_WORDSIZE ACC_SIZEOF_LONG
+# define ACC_SIZEOF_VOID_P 16
+# define ACC_SIZEOF_SIZE_T ACC_SIZEOF_LONG
+# define ACC_SIZEOF_PTRDIFF_T ACC_SIZEOF_LONG
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+# define ACC_SIZEOF_VOID_P 8
+# define ACC_SIZEOF_SIZE_T ACC_SIZEOF_LONG
+# define ACC_SIZEOF_PTRDIFF_T ACC_SIZEOF_LONG
+#elif (ACC_ARCH_SPU)
+# if 0
+# define __ACC_WORDSIZE 16
+# endif
+# define ACC_SIZEOF_VOID_P 4
+#else
+# define ACC_SIZEOF_VOID_P ACC_SIZEOF_LONG
+#endif
+#endif
+#if !defined(ACC_WORDSIZE)
+# if defined(__ACC_WORDSIZE)
+# define ACC_WORDSIZE __ACC_WORDSIZE
+# else
+# define ACC_WORDSIZE ACC_SIZEOF_VOID_P
+# endif
+#endif
+#if !defined(ACC_SIZEOF_SIZE_T)
+#if (ACC_ARCH_I086 || ACC_ARCH_M16C)
+# define ACC_SIZEOF_SIZE_T 2
+#else
+# define ACC_SIZEOF_SIZE_T ACC_SIZEOF_VOID_P
+#endif
+#endif
+#if !defined(ACC_SIZEOF_PTRDIFF_T)
+#if (ACC_ARCH_I086)
+# if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM || ACC_MM_HUGE)
+# define ACC_SIZEOF_PTRDIFF_T ACC_SIZEOF_VOID_P
+# elif (ACC_MM_COMPACT || ACC_MM_LARGE)
+# if (ACC_CC_BORLANDC || ACC_CC_TURBOC)
+# define ACC_SIZEOF_PTRDIFF_T 4
+# else
+# define ACC_SIZEOF_PTRDIFF_T 2
+# endif
+# else
+# error "ACC_MM"
+# endif
+#else
+# define ACC_SIZEOF_PTRDIFF_T ACC_SIZEOF_SIZE_T
+#endif
+#endif
+#if defined(ACC_ABI_NEUTRAL_ENDIAN)
+# undef ACC_ABI_BIG_ENDIAN
+# undef ACC_ABI_LITTLE_ENDIAN
+#elif !defined(ACC_ABI_BIG_ENDIAN) && !defined(ACC_ABI_LITTLE_ENDIAN)
+#if (ACC_ARCH_ALPHA) && (ACC_ARCH_CRAY_MPP)
+# define ACC_ABI_BIG_ENDIAN 1
+#elif (ACC_ARCH_ALPHA || ACC_ARCH_AMD64 || ACC_ARCH_BLACKFIN || ACC_ARCH_CRIS || ACC_ARCH_I086 || ACC_ARCH_I386 || ACC_ARCH_MSP430)
+# define ACC_ABI_LITTLE_ENDIAN 1
+#elif (ACC_ARCH_M68K || ACC_ARCH_S390)
+# define ACC_ABI_BIG_ENDIAN 1
+#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__)
+# if (__LITTLE_ENDIAN__ == 1)
+# define ACC_ABI_LITTLE_ENDIAN 1
+# else
+# define ACC_ABI_BIG_ENDIAN 1
+# endif
+#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
+# define ACC_ABI_BIG_ENDIAN 1
+#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
+# define ACC_ABI_LITTLE_ENDIAN 1
+#elif 1 && (ACC_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__)
+# define ACC_ABI_BIG_ENDIAN 1
+#elif 1 && (ACC_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__)
+# define ACC_ABI_LITTLE_ENDIAN 1
+#elif 1 && (ACC_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)
+# define ACC_ABI_BIG_ENDIAN 1
+#elif 1 && (ACC_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)
+# define ACC_ABI_LITTLE_ENDIAN 1
+#endif
+#endif
+#if defined(ACC_ABI_BIG_ENDIAN) && defined(ACC_ABI_LITTLE_ENDIAN)
+# error "this should not happen"
+#endif
+#if defined(ACC_ABI_BIG_ENDIAN)
+# define ACC_INFO_ABI_ENDIAN "be"
+#elif defined(ACC_ABI_LITTLE_ENDIAN)
+# define ACC_INFO_ABI_ENDIAN "le"
+#elif defined(ACC_ABI_NEUTRAL_ENDIAN)
+# define ACC_INFO_ABI_ENDIAN "neutral"
+#endif
+#if (ACC_SIZEOF_INT == 1 && ACC_SIZEOF_LONG == 2 && ACC_SIZEOF_VOID_P == 2)
+# define ACC_ABI_I8LP16 1
+# define ACC_INFO_ABI_PM "i8lp16"
+#elif (ACC_SIZEOF_INT == 2 && ACC_SIZEOF_LONG == 2 && ACC_SIZEOF_VOID_P == 2)
+# define ACC_ABI_ILP16 1
+# define ACC_INFO_ABI_PM "ilp16"
+#elif (ACC_SIZEOF_INT == 4 && ACC_SIZEOF_LONG == 4 && ACC_SIZEOF_VOID_P == 4)
+# define ACC_ABI_ILP32 1
+# define ACC_INFO_ABI_PM "ilp32"
+#elif (ACC_SIZEOF_INT == 4 && ACC_SIZEOF_LONG == 4 && ACC_SIZEOF_VOID_P == 8 && ACC_SIZEOF_SIZE_T == 8)
+# define ACC_ABI_LLP64 1
+# define ACC_INFO_ABI_PM "llp64"
+#elif (ACC_SIZEOF_INT == 4 && ACC_SIZEOF_LONG == 8 && ACC_SIZEOF_VOID_P == 8)
+# define ACC_ABI_LP64 1
+# define ACC_INFO_ABI_PM "lp64"
+#elif (ACC_SIZEOF_INT == 8 && ACC_SIZEOF_LONG == 8 && ACC_SIZEOF_VOID_P == 8)
+# define ACC_ABI_ILP64 1
+# define ACC_INFO_ABI_PM "ilp64"
+#elif (ACC_SIZEOF_INT == 4 && ACC_SIZEOF_LONG == 8 && ACC_SIZEOF_VOID_P == 4)
+# define ACC_ABI_IP32L64 1
+# define ACC_INFO_ABI_PM "ip32l64"
+#endif
+#if !defined(__ACC_LIBC_OVERRIDE)
+#if defined(ACC_LIBC_NAKED)
+# define ACC_INFO_LIBC "naked"
+#elif defined(ACC_LIBC_FREESTANDING)
+# define ACC_INFO_LIBC "freestanding"
+#elif defined(ACC_LIBC_MOSTLY_FREESTANDING)
+# define ACC_INFO_LIBC "mfreestanding"
+#elif defined(ACC_LIBC_ISOC90)
+# define ACC_INFO_LIBC "isoc90"
+#elif defined(ACC_LIBC_ISOC99)
+# define ACC_INFO_LIBC "isoc99"
+#elif defined(__dietlibc__)
+# define ACC_LIBC_DIETLIBC 1
+# define ACC_INFO_LIBC "dietlibc"
+#elif defined(_NEWLIB_VERSION)
+# define ACC_LIBC_NEWLIB 1
+# define ACC_INFO_LIBC "newlib"
+#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__)
+# if defined(__UCLIBC_SUBLEVEL__)
+# define ACC_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__)
+# else
+# define ACC_LIBC_UCLIBC 0x00090bL
+# endif
+# define ACC_INFO_LIBC "uclibc"
+#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__)
+# define ACC_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100)
+# define ACC_INFO_LIBC "glibc"
+#elif (ACC_CC_MWERKS) && defined(__MSL__)
+# define ACC_LIBC_MSL __MSL__
+# define ACC_INFO_LIBC "msl"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+# define ACC_LIBC_ISOC90 1
+# define ACC_INFO_LIBC "isoc90"
+#else
+# define ACC_LIBC_DEFAULT 1
+# define ACC_INFO_LIBC "default"
+#endif
+#endif
+#if !defined(__acc_gnuc_extension__)
+#if (ACC_CC_GNUC >= 0x020800ul)
+# define __acc_gnuc_extension__ __extension__
+#elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define __acc_gnuc_extension__ __extension__
+#else
+# define __acc_gnuc_extension__
+#endif
+#endif
+#if !defined(__acc_ua_volatile)
+# define __acc_ua_volatile volatile
+#endif
+#if !defined(__acc_alignof)
+#if (ACC_CC_CILLY || ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE || ACC_CC_PGI)
+# define __acc_alignof(e) __alignof__(e)
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 700))
+# define __acc_alignof(e) __alignof__(e)
+#elif (ACC_CC_MSC && (_MSC_VER >= 1300))
+# define __acc_alignof(e) __alignof(e)
+#endif
+#endif
+#if defined(__acc_alignof)
+# define __acc_HAVE_alignof 1
+#endif
+#if !defined(__acc_constructor)
+#if (ACC_CC_GNUC >= 0x030400ul)
+# define __acc_constructor __attribute__((__constructor__,__used__))
+#elif (ACC_CC_GNUC >= 0x020700ul)
+# define __acc_constructor __attribute__((__constructor__))
+#elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define __acc_constructor __attribute__((__constructor__))
+#endif
+#endif
+#if defined(__acc_constructor)
+# define __acc_HAVE_constructor 1
+#endif
+#if !defined(__acc_destructor)
+#if (ACC_CC_GNUC >= 0x030400ul)
+# define __acc_destructor __attribute__((__destructor__,__used__))
+#elif (ACC_CC_GNUC >= 0x020700ul)
+# define __acc_destructor __attribute__((__destructor__))
+#elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define __acc_destructor __attribute__((__destructor__))
+#endif
+#endif
+#if defined(__acc_destructor)
+# define __acc_HAVE_destructor 1
+#endif
+#if defined(__acc_HAVE_destructor) && !defined(__acc_HAVE_constructor)
+# error "this should not happen"
+#endif
+#if !defined(__acc_inline)
+#if (ACC_CC_TURBOC && (__TURBOC__ <= 0x0295))
+#elif defined(__cplusplus)
+# define __acc_inline inline
+#elif (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
+# define __acc_inline __inline
+#elif (ACC_CC_CILLY || ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE || ACC_CC_PGI)
+# define __acc_inline __inline__
+#elif (ACC_CC_DMC)
+# define __acc_inline __inline
+#elif (ACC_CC_INTELC)
+# define __acc_inline __inline
+#elif (ACC_CC_MWERKS && (__MWERKS__ >= 0x2405))
+# define __acc_inline __inline
+#elif (ACC_CC_MSC && (_MSC_VER >= 900))
+# define __acc_inline __inline
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define __acc_inline inline
+#endif
+#endif
+#if defined(__acc_inline)
+# define __acc_HAVE_inline 1
+#else
+# define __acc_inline
+#endif
+#if !defined(__acc_forceinline)
+#if (ACC_CC_GNUC >= 0x030200ul)
+# define __acc_forceinline __inline__ __attribute__((__always_inline__))
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 450) && ACC_CC_SYNTAX_MSC)
+# define __acc_forceinline __forceinline
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 800) && ACC_CC_SYNTAX_GNUC)
+# define __acc_forceinline __inline__ __attribute__((__always_inline__))
+#elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define __acc_forceinline __inline__ __attribute__((__always_inline__))
+#elif (ACC_CC_MSC && (_MSC_VER >= 1200))
+# define __acc_forceinline __forceinline
+#endif
+#endif
+#if defined(__acc_forceinline)
+# define __acc_HAVE_forceinline 1
+#else
+# define __acc_forceinline
+#endif
+#if !defined(__acc_noinline)
+#if 1 && (ACC_ARCH_I386) && (ACC_CC_GNUC >= 0x040000ul) && (ACC_CC_GNUC < 0x040003ul)
+# define __acc_noinline __attribute__((__noinline__,__used__))
+#elif (ACC_CC_GNUC >= 0x030200ul)
+# define __acc_noinline __attribute__((__noinline__))
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 600) && ACC_CC_SYNTAX_MSC)
+# define __acc_noinline __declspec(noinline)
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 800) && ACC_CC_SYNTAX_GNUC)
+# define __acc_noinline __attribute__((__noinline__))
+#elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define __acc_noinline __attribute__((__noinline__))
+#elif (ACC_CC_MSC && (_MSC_VER >= 1300))
+# define __acc_noinline __declspec(noinline)
+#elif (ACC_CC_MWERKS && (__MWERKS__ >= 0x3200) && (ACC_OS_WIN32 || ACC_OS_WIN64))
+# if defined(__cplusplus)
+# else
+# define __acc_noinline __declspec(noinline)
+# endif
+#endif
+#endif
+#if defined(__acc_noinline)
+# define __acc_HAVE_noinline 1
+#else
+# define __acc_noinline
+#endif
+#if (defined(__acc_HAVE_forceinline) || defined(__acc_HAVE_noinline)) && !defined(__acc_HAVE_inline)
+# error "this should not happen"
+#endif
+#if !defined(__acc_noreturn)
+#if (ACC_CC_GNUC >= 0x020700ul)
+# define __acc_noreturn __attribute__((__noreturn__))
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 450) && ACC_CC_SYNTAX_MSC)
+# define __acc_noreturn __declspec(noreturn)
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 600) && ACC_CC_SYNTAX_GNUC)
+# define __acc_noreturn __attribute__((__noreturn__))
+#elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define __acc_noreturn __attribute__((__noreturn__))
+#elif (ACC_CC_MSC && (_MSC_VER >= 1200))
+# define __acc_noreturn __declspec(noreturn)
+#endif
+#endif
+#if defined(__acc_noreturn)
+# define __acc_HAVE_noreturn 1
+#else
+# define __acc_noreturn
+#endif
+#if !defined(__acc_nothrow)
+#if (ACC_CC_GNUC >= 0x030300ul)
+# define __acc_nothrow __attribute__((__nothrow__))
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 450) && ACC_CC_SYNTAX_MSC) && defined(__cplusplus)
+# define __acc_nothrow __declspec(nothrow)
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 800) && ACC_CC_SYNTAX_GNUC)
+# define __acc_nothrow __attribute__((__nothrow__))
+#elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define __acc_nothrow __attribute__((__nothrow__))
+#elif (ACC_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus)
+# define __acc_nothrow __declspec(nothrow)
+#endif
+#endif
+#if defined(__acc_nothrow)
+# define __acc_HAVE_nothrow 1
+#else
+# define __acc_nothrow
+#endif
+#if !defined(__acc_restrict)
+#if (ACC_CC_GNUC >= 0x030400ul)
+# define __acc_restrict __restrict__
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 600) && ACC_CC_SYNTAX_GNUC)
+# define __acc_restrict __restrict__
+#elif (ACC_CC_LLVM)
+# define __acc_restrict __restrict__
+#elif (ACC_CC_MSC && (_MSC_VER >= 1400))
+# define __acc_restrict __restrict
+#endif
+#endif
+#if defined(__acc_restrict)
+# define __acc_HAVE_restrict 1
+#else
+# define __acc_restrict
+#endif
+#if !defined(__acc_likely) && !defined(__acc_unlikely)
+#if (ACC_CC_GNUC >= 0x030200ul)
+# define __acc_likely(e) (__builtin_expect(!!(e),1))
+# define __acc_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 800))
+# define __acc_likely(e) (__builtin_expect(!!(e),1))
+# define __acc_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define __acc_likely(e) (__builtin_expect(!!(e),1))
+# define __acc_unlikely(e) (__builtin_expect(!!(e),0))
+#endif
+#endif
+#if defined(__acc_likely)
+# define __acc_HAVE_likely 1
+#else
+# define __acc_likely(e) (e)
+#endif
+#if defined(__acc_unlikely)
+# define __acc_HAVE_unlikely 1
+#else
+# define __acc_unlikely(e) (e)
+#endif
+#if !defined(ACC_UNUSED)
+# if (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define ACC_UNUSED(var) ((void) &var)
+# elif (ACC_CC_BORLANDC || ACC_CC_HIGHC || ACC_CC_NDPC || ACC_CC_PELLESC || ACC_CC_TURBOC)
+# define ACC_UNUSED(var) if (&var) ; else
+# elif (ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define ACC_UNUSED(var) ((void) var)
+# elif (ACC_CC_MSC && (_MSC_VER < 900))
+# define ACC_UNUSED(var) if (&var) ; else
+# elif (ACC_CC_KEILC)
+# define ACC_UNUSED(var) {extern int __acc_unused[1-2*!(sizeof(var)>0)];}
+# elif (ACC_CC_PACIFICC)
+# define ACC_UNUSED(var) ((void) sizeof(var))
+# elif (ACC_CC_WATCOMC) && defined(__cplusplus)
+# define ACC_UNUSED(var) ((void) var)
+# else
+# define ACC_UNUSED(var) ((void) &var)
+# endif
+#endif
+#if !defined(ACC_UNUSED_FUNC)
+# if (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define ACC_UNUSED_FUNC(func) ((void) func)
+# elif (ACC_CC_BORLANDC || ACC_CC_NDPC || ACC_CC_TURBOC)
+# define ACC_UNUSED_FUNC(func) if (func) ; else
+# elif (ACC_CC_LLVM)
+# define ACC_UNUSED_FUNC(func) ((void) &func)
+# elif (ACC_CC_MSC && (_MSC_VER < 900))
+# define ACC_UNUSED_FUNC(func) if (func) ; else
+# elif (ACC_CC_MSC)
+# define ACC_UNUSED_FUNC(func) ((void) &func)
+# elif (ACC_CC_KEILC || ACC_CC_PELLESC)
+# define ACC_UNUSED_FUNC(func) {extern int __acc_unused[1-2*!(sizeof((int)func)>0)];}
+# else
+# define ACC_UNUSED_FUNC(func) ((void) func)
+# endif
+#endif
+#if !defined(ACC_UNUSED_LABEL)
+# if (ACC_CC_WATCOMC) && defined(__cplusplus)
+# define ACC_UNUSED_LABEL(l) switch(0) case 1:goto l
+# elif (ACC_CC_INTELC || ACC_CC_WATCOMC)
+# define ACC_UNUSED_LABEL(l) if (0) goto l
+# else
+# define ACC_UNUSED_LABEL(l) switch(0) case 1:goto l
+# endif
+#endif
+#if !defined(ACC_DEFINE_UNINITIALIZED_VAR)
+# if 0
+# define ACC_DEFINE_UNINITIALIZED_VAR(type,var,init) type var
+# elif 0 && (ACC_CC_GNUC)
+# define ACC_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var
+# else
+# define ACC_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init
+# endif
+#endif
+#if !defined(ACC_COMPILE_TIME_ASSERT_HEADER)
+# if (ACC_CC_AZTECC || ACC_CC_ZORTECHC)
+# define ACC_COMPILE_TIME_ASSERT_HEADER(e) extern int __acc_cta[1-!(e)];
+# elif (ACC_CC_DMC || ACC_CC_SYMANTECC)
+# define ACC_COMPILE_TIME_ASSERT_HEADER(e) extern int __acc_cta[1u-2*!(e)];
+# elif (ACC_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define ACC_COMPILE_TIME_ASSERT_HEADER(e) extern int __acc_cta[1-!(e)];
+# else
+# define ACC_COMPILE_TIME_ASSERT_HEADER(e) extern int __acc_cta[1-2*!(e)];
+# endif
+#endif
+#if !defined(ACC_COMPILE_TIME_ASSERT)
+# if (ACC_CC_AZTECC)
+# define ACC_COMPILE_TIME_ASSERT(e) {typedef int __acc_cta_t[1-!(e)];}
+# elif (ACC_CC_DMC || ACC_CC_PACIFICC || ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)
+# define ACC_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (ACC_CC_MSC && (_MSC_VER < 900))
+# define ACC_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (ACC_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define ACC_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# else
+# define ACC_COMPILE_TIME_ASSERT(e) {typedef int __acc_cta_t[1-2*!(e)];}
+# endif
+#endif
+#if (ACC_ARCH_I086 || ACC_ARCH_I386) && (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
+# if (ACC_CC_GNUC || ACC_CC_HIGHC || ACC_CC_NDPC || ACC_CC_PACIFICC)
+# elif (ACC_CC_DMC || ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)
+# define __acc_cdecl __cdecl
+# define __acc_cdecl_atexit
+# define __acc_cdecl_main __cdecl
+# if (ACC_OS_OS2 && (ACC_CC_DMC || ACC_CC_SYMANTECC))
+# define __acc_cdecl_qsort __pascal
+# elif (ACC_OS_OS2 && (ACC_CC_ZORTECHC))
+# define __acc_cdecl_qsort _stdcall
+# else
+# define __acc_cdecl_qsort __cdecl
+# endif
+# elif (ACC_CC_WATCOMC)
+# define __acc_cdecl __cdecl
+# else
+# define __acc_cdecl __cdecl
+# define __acc_cdecl_atexit __cdecl
+# define __acc_cdecl_main __cdecl
+# define __acc_cdecl_qsort __cdecl
+# endif
+# if (ACC_CC_GNUC || ACC_CC_HIGHC || ACC_CC_NDPC || ACC_CC_PACIFICC || ACC_CC_WATCOMC)
+# elif (ACC_OS_OS2 && (ACC_CC_DMC || ACC_CC_SYMANTECC))
+# define __acc_cdecl_sighandler __pascal
+# elif (ACC_OS_OS2 && (ACC_CC_ZORTECHC))
+# define __acc_cdecl_sighandler _stdcall
+# elif (ACC_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)
+# define __acc_cdecl_sighandler __clrcall
+# elif (ACC_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))
+# if defined(_DLL)
+# define __acc_cdecl_sighandler _far _cdecl _loadds
+# elif defined(_MT)
+# define __acc_cdecl_sighandler _far _cdecl
+# else
+# define __acc_cdecl_sighandler _cdecl
+# endif
+# else
+# define __acc_cdecl_sighandler __cdecl
+# endif
+#elif (ACC_ARCH_I386) && (ACC_CC_WATCOMC)
+# define __acc_cdecl __cdecl
+#elif (ACC_ARCH_M68K && ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))
+# define __acc_cdecl cdecl
+#endif
+#if !defined(__acc_cdecl)
+# define __acc_cdecl
+#endif
+#if !defined(__acc_cdecl_atexit)
+# define __acc_cdecl_atexit
+#endif
+#if !defined(__acc_cdecl_main)
+# define __acc_cdecl_main
+#endif
+#if !defined(__acc_cdecl_qsort)
+# define __acc_cdecl_qsort
+#endif
+#if !defined(__acc_cdecl_sighandler)
+# define __acc_cdecl_sighandler
+#endif
+#if !defined(__acc_cdecl_va)
+# define __acc_cdecl_va __acc_cdecl
+#endif
+#if !defined(ACC_CFG_NO_WINDOWS_H)
+#if (ACC_OS_CYGWIN || (ACC_OS_EMX && defined(__RSXNT__)) || ACC_OS_WIN32 || ACC_OS_WIN64)
+# if (ACC_CC_WATCOMC && (__WATCOMC__ < 1000))
+# elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)
+# elif ((ACC_OS_CYGWIN || defined(__MINGW32__)) && (ACC_CC_GNUC && (ACC_CC_GNUC < 0x025f00ul)))
+# else
+# define ACC_HAVE_WINDOWS_H 1
+# endif
+#endif
+#endif
+#if (ACC_ARCH_ALPHA)
+# define ACC_OPT_AVOID_UINT_INDEX 1
+# define ACC_OPT_AVOID_SHORT 1
+# define ACC_OPT_AVOID_USHORT 1
+#elif (ACC_ARCH_AMD64)
+# define ACC_OPT_AVOID_INT_INDEX 1
+# define ACC_OPT_AVOID_UINT_INDEX 1
+# define ACC_OPT_UNALIGNED16 1
+# define ACC_OPT_UNALIGNED32 1
+# define ACC_OPT_UNALIGNED64 1
+#elif (ACC_ARCH_ARM && ACC_ARCH_ARM_THUMB)
+#elif (ACC_ARCH_ARM)
+# define ACC_OPT_AVOID_SHORT 1
+# define ACC_OPT_AVOID_USHORT 1
+#elif (ACC_ARCH_CRIS)
+# define ACC_OPT_UNALIGNED16 1
+# define ACC_OPT_UNALIGNED32 1
+#elif (ACC_ARCH_I386)
+# define ACC_OPT_UNALIGNED16 1
+# define ACC_OPT_UNALIGNED32 1
+#elif (ACC_ARCH_IA64)
+# define ACC_OPT_AVOID_INT_INDEX 1
+# define ACC_OPT_AVOID_UINT_INDEX 1
+# define ACC_OPT_PREFER_POSTINC 1
+#elif (ACC_ARCH_M68K)
+# define ACC_OPT_PREFER_POSTINC 1
+# define ACC_OPT_PREFER_PREDEC 1
+# if defined(__mc68020__) && !defined(__mcoldfire__)
+# define ACC_OPT_UNALIGNED16 1
+# define ACC_OPT_UNALIGNED32 1
+# endif
+#elif (ACC_ARCH_MIPS)
+# define ACC_OPT_AVOID_UINT_INDEX 1
+#elif (ACC_ARCH_POWERPC)
+# define ACC_OPT_PREFER_PREINC 1
+# define ACC_OPT_PREFER_PREDEC 1
+# if defined(ACC_ABI_BIG_ENDIAN)
+# define ACC_OPT_UNALIGNED16 1
+# define ACC_OPT_UNALIGNED32 1
+# endif
+#elif (ACC_ARCH_S390)
+# define ACC_OPT_UNALIGNED16 1
+# define ACC_OPT_UNALIGNED32 1
+# if (ACC_SIZEOF_SIZE_T == 8)
+# define ACC_OPT_UNALIGNED64 1
+# endif
+#elif (ACC_ARCH_SH)
+# define ACC_OPT_PREFER_POSTINC 1
+# define ACC_OPT_PREFER_PREDEC 1
+#endif
+#if !defined(ACC_CFG_NO_INLINE_ASM)
+#if defined(ACC_CC_LLVM)
+# define ACC_CFG_NO_INLINE_ASM 1
+#endif
+#endif
+#if !defined(ACC_CFG_NO_UNALIGNED)
+#if defined(ACC_ABI_NEUTRAL_ENDIAN) || defined(ACC_ARCH_GENERIC)
+# define ACC_CFG_NO_UNALIGNED 1
+#endif
+#endif
+#if defined(ACC_CFG_NO_UNALIGNED)
+# undef ACC_OPT_UNALIGNED16
+# undef ACC_OPT_UNALIGNED32
+# undef ACC_OPT_UNALIGNED64
+#endif
+#if defined(ACC_CFG_NO_INLINE_ASM)
+#elif (ACC_ARCH_I386 && (ACC_OS_DOS32 || ACC_OS_WIN32) && (ACC_CC_DMC || ACC_CC_INTELC || ACC_CC_MSC || ACC_CC_PELLESC))
+# define ACC_ASM_SYNTAX_MSC 1
+#elif (ACC_OS_WIN64 && (ACC_CC_DMC || ACC_CC_INTELC || ACC_CC_MSC || ACC_CC_PELLESC))
+#elif (ACC_ARCH_I386 && (ACC_CC_GNUC || ACC_CC_INTELC || ACC_CC_PATHSCALE))
+# define ACC_ASM_SYNTAX_GNUC 1
+#elif (ACC_ARCH_AMD64 && (ACC_CC_GNUC || ACC_CC_INTELC || ACC_CC_PATHSCALE))
+# define ACC_ASM_SYNTAX_GNUC 1
+#endif
+#if (ACC_ASM_SYNTAX_GNUC)
+#if (ACC_ARCH_I386 && ACC_CC_GNUC && (ACC_CC_GNUC < 0x020000ul))
+# define __ACC_ASM_CLOBBER "ax"
+#elif (ACC_CC_INTELC)
+# define __ACC_ASM_CLOBBER "memory"
+#else
+# define __ACC_ASM_CLOBBER "cc", "memory"
+#endif
+#endif
+#if defined(__ACC_INFOSTR_MM)
+#elif (ACC_MM_FLAT) && (defined(__ACC_INFOSTR_PM) || defined(ACC_INFO_ABI_PM))
+# define __ACC_INFOSTR_MM ""
+#elif defined(ACC_INFO_MM)
+# define __ACC_INFOSTR_MM "." ACC_INFO_MM
+#else
+# define __ACC_INFOSTR_MM ""
+#endif
+#if defined(__ACC_INFOSTR_PM)
+#elif defined(ACC_INFO_ABI_PM)
+# define __ACC_INFOSTR_PM "." ACC_INFO_ABI_PM
+#else
+# define __ACC_INFOSTR_PM ""
+#endif
+#if defined(__ACC_INFOSTR_ENDIAN)
+#elif defined(ACC_INFO_ABI_ENDIAN)
+# define __ACC_INFOSTR_ENDIAN "." ACC_INFO_ABI_ENDIAN
+#else
+# define __ACC_INFOSTR_ENDIAN ""
+#endif
+#if defined(__ACC_INFOSTR_OSNAME)
+#elif defined(ACC_INFO_OS_CONSOLE)
+# define __ACC_INFOSTR_OSNAME ACC_INFO_OS "." ACC_INFO_OS_CONSOLE
+#elif defined(ACC_INFO_OS_POSIX)
+# define __ACC_INFOSTR_OSNAME ACC_INFO_OS "." ACC_INFO_OS_POSIX
+#else
+# define __ACC_INFOSTR_OSNAME ACC_INFO_OS
+#endif
+#if defined(__ACC_INFOSTR_LIBC)
+#elif defined(ACC_INFO_LIBC)
+# define __ACC_INFOSTR_LIBC "." ACC_INFO_LIBC
+#else
+# define __ACC_INFOSTR_LIBC ""
+#endif
+#if defined(__ACC_INFOSTR_CCVER)
+#elif defined(ACC_INFO_CCVER)
+# define __ACC_INFOSTR_CCVER " " ACC_INFO_CCVER
+#else
+# define __ACC_INFOSTR_CCVER ""
+#endif
+#define ACC_INFO_STRING \
+ ACC_INFO_ARCH __ACC_INFOSTR_MM __ACC_INFOSTR_PM __ACC_INFOSTR_ENDIAN \
+ " " __ACC_INFOSTR_OSNAME __ACC_INFOSTR_LIBC " " ACC_INFO_CC __ACC_INFOSTR_CCVER
+#if defined(ACC_CFG_NO_CONFIG_HEADER)
+#elif defined(ACC_CFG_CONFIG_HEADER)
+#else
+#if !defined(ACC_CFG_AUTO_NO_HEADERS)
+#if defined(ACC_LIBC_NAKED)
+#elif defined(ACC_LIBC_FREESTANDING)
+# define HAVE_LIMITS_H 1
+# define HAVE_STDARG_H 1
+# define HAVE_STDDEF_H 1
+#elif defined(ACC_LIBC_MOSTLY_FREESTANDING)
+# define HAVE_LIMITS_H 1
+# define HAVE_SETJMP_H 1
+# define HAVE_STDARG_H 1
+# define HAVE_STDDEF_H 1
+# define HAVE_STDIO_H 1
+# define HAVE_STRING_H 1
+#else
+#define STDC_HEADERS 1
+#define HAVE_ASSERT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_DIRENT_H 1
+#define HAVE_ERRNO_H 1
+#define HAVE_FCNTL_H 1
+#define HAVE_FLOAT_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_MALLOC_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_SETJMP_H 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDIO_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_TIME_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_UTIME_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TYPES_H 1
+#if (ACC_OS_POSIX)
+# if (ACC_OS_POSIX_AIX)
+# define HAVE_SYS_RESOURCE_H 1
+# elif (ACC_OS_POSIX_FREEBSD || ACC_OS_POSIX_MACOSX || ACC_OS_POSIX_NETBSD || ACC_OS_POSIX_OPENBSD)
+# define HAVE_STRINGS_H 1
+# undef HAVE_MALLOC_H
+# elif (ACC_OS_POSIX_HPUX || ACC_OS_POSIX_INTERIX)
+# define HAVE_ALLOCA_H 1
+# elif (ACC_OS_POSIX_MACOSX && ACC_LIBC_MSL)
+# undef HAVE_SYS_TIME_H
+# undef HAVE_SYS_TYPES_H
+# elif (ACC_OS_POSIX_SOLARIS || ACC_OS_POSIX_SUNOS)
+# define HAVE_ALLOCA_H 1
+# endif
+# if (ACC_LIBC_DIETLIBC || ACC_LIBC_GLIBC || ACC_LIBC_UCLIBC)
+# define HAVE_STRINGS_H 1
+# define HAVE_SYS_MMAN_H 1
+# define HAVE_SYS_RESOURCE_H 1
+# define HAVE_SYS_WAIT_H 1
+# endif
+# if (ACC_LIBC_NEWLIB)
+# undef HAVE_STRINGS_H
+# endif
+#elif (ACC_OS_CYGWIN)
+# define HAVE_IO_H 1
+#elif (ACC_OS_EMX)
+# define HAVE_ALLOCA_H 1
+# define HAVE_IO_H 1
+#elif (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC)
+# if !defined(__MINT__)
+# undef HAVE_MALLOC_H
+# endif
+#elif (ACC_ARCH_M68K && ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))
+# undef HAVE_DIRENT_H
+# undef HAVE_FCNTL_H
+# undef HAVE_MALLOC_H
+# undef HAVE_MEMORY_H
+# undef HAVE_UNISTD_H
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_STAT_H
+# undef HAVE_SYS_TIME_H
+# undef HAVE_SYS_TYPES_H
+#endif
+#if (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
+#define HAVE_CONIO_H 1
+#define HAVE_DIRECT_H 1
+#define HAVE_DOS_H 1
+#define HAVE_IO_H 1
+#define HAVE_SHARE_H 1
+#if (ACC_CC_AZTECC)
+# undef HAVE_CONIO_H
+# undef HAVE_DIRECT_H
+# undef HAVE_DIRENT_H
+# undef HAVE_MALLOC_H
+# undef HAVE_SHARE_H
+# undef HAVE_UNISTD_H
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_STAT_H
+# undef HAVE_SYS_TIME_H
+# undef HAVE_SYS_TYPES_H
+#elif (ACC_CC_BORLANDC)
+# undef HAVE_UNISTD_H
+# undef HAVE_SYS_TIME_H
+# if (ACC_OS_WIN32 || ACC_OS_WIN64)
+# undef HAVE_DIRENT_H
+# endif
+# if (__BORLANDC__ < 0x0400)
+# undef HAVE_DIRENT_H
+# undef HAVE_UTIME_H
+# endif
+#elif (ACC_CC_DMC)
+# undef HAVE_DIRENT_H
+# undef HAVE_UNISTD_H
+# define HAVE_SYS_DIRENT_H 1
+#elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)
+#elif (ACC_OS_DOS32 && ACC_CC_HIGHC)
+# define HAVE_ALLOCA_H 1
+# undef HAVE_DIRENT_H
+# undef HAVE_UNISTD_H
+#elif (ACC_CC_IBMC && ACC_OS_OS2)
+# undef HAVE_DOS_H
+# undef HAVE_DIRENT_H
+# undef HAVE_UNISTD_H
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_TIME_H
+# define HAVE_SYS_UTIME_H 1
+#elif (ACC_CC_INTELC || ACC_CC_MSC)
+# undef HAVE_DIRENT_H
+# undef HAVE_UNISTD_H
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_TIME_H
+# define HAVE_SYS_UTIME_H 1
+#elif (ACC_CC_LCCWIN32)
+# undef HAVE_DIRENT_H
+# undef HAVE_DOS_H
+# undef HAVE_UNISTD_H
+# undef HAVE_SYS_TIME_H
+#elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__MINGW32__)
+# undef HAVE_UTIME_H
+# define HAVE_SYS_UTIME_H 1
+#elif (ACC_OS_WIN32 && ACC_LIBC_MSL)
+# define HAVE_ALLOCA_H 1
+# undef HAVE_DOS_H
+# undef HAVE_SHARE_H
+# undef HAVE_SYS_TIME_H
+#elif (ACC_CC_NDPC)
+# undef HAVE_DIRENT_H
+# undef HAVE_DOS_H
+# undef HAVE_UNISTD_H
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_TIME_H
+#elif (ACC_CC_PACIFICC)
+# undef HAVE_DIRECT_H
+# undef HAVE_DIRENT_H
+# undef HAVE_FCNTL_H
+# undef HAVE_IO_H
+# undef HAVE_MALLOC_H
+# undef HAVE_MEMORY_H
+# undef HAVE_SHARE_H
+# undef HAVE_UNISTD_H
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_STAT_H
+# undef HAVE_SYS_TIME_H
+# undef HAVE_SYS_TYPES_H
+#elif (ACC_OS_WIN32 && ACC_CC_PELLESC)
+# undef HAVE_DIRENT_H
+# undef HAVE_DOS_H
+# undef HAVE_MALLOC_H
+# undef HAVE_SHARE_H
+# undef HAVE_UNISTD_H
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_TIME_H
+# if (__POCC__ < 280)
+# else
+# define HAVE_SYS_UTIME_H 1
+# endif
+#elif (ACC_OS_WIN32 && ACC_CC_PGI) && defined(__MINGW32__)
+# undef HAVE_UTIME_H
+# define HAVE_SYS_UTIME_H 1
+#elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)
+#elif (ACC_CC_SYMANTECC)
+# undef HAVE_DIRENT_H
+# undef HAVE_UNISTD_H
+# if (__SC__ < 0x700)
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_TIME_H
+# endif
+#elif (ACC_CC_TOPSPEEDC)
+# undef HAVE_DIRENT_H
+# undef HAVE_UNISTD_H
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_STAT_H
+# undef HAVE_SYS_TIME_H
+# undef HAVE_SYS_TYPES_H
+#elif (ACC_CC_TURBOC)
+# undef HAVE_UNISTD_H
+# undef HAVE_SYS_TIME_H
+# undef HAVE_SYS_TYPES_H
+# if (ACC_OS_WIN32 || ACC_OS_WIN64)
+# undef HAVE_DIRENT_H
+# endif
+# if (__TURBOC__ < 0x0200)
+# undef HAVE_SIGNAL_H
+# endif
+# if (__TURBOC__ < 0x0400)
+# undef HAVE_DIRECT_H
+# undef HAVE_DIRENT_H
+# undef HAVE_MALLOC_H
+# undef HAVE_MEMORY_H
+# undef HAVE_UTIME_H
+# endif
+#elif (ACC_CC_WATCOMC)
+# undef HAVE_DIRENT_H
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_TIME_H
+# define HAVE_SYS_UTIME_H 1
+# if (__WATCOMC__ < 950)
+# undef HAVE_UNISTD_H
+# endif
+#elif (ACC_CC_ZORTECHC)
+# undef HAVE_DIRENT_H
+# undef HAVE_MEMORY_H
+# undef HAVE_UNISTD_H
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_TIME_H
+#endif
+#endif
+#if (ACC_OS_CONSOLE)
+# undef HAVE_DIRENT_H
+#endif
+#if (ACC_OS_EMBEDDED)
+# undef HAVE_DIRENT_H
+#endif
+#if (ACC_LIBC_ISOC90 || ACC_LIBC_ISOC99)
+# undef HAVE_DIRENT_H
+# undef HAVE_FCNTL_H
+# undef HAVE_MALLOC_H
+# undef HAVE_UNISTD_H
+# undef HAVE_UTIME_H
+# undef HAVE_SYS_STAT_H
+# undef HAVE_SYS_TIME_H
+# undef HAVE_SYS_TYPES_H
+#endif
+#if (ACC_LIBC_GLIBC >= 0x020100ul)
+# define HAVE_STDINT_H 1
+#elif (ACC_LIBC_DIETLIBC)
+# undef HAVE_STDINT_H
+#elif (ACC_LIBC_UCLIBC)
+# define HAVE_STDINT_H 1
+#elif (ACC_CC_BORLANDC) && (__BORLANDC__ >= 0x560)
+# undef HAVE_STDINT_H
+#elif (ACC_CC_DMC) && (__DMC__ >= 0x825)
+# define HAVE_STDINT_H 1
+#endif
+#if (HAVE_SYS_TIME_H && HAVE_TIME_H)
+# define TIME_WITH_SYS_TIME 1
+#endif
+#endif
+#endif
+#if !defined(ACC_CFG_AUTO_NO_FUNCTIONS)
+#if defined(ACC_LIBC_NAKED)
+#elif defined(ACC_LIBC_FREESTANDING)
+#elif defined(ACC_LIBC_MOSTLY_FREESTANDING)
+# define HAVE_LONGJMP 1
+# define HAVE_MEMCMP 1
+# define HAVE_MEMCPY 1
+# define HAVE_MEMMOVE 1
+# define HAVE_MEMSET 1
+# define HAVE_SETJMP 1
+#else
+#define HAVE_ACCESS 1
+#define HAVE_ALLOCA 1
+#define HAVE_ATEXIT 1
+#define HAVE_ATOI 1
+#define HAVE_ATOL 1
+#define HAVE_CHMOD 1
+#define HAVE_CHOWN 1
+#define HAVE_CTIME 1
+#define HAVE_DIFFTIME 1
+#define HAVE_FILENO 1
+#define HAVE_FSTAT 1
+#define HAVE_GETENV 1
+#define HAVE_GETTIMEOFDAY 1
+#define HAVE_GMTIME 1
+#define HAVE_ISATTY 1
+#define HAVE_LOCALTIME 1
+#define HAVE_LONGJMP 1
+#define HAVE_LSTAT 1
+#define HAVE_MEMCMP 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMSET 1
+#define HAVE_MKDIR 1
+#define HAVE_MKTIME 1
+#define HAVE_QSORT 1
+#define HAVE_RAISE 1
+#define HAVE_RMDIR 1
+#define HAVE_SETJMP 1
+#define HAVE_SIGNAL 1
+#define HAVE_SNPRINTF 1
+#define HAVE_STAT 1
+#define HAVE_STRCHR 1
+#define HAVE_STRDUP 1
+#define HAVE_STRERROR 1
+#define HAVE_STRFTIME 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_TIME 1
+#define HAVE_UMASK 1
+#define HAVE_UTIME 1
+#define HAVE_VSNPRINTF 1
+#if (ACC_OS_BEOS || ACC_OS_CYGWIN || ACC_OS_POSIX || ACC_OS_QNX || ACC_OS_VMS)
+# define HAVE_STRCASECMP 1
+# define HAVE_STRNCASECMP 1
+#elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)
+# define HAVE_STRCASECMP 1
+# define HAVE_STRNCASECMP 1
+#else
+# define HAVE_STRICMP 1
+# define HAVE_STRNICMP 1
+#endif
+#if (ACC_OS_POSIX)
+# if (ACC_OS_POSIX_AIX)
+# define HAVE_GETRUSAGE 1
+# elif (ACC_OS_POSIX_MACOSX && ACC_LIBC_MSL)
+# undef HAVE_CHOWN
+# undef HAVE_LSTAT
+# elif (ACC_OS_POSIX_UNICOS)
+# undef HAVE_ALLOCA
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+# endif
+# if (ACC_CC_TINYC)
+# undef HAVE_ALLOCA
+# endif
+# if (ACC_LIBC_DIETLIBC || ACC_LIBC_GLIBC || ACC_LIBC_UCLIBC)
+# define HAVE_GETRUSAGE 1
+# define HAVE_GETPAGESIZE 1
+# define HAVE_MMAP 1
+# define HAVE_MPROTECT 1
+# define HAVE_MUNMAP 1
+# endif
+#elif (ACC_OS_CYGWIN)
+# if (ACC_CC_GNUC < 0x025a00ul)
+# undef HAVE_GETTIMEOFDAY
+# undef HAVE_LSTAT
+# endif
+# if (ACC_CC_GNUC < 0x025f00ul)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+# endif
+#elif (ACC_OS_EMX)
+# undef HAVE_CHOWN
+# undef HAVE_LSTAT
+#elif (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC)
+# if !defined(__MINT__)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+# endif
+#elif (ACC_ARCH_M68K && ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))
+# undef HAVE_ALLOCA
+# undef HAVE_ACCESS
+# undef HAVE_CHMOD
+# undef HAVE_CHOWN
+# undef HAVE_FSTAT
+# undef HAVE_GETTIMEOFDAY
+# undef HAVE_LSTAT
+# undef HAVE_SNPRINTF
+# undef HAVE_UMASK
+# undef HAVE_UTIME
+# undef HAVE_VSNPRINTF
+#endif
+#if (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
+#undef HAVE_CHOWN
+#undef HAVE_GETTIMEOFDAY
+#undef HAVE_LSTAT
+#undef HAVE_UMASK
+#if (ACC_CC_AZTECC)
+# undef HAVE_ALLOCA
+# undef HAVE_DIFFTIME
+# undef HAVE_FSTAT
+# undef HAVE_STRDUP
+# undef HAVE_SNPRINTF
+# undef HAVE_UTIME
+# undef HAVE_VSNPRINTF
+#elif (ACC_CC_BORLANDC)
+# if (__BORLANDC__ < 0x0400)
+# undef HAVE_ALLOCA
+# undef HAVE_UTIME
+# endif
+# if ((__BORLANDC__ < 0x0410) && ACC_OS_WIN16)
+# undef HAVE_ALLOCA
+# endif
+# if (__BORLANDC__ < 0x0550)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+# endif
+#elif (ACC_CC_DMC)
+# if (ACC_OS_WIN16)
+# undef HAVE_ALLOCA
+# endif
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+#elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+#elif (ACC_OS_DOS32 && ACC_CC_HIGHC)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+#elif (ACC_CC_IBMC)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+#elif (ACC_CC_INTELC)
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+#elif (ACC_CC_LCCWIN32)
+# define utime _utime
+#elif (ACC_CC_MSC)
+# if (_MSC_VER < 600)
+# undef HAVE_STRFTIME
+# endif
+# if (_MSC_VER < 700)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+# elif (_MSC_VER < 1500)
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+# endif
+# if ((_MSC_VER < 800) && ACC_OS_WIN16)
+# undef HAVE_ALLOCA
+# endif
+# if (ACC_ARCH_I086) && defined(__cplusplus)
+# undef HAVE_LONGJMP
+# undef HAVE_SETJMP
+# endif
+#elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__MINGW32__)
+# if (ACC_CC_GNUC < 0x025f00ul)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+# else
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+# endif
+#elif (ACC_OS_WIN32 && ACC_LIBC_MSL)
+# if (__MSL__ < 0x8000ul)
+# undef HAVE_CHMOD
+# endif
+#elif (ACC_CC_NDPC)
+# undef HAVE_ALLOCA
+# undef HAVE_SNPRINTF
+# undef HAVE_STRNICMP
+# undef HAVE_UTIME
+# undef HAVE_VSNPRINTF
+# if defined(__cplusplus)
+# undef HAVE_STAT
+# endif
+#elif (ACC_CC_PACIFICC)
+# undef HAVE_ACCESS
+# undef HAVE_ALLOCA
+# undef HAVE_CHMOD
+# undef HAVE_DIFFTIME
+# undef HAVE_FSTAT
+# undef HAVE_MKTIME
+# undef HAVE_RAISE
+# undef HAVE_SNPRINTF
+# undef HAVE_STRFTIME
+# undef HAVE_UTIME
+# undef HAVE_VSNPRINTF
+#elif (ACC_OS_WIN32 && ACC_CC_PELLESC)
+# if (__POCC__ < 280)
+# define alloca _alloca
+# undef HAVE_UTIME
+# endif
+#elif (ACC_OS_WIN32 && ACC_CC_PGI) && defined(__MINGW32__)
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+#elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+#elif (ACC_CC_SYMANTECC)
+# if (ACC_OS_WIN16 && (ACC_MM_MEDIUM || ACC_MM_LARGE || ACC_MM_HUGE))
+# undef HAVE_ALLOCA
+# endif
+# if (__SC__ < 0x600)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+# else
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+# endif
+# if (__SC__ < 0x700)
+# undef HAVE_DIFFTIME
+# undef HAVE_UTIME
+# endif
+#elif (ACC_CC_TOPSPEEDC)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+#elif (ACC_CC_TURBOC)
+# undef HAVE_ALLOCA
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+# if (__TURBOC__ < 0x0200)
+# undef HAVE_RAISE
+# undef HAVE_SIGNAL
+# endif
+# if (__TURBOC__ < 0x0295)
+# undef HAVE_MKTIME
+# undef HAVE_STRFTIME
+# endif
+# if (__TURBOC__ < 0x0400)
+# undef HAVE_UTIME
+# endif
+#elif (ACC_CC_WATCOMC)
+# if (__WATCOMC__ < 1100)
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+# elif (__WATCOMC__ < 1200)
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+# endif
+#elif (ACC_CC_ZORTECHC)
+# if (ACC_OS_WIN16 && (ACC_MM_MEDIUM || ACC_MM_LARGE || ACC_MM_HUGE))
+# undef HAVE_ALLOCA
+# endif
+# undef HAVE_DIFFTIME
+# undef HAVE_SNPRINTF
+# undef HAVE_UTIME
+# undef HAVE_VSNPRINTF
+#endif
+#endif
+#if (ACC_OS_CONSOLE)
+# undef HAVE_ACCESS
+# undef HAVE_CHMOD
+# undef HAVE_CHOWN
+# undef HAVE_GETTIMEOFDAY
+# undef HAVE_LSTAT
+# undef HAVE_TIME
+# undef HAVE_UMASK
+# undef HAVE_UTIME
+#endif
+#if (ACC_LIBC_ISOC90 || ACC_LIBC_ISOC99)
+# undef HAVE_ACCESS
+# undef HAVE_CHMOD
+# undef HAVE_CHOWN
+# undef HAVE_FSTAT
+# undef HAVE_GETTIMEOFDAY
+# undef HAVE_LSTAT
+# undef HAVE_STAT
+# undef HAVE_UMASK
+# undef HAVE_UTIME
+# if 1
+# undef HAVE_ALLOCA
+# undef HAVE_ISATTY
+# undef HAVE_MKDIR
+# undef HAVE_RMDIR
+# undef HAVE_STRDUP
+# undef HAVE_STRICMP
+# undef HAVE_STRNICMP
+# endif
+#endif
+#endif
+#endif
+#if !defined(ACC_CFG_AUTO_NO_SIZES)
+#if !defined(SIZEOF_SHORT) && defined(ACC_SIZEOF_SHORT)
+# define SIZEOF_SHORT ACC_SIZEOF_SHORT
+#endif
+#if !defined(SIZEOF_INT) && defined(ACC_SIZEOF_INT)
+# define SIZEOF_INT ACC_SIZEOF_INT
+#endif
+#if !defined(SIZEOF_LONG) && defined(ACC_SIZEOF_LONG)
+# define SIZEOF_LONG ACC_SIZEOF_LONG
+#endif
+#if !defined(SIZEOF_LONG_LONG) && defined(ACC_SIZEOF_LONG_LONG)
+# define SIZEOF_LONG_LONG ACC_SIZEOF_LONG_LONG
+#endif
+#if !defined(SIZEOF___INT32) && defined(ACC_SIZEOF___INT32)
+# define SIZEOF___INT32 ACC_SIZEOF___INT32
+#endif
+#if !defined(SIZEOF___INT64) && defined(ACC_SIZEOF___INT64)
+# define SIZEOF___INT64 ACC_SIZEOF___INT64
+#endif
+#if !defined(SIZEOF_VOID_P) && defined(ACC_SIZEOF_VOID_P)
+# define SIZEOF_VOID_P ACC_SIZEOF_VOID_P
+#endif
+#if !defined(SIZEOF_SIZE_T) && defined(ACC_SIZEOF_SIZE_T)
+# define SIZEOF_SIZE_T ACC_SIZEOF_SIZE_T
+#endif
+#if !defined(SIZEOF_PTRDIFF_T) && defined(ACC_SIZEOF_PTRDIFF_T)
+# define SIZEOF_PTRDIFF_T ACC_SIZEOF_PTRDIFF_T
+#endif
+#endif
+#if defined(HAVE_SIGNAL) && !defined(RETSIGTYPE)
+# define RETSIGTYPE void
+#endif
+#endif
+#if defined(ACC_CFG_NO_ACC_TYPE_H)
+#else
+#if (ACC_SIZEOF_LONG_LONG+0 > 0)
+__acc_gnuc_extension__ typedef long long acc_llong_t;
+__acc_gnuc_extension__ typedef unsigned long long acc_ullong_t;
+#endif
+#if (!(ACC_SIZEOF_SHORT+0 > 0 && ACC_SIZEOF_INT+0 > 0 && ACC_SIZEOF_LONG+0 > 0))
+# error "missing defines for sizes"
+#endif
+#if (!(ACC_SIZEOF_PTRDIFF_T+0 > 0 && ACC_SIZEOF_SIZE_T+0 > 0 && ACC_SIZEOF_VOID_P+0 > 0))
+# error "missing defines for sizes"
+#endif
+#if !defined(acc_int16e_t)
+#if (ACC_SIZEOF_LONG == 2)
+# define acc_int16e_t long
+# define acc_uint16e_t unsigned long
+#elif (ACC_SIZEOF_INT == 2)
+# define acc_int16e_t int
+# define acc_uint16e_t unsigned int
+#elif (ACC_SIZEOF_SHORT == 2)
+# define acc_int16e_t short int
+# define acc_uint16e_t unsigned short int
+#elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_HI) && (ACC_CC_GNUC >= 0x025f00ul || ACC_CC_LLVM)
+ typedef int __acc_int16e_hi_t __attribute__((__mode__(__HI__)));
+ typedef unsigned int __acc_uint16e_hi_t __attribute__((__mode__(__HI__)));
+# define acc_int16e_t __acc_int16e_hi_t
+# define acc_uint16e_t __acc_uint16e_hi_t
+#elif (ACC_SIZEOF___INT16 == 2)
+# define acc_int16e_t __int16
+# define acc_uint16e_t unsigned __int16
+#else
+#endif
+#endif
+#if defined(acc_int16e_t)
+# define ACC_SIZEOF_ACC_INT16E_T 2
+#endif
+#if !defined(acc_int32e_t)
+#if (ACC_SIZEOF_LONG == 4)
+# define acc_int32e_t long int
+# define acc_uint32e_t unsigned long int
+#elif (ACC_SIZEOF_INT == 4)
+# define acc_int32e_t int
+# define acc_uint32e_t unsigned int
+#elif (ACC_SIZEOF_SHORT == 4)
+# define acc_int32e_t short int
+# define acc_uint32e_t unsigned short int
+#elif (ACC_SIZEOF_LONG_LONG == 4)
+# define acc_int32e_t acc_llong_t
+# define acc_uint32e_t acc_ullong_t
+#elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_SI) && (ACC_CC_GNUC >= 0x025f00ul || ACC_CC_LLVM) && (__INT_MAX__+0 > 2147483647L)
+ typedef int __acc_int32e_si_t __attribute__((__mode__(__SI__)));
+ typedef unsigned int __acc_uint32e_si_t __attribute__((__mode__(__SI__)));
+# define acc_int32e_t __acc_int32e_si_t
+# define acc_uint32e_t __acc_uint32e_si_t
+#elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_SI) && (ACC_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L)
+ typedef int __acc_int32e_si_t __attribute__((__mode__(__SI__)));
+ typedef unsigned int __acc_uint32e_si_t __attribute__((__mode__(__SI__)));
+# define acc_int32e_t __acc_int32e_si_t
+# define acc_uint32e_t __acc_uint32e_si_t
+# define ACC_INT32_C(c) c##LL
+# define ACC_UINT32_C(c) c##ULL
+#elif (ACC_SIZEOF___INT32 == 4)
+# define acc_int32e_t __int32
+# define acc_uint32e_t unsigned __int32
+#else
+#endif
+#endif
+#if defined(acc_int32e_t)
+# define ACC_SIZEOF_ACC_INT32E_T 4
+#endif
+#if !defined(acc_int64e_t)
+#if (ACC_SIZEOF___INT64 == 8)
+# if (ACC_CC_BORLANDC) && !defined(ACC_CFG_TYPE_PREFER___INT64)
+# define ACC_CFG_TYPE_PREFER___INT64 1
+# endif
+#endif
+#if (ACC_SIZEOF_INT == 8) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)
+# define acc_int64e_t int
+# define acc_uint64e_t unsigned int
+# define ACC_SIZEOF_ACC_INT64E_T ACC_SIZEOF_INT
+#elif (ACC_SIZEOF_LONG == 8)
+# define acc_int64e_t long int
+# define acc_uint64e_t unsigned long int
+# define ACC_SIZEOF_ACC_INT64E_T ACC_SIZEOF_LONG
+#elif (ACC_SIZEOF_LONG_LONG == 8) && !defined(ACC_CFG_TYPE_PREFER___INT64)
+# define acc_int64e_t acc_llong_t
+# define acc_uint64e_t acc_ullong_t
+# if (ACC_CC_BORLANDC)
+# define ACC_INT64_C(c) ((c) + 0ll)
+# define ACC_UINT64_C(c) ((c) + 0ull)
+# else
+# define ACC_INT64_C(c) c##LL
+# define ACC_UINT64_C(c) c##ULL
+# endif
+# define ACC_SIZEOF_ACC_INT64E_T ACC_SIZEOF_LONG_LONG
+#elif (ACC_SIZEOF___INT64 == 8)
+# define acc_int64e_t __int64
+# define acc_uint64e_t unsigned __int64
+# if (ACC_CC_BORLANDC)
+# define ACC_INT64_C(c) ((c) + 0i64)
+# define ACC_UINT64_C(c) ((c) + 0ui64)
+# else
+# define ACC_INT64_C(c) c##i64
+# define ACC_UINT64_C(c) c##ui64
+# endif
+# define ACC_SIZEOF_ACC_INT64E_T ACC_SIZEOF___INT64
+#else
+#endif
+#endif
+#if !defined(acc_int32l_t)
+#if defined(acc_int32e_t)
+# define acc_int32l_t acc_int32e_t
+# define acc_uint32l_t acc_uint32e_t
+# define ACC_SIZEOF_ACC_INT32L_T ACC_SIZEOF_ACC_INT32E_T
+#elif (ACC_SIZEOF_INT >= 4) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)
+# define acc_int32l_t int
+# define acc_uint32l_t unsigned int
+# define ACC_SIZEOF_ACC_INT32L_T ACC_SIZEOF_INT
+#elif (ACC_SIZEOF_LONG >= 4)
+# define acc_int32l_t long int
+# define acc_uint32l_t unsigned long int
+# define ACC_SIZEOF_ACC_INT32L_T ACC_SIZEOF_LONG
+#else
+# error "acc_int32l_t"
+#endif
+#endif
+#if !defined(acc_int64l_t)
+#if defined(acc_int64e_t)
+# define acc_int64l_t acc_int64e_t
+# define acc_uint64l_t acc_uint64e_t
+# define ACC_SIZEOF_ACC_INT64L_T ACC_SIZEOF_ACC_INT64E_T
+#else
+#endif
+#endif
+#if !defined(acc_int32f_t)
+#if (ACC_SIZEOF_SIZE_T >= 8)
+# define acc_int32f_t acc_int64l_t
+# define acc_uint32f_t acc_uint64l_t
+# define ACC_SIZEOF_ACC_INT32F_T ACC_SIZEOF_ACC_INT64L_T
+#else
+# define acc_int32f_t acc_int32l_t
+# define acc_uint32f_t acc_uint32l_t
+# define ACC_SIZEOF_ACC_INT32F_T ACC_SIZEOF_ACC_INT32L_T
+#endif
+#endif
+#if !defined(acc_intptr_t)
+#if 1 && (ACC_OS_OS400 && (ACC_SIZEOF_VOID_P == 16))
+# define __ACC_INTPTR_T_IS_POINTER 1
+ typedef char* acc_intptr_t;
+ typedef char* acc_uintptr_t;
+# define acc_intptr_t acc_intptr_t
+# define acc_uintptr_t acc_uintptr_t
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_VOID_P
+#elif (ACC_CC_MSC && (_MSC_VER >= 1300) && (ACC_SIZEOF_VOID_P == 4) && (ACC_SIZEOF_INT == 4))
+ typedef __w64 int acc_intptr_t;
+ typedef __w64 unsigned int acc_uintptr_t;
+# define acc_intptr_t acc_intptr_t
+# define acc_uintptr_t acc_uintptr_t
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_INT
+#elif (ACC_SIZEOF_SHORT == ACC_SIZEOF_VOID_P) && (ACC_SIZEOF_INT > ACC_SIZEOF_VOID_P)
+# define acc_intptr_t short
+# define acc_uintptr_t unsigned short
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_SHORT
+#elif (ACC_SIZEOF_INT >= ACC_SIZEOF_VOID_P) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)
+# define acc_intptr_t int
+# define acc_uintptr_t unsigned int
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_INT
+#elif (ACC_SIZEOF_LONG >= ACC_SIZEOF_VOID_P)
+# define acc_intptr_t long
+# define acc_uintptr_t unsigned long
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_LONG
+#elif (ACC_SIZEOF_ACC_INT64L_T >= ACC_SIZEOF_VOID_P)
+# define acc_intptr_t acc_int64l_t
+# define acc_uintptr_t acc_uint64l_t
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_ACC_INT64L_T
+#else
+# error "acc_intptr_t"
+#endif
+#endif
+#if !defined(acc_word_t)
+#if defined(ACC_WORDSIZE) && (ACC_WORDSIZE > 0)
+#if (ACC_WORDSIZE == ACC_SIZEOF_ACC_INTPTR_T) && !defined(__ACC_INTPTR_T_IS_POINTER)
+# define acc_word_t acc_uintptr_t
+# define acc_sword_t acc_intptr_t
+# define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_ACC_INTPTR_T
+#elif (ACC_WORDSIZE == ACC_SIZEOF_LONG)
+# define acc_word_t unsigned long
+# define acc_sword_t long
+# define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_LONG
+#elif (ACC_WORDSIZE == ACC_SIZEOF_INT)
+# define acc_word_t unsigned int
+# define acc_sword_t int
+# define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_INT
+#elif (ACC_WORDSIZE == ACC_SIZEOF_SHORT)
+# define acc_word_t unsigned short
+# define acc_sword_t short
+# define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_SHORT
+#elif (ACC_WORDSIZE == 1)
+# define acc_word_t unsigned char
+# define acc_sword_t signed char
+# define ACC_SIZEOF_ACC_WORD_T 1
+#elif (ACC_WORDSIZE == ACC_SIZEOF_ACC_INT64L_T)
+# define acc_word_t acc_uint64l_t
+# define acc_sword_t acc_int64l_t
+# define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_ACC_INT64L_T
+#elif (ACC_ARCH_SPU) && (ACC_CC_GNUC)
+#if 0
+ typedef unsigned acc_word_t __attribute__((__mode__(__V16QI__)));
+ typedef int acc_sword_t __attribute__((__mode__(__V16QI__)));
+# define acc_word_t acc_word_t
+# define acc_sword_t acc_sword_t
+# define ACC_SIZEOF_ACC_WORD_T 16
+#endif
+#else
+# error "acc_word_t"
+#endif
+#endif
+#endif
+#if !defined(ACC_INT16_C)
+# if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 2)
+# define ACC_INT16_C(c) ((c) + 0)
+# define ACC_UINT16_C(c) ((c) + 0U)
+# elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 2)
+# define ACC_INT16_C(c) ((c) + 0L)
+# define ACC_UINT16_C(c) ((c) + 0UL)
+# elif (ACC_SIZEOF_INT >= 2)
+# define ACC_INT16_C(c) c
+# define ACC_UINT16_C(c) c##U
+# elif (ACC_SIZEOF_LONG >= 2)
+# define ACC_INT16_C(c) c##L
+# define ACC_UINT16_C(c) c##UL
+# else
+# error "ACC_INT16_C"
+# endif
+#endif
+#if !defined(ACC_INT32_C)
+# if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 4)
+# define ACC_INT32_C(c) ((c) + 0)
+# define ACC_UINT32_C(c) ((c) + 0U)
+# elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 4)
+# define ACC_INT32_C(c) ((c) + 0L)
+# define ACC_UINT32_C(c) ((c) + 0UL)
+# elif (ACC_SIZEOF_INT >= 4)
+# define ACC_INT32_C(c) c
+# define ACC_UINT32_C(c) c##U
+# elif (ACC_SIZEOF_LONG >= 4)
+# define ACC_INT32_C(c) c##L
+# define ACC_UINT32_C(c) c##UL
+# elif (ACC_SIZEOF_LONG_LONG >= 4)
+# define ACC_INT32_C(c) c##LL
+# define ACC_UINT32_C(c) c##ULL
+# else
+# error "ACC_INT32_C"
+# endif
+#endif
+#if !defined(ACC_INT64_C) && defined(acc_int64l_t)
+# if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 8)
+# define ACC_INT64_C(c) ((c) + 0)
+# define ACC_UINT64_C(c) ((c) + 0U)
+# elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 8)
+# define ACC_INT64_C(c) ((c) + 0L)
+# define ACC_UINT64_C(c) ((c) + 0UL)
+# elif (ACC_SIZEOF_INT >= 8)
+# define ACC_INT64_C(c) c
+# define ACC_UINT64_C(c) c##U
+# elif (ACC_SIZEOF_LONG >= 8)
+# define ACC_INT64_C(c) c##L
+# define ACC_UINT64_C(c) c##UL
+# else
+# error "ACC_INT64_C"
+# endif
+#endif
+#if !defined(SIZEOF_ACC_INT16E_T) && defined(ACC_SIZEOF_ACC_INT16E_T)
+# define SIZEOF_ACC_INT16E_T ACC_SIZEOF_ACC_INT16E_T
+#endif
+#if !defined(SIZEOF_ACC_INT32E_T) && defined(ACC_SIZEOF_ACC_INT32E_T)
+# define SIZEOF_ACC_INT32E_T ACC_SIZEOF_ACC_INT32E_T
+#endif
+#if !defined(SIZEOF_ACC_INT64E_T) && defined(ACC_SIZEOF_ACC_INT64E_T)
+# define SIZEOF_ACC_INT64E_T ACC_SIZEOF_ACC_INT64E_T
+#endif
+#if !defined(SIZEOF_ACC_INT32L_T) && defined(ACC_SIZEOF_ACC_INT32L_T)
+# define SIZEOF_ACC_INT32L_T ACC_SIZEOF_ACC_INT32L_T
+#endif
+#if !defined(SIZEOF_ACC_INT64L_T) && defined(ACC_SIZEOF_ACC_INT64L_T)
+# define SIZEOF_ACC_INT64L_T ACC_SIZEOF_ACC_INT64L_T
+#endif
+#if !defined(SIZEOF_ACC_INT32F_T) && defined(ACC_SIZEOF_ACC_INT32F_T)
+# define SIZEOF_ACC_INT32F_T ACC_SIZEOF_ACC_INT32F_T
+#endif
+#if !defined(SIZEOF_ACC_INTPTR_T) && defined(ACC_SIZEOF_ACC_INTPTR_T)
+# define SIZEOF_ACC_INTPTR_T ACC_SIZEOF_ACC_INTPTR_T
+#endif
+#if !defined(SIZEOF_ACC_WORD_T) && defined(ACC_SIZEOF_ACC_WORD_T)
+# define SIZEOF_ACC_WORD_T ACC_SIZEOF_ACC_WORD_T
+#endif
+#if 1 && !defined(acc_signo_t) && defined(__linux__) && defined(__dietlibc__) && (ACC_SIZEOF_INT != 4)
+# define acc_signo_t acc_int32e_t
+#endif
+#if !defined(acc_signo_t)
+# define acc_signo_t int
+#endif
+#if defined(__cplusplus)
+extern "C" {
+#endif
+#if (ACC_BROKEN_CDECL_ALT_SYNTAX)
+typedef void __acc_cdecl_sighandler (*acc_sighandler_t)(acc_signo_t);
+#elif defined(RETSIGTYPE)
+typedef RETSIGTYPE (__acc_cdecl_sighandler *acc_sighandler_t)(acc_signo_t);
+#else
+typedef void (__acc_cdecl_sighandler *acc_sighandler_t)(acc_signo_t);
+#endif
+#if defined(__cplusplus)
+}
+#endif
+# if defined(ACC_CFG_NO_ACC_UA_H)
+# else
+#if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020700ul))
+#elif (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020800ul)) && defined(__cplusplus)
+#elif (ACC_CC_INTELC) && defined(_WIN32)
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER < 700))
+#elif (ACC_CC_LLVM)
+#elif (ACC_CC_GNUC || ACC_CC_INTELC || ACC_CC_PATHSCALE)
+#if !defined(__acc_ua16_t) && (ACC_OPT_UNALIGNED16) && defined(acc_int16e_t)
+ typedef struct { __acc_ua_volatile acc_uint16e_t v __attribute__((__packed__)); } __acc_ua16_t;
+# define __acc_ua16_t __acc_ua16_t
+#endif
+#if !defined(__acc_ua32_t) && (ACC_OPT_UNALIGNED32) && defined(acc_int32e_t)
+ typedef struct { __acc_ua_volatile acc_uint32e_t v __attribute__((__packed__)); } __acc_ua32_t;
+# define __acc_ua32_t __acc_ua32_t
+#endif
+#if !defined(__acc_ua64_t) && (ACC_OPT_UNALIGNED64) && defined(acc_int64l_t)
+ typedef struct { __acc_ua_volatile acc_uint64l_t v __attribute__((__packed__)); } __acc_ua64_t;
+# define __acc_ua64_t __acc_ua64_t
+#endif
+#endif
+#if (ACC_OPT_UNALIGNED16) && defined(acc_int16e_t)
+#define ACC_UA_GET16(p) (* (__acc_ua_volatile const acc_uint16e_t*) (__acc_ua_volatile const void*) (p))
+#define ACC_UA_SET16(p,v) (* (__acc_ua_volatile acc_uint16e_t*) (__acc_ua_volatile void*) (p) = (acc_uint16e_t) (v))
+#if (ACC_ABI_BIG_ENDIAN)
+# define ACC_UA_GET_BE16(p) ACC_UA_GET16(p)
+# define ACC_UA_SET_BE16(p,v) ACC_UA_SET16(p,v)
+#elif (ACC_ABI_LITTLE_ENDIAN)
+# define ACC_UA_GET_LE16(p) ACC_UA_GET16(p)
+# define ACC_UA_SET_LE16(p,v) ACC_UA_SET16(p,v)
+#endif
+#if !defined(ACC_CFG_NO_INLINE_ASM) && defined(__acc_HAVE_forceinline)
+#if (ACC_ARCH_POWERPC && ACC_ABI_BIG_ENDIAN) && (ACC_CC_GNUC)
+#if !defined(ACC_UA_GET_LE16)
+extern __acc_forceinline unsigned long __ACC_UA_GET_LE16(__acc_ua_volatile const void* pp);
+extern __acc_forceinline unsigned long __ACC_UA_GET_LE16(__acc_ua_volatile const void* pp) {
+ __acc_ua_volatile const acc_uint16e_t* p = (__acc_ua_volatile const acc_uint16e_t*) pp;
+ unsigned long v;
+ __asm__ __volatile__("lhbrx %0,0,%1" : "=r" (v) : "r" (p), "m" (*p));
+ return v;
+}
+#define ACC_UA_GET_LE16(p) __ACC_UA_GET_LE16(p)
+#endif
+#if !defined(ACC_UA_SET_LE16)
+extern __acc_forceinline void __ACC_UA_SET_LE16(__acc_ua_volatile void* pp, unsigned long v);
+extern __acc_forceinline void __ACC_UA_SET_LE16(__acc_ua_volatile void* pp, unsigned long v) {
+ __acc_ua_volatile acc_uint16e_t* p = (__acc_ua_volatile acc_uint16e_t*) pp;
+ __asm__ __volatile__("sthbrx %2,0,%1" : "=m" (*p) : "r" (p), "r" (v));
+}
+#define ACC_UA_SET_LE16(p,v) __ACC_UA_SET_LE16(p,v)
+#endif
+#endif
+#endif
+#if !defined(ACC_UA_COPY16)
+# define ACC_UA_COPY16(d,s) ACC_UA_SET16(d, ACC_UA_GET16(s))
+#endif
+#endif
+#if (ACC_OPT_UNALIGNED32) && defined(acc_int32e_t)
+#define ACC_UA_GET32(p) (* (__acc_ua_volatile const acc_uint32e_t*) (__acc_ua_volatile const void*) (p))
+#define ACC_UA_SET32(p,v) (* (__acc_ua_volatile acc_uint32e_t*) (__acc_ua_volatile void*) (p) = (acc_uint32e_t) (v))
+#if (ACC_ABI_BIG_ENDIAN)
+# define ACC_UA_GET_BE32(p) ACC_UA_GET32(p)
+# define ACC_UA_SET_BE32(p,v) ACC_UA_SET32(p,v)
+#elif (ACC_ABI_LITTLE_ENDIAN)
+# define ACC_UA_GET_LE32(p) ACC_UA_GET32(p)
+# define ACC_UA_SET_LE32(p,v) ACC_UA_SET32(p,v)
+#endif
+#if !defined(ACC_CFG_NO_INLINE_ASM) && defined(__acc_HAVE_forceinline)
+#if (ACC_ARCH_POWERPC && ACC_ABI_BIG_ENDIAN) && (ACC_CC_GNUC)
+#if !defined(ACC_UA_GET_LE32)
+extern __acc_forceinline unsigned long __ACC_UA_GET_LE32(__acc_ua_volatile const void* pp);
+extern __acc_forceinline unsigned long __ACC_UA_GET_LE32(__acc_ua_volatile const void* pp) {
+ __acc_ua_volatile const acc_uint32e_t* p = (__acc_ua_volatile const acc_uint32e_t*) pp;
+ unsigned long v;
+ __asm__ __volatile__("lwbrx %0,0,%1" : "=r" (v) : "r" (p), "m" (*p));
+ return v;
+}
+#define ACC_UA_GET_LE32(p) __ACC_UA_GET_LE32(p)
+#endif
+#if !defined(ACC_UA_SET_LE32)
+extern __acc_forceinline void __ACC_UA_SET_LE32(__acc_ua_volatile void* pp, unsigned long v);
+extern __acc_forceinline void __ACC_UA_SET_LE32(__acc_ua_volatile void* pp, unsigned long v) {
+ __acc_ua_volatile acc_uint32e_t* p = (__acc_ua_volatile acc_uint32e_t*) pp;
+ __asm__ __volatile__("stwbrx %2,0,%1" : "=m" (*p) : "r" (p), "r" (v));
+}
+#define ACC_UA_SET_LE32(p,v) __ACC_UA_SET_LE32(p,v)
+#endif
+#endif
+#endif
+#if !defined(ACC_UA_COPY32)
+# define ACC_UA_COPY32(d,s) ACC_UA_SET32(d, ACC_UA_GET32(s))
+#endif
+#endif
+#if (ACC_OPT_UNALIGNED64) && defined(acc_int64l_t)
+#define ACC_UA_GET64(p) (* (__acc_ua_volatile const acc_uint64l_t*) (__acc_ua_volatile const void*) (p))
+#define ACC_UA_SET64(p,v) (* (__acc_ua_volatile acc_uint64l_t*) (__acc_ua_volatile void*) (p) = (acc_uint64l_t) (v))
+#if (ACC_ABI_BIG_ENDIAN)
+# define ACC_UA_GET_BE64(p) ACC_UA_GET64(p)
+# define ACC_UA_SET_BE64(p,v) ACC_UA_SET64(p,v)
+#elif (ACC_ABI_LITTLE_ENDIAN)
+# define ACC_UA_GET_LE64(p) ACC_UA_GET64(p)
+# define ACC_UA_SET_LE64(p,v) ACC_UA_SET64(p,v)
+#endif
+#if !defined(ACC_UA_COPY64)
+# define ACC_UA_COPY64(d,s) ACC_UA_SET64(d, ACC_UA_GET64(s))
+#endif
+#endif
+# endif
+#endif
+#endif
+#if defined(ACC_WANT_ACC_TYPE_H)
+# undef ACC_WANT_ACC_TYPE_H
+# if defined(ACC_CFG_NO_ACC_TYPE_H)
+# error "ACC_WANT_ACC_TYPE_H with ACC_CFG_NO_ACC_TYPE_H"
+# endif
+#if (ACC_SIZEOF_LONG_LONG+0 > 0)
+__acc_gnuc_extension__ typedef long long acc_llong_t;
+__acc_gnuc_extension__ typedef unsigned long long acc_ullong_t;
+#endif
+#if (!(ACC_SIZEOF_SHORT+0 > 0 && ACC_SIZEOF_INT+0 > 0 && ACC_SIZEOF_LONG+0 > 0))
+# error "missing defines for sizes"
+#endif
+#if (!(ACC_SIZEOF_PTRDIFF_T+0 > 0 && ACC_SIZEOF_SIZE_T+0 > 0 && ACC_SIZEOF_VOID_P+0 > 0))
+# error "missing defines for sizes"
+#endif
+#if !defined(acc_int16e_t)
+#if (ACC_SIZEOF_LONG == 2)
+# define acc_int16e_t long
+# define acc_uint16e_t unsigned long
+#elif (ACC_SIZEOF_INT == 2)
+# define acc_int16e_t int
+# define acc_uint16e_t unsigned int
+#elif (ACC_SIZEOF_SHORT == 2)
+# define acc_int16e_t short int
+# define acc_uint16e_t unsigned short int
+#elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_HI) && (ACC_CC_GNUC >= 0x025f00ul || ACC_CC_LLVM)
+ typedef int __acc_int16e_hi_t __attribute__((__mode__(__HI__)));
+ typedef unsigned int __acc_uint16e_hi_t __attribute__((__mode__(__HI__)));
+# define acc_int16e_t __acc_int16e_hi_t
+# define acc_uint16e_t __acc_uint16e_hi_t
+#elif (ACC_SIZEOF___INT16 == 2)
+# define acc_int16e_t __int16
+# define acc_uint16e_t unsigned __int16
+#else
+#endif
+#endif
+#if defined(acc_int16e_t)
+# define ACC_SIZEOF_ACC_INT16E_T 2
+#endif
+#if !defined(acc_int32e_t)
+#if (ACC_SIZEOF_LONG == 4)
+# define acc_int32e_t long int
+# define acc_uint32e_t unsigned long int
+#elif (ACC_SIZEOF_INT == 4)
+# define acc_int32e_t int
+# define acc_uint32e_t unsigned int
+#elif (ACC_SIZEOF_SHORT == 4)
+# define acc_int32e_t short int
+# define acc_uint32e_t unsigned short int
+#elif (ACC_SIZEOF_LONG_LONG == 4)
+# define acc_int32e_t acc_llong_t
+# define acc_uint32e_t acc_ullong_t
+#elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_SI) && (ACC_CC_GNUC >= 0x025f00ul || ACC_CC_LLVM) && (__INT_MAX__+0 > 2147483647L)
+ typedef int __acc_int32e_si_t __attribute__((__mode__(__SI__)));
+ typedef unsigned int __acc_uint32e_si_t __attribute__((__mode__(__SI__)));
+# define acc_int32e_t __acc_int32e_si_t
+# define acc_uint32e_t __acc_uint32e_si_t
+#elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_SI) && (ACC_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L)
+ typedef int __acc_int32e_si_t __attribute__((__mode__(__SI__)));
+ typedef unsigned int __acc_uint32e_si_t __attribute__((__mode__(__SI__)));
+# define acc_int32e_t __acc_int32e_si_t
+# define acc_uint32e_t __acc_uint32e_si_t
+# define ACC_INT32_C(c) c##LL
+# define ACC_UINT32_C(c) c##ULL
+#elif (ACC_SIZEOF___INT32 == 4)
+# define acc_int32e_t __int32
+# define acc_uint32e_t unsigned __int32
+#else
+#endif
+#endif
+#if defined(acc_int32e_t)
+# define ACC_SIZEOF_ACC_INT32E_T 4
+#endif
+#if !defined(acc_int64e_t)
+#if (ACC_SIZEOF___INT64 == 8)
+# if (ACC_CC_BORLANDC) && !defined(ACC_CFG_TYPE_PREFER___INT64)
+# define ACC_CFG_TYPE_PREFER___INT64 1
+# endif
+#endif
+#if (ACC_SIZEOF_INT == 8) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)
+# define acc_int64e_t int
+# define acc_uint64e_t unsigned int
+# define ACC_SIZEOF_ACC_INT64E_T ACC_SIZEOF_INT
+#elif (ACC_SIZEOF_LONG == 8)
+# define acc_int64e_t long int
+# define acc_uint64e_t unsigned long int
+# define ACC_SIZEOF_ACC_INT64E_T ACC_SIZEOF_LONG
+#elif (ACC_SIZEOF_LONG_LONG == 8) && !defined(ACC_CFG_TYPE_PREFER___INT64)
+# define acc_int64e_t acc_llong_t
+# define acc_uint64e_t acc_ullong_t
+# if (ACC_CC_BORLANDC)
+# define ACC_INT64_C(c) ((c) + 0ll)
+# define ACC_UINT64_C(c) ((c) + 0ull)
+# else
+# define ACC_INT64_C(c) c##LL
+# define ACC_UINT64_C(c) c##ULL
+# endif
+# define ACC_SIZEOF_ACC_INT64E_T ACC_SIZEOF_LONG_LONG
+#elif (ACC_SIZEOF___INT64 == 8)
+# define acc_int64e_t __int64
+# define acc_uint64e_t unsigned __int64
+# if (ACC_CC_BORLANDC)
+# define ACC_INT64_C(c) ((c) + 0i64)
+# define ACC_UINT64_C(c) ((c) + 0ui64)
+# else
+# define ACC_INT64_C(c) c##i64
+# define ACC_UINT64_C(c) c##ui64
+# endif
+# define ACC_SIZEOF_ACC_INT64E_T ACC_SIZEOF___INT64
+#else
+#endif
+#endif
+#if !defined(acc_int32l_t)
+#if defined(acc_int32e_t)
+# define acc_int32l_t acc_int32e_t
+# define acc_uint32l_t acc_uint32e_t
+# define ACC_SIZEOF_ACC_INT32L_T ACC_SIZEOF_ACC_INT32E_T
+#elif (ACC_SIZEOF_INT >= 4) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)
+# define acc_int32l_t int
+# define acc_uint32l_t unsigned int
+# define ACC_SIZEOF_ACC_INT32L_T ACC_SIZEOF_INT
+#elif (ACC_SIZEOF_LONG >= 4)
+# define acc_int32l_t long int
+# define acc_uint32l_t unsigned long int
+# define ACC_SIZEOF_ACC_INT32L_T ACC_SIZEOF_LONG
+#else
+# error "acc_int32l_t"
+#endif
+#endif
+#if !defined(acc_int64l_t)
+#if defined(acc_int64e_t)
+# define acc_int64l_t acc_int64e_t
+# define acc_uint64l_t acc_uint64e_t
+# define ACC_SIZEOF_ACC_INT64L_T ACC_SIZEOF_ACC_INT64E_T
+#else
+#endif
+#endif
+#if !defined(acc_int32f_t)
+#if (ACC_SIZEOF_SIZE_T >= 8)
+# define acc_int32f_t acc_int64l_t
+# define acc_uint32f_t acc_uint64l_t
+# define ACC_SIZEOF_ACC_INT32F_T ACC_SIZEOF_ACC_INT64L_T
+#else
+# define acc_int32f_t acc_int32l_t
+# define acc_uint32f_t acc_uint32l_t
+# define ACC_SIZEOF_ACC_INT32F_T ACC_SIZEOF_ACC_INT32L_T
+#endif
+#endif
+#if !defined(acc_intptr_t)
+#if 1 && (ACC_OS_OS400 && (ACC_SIZEOF_VOID_P == 16))
+# define __ACC_INTPTR_T_IS_POINTER 1
+ typedef char* acc_intptr_t;
+ typedef char* acc_uintptr_t;
+# define acc_intptr_t acc_intptr_t
+# define acc_uintptr_t acc_uintptr_t
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_VOID_P
+#elif (ACC_CC_MSC && (_MSC_VER >= 1300) && (ACC_SIZEOF_VOID_P == 4) && (ACC_SIZEOF_INT == 4))
+ typedef __w64 int acc_intptr_t;
+ typedef __w64 unsigned int acc_uintptr_t;
+# define acc_intptr_t acc_intptr_t
+# define acc_uintptr_t acc_uintptr_t
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_INT
+#elif (ACC_SIZEOF_SHORT == ACC_SIZEOF_VOID_P) && (ACC_SIZEOF_INT > ACC_SIZEOF_VOID_P)
+# define acc_intptr_t short
+# define acc_uintptr_t unsigned short
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_SHORT
+#elif (ACC_SIZEOF_INT >= ACC_SIZEOF_VOID_P) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)
+# define acc_intptr_t int
+# define acc_uintptr_t unsigned int
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_INT
+#elif (ACC_SIZEOF_LONG >= ACC_SIZEOF_VOID_P)
+# define acc_intptr_t long
+# define acc_uintptr_t unsigned long
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_LONG
+#elif (ACC_SIZEOF_ACC_INT64L_T >= ACC_SIZEOF_VOID_P)
+# define acc_intptr_t acc_int64l_t
+# define acc_uintptr_t acc_uint64l_t
+# define ACC_SIZEOF_ACC_INTPTR_T ACC_SIZEOF_ACC_INT64L_T
+#else
+# error "acc_intptr_t"
+#endif
+#endif
+#if !defined(acc_word_t)
+#if defined(ACC_WORDSIZE) && (ACC_WORDSIZE > 0)
+#if (ACC_WORDSIZE == ACC_SIZEOF_ACC_INTPTR_T) && !defined(__ACC_INTPTR_T_IS_POINTER)
+# define acc_word_t acc_uintptr_t
+# define acc_sword_t acc_intptr_t
+# define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_ACC_INTPTR_T
+#elif (ACC_WORDSIZE == ACC_SIZEOF_LONG)
+# define acc_word_t unsigned long
+# define acc_sword_t long
+# define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_LONG
+#elif (ACC_WORDSIZE == ACC_SIZEOF_INT)
+# define acc_word_t unsigned int
+# define acc_sword_t int
+# define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_INT
+#elif (ACC_WORDSIZE == ACC_SIZEOF_SHORT)
+# define acc_word_t unsigned short
+# define acc_sword_t short
+# define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_SHORT
+#elif (ACC_WORDSIZE == 1)
+# define acc_word_t unsigned char
+# define acc_sword_t signed char
+# define ACC_SIZEOF_ACC_WORD_T 1
+#elif (ACC_WORDSIZE == ACC_SIZEOF_ACC_INT64L_T)
+# define acc_word_t acc_uint64l_t
+# define acc_sword_t acc_int64l_t
+# define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_ACC_INT64L_T
+#elif (ACC_ARCH_SPU) && (ACC_CC_GNUC)
+#if 0
+ typedef unsigned acc_word_t __attribute__((__mode__(__V16QI__)));
+ typedef int acc_sword_t __attribute__((__mode__(__V16QI__)));
+# define acc_word_t acc_word_t
+# define acc_sword_t acc_sword_t
+# define ACC_SIZEOF_ACC_WORD_T 16
+#endif
+#else
+# error "acc_word_t"
+#endif
+#endif
+#endif
+#if !defined(ACC_INT16_C)
+# if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 2)
+# define ACC_INT16_C(c) ((c) + 0)
+# define ACC_UINT16_C(c) ((c) + 0U)
+# elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 2)
+# define ACC_INT16_C(c) ((c) + 0L)
+# define ACC_UINT16_C(c) ((c) + 0UL)
+# elif (ACC_SIZEOF_INT >= 2)
+# define ACC_INT16_C(c) c
+# define ACC_UINT16_C(c) c##U
+# elif (ACC_SIZEOF_LONG >= 2)
+# define ACC_INT16_C(c) c##L
+# define ACC_UINT16_C(c) c##UL
+# else
+# error "ACC_INT16_C"
+# endif
+#endif
+#if !defined(ACC_INT32_C)
+# if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 4)
+# define ACC_INT32_C(c) ((c) + 0)
+# define ACC_UINT32_C(c) ((c) + 0U)
+# elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 4)
+# define ACC_INT32_C(c) ((c) + 0L)
+# define ACC_UINT32_C(c) ((c) + 0UL)
+# elif (ACC_SIZEOF_INT >= 4)
+# define ACC_INT32_C(c) c
+# define ACC_UINT32_C(c) c##U
+# elif (ACC_SIZEOF_LONG >= 4)
+# define ACC_INT32_C(c) c##L
+# define ACC_UINT32_C(c) c##UL
+# elif (ACC_SIZEOF_LONG_LONG >= 4)
+# define ACC_INT32_C(c) c##LL
+# define ACC_UINT32_C(c) c##ULL
+# else
+# error "ACC_INT32_C"
+# endif
+#endif
+#if !defined(ACC_INT64_C) && defined(acc_int64l_t)
+# if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 8)
+# define ACC_INT64_C(c) ((c) + 0)
+# define ACC_UINT64_C(c) ((c) + 0U)
+# elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 8)
+# define ACC_INT64_C(c) ((c) + 0L)
+# define ACC_UINT64_C(c) ((c) + 0UL)
+# elif (ACC_SIZEOF_INT >= 8)
+# define ACC_INT64_C(c) c
+# define ACC_UINT64_C(c) c##U
+# elif (ACC_SIZEOF_LONG >= 8)
+# define ACC_INT64_C(c) c##L
+# define ACC_UINT64_C(c) c##UL
+# else
+# error "ACC_INT64_C"
+# endif
+#endif
+#if !defined(SIZEOF_ACC_INT16E_T) && defined(ACC_SIZEOF_ACC_INT16E_T)
+# define SIZEOF_ACC_INT16E_T ACC_SIZEOF_ACC_INT16E_T
+#endif
+#if !defined(SIZEOF_ACC_INT32E_T) && defined(ACC_SIZEOF_ACC_INT32E_T)
+# define SIZEOF_ACC_INT32E_T ACC_SIZEOF_ACC_INT32E_T
+#endif
+#if !defined(SIZEOF_ACC_INT64E_T) && defined(ACC_SIZEOF_ACC_INT64E_T)
+# define SIZEOF_ACC_INT64E_T ACC_SIZEOF_ACC_INT64E_T
+#endif
+#if !defined(SIZEOF_ACC_INT32L_T) && defined(ACC_SIZEOF_ACC_INT32L_T)
+# define SIZEOF_ACC_INT32L_T ACC_SIZEOF_ACC_INT32L_T
+#endif
+#if !defined(SIZEOF_ACC_INT64L_T) && defined(ACC_SIZEOF_ACC_INT64L_T)
+# define SIZEOF_ACC_INT64L_T ACC_SIZEOF_ACC_INT64L_T
+#endif
+#if !defined(SIZEOF_ACC_INT32F_T) && defined(ACC_SIZEOF_ACC_INT32F_T)
+# define SIZEOF_ACC_INT32F_T ACC_SIZEOF_ACC_INT32F_T
+#endif
+#if !defined(SIZEOF_ACC_INTPTR_T) && defined(ACC_SIZEOF_ACC_INTPTR_T)
+# define SIZEOF_ACC_INTPTR_T ACC_SIZEOF_ACC_INTPTR_T
+#endif
+#if !defined(SIZEOF_ACC_WORD_T) && defined(ACC_SIZEOF_ACC_WORD_T)
+# define SIZEOF_ACC_WORD_T ACC_SIZEOF_ACC_WORD_T
+#endif
+#if 1 && !defined(acc_signo_t) && defined(__linux__) && defined(__dietlibc__) && (ACC_SIZEOF_INT != 4)
+# define acc_signo_t acc_int32e_t
+#endif
+#if !defined(acc_signo_t)
+# define acc_signo_t int
+#endif
+#if defined(__cplusplus)
+extern "C" {
+#endif
+#if (ACC_BROKEN_CDECL_ALT_SYNTAX)
+typedef void __acc_cdecl_sighandler (*acc_sighandler_t)(acc_signo_t);
+#elif defined(RETSIGTYPE)
+typedef RETSIGTYPE (__acc_cdecl_sighandler *acc_sighandler_t)(acc_signo_t);
+#else
+typedef void (__acc_cdecl_sighandler *acc_sighandler_t)(acc_signo_t);
+#endif
+#if defined(__cplusplus)
+}
+#endif
+# if !defined(ACC_CFG_NO_ACC_UA_H)
+#if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020700ul))
+#elif (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020800ul)) && defined(__cplusplus)
+#elif (ACC_CC_INTELC) && defined(_WIN32)
+#elif (ACC_CC_INTELC && (__INTEL_COMPILER < 700))
+#elif (ACC_CC_LLVM)
+#elif (ACC_CC_GNUC || ACC_CC_INTELC || ACC_CC_PATHSCALE)
+#if !defined(__acc_ua16_t) && (ACC_OPT_UNALIGNED16) && defined(acc_int16e_t)
+ typedef struct { __acc_ua_volatile acc_uint16e_t v __attribute__((__packed__)); } __acc_ua16_t;
+# define __acc_ua16_t __acc_ua16_t
+#endif
+#if !defined(__acc_ua32_t) && (ACC_OPT_UNALIGNED32) && defined(acc_int32e_t)
+ typedef struct { __acc_ua_volatile acc_uint32e_t v __attribute__((__packed__)); } __acc_ua32_t;
+# define __acc_ua32_t __acc_ua32_t
+#endif
+#if !defined(__acc_ua64_t) && (ACC_OPT_UNALIGNED64) && defined(acc_int64l_t)
+ typedef struct { __acc_ua_volatile acc_uint64l_t v __attribute__((__packed__)); } __acc_ua64_t;
+# define __acc_ua64_t __acc_ua64_t
+#endif
+#endif
+#if (ACC_OPT_UNALIGNED16) && defined(acc_int16e_t)
+#define ACC_UA_GET16(p) (* (__acc_ua_volatile const acc_uint16e_t*) (__acc_ua_volatile const void*) (p))
+#define ACC_UA_SET16(p,v) (* (__acc_ua_volatile acc_uint16e_t*) (__acc_ua_volatile void*) (p) = (acc_uint16e_t) (v))
+#if (ACC_ABI_BIG_ENDIAN)
+# define ACC_UA_GET_BE16(p) ACC_UA_GET16(p)
+# define ACC_UA_SET_BE16(p,v) ACC_UA_SET16(p,v)
+#elif (ACC_ABI_LITTLE_ENDIAN)
+# define ACC_UA_GET_LE16(p) ACC_UA_GET16(p)
+# define ACC_UA_SET_LE16(p,v) ACC_UA_SET16(p,v)
+#endif
+#if !defined(ACC_CFG_NO_INLINE_ASM) && defined(__acc_HAVE_forceinline)
+#if (ACC_ARCH_POWERPC && ACC_ABI_BIG_ENDIAN) && (ACC_CC_GNUC)
+#if !defined(ACC_UA_GET_LE16)
+extern __acc_forceinline unsigned long __ACC_UA_GET_LE16(__acc_ua_volatile const void* pp);
+extern __acc_forceinline unsigned long __ACC_UA_GET_LE16(__acc_ua_volatile const void* pp) {
+ __acc_ua_volatile const acc_uint16e_t* p = (__acc_ua_volatile const acc_uint16e_t*) pp;
+ unsigned long v;
+ __asm__ __volatile__("lhbrx %0,0,%1" : "=r" (v) : "r" (p), "m" (*p));
+ return v;
+}
+#define ACC_UA_GET_LE16(p) __ACC_UA_GET_LE16(p)
+#endif
+#if !defined(ACC_UA_SET_LE16)
+extern __acc_forceinline void __ACC_UA_SET_LE16(__acc_ua_volatile void* pp, unsigned long v);
+extern __acc_forceinline void __ACC_UA_SET_LE16(__acc_ua_volatile void* pp, unsigned long v) {
+ __acc_ua_volatile acc_uint16e_t* p = (__acc_ua_volatile acc_uint16e_t*) pp;
+ __asm__ __volatile__("sthbrx %2,0,%1" : "=m" (*p) : "r" (p), "r" (v));
+}
+#define ACC_UA_SET_LE16(p,v) __ACC_UA_SET_LE16(p,v)
+#endif
+#endif
+#endif
+#if !defined(ACC_UA_COPY16)
+# define ACC_UA_COPY16(d,s) ACC_UA_SET16(d, ACC_UA_GET16(s))
+#endif
+#endif
+#if (ACC_OPT_UNALIGNED32) && defined(acc_int32e_t)
+#define ACC_UA_GET32(p) (* (__acc_ua_volatile const acc_uint32e_t*) (__acc_ua_volatile const void*) (p))
+#define ACC_UA_SET32(p,v) (* (__acc_ua_volatile acc_uint32e_t*) (__acc_ua_volatile void*) (p) = (acc_uint32e_t) (v))
+#if (ACC_ABI_BIG_ENDIAN)
+# define ACC_UA_GET_BE32(p) ACC_UA_GET32(p)
+# define ACC_UA_SET_BE32(p,v) ACC_UA_SET32(p,v)
+#elif (ACC_ABI_LITTLE_ENDIAN)
+# define ACC_UA_GET_LE32(p) ACC_UA_GET32(p)
+# define ACC_UA_SET_LE32(p,v) ACC_UA_SET32(p,v)
+#endif
+#if !defined(ACC_CFG_NO_INLINE_ASM) && defined(__acc_HAVE_forceinline)
+#if (ACC_ARCH_POWERPC && ACC_ABI_BIG_ENDIAN) && (ACC_CC_GNUC)
+#if !defined(ACC_UA_GET_LE32)
+extern __acc_forceinline unsigned long __ACC_UA_GET_LE32(__acc_ua_volatile const void* pp);
+extern __acc_forceinline unsigned long __ACC_UA_GET_LE32(__acc_ua_volatile const void* pp) {
+ __acc_ua_volatile const acc_uint32e_t* p = (__acc_ua_volatile const acc_uint32e_t*) pp;
+ unsigned long v;
+ __asm__ __volatile__("lwbrx %0,0,%1" : "=r" (v) : "r" (p), "m" (*p));
+ return v;
+}
+#define ACC_UA_GET_LE32(p) __ACC_UA_GET_LE32(p)
+#endif
+#if !defined(ACC_UA_SET_LE32)
+extern __acc_forceinline void __ACC_UA_SET_LE32(__acc_ua_volatile void* pp, unsigned long v);
+extern __acc_forceinline void __ACC_UA_SET_LE32(__acc_ua_volatile void* pp, unsigned long v) {
+ __acc_ua_volatile acc_uint32e_t* p = (__acc_ua_volatile acc_uint32e_t*) pp;
+ __asm__ __volatile__("stwbrx %2,0,%1" : "=m" (*p) : "r" (p), "r" (v));
+}
+#define ACC_UA_SET_LE32(p,v) __ACC_UA_SET_LE32(p,v)
+#endif
+#endif
+#endif
+#if !defined(ACC_UA_COPY32)
+# define ACC_UA_COPY32(d,s) ACC_UA_SET32(d, ACC_UA_GET32(s))
+#endif
+#endif
+#if (ACC_OPT_UNALIGNED64) && defined(acc_int64l_t)
+#define ACC_UA_GET64(p) (* (__acc_ua_volatile const acc_uint64l_t*) (__acc_ua_volatile const void*) (p))
+#define ACC_UA_SET64(p,v) (* (__acc_ua_volatile acc_uint64l_t*) (__acc_ua_volatile void*) (p) = (acc_uint64l_t) (v))
+#if (ACC_ABI_BIG_ENDIAN)
+# define ACC_UA_GET_BE64(p) ACC_UA_GET64(p)
+# define ACC_UA_SET_BE64(p,v) ACC_UA_SET64(p,v)
+#elif (ACC_ABI_LITTLE_ENDIAN)
+# define ACC_UA_GET_LE64(p) ACC_UA_GET64(p)
+# define ACC_UA_SET_LE64(p,v) ACC_UA_SET64(p,v)
+#endif
+#if !defined(ACC_UA_COPY64)
+# define ACC_UA_COPY64(d,s) ACC_UA_SET64(d, ACC_UA_GET64(s))
+#endif
+#endif
+# endif
+#endif
+#if defined(ACC_WANT_ACC_INCD_H)
+# undef ACC_WANT_ACC_INCD_H
+#ifndef __ACC_INCD_H_INCLUDED
+#define __ACC_INCD_H_INCLUDED 1
+#if defined(ACC_LIBC_NAKED)
+#ifndef __ACC_FALLBACK_STDDEF_H_INCLUDED
+#define __ACC_FALLBACK_STDDEF_H_INCLUDED
+#if defined(__PTRDIFF_TYPE__)
+typedef __PTRDIFF_TYPE__ acc_fallback_ptrdiff_t;
+#elif defined(__MIPS_PSX2__)
+typedef int acc_fallback_ptrdiff_t;
+#else
+typedef long acc_fallback_ptrdiff_t;
+#endif
+#if defined(__SIZE_TYPE__)
+typedef __SIZE_TYPE__ acc_fallback_size_t;
+#elif defined(__MIPS_PSX2__)
+typedef unsigned int acc_fallback_size_t;
+#else
+typedef unsigned long acc_fallback_size_t;
+#endif
+#if !defined(ptrdiff_t)
+typedef acc_fallback_ptrdiff_t ptrdiff_t;
+#ifndef _PTRDIFF_T_DEFINED
+#define _PTRDIFF_T_DEFINED 1
+#endif
+#endif
+#if !defined(size_t)
+typedef acc_fallback_size_t size_t;
+#ifndef _SIZE_T_DEFINED
+#define _SIZE_T_DEFINED 1
+#endif
+#endif
+#if !defined(__cplusplus) && !defined(wchar_t)
+typedef unsigned short wchar_t;
+#ifndef _WCHAR_T_DEFINED
+#define _WCHAR_T_DEFINED 1
+#endif
+#endif
+#ifndef NULL
+#if defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ >= 4)
+#define NULL __null
+#elif defined(__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void*)0)
+#endif
+#endif
+#ifndef offsetof
+#define offsetof(s,m) ((size_t)((ptrdiff_t)&(((s*)0)->m)))
+#endif
+#endif
+#elif defined(ACC_LIBC_FREESTANDING)
+# if HAVE_STDDEF_H
+# include <stddef.h>
+# endif
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#elif defined(ACC_LIBC_MOSTLY_FREESTANDING)
+# if HAVE_STDIO_H
+# include <stdio.h>
+# endif
+# if HAVE_STDDEF_H
+# include <stddef.h>
+# endif
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#else
+#include <stdio.h>
+#if defined(HAVE_TIME_H) && defined(__MSL__) && defined(__cplusplus)
+# include <time.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#endif
+#endif
+#endif
+#if defined(ACC_WANT_ACC_INCE_H)
+# undef ACC_WANT_ACC_INCE_H
+#ifndef __ACC_INCE_H_INCLUDED
+#define __ACC_INCE_H_INCLUDED 1
+#if defined(ACC_LIBC_NAKED)
+#elif defined(ACC_LIBC_FREESTANDING)
+#elif defined(ACC_LIBC_MOSTLY_FREESTANDING)
+# if defined(HAVE_SETJMP_H)
+# include <setjmp.h>
+# endif
+#else
+#if defined(HAVE_STDARG_H)
+# include <stdarg.h>
+#endif
+#if defined(HAVE_CTYPE_H)
+# include <ctype.h>
+#endif
+#if defined(HAVE_ERRNO_H)
+# include <errno.h>
+#endif
+#if defined(HAVE_MALLOC_H)
+# include <malloc.h>
+#endif
+#if defined(HAVE_ALLOCA_H)
+# include <alloca.h>
+#endif
+#if defined(HAVE_FCNTL_H)
+# include <fcntl.h>
+#endif
+#if defined(HAVE_DIRENT_H)
+# include <dirent.h>
+#endif
+#if defined(HAVE_SETJMP_H)
+# include <setjmp.h>
+#endif
+#if defined(HAVE_SIGNAL_H)
+# include <signal.h>
+#endif
+#if defined(TIME_WITH_SYS_TIME)
+# include <sys/time.h>
+# include <time.h>
+#elif defined(HAVE_TIME_H)
+# include <time.h>
+#endif
+#if defined(HAVE_UTIME_H)
+# include <utime.h>
+#elif defined(HAVE_SYS_UTIME_H)
+# include <sys/utime.h>
+#endif
+#if defined(HAVE_IO_H)
+# include <io.h>
+#endif
+#if defined(HAVE_DOS_H)
+# include <dos.h>
+#endif
+#if defined(HAVE_DIRECT_H)
+# include <direct.h>
+#endif
+#if defined(HAVE_SHARE_H)
+# include <share.h>
+#endif
+#if defined(ACC_CC_NDPC)
+# include <os.h>
+#endif
+#if defined(__TOS__) && (defined(__PUREC__) || defined(__TURBOC__))
+# include <ext.h>
+#endif
+#endif
+#endif
+#endif
+#if defined(ACC_WANT_ACC_INCI_H)
+# undef ACC_WANT_ACC_INCI_H
+#ifndef __ACC_INCI_H_INCLUDED
+#define __ACC_INCI_H_INCLUDED 1
+#if defined(ACC_LIBC_NAKED)
+#elif defined(ACC_LIBC_FREESTANDING)
+#elif defined(ACC_LIBC_MOSTLY_FREESTANDING)
+#else
+#if (ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))
+# include <tos.h>
+#elif (ACC_HAVE_WINDOWS_H)
+# if 1 && !defined(WIN32_LEAN_AND_MEAN)
+# define WIN32_LEAN_AND_MEAN 1
+# endif
+# if 1 && !defined(_WIN32_WINNT)
+# define _WIN32_WINNT 0x0400
+# endif
+# include <windows.h>
+# if (ACC_CC_BORLANDC || ACC_CC_TURBOC)
+# include <dir.h>
+# endif
+#elif (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_WIN16)
+# if (ACC_CC_AZTECC)
+# include <model.h>
+# include <stat.h>
+# elif (ACC_CC_BORLANDC || ACC_CC_TURBOC)
+# include <alloc.h>
+# include <dir.h>
+# elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)
+# include <sys/exceptn.h>
+# elif (ACC_CC_PACIFICC)
+# include <unixio.h>
+# include <stat.h>
+# include <sys.h>
+# elif (ACC_CC_WATCOMC)
+# include <i86.h>
+# endif
+#elif (ACC_OS_OS216)
+# if (ACC_CC_WATCOMC)
+# include <i86.h>
+# endif
+#endif
+#if defined(HAVE_SYS_MMAN_H)
+# include <sys/mman.h>
+#endif
+#if defined(HAVE_SYS_RESOURCE_H)
+# include <sys/resource.h>
+#endif
+#if (ACC_OS_DOS16 || ACC_OS_OS216 || ACC_OS_WIN16)
+# if defined(FP_OFF)
+# define ACC_PTR_FP_OFF(x) FP_OFF(x)
+# elif defined(_FP_OFF)
+# define ACC_PTR_FP_OFF(x) _FP_OFF(x)
+# else
+# define ACC_PTR_FP_OFF(x) (((const unsigned __far*)&(x))[0])
+# endif
+# if defined(FP_SEG)
+# define ACC_PTR_FP_SEG(x) FP_SEG(x)
+# elif defined(_FP_SEG)
+# define ACC_PTR_FP_SEG(x) _FP_SEG(x)
+# else
+# define ACC_PTR_FP_SEG(x) (((const unsigned __far*)&(x))[1])
+# endif
+# if defined(MK_FP)
+# define ACC_PTR_MK_FP(s,o) MK_FP(s,o)
+# elif defined(_MK_FP)
+# define ACC_PTR_MK_FP(s,o) _MK_FP(s,o)
+# else
+# define ACC_PTR_MK_FP(s,o) ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o)))
+# endif
+# if 0
+# undef ACC_PTR_FP_OFF
+# undef ACC_PTR_FP_SEG
+# undef ACC_PTR_MK_FP
+# define ACC_PTR_FP_OFF(x) (((const unsigned __far*)&(x))[0])
+# define ACC_PTR_FP_SEG(x) (((const unsigned __far*)&(x))[1])
+# define ACC_PTR_MK_FP(s,o) ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o)))
+# endif
+#endif
+#endif
+#endif
+#endif
+#if defined(ACC_WANT_ACC_LIB_H)
+# undef ACC_WANT_ACC_LIB_H
+#ifndef __ACC_LIB_H_INCLUDED
+#define __ACC_LIB_H_INCLUDED 1
+#if !defined(__ACCLIB_FUNCNAME)
+# define __ACCLIB_FUNCNAME(f) f
+#endif
+#if !defined(ACCLIB_EXTERN)
+# define ACCLIB_EXTERN(r,f) extern r __ACCLIB_FUNCNAME(f)
+#endif
+#if !defined(ACCLIB_EXTERN_NOINLINE)
+# if defined(__acc_noinline)
+# define ACCLIB_EXTERN_NOINLINE(r,f) extern __acc_noinline r __ACCLIB_FUNCNAME(f)
+# else
+# define ACCLIB_EXTERN_NOINLINE(r,f) extern r __ACCLIB_FUNCNAME(f)
+# endif
+#endif
+#if !defined(__ACCLIB_CONST_CAST_RETURN)
+#if 1 && (ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define __ACCLIB_CONST_CAST_RETURN(type,var) return (type) (acc_uintptr_t) (var);
+#elif (ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define __ACCLIB_CONST_CAST_RETURN(type,var) \
+ { union { type a; const type b; } u; u.b = (var); return u.a; }
+#else
+# define __ACCLIB_CONST_CAST_RETURN(type,var) return (type) (var);
+#endif
+#endif
+#if (ACC_OS_WIN64)
+# define acclib_handle_t acc_int64l_t
+# define acclib_uhandle_t acc_uint64l_t
+#elif (ACC_ARCH_I386 && ACC_CC_MSC && (_MSC_VER >= 1300))
+ typedef __w64 long acclib_handle_t;
+ typedef __w64 unsigned long acclib_uhandle_t;
+# define acclib_handle_t acclib_handle_t
+# define acclib_uhandle_t acclib_uhandle_t
+#else
+# define acclib_handle_t long
+# define acclib_uhandle_t unsigned long
+#endif
+#if 0
+ACCLIB_EXTERN(int, acc_ascii_digit) (int);
+ACCLIB_EXTERN(int, acc_ascii_islower) (int);
+ACCLIB_EXTERN(int, acc_ascii_isupper) (int);
+ACCLIB_EXTERN(int, acc_ascii_tolower) (int);
+ACCLIB_EXTERN(int, acc_ascii_toupper) (int);
+ACCLIB_EXTERN(int, acc_ascii_utolower) (int);
+ACCLIB_EXTERN(int, acc_ascii_utoupper) (int);
+#endif
+#define acc_ascii_isdigit(c) (((unsigned)(c) - 48) < 10)
+#define acc_ascii_islower(c) (((unsigned)(c) - 97) < 26)
+#define acc_ascii_isupper(c) (((unsigned)(c) - 65) < 26)
+#define acc_ascii_tolower(c) ((int)(c) + (acc_ascii_isupper(c) << 5))
+#define acc_ascii_toupper(c) ((int)(c) - (acc_ascii_islower(c) << 5))
+#define acc_ascii_utolower(c) acc_ascii_tolower((unsigned char)(c))
+#define acc_ascii_utoupper(c) acc_ascii_toupper((unsigned char)(c))
+#ifndef acc_hsize_t
+#if (ACC_HAVE_MM_HUGE_PTR)
+# define acc_hsize_t unsigned long
+# define acc_hvoid_p void __huge *
+# define acc_hchar_p char __huge *
+# define acc_hchar_pp char __huge * __huge *
+# define acc_hbyte_p unsigned char __huge *
+#else
+# define acc_hsize_t size_t
+# define acc_hvoid_p void *
+# define acc_hchar_p char *
+# define acc_hchar_pp char **
+# define acc_hbyte_p unsigned char *
+#endif
+#endif
+ACCLIB_EXTERN(acc_hvoid_p, acc_halloc) (acc_hsize_t);
+ACCLIB_EXTERN(void, acc_hfree) (acc_hvoid_p);
+#if (ACC_OS_DOS16 || ACC_OS_OS216)
+ACCLIB_EXTERN(void __far*, acc_dos_alloc) (unsigned long);
+ACCLIB_EXTERN(int, acc_dos_free) (void __far*);
+#endif
+ACCLIB_EXTERN(int, acc_hmemcmp) (const acc_hvoid_p, const acc_hvoid_p, acc_hsize_t);
+ACCLIB_EXTERN(acc_hvoid_p, acc_hmemcpy) (acc_hvoid_p, const acc_hvoid_p, acc_hsize_t);
+ACCLIB_EXTERN(acc_hvoid_p, acc_hmemmove) (acc_hvoid_p, const acc_hvoid_p, acc_hsize_t);
+ACCLIB_EXTERN(acc_hvoid_p, acc_hmemset) (acc_hvoid_p, int, acc_hsize_t);
+ACCLIB_EXTERN(acc_hsize_t, acc_hstrlen) (const acc_hchar_p);
+ACCLIB_EXTERN(int, acc_hstrcmp) (const acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(int, acc_hstrncmp)(const acc_hchar_p, const acc_hchar_p, acc_hsize_t);
+ACCLIB_EXTERN(int, acc_ascii_hstricmp) (const acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(int, acc_ascii_hstrnicmp)(const acc_hchar_p, const acc_hchar_p, acc_hsize_t);
+ACCLIB_EXTERN(int, acc_ascii_hmemicmp) (const acc_hvoid_p, const acc_hvoid_p, acc_hsize_t);
+ACCLIB_EXTERN(acc_hchar_p, acc_hstrstr) (const acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hchar_p, acc_ascii_hstristr) (const acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hvoid_p, acc_hmemmem) (const acc_hvoid_p, acc_hsize_t, const acc_hvoid_p, acc_hsize_t);
+ACCLIB_EXTERN(acc_hvoid_p, acc_ascii_hmemimem) (const acc_hvoid_p, acc_hsize_t, const acc_hvoid_p, acc_hsize_t);
+ACCLIB_EXTERN(acc_hchar_p, acc_hstrcpy) (acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hchar_p, acc_hstrcat) (acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hsize_t, acc_hstrlcpy) (acc_hchar_p, const acc_hchar_p, acc_hsize_t);
+ACCLIB_EXTERN(acc_hsize_t, acc_hstrlcat) (acc_hchar_p, const acc_hchar_p, acc_hsize_t);
+ACCLIB_EXTERN(int, acc_hstrscpy) (acc_hchar_p, const acc_hchar_p, acc_hsize_t);
+ACCLIB_EXTERN(int, acc_hstrscat) (acc_hchar_p, const acc_hchar_p, acc_hsize_t);
+ACCLIB_EXTERN(acc_hchar_p, acc_hstrccpy) (acc_hchar_p, const acc_hchar_p, int);
+ACCLIB_EXTERN(acc_hvoid_p, acc_hmemccpy) (acc_hvoid_p, const acc_hvoid_p, int, acc_hsize_t);
+ACCLIB_EXTERN(acc_hchar_p, acc_hstrchr) (const acc_hchar_p, int);
+ACCLIB_EXTERN(acc_hchar_p, acc_hstrrchr) (const acc_hchar_p, int);
+ACCLIB_EXTERN(acc_hchar_p, acc_ascii_hstrichr) (const acc_hchar_p, int);
+ACCLIB_EXTERN(acc_hchar_p, acc_ascii_hstrrichr) (const acc_hchar_p, int);
+ACCLIB_EXTERN(acc_hvoid_p, acc_hmemchr) (const acc_hvoid_p, int, acc_hsize_t);
+ACCLIB_EXTERN(acc_hvoid_p, acc_hmemrchr) (const acc_hvoid_p, int, acc_hsize_t);
+ACCLIB_EXTERN(acc_hvoid_p, acc_ascii_hmemichr) (const acc_hvoid_p, int, acc_hsize_t);
+ACCLIB_EXTERN(acc_hvoid_p, acc_ascii_hmemrichr) (const acc_hvoid_p, int, acc_hsize_t);
+ACCLIB_EXTERN(acc_hsize_t, acc_hstrspn) (const acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hsize_t, acc_hstrrspn) (const acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hsize_t, acc_hstrcspn) (const acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hsize_t, acc_hstrrcspn) (const acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hchar_p, acc_hstrpbrk) (const acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hchar_p, acc_hstrrpbrk) (const acc_hchar_p, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hchar_p, acc_hstrsep) (acc_hchar_pp, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hchar_p, acc_hstrrsep) (acc_hchar_pp, const acc_hchar_p);
+ACCLIB_EXTERN(acc_hchar_p, acc_ascii_hstrlwr) (acc_hchar_p);
+ACCLIB_EXTERN(acc_hchar_p, acc_ascii_hstrupr) (acc_hchar_p);
+ACCLIB_EXTERN(acc_hvoid_p, acc_ascii_hmemlwr) (acc_hvoid_p, acc_hsize_t);
+ACCLIB_EXTERN(acc_hvoid_p, acc_ascii_hmemupr) (acc_hvoid_p, acc_hsize_t);
+ACCLIB_EXTERN(acc_hsize_t, acc_hfread) (void *, acc_hvoid_p, acc_hsize_t);
+ACCLIB_EXTERN(acc_hsize_t, acc_hfwrite) (void *, const acc_hvoid_p, acc_hsize_t);
+#if (ACC_HAVE_MM_HUGE_PTR)
+ACCLIB_EXTERN(long, acc_hread) (int, acc_hvoid_p, long);
+ACCLIB_EXTERN(long, acc_hwrite) (int, const acc_hvoid_p, long);
+#endif
+ACCLIB_EXTERN(long, acc_safe_hread) (int, acc_hvoid_p, long);
+ACCLIB_EXTERN(long, acc_safe_hwrite) (int, const acc_hvoid_p, long);
+ACCLIB_EXTERN(unsigned, acc_ua_get_be16) (const acc_hvoid_p);
+ACCLIB_EXTERN(acc_uint32l_t, acc_ua_get_be24) (const acc_hvoid_p);
+ACCLIB_EXTERN(acc_uint32l_t, acc_ua_get_be32) (const acc_hvoid_p);
+ACCLIB_EXTERN(void, acc_ua_set_be16) (acc_hvoid_p, unsigned);
+ACCLIB_EXTERN(void, acc_ua_set_be24) (acc_hvoid_p, acc_uint32l_t);
+ACCLIB_EXTERN(void, acc_ua_set_be32) (acc_hvoid_p, acc_uint32l_t);
+ACCLIB_EXTERN(unsigned, acc_ua_get_le16) (const acc_hvoid_p);
+ACCLIB_EXTERN(acc_uint32l_t, acc_ua_get_le24) (const acc_hvoid_p);
+ACCLIB_EXTERN(acc_uint32l_t, acc_ua_get_le32) (const acc_hvoid_p);
+ACCLIB_EXTERN(void, acc_ua_set_le16) (acc_hvoid_p, unsigned);
+ACCLIB_EXTERN(void, acc_ua_set_le24) (acc_hvoid_p, acc_uint32l_t);
+ACCLIB_EXTERN(void, acc_ua_set_le32) (acc_hvoid_p, acc_uint32l_t);
+#if defined(acc_int64l_t)
+ACCLIB_EXTERN(acc_uint64l_t, acc_ua_get_be64) (const acc_hvoid_p);
+ACCLIB_EXTERN(void, acc_ua_set_be64) (acc_hvoid_p, acc_uint64l_t);
+ACCLIB_EXTERN(acc_uint64l_t, acc_ua_get_le64) (const acc_hvoid_p);
+ACCLIB_EXTERN(void, acc_ua_set_le64) (acc_hvoid_p, acc_uint64l_t);
+#endif
+ACCLIB_EXTERN_NOINLINE(short, acc_vget_short) (short, int);
+ACCLIB_EXTERN_NOINLINE(int, acc_vget_int) (int, int);
+ACCLIB_EXTERN_NOINLINE(long, acc_vget_long) (long, int);
+#if defined(acc_int64l_t)
+ACCLIB_EXTERN_NOINLINE(acc_int64l_t, acc_vget_acc_int64l_t) (acc_int64l_t, int);
+#endif
+ACCLIB_EXTERN_NOINLINE(acc_hsize_t, acc_vget_acc_hsize_t) (acc_hsize_t, int);
+#if !defined(ACC_CFG_NO_FLOAT)
+ACCLIB_EXTERN_NOINLINE(float, acc_vget_float) (float, int);
+#endif
+#if !defined(ACC_CFG_NO_DOUBLE)
+ACCLIB_EXTERN_NOINLINE(double, acc_vget_double) (double, int);
+#endif
+ACCLIB_EXTERN_NOINLINE(acc_hvoid_p, acc_vget_acc_hvoid_p) (acc_hvoid_p, int);
+ACCLIB_EXTERN_NOINLINE(const acc_hvoid_p, acc_vget_acc_hvoid_cp) (const acc_hvoid_p, int);
+#if !defined(ACC_FN_PATH_MAX)
+#if (ACC_OS_DOS16 || ACC_OS_WIN16)
+# define ACC_FN_PATH_MAX 143
+#elif (ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN32 || ACC_OS_WIN64)
+# define ACC_FN_PATH_MAX 259
+#elif (ACC_OS_TOS)
+# define ACC_FN_PATH_MAX 259
+#endif
+#endif
+#if !defined(ACC_FN_PATH_MAX)
+# define ACC_FN_PATH_MAX 1023
+#endif
+#if !defined(ACC_FN_NAME_MAX)
+#if (ACC_OS_DOS16 || ACC_OS_WIN16)
+# define ACC_FN_NAME_MAX 12
+#elif (ACC_ARCH_M68K && ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))
+# define ACC_FN_NAME_MAX 12
+#elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)
+#elif (ACC_OS_DOS32)
+# define ACC_FN_NAME_MAX 12
+#endif
+#endif
+#if !defined(ACC_FN_NAME_MAX)
+# define ACC_FN_NAME_MAX ACC_FN_PATH_MAX
+#endif
+#define ACC_FNMATCH_NOESCAPE 1
+#define ACC_FNMATCH_PATHNAME 2
+#define ACC_FNMATCH_PATHSTAR 4
+#define ACC_FNMATCH_PERIOD 8
+#define ACC_FNMATCH_ASCII_CASEFOLD 16
+ACCLIB_EXTERN(int, acc_fnmatch) (const acc_hchar_p, const acc_hchar_p, int);
+#undef __ACCLIB_USE_OPENDIR
+#if (HAVE_DIRENT_H || ACC_CC_WATCOMC)
+# define __ACCLIB_USE_OPENDIR 1
+# if (ACC_OS_DOS32 && defined(__BORLANDC__))
+# elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)
+# elif (ACC_OS_OS2 || ACC_OS_OS216)
+# elif (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC)
+# elif (ACC_OS_WIN32 && !defined(ACC_HAVE_WINDOWS_H))
+# elif (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_TOS || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
+# undef __ACCLIB_USE_OPENDIR
+# endif
+#endif
+typedef struct
+{
+#if defined(__ACCLIB_USE_OPENDIR)
+ void* u_dirp;
+# if (ACC_CC_WATCOMC)
+ unsigned short f_time;
+ unsigned short f_date;
+ unsigned long f_size;
+# endif
+ char f_name[ACC_FN_NAME_MAX+1];
+#elif (ACC_OS_WIN32 || ACC_OS_WIN64)
+ acclib_handle_t u_handle;
+ unsigned f_attr;
+ unsigned f_size_low;
+ unsigned f_size_high;
+ char f_name[ACC_FN_NAME_MAX+1];
+#elif (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_TOS || ACC_OS_WIN16)
+ char u_dta[21];
+ unsigned char f_attr;
+ unsigned short f_time;
+ unsigned short f_date;
+ unsigned short f_size_low;
+ unsigned short f_size_high;
+ char f_name[ACC_FN_NAME_MAX+1];
+ char u_dirp;
+#else
+ void* u_dirp;
+ char f_name[ACC_FN_NAME_MAX+1];
+#endif
+} acc_dir_t;
+#ifndef acc_dir_p
+#define acc_dir_p acc_dir_t *
+#endif
+ACCLIB_EXTERN(int, acc_opendir) (acc_dir_p, const char*);
+ACCLIB_EXTERN(int, acc_readdir) (acc_dir_p);
+ACCLIB_EXTERN(int, acc_closedir) (acc_dir_p);
+#if (ACC_CC_GNUC) && (defined(__CYGWIN__) || defined(__MINGW32__))
+# define acc_alloca(x) __builtin_alloca((x))
+#elif (ACC_CC_GNUC) && (ACC_OS_CONSOLE_PS2)
+# define acc_alloca(x) __builtin_alloca((x))
+#elif (ACC_CC_BORLANDC || ACC_CC_LCC) && defined(__linux__)
+#elif (HAVE_ALLOCA)
+# define acc_alloca(x) ((void *) (alloca((x))))
+#endif
+#if (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)
+# define acc_stackavail() stackavail()
+#elif (ACC_ARCH_I086 && ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0410))
+# define acc_stackavail() stackavail()
+#elif (ACC_ARCH_I086 && ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0400))
+# if (ACC_OS_WIN16) && (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM)
+# else
+# define acc_stackavail() stackavail()
+# endif
+#elif ((ACC_ARCH_I086 || ACC_ARCH_I386) && (ACC_CC_DMC || ACC_CC_SYMANTECC))
+# define acc_stackavail() stackavail()
+#elif ((ACC_ARCH_I086) && ACC_CC_MSC && (_MSC_VER >= 700))
+# define acc_stackavail() _stackavail()
+#elif ((ACC_ARCH_I086) && ACC_CC_MSC)
+# define acc_stackavail() stackavail()
+#elif ((ACC_ARCH_I086 || ACC_ARCH_I386) && ACC_CC_TURBOC && (__TURBOC__ >= 0x0450))
+# define acc_stackavail() stackavail()
+#elif (ACC_ARCH_I086 && ACC_CC_TURBOC && (__TURBOC__ >= 0x0400))
+ ACC_EXTERN_C size_t __cdecl stackavail(void);
+# define acc_stackavail() stackavail()
+#elif ((ACC_ARCH_I086 || ACC_ARCH_I386) && (ACC_CC_WATCOMC))
+# define acc_stackavail() stackavail()
+#elif (ACC_ARCH_I086 && ACC_CC_ZORTECHC)
+# define acc_stackavail() _chkstack()
+#endif
+ACCLIB_EXTERN(acclib_handle_t, acc_get_osfhandle) (int);
+ACCLIB_EXTERN(const char *, acc_getenv) (const char *);
+ACCLIB_EXTERN(int, acc_isatty) (int);
+ACCLIB_EXTERN(int, acc_mkdir) (const char*, unsigned);
+ACCLIB_EXTERN(int, acc_rmdir) (const char*);
+ACCLIB_EXTERN(int, acc_response) (int*, char***);
+ACCLIB_EXTERN(int, acc_set_binmode) (int, int);
+#if defined(acc_int32e_t)
+ACCLIB_EXTERN(acc_int32e_t, acc_muldiv32s) (acc_int32e_t, acc_int32e_t, acc_int32e_t);
+ACCLIB_EXTERN(acc_uint32e_t, acc_muldiv32u) (acc_uint32e_t, acc_uint32e_t, acc_uint32e_t);
+#endif
+ACCLIB_EXTERN(void, acc_wildargv) (int*, char***);
+ACCLIB_EXTERN_NOINLINE(void, acc_debug_break) (void);
+ACCLIB_EXTERN_NOINLINE(void, acc_debug_nop) (void);
+ACCLIB_EXTERN_NOINLINE(int, acc_debug_align_check_query) (void);
+ACCLIB_EXTERN_NOINLINE(int, acc_debug_align_check_enable) (int);
+ACCLIB_EXTERN_NOINLINE(unsigned, acc_debug_running_on_qemu) (void);
+ACCLIB_EXTERN_NOINLINE(unsigned, acc_debug_running_on_valgrind) (void);
+#if !defined(acc_int64l_t) || defined(ACC_CFG_NO_DOUBLE)
+# undef __ACCLIB_PCLOCK_USE_RDTSC
+# undef __ACCLIB_PCLOCK_USE_PERFCTR
+# undef __ACCLIB_UCLOCK_USE_RDTSC
+# undef __ACCLIB_UCLOCK_USE_PERFCTR
+#else
+typedef struct {
+ void* h;
+ int mode;
+ double tsc_to_seconds;
+ unsigned cpu_type, cpu_features, cpu_khz, cpu_nrctrs;
+ const char* cpu_name;
+} acc_perfctr_handle_t;
+typedef struct {
+ acc_uint64l_t tsc;
+#if (ACC_OS_POSIX_LINUX)
+ acc_uint64l_t pmc[18];
+#else
+ acc_uint64l_t pmc[1];
+#endif
+} acc_perfctr_clock_t;
+#ifndef acc_perfctr_handle_p
+#define acc_perfctr_handle_p acc_perfctr_handle_t *
+#endif
+#ifndef acc_perfctr_clock_p
+#define acc_perfctr_clock_p acc_perfctr_clock_t *
+#endif
+ACCLIB_EXTERN(int, acc_perfctr_open) (acc_perfctr_handle_p);
+ACCLIB_EXTERN(int, acc_perfctr_close) (acc_perfctr_handle_p);
+ACCLIB_EXTERN(void, acc_perfctr_read) (acc_perfctr_handle_p, acc_perfctr_clock_p);
+#if !defined(ACC_CFG_NO_DOUBLE)
+ACCLIB_EXTERN(double, acc_perfctr_get_elapsed) (acc_perfctr_handle_p, const acc_perfctr_clock_p, const acc_perfctr_clock_p);
+ACCLIB_EXTERN(double, acc_perfctr_get_elapsed_tsc) (acc_perfctr_handle_p, acc_uint64l_t);
+#endif
+ACCLIB_EXTERN(int, acc_perfctr_flush_cpu_cache) (acc_perfctr_handle_p, unsigned);
+#endif
+#if defined(acc_int32e_t)
+ACCLIB_EXTERN(int, acc_tsc_read) (acc_uint32e_t*);
+#else
+# undef __ACCLIB_PCLOCK_USE_RDTSC
+# undef __ACCLIB_UCLOCK_USE_RDTSC
+#endif
+struct acc_pclock_handle_t;
+struct acc_pclock_t;
+typedef struct acc_pclock_handle_t acc_pclock_handle_t;
+typedef struct acc_pclock_t acc_pclock_t;
+#ifndef acc_pclock_handle_p
+#define acc_pclock_handle_p acc_pclock_handle_t *
+#endif
+#ifndef acc_pclock_p
+#define acc_pclock_p acc_pclock_t *
+#endif
+#define ACC_PCLOCK_REALTIME 0
+#define ACC_PCLOCK_MONOTONIC 1
+#define ACC_PCLOCK_PROCESS_CPUTIME_ID 2
+#define ACC_PCLOCK_THREAD_CPUTIME_ID 3
+#define ACC_PCLOCK_REALTIME_HR 4
+#define ACC_PCLOCK_MONOTONIC_HR 5
+struct acc_pclock_handle_t {
+ acclib_handle_t h;
+ int mode;
+ const char* name;
+ int (*gettime) (acc_pclock_handle_p, acc_pclock_p);
+#if defined(acc_int64l_t)
+ acc_uint64l_t ticks_base;
+#endif
+#if defined(__ACCLIB_PCLOCK_USE_PERFCTR)
+ acc_perfctr_handle_t pch;
+#endif
+};
+struct acc_pclock_t {
+#if defined(acc_int64l_t)
+ acc_int64l_t tv_sec;
+#else
+ acc_int32l_t tv_sec_high;
+ acc_uint32l_t tv_sec_low;
+#endif
+ acc_uint32l_t tv_nsec;
+};
+ACCLIB_EXTERN(int, acc_pclock_open) (acc_pclock_handle_p, int);
+ACCLIB_EXTERN(int, acc_pclock_open_default) (acc_pclock_handle_p);
+ACCLIB_EXTERN(int, acc_pclock_close) (acc_pclock_handle_p);
+ACCLIB_EXTERN(void, acc_pclock_read) (acc_pclock_handle_p, acc_pclock_p);
+#if !defined(ACC_CFG_NO_DOUBLE)
+ACCLIB_EXTERN(double, acc_pclock_get_elapsed) (acc_pclock_handle_p, const acc_pclock_p, const acc_pclock_p);
+#endif
+ACCLIB_EXTERN(int, acc_pclock_flush_cpu_cache) (acc_pclock_handle_p, unsigned);
+#if !defined(acc_int64l_t) || defined(ACC_CFG_NO_DOUBLE)
+# undef __ACCLIB_UCLOCK_USE_QPC
+#elif (ACC_OS_CYGWIN || ACC_OS_EMX || ACC_OS_WIN32 || ACC_OS_WIN64) && (ACC_HAVE_WINDOWS_H)
+# define __ACCLIB_UCLOCK_USE_QPC 1
+#else
+# undef __ACCLIB_UCLOCK_USE_QPC
+#endif
+typedef struct {
+ acclib_handle_t h;
+ int mode;
+ const char* name;
+#if defined(__ACCLIB_UCLOCK_USE_PERFCTR)
+ acc_perfctr_handle_t pch;
+#endif
+#if defined(__ACCLIB_UCLOCK_USE_QPC)
+ double qpf;
+#endif
+} acc_uclock_handle_t;
+typedef struct {
+ union {
+ acc_uint32l_t t32;
+#if !(ACC_OS_DOS16 || ACC_OS_WIN16)
+# if !defined(ACC_CFG_NO_DOUBLE)
+ double td;
+# endif
+# if defined(acc_int64l_t)
+ acc_int64l_t t64;
+# endif
+#endif
+ } ticks;
+#if defined(__ACCLIB_UCLOCK_USE_RDTSC)
+ acc_uint64l_t tsc;
+#endif
+#if defined(__ACCLIB_UCLOCK_USE_PERFCTR)
+ acc_perfctr_clock_t pcc;
+#endif
+#if defined(__ACCLIB_UCLOCK_USE_QPC)
+ acc_int64l_t qpc;
+#endif
+} acc_uclock_t;
+#ifndef acc_uclock_handle_p
+#define acc_uclock_handle_p acc_uclock_handle_t *
+#endif
+#ifndef acc_uclock_p
+#define acc_uclock_p acc_uclock_t *
+#endif
+ACCLIB_EXTERN(int, acc_uclock_open) (acc_uclock_handle_p);
+ACCLIB_EXTERN(int, acc_uclock_close) (acc_uclock_handle_p);
+ACCLIB_EXTERN(void, acc_uclock_read) (acc_uclock_handle_p, acc_uclock_p);
+#if !defined(ACC_CFG_NO_DOUBLE)
+ACCLIB_EXTERN(double, acc_uclock_get_elapsed) (acc_uclock_handle_p, const acc_uclock_p, const acc_uclock_p);
+#endif
+ACCLIB_EXTERN(int, acc_uclock_flush_cpu_cache) (acc_uclock_handle_p, unsigned);
+struct acc_getopt_t;
+typedef struct acc_getopt_t acc_getopt_t;
+#ifndef acc_getopt_p
+#define acc_getopt_p acc_getopt_t *
+#endif
+struct acc_getopt_longopt_t;
+typedef struct acc_getopt_longopt_t acc_getopt_longopt_t;
+#ifndef acc_getopt_longopt_p
+#define acc_getopt_longopt_p acc_getopt_longopt_t *
+#endif
+struct acc_getopt_longopt_t {
+ const char* name;
+ int has_arg;
+ int* flag;
+ int val;
+};
+struct acc_getopt_t {
+ void *user;
+ char *optarg;
+ void (*opterr)(acc_getopt_p, const char*, void *);
+ int optind;
+ int optopt;
+ int errcount;
+ const char* progname;
+ int argc; char** argv;
+ int eof; int shortpos;
+ int pending_rotate_first, pending_rotate_middle;
+};
+enum { ACC_GETOPT_NO_ARG, ACC_GETOPT_REQUIRED_ARG, ACC_GETOPT_OPTIONAL_ARG, ACC_GETOPT_EXACT_ARG = 0x10 };
+enum { ACC_GETOPT_PERMUTE, ACC_GETOPT_RETURN_IN_ORDER, ACC_GETOPT_REQUIRE_ORDER };
+ACCLIB_EXTERN(void, acc_getopt_init) (acc_getopt_p g,
+ int start_argc, int argc, char** argv);
+ACCLIB_EXTERN(int, acc_getopt) (acc_getopt_p g,
+ const char* shortopts,
+ const acc_getopt_longopt_p longopts,
+ int* longind);
+typedef struct {
+ acc_uint32l_t seed;
+} acc_rand31_t;
+#ifndef acc_rand31_p
+#define acc_rand31_p acc_rand31_t *
+#endif
+ACCLIB_EXTERN(void, acc_srand31) (acc_rand31_p, acc_uint32l_t);
+ACCLIB_EXTERN(acc_uint32l_t, acc_rand31) (acc_rand31_p);
+#if defined(acc_int64l_t)
+typedef struct {
+ acc_uint64l_t seed;
+} acc_rand48_t;
+#ifndef acc_rand48_p
+#define acc_rand48_p acc_rand48_t *
+#endif
+ACCLIB_EXTERN(void, acc_srand48) (acc_rand48_p, acc_uint32l_t);
+ACCLIB_EXTERN(acc_uint32l_t, acc_rand48) (acc_rand48_p);
+ACCLIB_EXTERN(acc_uint32l_t, acc_rand48_r32) (acc_rand48_p);
+#endif
+#if defined(acc_int64l_t)
+typedef struct {
+ acc_uint64l_t seed;
+} acc_rand64_t;
+#ifndef acc_rand64_p
+#define acc_rand64_p acc_rand64_t *
+#endif
+ACCLIB_EXTERN(void, acc_srand64) (acc_rand64_p, acc_uint64l_t);
+ACCLIB_EXTERN(acc_uint32l_t, acc_rand64) (acc_rand64_p);
+ACCLIB_EXTERN(acc_uint32l_t, acc_rand64_r32) (acc_rand64_p);
+#endif
+typedef struct {
+ unsigned n;
+ acc_uint32l_t s[624];
+} acc_randmt_t;
+#ifndef acc_randmt_p
+#define acc_randmt_p acc_randmt_t *
+#endif
+ACCLIB_EXTERN(void, acc_srandmt) (acc_randmt_p, acc_uint32l_t);
+ACCLIB_EXTERN(acc_uint32l_t, acc_randmt) (acc_randmt_p);
+ACCLIB_EXTERN(acc_uint32l_t, acc_randmt_r32) (acc_randmt_p);
+#if defined(acc_int64l_t)
+typedef struct {
+ unsigned n;
+ acc_uint64l_t s[312];
+} acc_randmt64_t;
+#ifndef acc_randmt64_p
+#define acc_randmt64_p acc_randmt64_t *
+#endif
+ACCLIB_EXTERN(void, acc_srandmt64) (acc_randmt64_p, acc_uint64l_t);
+ACCLIB_EXTERN(acc_uint64l_t, acc_randmt64_r64) (acc_randmt64_p);
+#endif
+#define ACC_SPAWN_P_WAIT 0
+#define ACC_SPAWN_P_NOWAIT 1
+ACCLIB_EXTERN(int, acc_spawnv) (int mode, const char* fn, const char* const * argv);
+ACCLIB_EXTERN(int, acc_spawnvp) (int mode, const char* fn, const char* const * argv);
+ACCLIB_EXTERN(int, acc_spawnve) (int mode, const char* fn, const char* const * argv, const char * const envp);
+#endif
+#endif
+#if defined(ACC_WANT_ACC_CXX_H)
+# undef ACC_WANT_ACC_CXX_H
+#ifndef __ACC_CXX_H_INCLUDED
+#define __ACC_CXX_H_INCLUDED 1
+#if defined(__cplusplus)
+#if defined(ACC_CXX_NOTHROW)
+#elif (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020800ul))
+#elif (ACC_CC_BORLANDC && (__BORLANDC__ < 0x0450))
+#elif (ACC_CC_HIGHC)
+#elif (ACC_CC_MSC && (_MSC_VER < 1100))
+#elif (ACC_CC_NDPC)
+#elif (ACC_CC_TURBOC)
+#elif (ACC_CC_WATCOMC && !defined(_CPPUNWIND))
+#elif (ACC_CC_ZORTECHC)
+#else
+# define ACC_CXX_NOTHROW throw()
+#endif
+#if !defined(ACC_CXX_NOTHROW)
+# define ACC_CXX_NOTHROW
+#endif
+#if defined(__ACC_CXX_DO_NEW)
+#elif (ACC_CC_NDPC || ACC_CC_PGI)
+# define __ACC_CXX_DO_NEW { return 0; }
+#elif ((ACC_CC_BORLANDC || ACC_CC_TURBOC) && ACC_ARCH_I086)
+# define __ACC_CXX_DO_NEW { return 0; }
+#else
+# define __ACC_CXX_DO_NEW ;
+#endif
+#if defined(__ACC_CXX_DO_DELETE)
+#elif (ACC_CC_BORLANDC || ACC_CC_TURBOC)
+# define __ACC_CXX_DO_DELETE { }
+#else
+# define __ACC_CXX_DO_DELETE ACC_CXX_NOTHROW { }
+#endif
+#if (ACC_CC_BORLANDC && (__BORLANDC__ < 0x0450))
+#elif (ACC_CC_MSC && ACC_MM_HUGE)
+# define ACC_CXX_DISABLE_NEW_DELETE private:
+#elif (ACC_CC_MSC && (_MSC_VER < 1100))
+#elif (ACC_CC_NDPC)
+#elif (ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)
+#elif (ACC_CC_TURBOC)
+#elif (ACC_CC_WATCOMC && (__WATCOMC__ < 1100))
+#else
+# define __ACC_CXX_HAVE_ARRAY_NEW 1
+#endif
+#if (__ACC_CXX_HAVE_ARRAY_NEW)
+# define __ACC_CXX_HAVE_PLACEMENT_NEW 1
+#endif
+#if (__ACC_CXX_HAVE_PLACEMENT_NEW)
+# if (ACC_CC_GNUC >= 0x030000ul)
+# define __ACC_CXX_HAVE_PLACEMENT_DELETE 1
+# elif (ACC_CC_INTELC)
+# define __ACC_CXX_HAVE_PLACEMENT_DELETE 1
+# elif (ACC_CC_MSC && (_MSC_VER >= 1200))
+# define __ACC_CXX_HAVE_PLACEMENT_DELETE 1
+# elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)
+# define __ACC_CXX_HAVE_PLACEMENT_DELETE 1
+# elif (ACC_CC_PGI)
+# define __ACC_CXX_HAVE_PLACEMENT_DELETE 1
+# endif
+#endif
+#if defined(ACC_CXX_DISABLE_NEW_DELETE)
+#elif defined(new) || defined(delete)
+# define ACC_CXX_DISABLE_NEW_DELETE private:
+#elif (ACC_CC_GNUC && (ACC_CC_GNUC < 0x025b00ul))
+# define ACC_CXX_DISABLE_NEW_DELETE private:
+#elif (ACC_CC_HIGHC)
+# define ACC_CXX_DISABLE_NEW_DELETE private:
+#elif !defined(__ACC_CXX_HAVE_ARRAY_NEW)
+# define ACC_CXX_DISABLE_NEW_DELETE \
+ protected: static void operator delete(void*) __ACC_CXX_DO_DELETE \
+ protected: static void* operator new(size_t) __ACC_CXX_DO_NEW \
+ private:
+#else
+# define ACC_CXX_DISABLE_NEW_DELETE \
+ protected: static void operator delete(void*) __ACC_CXX_DO_DELETE \
+ static void operator delete[](void*) __ACC_CXX_DO_DELETE \
+ private: static void* operator new(size_t) __ACC_CXX_DO_NEW \
+ static void* operator new[](size_t) __ACC_CXX_DO_NEW
+#endif
+#if defined(ACC_CXX_TRIGGER_FUNCTION)
+#else
+# define ACC_CXX_TRIGGER_FUNCTION \
+ protected: virtual const void* acc_cxx_trigger_function() const; \
+ private:
+#endif
+#if defined(ACC_CXX_TRIGGER_FUNCTION_IMPL)
+#else
+# define ACC_CXX_TRIGGER_FUNCTION_IMPL(klass) \
+ const void* klass::acc_cxx_trigger_function() const { return 0; }
+#endif
+#endif
+#endif
+#endif
+#if defined(ACC_WANT_ACC_CHK_CH)
+# undef ACC_WANT_ACC_CHK_CH
+#if !defined(ACCCHK_ASSERT)
+# define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT_HEADER(expr)
+#endif
+#if !defined(ACCCHK_ASSERT_SIGN_T)
+# define ACCCHK_ASSERT_SIGN_T(type,relop) \
+ ACCCHK_ASSERT( (type) (-1) relop (type) 0 ) \
+ ACCCHK_ASSERT( (type) (~(type)0) relop (type) 0 ) \
+ ACCCHK_ASSERT( (type) (~(type)0) == (type) (-1) )
+#endif
+#if !defined(ACCCHK_ASSERT_IS_SIGNED_T)
+# define ACCCHK_ASSERT_IS_SIGNED_T(type) ACCCHK_ASSERT_SIGN_T(type,<)
+#endif
+#if !defined(ACCCHK_ASSERT_IS_UNSIGNED_T)
+# if (ACC_BROKEN_INTEGRAL_PROMOTION)
+# define ACCCHK_ASSERT_IS_UNSIGNED_T(type) \
+ ACCCHK_ASSERT( (type) (-1) > (type) 0 )
+# else
+# define ACCCHK_ASSERT_IS_UNSIGNED_T(type) ACCCHK_ASSERT_SIGN_T(type,>)
+# endif
+#endif
+#if (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0550) && (__BORLANDC__ < 0x0560))
+# pragma option push -w-8055
+#elif (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0530) && (__BORLANDC__ < 0x0550))
+# pragma option push -w-osh
+#endif
+#if (ACC_0xffffffffL - ACC_UINT32_C(4294967294) != 1)
+# error "preprocessor error 1"
+#endif
+#if (ACC_0xffffffffL - ACC_UINT32_C(0xfffffffd) != 2)
+# error "preprocessor error 2"
+#endif
+#define ACCCHK_VAL 1
+#define ACCCHK_TMP1 ACCCHK_VAL
+#undef ACCCHK_VAL
+#define ACCCHK_VAL 2
+#define ACCCHK_TMP2 ACCCHK_VAL
+#if (ACCCHK_TMP1 != 2)
+# error "preprocessor error 3a"
+#endif
+#if (ACCCHK_TMP2 != 2)
+# error "preprocessor error 3b"
+#endif
+#undef ACCCHK_VAL
+#if (ACCCHK_TMP2)
+# error "preprocessor error 3c"
+#endif
+#if (ACCCHK_TMP2 + 0 != 0)
+# error "preprocessor error 3d"
+#endif
+#undef ACCCHK_TMP1
+#undef ACCCHK_TMP2
+#if 0 || defined(ACCCHK_CFG_PEDANTIC)
+# if (ACC_ARCH_MIPS) && defined(_MIPS_SZINT)
+ ACCCHK_ASSERT((_MIPS_SZINT) == 8 * sizeof(int))
+# endif
+# if (ACC_ARCH_MIPS) && defined(_MIPS_SZLONG)
+ ACCCHK_ASSERT((_MIPS_SZLONG) == 8 * sizeof(long))
+# endif
+# if (ACC_ARCH_MIPS) && defined(_MIPS_SZPTR)
+ ACCCHK_ASSERT((_MIPS_SZPTR) == 8 * sizeof(void *))
+# endif
+#endif
+ ACCCHK_ASSERT(1 == 1)
+ ACCCHK_ASSERT(__ACC_MASK_GEN(1u,2) == 3)
+ ACCCHK_ASSERT(__ACC_MASK_GEN(1u,8) == 255)
+#if (SIZEOF_INT >= 2)
+ ACCCHK_ASSERT(__ACC_MASK_GEN(1,15) == 32767)
+ ACCCHK_ASSERT(__ACC_MASK_GEN(1u,16) == 0xffffU)
+#else
+ ACCCHK_ASSERT(__ACC_MASK_GEN(1ul,16) == 0xffffUL)
+#endif
+#if (SIZEOF_INT >= 4)
+ ACCCHK_ASSERT(__ACC_MASK_GEN(1,31) == 2147483647)
+ ACCCHK_ASSERT(__ACC_MASK_GEN(1u,32) == 0xffffffffU)
+#endif
+#if (SIZEOF_LONG >= 4)
+ ACCCHK_ASSERT(__ACC_MASK_GEN(1ul,32) == 0xffffffffUL)
+#endif
+#if (SIZEOF_LONG >= 8)
+ ACCCHK_ASSERT(__ACC_MASK_GEN(1ul,64) == 0xffffffffffffffffUL)
+#endif
+#if !defined(ACC_BROKEN_INTEGRAL_PROMOTION)
+ ACCCHK_ASSERT(__ACC_MASK_GEN(1u,SIZEOF_INT*8) == ~0u)
+ ACCCHK_ASSERT(__ACC_MASK_GEN(1ul,SIZEOF_LONG*8) == ~0ul)
+#endif
+#if !defined(ACC_BROKEN_SIGNED_RIGHT_SHIFT)
+ ACCCHK_ASSERT(((-1) >> 7) == -1)
+#endif
+ ACCCHK_ASSERT(((1) >> 7) == 0)
+ ACCCHK_ASSERT((~0l & ~0) == ~0l)
+ ACCCHK_ASSERT((~0l & ~0u) == ~0u)
+ ACCCHK_ASSERT((~0ul & ~0) == ~0ul)
+ ACCCHK_ASSERT((~0ul & ~0u) == ~0u)
+#if defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0150)
+#elif (SIZEOF_INT == 2)
+ ACCCHK_ASSERT((~0l & ~0u) == 0xffffU)
+ ACCCHK_ASSERT((~0ul & ~0u) == 0xffffU)
+#elif (SIZEOF_INT == 4)
+ ACCCHK_ASSERT((~0l & ~0u) == 0xffffffffU)
+ ACCCHK_ASSERT((~0ul & ~0u) == 0xffffffffU)
+#endif
+ ACCCHK_ASSERT_IS_SIGNED_T(signed char)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(unsigned char)
+ ACCCHK_ASSERT(sizeof(signed char) == sizeof(char))
+ ACCCHK_ASSERT(sizeof(unsigned char) == sizeof(char))
+ ACCCHK_ASSERT(sizeof(char) == 1)
+#if (ACC_CC_CILLY) && (!defined(__CILLY__) || (__CILLY__ < 0x010302L))
+#else
+ ACCCHK_ASSERT(sizeof(char) == sizeof((char)0))
+#endif
+#if defined(__cplusplus)
+ ACCCHK_ASSERT(sizeof('\0') == sizeof(char))
+#else
+# if (ACC_CC_DMC)
+# else
+ ACCCHK_ASSERT(sizeof('\0') == sizeof(int))
+# endif
+#endif
+#if defined(__acc_alignof)
+ ACCCHK_ASSERT(__acc_alignof(char) == 1)
+ ACCCHK_ASSERT(__acc_alignof(signed char) == 1)
+ ACCCHK_ASSERT(__acc_alignof(unsigned char) == 1)
+#if defined(acc_int16e_t)
+ ACCCHK_ASSERT(__acc_alignof(acc_int16e_t) >= 1)
+ ACCCHK_ASSERT(__acc_alignof(acc_int16e_t) <= 2)
+#endif
+#if defined(acc_int32e_t)
+ ACCCHK_ASSERT(__acc_alignof(acc_int32e_t) >= 1)
+ ACCCHK_ASSERT(__acc_alignof(acc_int32e_t) <= 4)
+#endif
+#endif
+ ACCCHK_ASSERT_IS_SIGNED_T(short)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(unsigned short)
+ ACCCHK_ASSERT(sizeof(short) == sizeof(unsigned short))
+#if !defined(ACC_ABI_I8LP16)
+ ACCCHK_ASSERT(sizeof(short) >= 2)
+#endif
+ ACCCHK_ASSERT(sizeof(short) >= sizeof(char))
+#if (ACC_CC_CILLY) && (!defined(__CILLY__) || (__CILLY__ < 0x010302L))
+#else
+ ACCCHK_ASSERT(sizeof(short) == sizeof((short)0))
+#endif
+#if (SIZEOF_SHORT > 0)
+ ACCCHK_ASSERT(sizeof(short) == SIZEOF_SHORT)
+#endif
+ ACCCHK_ASSERT_IS_SIGNED_T(int)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(unsigned int)
+ ACCCHK_ASSERT(sizeof(int) == sizeof(unsigned int))
+#if !defined(ACC_ABI_I8LP16)
+ ACCCHK_ASSERT(sizeof(int) >= 2)
+#endif
+ ACCCHK_ASSERT(sizeof(int) >= sizeof(short))
+ ACCCHK_ASSERT(sizeof(int) == sizeof(0))
+ ACCCHK_ASSERT(sizeof(int) == sizeof((int)0))
+#if (SIZEOF_INT > 0)
+ ACCCHK_ASSERT(sizeof(int) == SIZEOF_INT)
+#endif
+ ACCCHK_ASSERT(sizeof(0) == sizeof(int))
+ ACCCHK_ASSERT_IS_SIGNED_T(long)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(unsigned long)
+ ACCCHK_ASSERT(sizeof(long) == sizeof(unsigned long))
+#if !defined(ACC_ABI_I8LP16)
+ ACCCHK_ASSERT(sizeof(long) >= 4)
+#endif
+ ACCCHK_ASSERT(sizeof(long) >= sizeof(int))
+ ACCCHK_ASSERT(sizeof(long) == sizeof(0L))
+ ACCCHK_ASSERT(sizeof(long) == sizeof((long)0))
+#if (SIZEOF_LONG > 0)
+ ACCCHK_ASSERT(sizeof(long) == SIZEOF_LONG)
+#endif
+ ACCCHK_ASSERT(sizeof(0L) == sizeof(long))
+ ACCCHK_ASSERT_IS_UNSIGNED_T(size_t)
+ ACCCHK_ASSERT(sizeof(size_t) >= sizeof(int))
+ ACCCHK_ASSERT(sizeof(size_t) == sizeof(sizeof(0)))
+#if (SIZEOF_SIZE_T > 0)
+ ACCCHK_ASSERT(sizeof(size_t) == SIZEOF_SIZE_T)
+#endif
+ ACCCHK_ASSERT_IS_SIGNED_T(ptrdiff_t)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) >= sizeof(int))
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t))
+#if !defined(ACC_BROKEN_SIZEOF)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof((char*)0 - (char*)0))
+# if (ACC_HAVE_MM_HUGE_PTR)
+ ACCCHK_ASSERT(4 == sizeof((char __huge*)0 - (char __huge*)0))
+# endif
+#endif
+#if (SIZEOF_PTRDIFF_T > 0)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) == SIZEOF_PTRDIFF_T)
+#endif
+ ACCCHK_ASSERT(sizeof(void*) >= sizeof(char*))
+#if (SIZEOF_VOID_P > 0)
+ ACCCHK_ASSERT(sizeof(void*) == SIZEOF_VOID_P)
+ ACCCHK_ASSERT(sizeof(char*) == SIZEOF_VOID_P)
+#endif
+#if (ACC_HAVE_MM_HUGE_PTR)
+ ACCCHK_ASSERT(4 == sizeof(void __huge*))
+ ACCCHK_ASSERT(4 == sizeof(char __huge*))
+#endif
+#if defined(ACC_ABI_I8LP16)
+ ACCCHK_ASSERT((((1u << 7) + 1) >> 7) == 1)
+ ACCCHK_ASSERT((((1ul << 15) + 1) >> 15) == 1)
+#else
+ ACCCHK_ASSERT((((1u << 15) + 1) >> 15) == 1)
+ ACCCHK_ASSERT((((1ul << 31) + 1) >> 31) == 1)
+#endif
+#if defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0150)
+#elif 1 && (ACC_CC_SUNPROC) && !defined(ACCCHK_CFG_PEDANTIC)
+#else
+ ACCCHK_ASSERT((1 << (8*SIZEOF_INT-1)) < 0)
+#endif
+ ACCCHK_ASSERT((1u << (8*SIZEOF_INT-1)) > 0)
+#if 1 && (ACC_CC_SUNPROC) && !defined(ACCCHK_CFG_PEDANTIC)
+#else
+ ACCCHK_ASSERT((1l << (8*SIZEOF_LONG-1)) < 0)
+#endif
+ ACCCHK_ASSERT((1ul << (8*SIZEOF_LONG-1)) > 0)
+#if defined(acc_int16e_t)
+ ACCCHK_ASSERT(sizeof(acc_int16e_t) == 2)
+ ACCCHK_ASSERT(sizeof(acc_int16e_t) == SIZEOF_ACC_INT16E_T)
+ ACCCHK_ASSERT(sizeof(acc_uint16e_t) == 2)
+ ACCCHK_ASSERT(sizeof(acc_int16e_t) == sizeof(acc_uint16e_t))
+ ACCCHK_ASSERT_IS_SIGNED_T(acc_int16e_t)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint16e_t)
+#if defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0150)
+#else
+ ACCCHK_ASSERT(((acc_uint16e_t)(~(acc_uint16e_t)0ul) >> 15) == 1)
+#endif
+ ACCCHK_ASSERT( (acc_int16e_t) (1 + ~(acc_int16e_t)0) == 0)
+#if defined(ACCCHK_CFG_PEDANTIC)
+ ACCCHK_ASSERT( (acc_uint16e_t)(1 + ~(acc_uint16e_t)0) == 0)
+#endif
+#endif
+#if defined(acc_int32e_t)
+ ACCCHK_ASSERT(sizeof(acc_int32e_t) == 4)
+ ACCCHK_ASSERT(sizeof(acc_int32e_t) == SIZEOF_ACC_INT32E_T)
+ ACCCHK_ASSERT(sizeof(acc_uint32e_t) == 4)
+ ACCCHK_ASSERT(sizeof(acc_int32e_t) == sizeof(acc_uint32e_t))
+ ACCCHK_ASSERT_IS_SIGNED_T(acc_int32e_t)
+ ACCCHK_ASSERT(((( (acc_int32e_t)1 << 30) + 1) >> 30) == 1)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint32e_t)
+ ACCCHK_ASSERT(((( (acc_uint32e_t)1 << 31) + 1) >> 31) == 1)
+ ACCCHK_ASSERT(((acc_uint32e_t)(~(acc_uint32e_t)0ul) >> 31) == 1)
+ ACCCHK_ASSERT( (acc_int32e_t) (1 + ~(acc_int32e_t)0) == 0)
+#if defined(ACCCHK_CFG_PEDANTIC)
+ ACCCHK_ASSERT( (acc_uint32e_t)(1 + ~(acc_uint32e_t)0) == 0)
+#endif
+#endif
+#if defined(acc_int32e_t)
+ ACCCHK_ASSERT(sizeof(acc_int32l_t) >= sizeof(acc_int32e_t))
+#endif
+ ACCCHK_ASSERT(sizeof(acc_int32l_t) >= 4)
+ ACCCHK_ASSERT(sizeof(acc_int32l_t) == SIZEOF_ACC_INT32L_T)
+ ACCCHK_ASSERT(sizeof(acc_uint32l_t) >= 4)
+ ACCCHK_ASSERT(sizeof(acc_int32l_t) == sizeof(acc_uint32l_t))
+ ACCCHK_ASSERT_IS_SIGNED_T(acc_int32l_t)
+ ACCCHK_ASSERT(((( (acc_int32l_t)1 << 30) + 1) >> 30) == 1)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint32l_t)
+ ACCCHK_ASSERT(((( (acc_uint32l_t)1 << 31) + 1) >> 31) == 1)
+ ACCCHK_ASSERT(sizeof(acc_int32f_t) >= sizeof(int))
+#if defined(acc_int32e_t)
+ ACCCHK_ASSERT(sizeof(acc_int32f_t) >= sizeof(acc_int32e_t))
+#endif
+ ACCCHK_ASSERT(sizeof(acc_int32f_t) >= sizeof(acc_int32l_t))
+ ACCCHK_ASSERT(sizeof(acc_int32f_t) >= 4)
+ ACCCHK_ASSERT(sizeof(acc_int32f_t) >= sizeof(acc_int32l_t))
+ ACCCHK_ASSERT(sizeof(acc_int32f_t) == SIZEOF_ACC_INT32F_T)
+ ACCCHK_ASSERT(sizeof(acc_uint32f_t) >= 4)
+ ACCCHK_ASSERT(sizeof(acc_uint32f_t) >= sizeof(acc_uint32l_t))
+ ACCCHK_ASSERT(sizeof(acc_int32f_t) == sizeof(acc_uint32f_t))
+ ACCCHK_ASSERT_IS_SIGNED_T(acc_int32f_t)
+ ACCCHK_ASSERT(((( (acc_int32f_t)1 << 30) + 1) >> 30) == 1)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint32f_t)
+ ACCCHK_ASSERT(((( (acc_uint32f_t)1 << 31) + 1) >> 31) == 1)
+#if defined(acc_int64e_t)
+ ACCCHK_ASSERT(sizeof(acc_int64e_t) == 8)
+ ACCCHK_ASSERT(sizeof(acc_int64e_t) == SIZEOF_ACC_INT64E_T)
+ ACCCHK_ASSERT(sizeof(acc_uint64e_t) == 8)
+ ACCCHK_ASSERT(sizeof(acc_int64e_t) == sizeof(acc_uint64e_t))
+ ACCCHK_ASSERT_IS_SIGNED_T(acc_int64e_t)
+#if (ACC_CC_BORLANDC && (__BORLANDC__ < 0x0530))
+#else
+ ACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint64e_t)
+#endif
+#endif
+#if defined(acc_int64l_t)
+#if defined(acc_int64e_t)
+ ACCCHK_ASSERT(sizeof(acc_int64l_t) >= sizeof(acc_int64e_t))
+#endif
+ ACCCHK_ASSERT(sizeof(acc_int64l_t) >= 8)
+ ACCCHK_ASSERT(sizeof(acc_int64l_t) == SIZEOF_ACC_INT64L_T)
+ ACCCHK_ASSERT(sizeof(acc_uint64l_t) >= 8)
+ ACCCHK_ASSERT(sizeof(acc_int64l_t) == sizeof(acc_uint64l_t))
+ ACCCHK_ASSERT_IS_SIGNED_T(acc_int64l_t)
+ ACCCHK_ASSERT(((( (acc_int64l_t)1 << 62) + 1) >> 62) == 1)
+ ACCCHK_ASSERT(((( ACC_INT64_C(1) << 62) + 1) >> 62) == 1)
+#if (ACC_CC_BORLANDC && (__BORLANDC__ < 0x0530))
+#else
+ ACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint64l_t)
+ ACCCHK_ASSERT(ACC_UINT64_C(18446744073709551615) > 0)
+#endif
+ ACCCHK_ASSERT(((( (acc_uint64l_t)1 << 63) + 1) >> 63) == 1)
+ ACCCHK_ASSERT(((( ACC_UINT64_C(1) << 63) + 1) >> 63) == 1)
+#if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020600ul))
+ ACCCHK_ASSERT(ACC_INT64_C(9223372036854775807) > ACC_INT64_C(0))
+#else
+ ACCCHK_ASSERT(ACC_INT64_C(9223372036854775807) > 0)
+#endif
+ ACCCHK_ASSERT(ACC_INT64_C(-9223372036854775807) - 1 < 0)
+ ACCCHK_ASSERT( ACC_INT64_C(9223372036854775807) % ACC_INT32_C(2147483629) == 721)
+ ACCCHK_ASSERT( ACC_INT64_C(9223372036854775807) % ACC_INT32_C(2147483647) == 1)
+ ACCCHK_ASSERT(ACC_UINT64_C(9223372036854775807) % ACC_UINT32_C(2147483629) == 721)
+ ACCCHK_ASSERT(ACC_UINT64_C(9223372036854775807) % ACC_UINT32_C(2147483647) == 1)
+#endif
+#if !defined(__ACC_INTPTR_T_IS_POINTER)
+ ACCCHK_ASSERT_IS_SIGNED_T(acc_intptr_t)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(acc_uintptr_t)
+#endif
+ ACCCHK_ASSERT(sizeof(acc_intptr_t) >= sizeof(void *))
+ ACCCHK_ASSERT(sizeof(acc_intptr_t) == SIZEOF_ACC_INTPTR_T)
+ ACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(acc_uintptr_t))
+#if defined(acc_word_t)
+ ACCCHK_ASSERT(ACC_WORDSIZE == SIZEOF_ACC_WORD_T)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(acc_word_t)
+ ACCCHK_ASSERT_IS_SIGNED_T(acc_sword_t)
+ ACCCHK_ASSERT(sizeof(acc_word_t) == SIZEOF_ACC_WORD_T)
+ ACCCHK_ASSERT(sizeof(acc_word_t) == sizeof(acc_sword_t))
+#endif
+#if defined(ACC_INT16_C)
+ ACCCHK_ASSERT(sizeof(ACC_INT16_C(0)) >= 2)
+ ACCCHK_ASSERT(sizeof(ACC_UINT16_C(0)) >= 2)
+ ACCCHK_ASSERT((ACC_UINT16_C(0xffff) >> 15) == 1)
+#endif
+#if defined(ACC_INT32_C)
+ ACCCHK_ASSERT(sizeof(ACC_INT32_C(0)) >= 4)
+ ACCCHK_ASSERT(sizeof(ACC_UINT32_C(0)) >= 4)
+ ACCCHK_ASSERT((ACC_UINT32_C(0xffffffff) >> 31) == 1)
+#endif
+#if defined(ACC_INT64_C)
+#if (ACC_CC_BORLANDC && (__BORLANDC__ < 0x0560))
+#else
+ ACCCHK_ASSERT(sizeof(ACC_INT64_C(0)) >= 8)
+ ACCCHK_ASSERT(sizeof(ACC_UINT64_C(0)) >= 8)
+#endif
+ ACCCHK_ASSERT((ACC_UINT64_C(0xffffffffffffffff) >> 63) == 1)
+ ACCCHK_ASSERT((ACC_UINT64_C(0xffffffffffffffff) & ~0) == ACC_UINT64_C(0xffffffffffffffff))
+ ACCCHK_ASSERT((ACC_UINT64_C(0xffffffffffffffff) & ~0l) == ACC_UINT64_C(0xffffffffffffffff))
+#if (SIZEOF_INT == 4)
+# if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020000ul))
+# else
+ ACCCHK_ASSERT((ACC_UINT64_C(0xffffffffffffffff) & ~0u) == 0xffffffffu)
+# endif
+#endif
+#if (SIZEOF_LONG == 4)
+# if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020000ul))
+# else
+ ACCCHK_ASSERT((ACC_UINT64_C(0xffffffffffffffff) & ~0ul) == 0xfffffffful)
+# endif
+#endif
+#endif
+#if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM)
+ ACCCHK_ASSERT(sizeof(void*) == 2)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) == 2)
+#elif (ACC_MM_COMPACT || ACC_MM_LARGE || ACC_MM_HUGE)
+ ACCCHK_ASSERT(sizeof(void*) == 4)
+#endif
+#if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_COMPACT)
+ ACCCHK_ASSERT(sizeof(void (*)(void)) == 2)
+#elif (ACC_MM_MEDIUM || ACC_MM_LARGE || ACC_MM_HUGE)
+ ACCCHK_ASSERT(sizeof(void (*)(void)) == 4)
+#endif
+#if (ACC_ABI_ILP32)
+ ACCCHK_ASSERT(sizeof(int) == 4)
+ ACCCHK_ASSERT(sizeof(long) == 4)
+ ACCCHK_ASSERT(sizeof(void*) == 4)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof(void*))
+ ACCCHK_ASSERT(sizeof(size_t) == sizeof(void*))
+ ACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))
+#endif
+#if (ACC_ABI_ILP64)
+ ACCCHK_ASSERT(sizeof(int) == 8)
+ ACCCHK_ASSERT(sizeof(long) == 8)
+ ACCCHK_ASSERT(sizeof(void*) == 8)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof(void*))
+ ACCCHK_ASSERT(sizeof(size_t) == sizeof(void*))
+ ACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))
+#endif
+#if (ACC_ABI_IP32L64)
+ ACCCHK_ASSERT(sizeof(int) == 4)
+ ACCCHK_ASSERT(sizeof(long) == 8)
+ ACCCHK_ASSERT(sizeof(void*) == 4)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof(void*))
+ ACCCHK_ASSERT(sizeof(size_t) == sizeof(void*))
+ ACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))
+#endif
+#if (ACC_ABI_LLP64)
+ ACCCHK_ASSERT(sizeof(int) == 4)
+ ACCCHK_ASSERT(sizeof(long) == 4)
+ ACCCHK_ASSERT(sizeof(void*) == 8)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof(void*))
+ ACCCHK_ASSERT(sizeof(size_t) == sizeof(void*))
+ ACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))
+#endif
+#if (ACC_ABI_LP32)
+ ACCCHK_ASSERT(sizeof(int) == 2)
+ ACCCHK_ASSERT(sizeof(long) == 4)
+ ACCCHK_ASSERT(sizeof(void*) == 4)
+ ACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))
+#endif
+#if (ACC_ABI_LP64)
+ ACCCHK_ASSERT(sizeof(int) == 4)
+ ACCCHK_ASSERT(sizeof(long) == 8)
+ ACCCHK_ASSERT(sizeof(void*) == 8)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof(void*))
+ ACCCHK_ASSERT(sizeof(size_t) == sizeof(void*))
+ ACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))
+#endif
+#if (ACC_ARCH_I086)
+ ACCCHK_ASSERT(sizeof(size_t) == 2)
+ ACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))
+#elif (ACC_ARCH_I386 || ACC_ARCH_M68K)
+ ACCCHK_ASSERT(sizeof(size_t) == 4)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) == 4)
+ ACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))
+#endif
+#if (ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_WIN32)
+ ACCCHK_ASSERT(sizeof(size_t) == 4)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) == 4)
+ ACCCHK_ASSERT(sizeof(void (*)(void)) == 4)
+#elif (ACC_OS_WIN64)
+ ACCCHK_ASSERT(sizeof(size_t) == 8)
+ ACCCHK_ASSERT(sizeof(ptrdiff_t) == 8)
+ ACCCHK_ASSERT(sizeof(void (*)(void)) == 8)
+#endif
+#if (ACC_CC_NDPC)
+#elif (SIZEOF_INT > 1)
+ ACCCHK_ASSERT( (int) ((unsigned char) ((signed char) -1)) == 255)
+#endif
+#if (ACC_CC_KEILC)
+#elif (ACC_CC_NDPC)
+#elif 1 && (ACC_CC_LCC || ACC_CC_LCCWIN32) && !defined(ACCCHK_CFG_PEDANTIC)
+#elif 1 && (ACC_CC_SUNPROC) && !defined(ACCCHK_CFG_PEDANTIC)
+#elif !defined(ACC_BROKEN_INTEGRAL_PROMOTION) && (SIZEOF_INT > 1)
+ ACCCHK_ASSERT( (((unsigned char)128) << (int)(8*sizeof(int)-8)) < 0)
+#endif
+#if (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0530) && (__BORLANDC__ < 0x0560))
+# pragma option pop
+#endif
+#endif
+#if defined(ACC_WANT_ACCLIB_UA)
+# undef ACC_WANT_ACCLIB_UA
+#define __ACCLIB_UA_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+ACCLIB_PUBLIC(unsigned, acc_ua_get_be16) (const acc_hvoid_p p)
+{
+#if defined(ACC_UA_GET_BE16)
+ return ACC_UA_GET_BE16(p);
+#else
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ return ((unsigned)b[1]) | ((unsigned)b[0] << 8);
+#endif
+}
+ACCLIB_PUBLIC(acc_uint32l_t, acc_ua_get_be24) (const acc_hvoid_p p)
+{
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ return ((acc_uint32l_t)b[2]) | ((acc_uint32l_t)b[1] << 8) | ((acc_uint32l_t)b[0] << 16);
+}
+ACCLIB_PUBLIC(acc_uint32l_t, acc_ua_get_be32) (const acc_hvoid_p p)
+{
+#if defined(ACC_UA_GET_BE32)
+ return ACC_UA_GET_BE32(p);
+#else
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ return ((acc_uint32l_t)b[3]) | ((acc_uint32l_t)b[2] << 8) | ((acc_uint32l_t)b[1] << 16) | ((acc_uint32l_t)b[0] << 24);
+#endif
+}
+ACCLIB_PUBLIC(void, acc_ua_set_be16) (acc_hvoid_p p, unsigned v)
+{
+#if defined(ACC_UA_SET_BE16)
+ ACC_UA_SET_BE16(p, v);
+#else
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ b[1] = (unsigned char) ((v >> 0) & 0xff);
+ b[0] = (unsigned char) ((v >> 8) & 0xff);
+#endif
+}
+ACCLIB_PUBLIC(void, acc_ua_set_be24) (acc_hvoid_p p, acc_uint32l_t v)
+{
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ b[2] = (unsigned char) ((v >> 0) & 0xff);
+ b[1] = (unsigned char) ((v >> 8) & 0xff);
+ b[0] = (unsigned char) ((v >> 16) & 0xff);
+}
+ACCLIB_PUBLIC(void, acc_ua_set_be32) (acc_hvoid_p p, acc_uint32l_t v)
+{
+#if defined(ACC_UA_SET_BE32)
+ ACC_UA_SET_BE32(p, v);
+#else
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ b[3] = (unsigned char) ((v >> 0) & 0xff);
+ b[2] = (unsigned char) ((v >> 8) & 0xff);
+ b[1] = (unsigned char) ((v >> 16) & 0xff);
+ b[0] = (unsigned char) ((v >> 24) & 0xff);
+#endif
+}
+ACCLIB_PUBLIC(unsigned, acc_ua_get_le16) (const acc_hvoid_p p)
+{
+#if defined(ACC_UA_GET_LE16)
+ return ACC_UA_GET_LE16(p);
+#else
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ return ((unsigned)b[0]) | ((unsigned)b[1] << 8);
+#endif
+}
+ACCLIB_PUBLIC(acc_uint32l_t, acc_ua_get_le24) (const acc_hvoid_p p)
+{
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ return ((acc_uint32l_t)b[0]) | ((acc_uint32l_t)b[1] << 8) | ((acc_uint32l_t)b[2] << 16);
+}
+ACCLIB_PUBLIC(acc_uint32l_t, acc_ua_get_le32) (const acc_hvoid_p p)
+{
+#if defined(ACC_UA_GET_LE32)
+ return ACC_UA_GET_LE32(p);
+#else
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ return ((acc_uint32l_t)b[0]) | ((acc_uint32l_t)b[1] << 8) | ((acc_uint32l_t)b[2] << 16) | ((acc_uint32l_t)b[3] << 24);
+#endif
+}
+ACCLIB_PUBLIC(void, acc_ua_set_le16) (acc_hvoid_p p, unsigned v)
+{
+#if defined(ACC_UA_SET_LE16)
+ ACC_UA_SET_LE16(p, v);
+#else
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ b[0] = (unsigned char) ((v >> 0) & 0xff);
+ b[1] = (unsigned char) ((v >> 8) & 0xff);
+#endif
+}
+ACCLIB_PUBLIC(void, acc_ua_set_le24) (acc_hvoid_p p, acc_uint32l_t v)
+{
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ b[0] = (unsigned char) ((v >> 0) & 0xff);
+ b[1] = (unsigned char) ((v >> 8) & 0xff);
+ b[2] = (unsigned char) ((v >> 16) & 0xff);
+}
+ACCLIB_PUBLIC(void, acc_ua_set_le32) (acc_hvoid_p p, acc_uint32l_t v)
+{
+#if defined(ACC_UA_SET_LE32)
+ ACC_UA_SET_LE32(p, v);
+#else
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ b[0] = (unsigned char) ((v >> 0) & 0xff);
+ b[1] = (unsigned char) ((v >> 8) & 0xff);
+ b[2] = (unsigned char) ((v >> 16) & 0xff);
+ b[3] = (unsigned char) ((v >> 24) & 0xff);
+#endif
+}
+#if defined(acc_int64l_t)
+ACCLIB_PUBLIC(acc_uint64l_t, acc_ua_get_be64) (const acc_hvoid_p p)
+{
+#if defined(ACC_UA_GET_BE64)
+ return ACC_UA_GET_BE64(p);
+#elif defined(ACC_UA_GET_BE32)
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ acc_uint32e_t v0, v1;
+ v1 = ACC_UA_GET_BE32(b + 0);
+ v0 = ACC_UA_GET_BE32(b + 4);
+ return ((acc_uint64l_t)v0) | ((acc_uint64l_t)v1 << 32);
+#elif (ACC_SIZEOF_LONG >= 8) || (ACC_SIZEOF_SIZE_T >= 8)
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ return ((acc_uint64l_t)b[7]) | ((acc_uint64l_t)b[6] << 8) | ((acc_uint64l_t)b[5] << 16) | ((acc_uint64l_t)b[4] << 24) | ((acc_uint64l_t)b[3] << 32) | ((acc_uint64l_t)b[2] << 40) | ((acc_uint64l_t)b[1] << 48) | ((acc_uint64l_t)b[0] << 56);
+#else
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ acc_uint32l_t v0, v1;
+ v1 = ((acc_uint32l_t)b[3]) | ((acc_uint32l_t)b[2] << 8) | ((acc_uint32l_t)b[1] << 16) | ((acc_uint32l_t)b[0] << 24);
+ b += 4;
+ v0 = ((acc_uint32l_t)b[3]) | ((acc_uint32l_t)b[2] << 8) | ((acc_uint32l_t)b[1] << 16) | ((acc_uint32l_t)b[0] << 24);
+ return ((acc_uint64l_t)v0) | ((acc_uint64l_t)v1 << 32);
+#endif
+}
+ACCLIB_PUBLIC(void, acc_ua_set_be64) (acc_hvoid_p p, acc_uint64l_t v)
+{
+#if defined(ACC_UA_SET_BE64)
+ ACC_UA_SET_BE64(p, v);
+#elif defined(ACC_UA_SET_BE32)
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ ACC_UA_SET_BE32(b + 4, (v >> 0));
+ ACC_UA_SET_BE32(b + 0, (v >> 32));
+#elif (ACC_SIZEOF_LONG >= 8) || (ACC_SIZEOF_SIZE_T >= 8)
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ b[7] = (unsigned char) ((v >> 0) & 0xff);
+ b[6] = (unsigned char) ((v >> 8) & 0xff);
+ b[5] = (unsigned char) ((v >> 16) & 0xff);
+ b[4] = (unsigned char) ((v >> 24) & 0xff);
+ b[3] = (unsigned char) ((v >> 32) & 0xff);
+ b[2] = (unsigned char) ((v >> 40) & 0xff);
+ b[1] = (unsigned char) ((v >> 48) & 0xff);
+ b[0] = (unsigned char) ((v >> 56) & 0xff);
+#else
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ acc_uint32l_t x;
+ x = (acc_uint32l_t) (v >> 0);
+ b[7] = (unsigned char) ((x >> 0) & 0xff);
+ b[6] = (unsigned char) ((x >> 8) & 0xff);
+ b[5] = (unsigned char) ((x >> 16) & 0xff);
+ b[4] = (unsigned char) ((x >> 24) & 0xff);
+ x = (acc_uint32l_t) (v >> 32);
+ b[3] = (unsigned char) ((x >> 0) & 0xff);
+ b[2] = (unsigned char) ((x >> 8) & 0xff);
+ b[1] = (unsigned char) ((x >> 16) & 0xff);
+ b[0] = (unsigned char) ((x >> 24) & 0xff);
+#endif
+}
+#endif
+#if defined(acc_int64l_t)
+ACCLIB_PUBLIC(acc_uint64l_t, acc_ua_get_le64) (const acc_hvoid_p p)
+{
+#if defined(ACC_UA_GET_LE64)
+ return ACC_UA_GET_LE64(p);
+#elif defined(ACC_UA_GET_LE32)
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ acc_uint32e_t v0, v1;
+ v0 = ACC_UA_GET_LE32(b + 0);
+ v1 = ACC_UA_GET_LE32(b + 4);
+ return ((acc_uint64l_t)v0) | ((acc_uint64l_t)v1 << 32);
+#elif (ACC_SIZEOF_LONG >= 8) || (ACC_SIZEOF_SIZE_T >= 8)
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ return ((acc_uint64l_t)b[0]) | ((acc_uint64l_t)b[1] << 8) | ((acc_uint64l_t)b[2] << 16) | ((acc_uint64l_t)b[3] << 24) | ((acc_uint64l_t)b[4] << 32) | ((acc_uint64l_t)b[5] << 40) | ((acc_uint64l_t)b[6] << 48) | ((acc_uint64l_t)b[7] << 56);
+#else
+ const acc_hbyte_p b = (const acc_hbyte_p) p;
+ acc_uint32l_t v0, v1;
+ v0 = ((acc_uint32l_t)b[0]) | ((acc_uint32l_t)b[1] << 8) | ((acc_uint32l_t)b[2] << 16) | ((acc_uint32l_t)b[3] << 24);
+ b += 4;
+ v1 = ((acc_uint32l_t)b[0]) | ((acc_uint32l_t)b[1] << 8) | ((acc_uint32l_t)b[2] << 16) | ((acc_uint32l_t)b[3] << 24);
+ return ((acc_uint64l_t)v0) | ((acc_uint64l_t)v1 << 32);
+#endif
+}
+ACCLIB_PUBLIC(void, acc_ua_set_le64) (acc_hvoid_p p, acc_uint64l_t v)
+{
+#if defined(ACC_UA_SET_LE64)
+ ACC_UA_SET_LE64(p, v);
+#elif defined(ACC_UA_SET_LE32)
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ ACC_UA_SET_LE32(b + 0, (v >> 0));
+ ACC_UA_SET_LE32(b + 4, (v >> 32));
+#elif (ACC_SIZEOF_LONG >= 8) || (ACC_SIZEOF_SIZE_T >= 8)
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ b[0] = (unsigned char) ((v >> 0) & 0xff);
+ b[1] = (unsigned char) ((v >> 8) & 0xff);
+ b[2] = (unsigned char) ((v >> 16) & 0xff);
+ b[3] = (unsigned char) ((v >> 24) & 0xff);
+ b[4] = (unsigned char) ((v >> 32) & 0xff);
+ b[5] = (unsigned char) ((v >> 40) & 0xff);
+ b[6] = (unsigned char) ((v >> 48) & 0xff);
+ b[7] = (unsigned char) ((v >> 56) & 0xff);
+#else
+ acc_hbyte_p b = (acc_hbyte_p) p;
+ acc_uint32l_t x;
+ x = (acc_uint32l_t) (v >> 0);
+ b[0] = (unsigned char) ((x >> 0) & 0xff);
+ b[1] = (unsigned char) ((x >> 8) & 0xff);
+ b[2] = (unsigned char) ((x >> 16) & 0xff);
+ b[3] = (unsigned char) ((x >> 24) & 0xff);
+ x = (acc_uint32l_t) (v >> 32);
+ b[4] = (unsigned char) ((x >> 0) & 0xff);
+ b[5] = (unsigned char) ((x >> 8) & 0xff);
+ b[6] = (unsigned char) ((x >> 16) & 0xff);
+ b[7] = (unsigned char) ((x >> 24) & 0xff);
+#endif
+}
+#endif
+#endif
+#if defined(ACC_WANT_ACCLIB_VGET)
+# undef ACC_WANT_ACCLIB_VGET
+#define __ACCLIB_VGET_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+#if !defined(ACCLIB_PUBLIC_NOINLINE)
+# if !defined(__acc_noinline)
+# define ACCLIB_PUBLIC_NOINLINE(r,f) r __ACCLIB_FUNCNAME(f)
+# elif (ACC_CC_GNUC >= 0x030400ul) || (ACC_CC_LLVM)
+# define ACCLIB_PUBLIC_NOINLINE(r,f) __acc_noinline __attribute__((__used__)) r __ACCLIB_FUNCNAME(f)
+# else
+# define ACCLIB_PUBLIC_NOINLINE(r,f) __acc_noinline r __ACCLIB_FUNCNAME(f)
+# endif
+#endif
+#if (ACC_CC_GNUC >= 0x030400ul) || (ACC_CC_LLVM)
+extern void* volatile __acc_vget_ptr;
+void* volatile __attribute__((__used__)) __acc_vget_ptr = (void *) 0;
+#else
+extern void* volatile __acc_vget_ptr;
+void* volatile __acc_vget_ptr = (void *) 0;
+#endif
+#ifndef __ACCLIB_VGET_BODY
+#define __ACCLIB_VGET_BODY(T) \
+ if __acc_unlikely(__acc_vget_ptr) { \
+ * (T *) __acc_vget_ptr = v; \
+ * (int *) __acc_vget_ptr = expr; \
+ v = * (T *) __acc_vget_ptr; \
+ } \
+ return v;
+#endif
+ACCLIB_PUBLIC_NOINLINE(short, acc_vget_short) (short v, int expr)
+{
+ __ACCLIB_VGET_BODY(short)
+}
+ACCLIB_PUBLIC_NOINLINE(int, acc_vget_int) (int v, int expr)
+{
+ __ACCLIB_VGET_BODY(int)
+}
+ACCLIB_PUBLIC_NOINLINE(long, acc_vget_long) (long v, int expr)
+{
+ __ACCLIB_VGET_BODY(long)
+}
+#if defined(acc_int64l_t)
+ACCLIB_PUBLIC_NOINLINE(acc_int64l_t, acc_vget_acc_int64l_t) (acc_int64l_t v, int expr)
+{
+ __ACCLIB_VGET_BODY(acc_int64l_t)
+}
+#endif
+ACCLIB_PUBLIC_NOINLINE(acc_hsize_t, acc_vget_acc_hsize_t) (acc_hsize_t v, int expr)
+{
+ __ACCLIB_VGET_BODY(acc_hsize_t)
+}
+#if !defined(ACC_CFG_NO_FLOAT)
+ACCLIB_PUBLIC_NOINLINE(float, acc_vget_float) (float v, int expr)
+{
+ __ACCLIB_VGET_BODY(float)
+}
+#endif
+#if !defined(ACC_CFG_NO_DOUBLE)
+ACCLIB_PUBLIC_NOINLINE(double, acc_vget_double) (double v, int expr)
+{
+ __ACCLIB_VGET_BODY(double)
+}
+#endif
+ACCLIB_PUBLIC_NOINLINE(acc_hvoid_p, acc_vget_acc_hvoid_p) (acc_hvoid_p v, int expr)
+{
+ __ACCLIB_VGET_BODY(acc_hvoid_p)
+}
+#if (ACC_ARCH_I086 && ACC_CC_TURBOC && (__TURBOC__ == 0x0295)) && !defined(__cplusplus)
+ACCLIB_PUBLIC_NOINLINE(acc_hvoid_p, acc_vget_acc_hvoid_cp) (const acc_hvoid_p vv, int expr)
+{
+ acc_hvoid_p v = (acc_hvoid_p) vv;
+ __ACCLIB_VGET_BODY(acc_hvoid_p)
+}
+#else
+ACCLIB_PUBLIC_NOINLINE(const acc_hvoid_p, acc_vget_acc_hvoid_cp) (const acc_hvoid_p v, int expr)
+{
+ __ACCLIB_VGET_BODY(const acc_hvoid_p)
+}
+#endif
+#endif
+#if defined(ACC_WANT_ACCLIB_HMEMCPY)
+# undef ACC_WANT_ACCLIB_HMEMCPY
+#define __ACCLIB_HMEMCPY_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+ACCLIB_PUBLIC(int, acc_hmemcmp) (const acc_hvoid_p s1, const acc_hvoid_p s2, acc_hsize_t len)
+{
+#if (ACC_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCMP)
+ const acc_hbyte_p p1 = (const acc_hbyte_p) s1;
+ const acc_hbyte_p p2 = (const acc_hbyte_p) s2;
+ if __acc_likely(len > 0) do
+ {
+ int d = *p1 - *p2;
+ if (d != 0)
+ return d;
+ p1++; p2++;
+ } while __acc_likely(--len > 0);
+ return 0;
+#else
+ return memcmp(s1, s2, len);
+#endif
+}
+ACCLIB_PUBLIC(acc_hvoid_p, acc_hmemcpy) (acc_hvoid_p dest, const acc_hvoid_p src, acc_hsize_t len)
+{
+#if (ACC_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCPY)
+ acc_hbyte_p p1 = (acc_hbyte_p) dest;
+ const acc_hbyte_p p2 = (const acc_hbyte_p) src;
+ if (!(len > 0) || p1 == p2)
+ return dest;
+ do
+ *p1++ = *p2++;
+ while __acc_likely(--len > 0);
+ return dest;
+#else
+ return memcpy(dest, src, len);
+#endif
+}
+ACCLIB_PUBLIC(acc_hvoid_p, acc_hmemmove) (acc_hvoid_p dest, const acc_hvoid_p src, acc_hsize_t len)
+{
+#if (ACC_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMMOVE)
+ acc_hbyte_p p1 = (acc_hbyte_p) dest;
+ const acc_hbyte_p p2 = (const acc_hbyte_p) src;
+ if (!(len > 0) || p1 == p2)
+ return dest;
+ if (p1 < p2)
+ {
+ do
+ *p1++ = *p2++;
+ while __acc_likely(--len > 0);
+ }
+ else
+ {
+ p1 += len;
+ p2 += len;
+ do
+ *--p1 = *--p2;
+ while __acc_likely(--len > 0);
+ }
+ return dest;
+#else
+ return memmove(dest, src, len);
+#endif
+}
+ACCLIB_PUBLIC(acc_hvoid_p, acc_hmemset) (acc_hvoid_p s, int c, acc_hsize_t len)
+{
+#if (ACC_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMSET)
+ acc_hbyte_p p = (acc_hbyte_p) s;
+ if __acc_likely(len > 0) do
+ *p++ = (unsigned char) c;
+ while __acc_likely(--len > 0);
+ return s;
+#else
+ return memset(s, c, len);
+#endif
+}
+#endif
+#if defined(ACC_WANT_ACCLIB_RAND)
+# undef ACC_WANT_ACCLIB_RAND
+#define __ACCLIB_RAND_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+ACCLIB_PUBLIC(void, acc_srand31) (acc_rand31_p r, acc_uint32l_t seed)
+{
+ r->seed = seed & ACC_UINT32_C(0xffffffff);
+}
+ACCLIB_PUBLIC(acc_uint32l_t, acc_rand31) (acc_rand31_p r)
+{
+ r->seed = r->seed * ACC_UINT32_C(1103515245) + 12345;
+ r->seed &= ACC_UINT32_C(0x7fffffff);
+ return r->seed;
+}
+#if defined(acc_int64l_t)
+ACCLIB_PUBLIC(void, acc_srand48) (acc_rand48_p r, acc_uint32l_t seed)
+{
+ r->seed = seed & ACC_UINT32_C(0xffffffff);
+ r->seed <<= 16; r->seed |= 0x330e;
+}
+ACCLIB_PUBLIC(acc_uint32l_t, acc_rand48) (acc_rand48_p r)
+{
+ r->seed = r->seed * ACC_UINT64_C(25214903917) + 11;
+ r->seed &= ACC_UINT64_C(0xffffffffffff);
+ return (acc_uint32l_t) (r->seed >> 17);
+}
+ACCLIB_PUBLIC(acc_uint32l_t, acc_rand48_r32) (acc_rand48_p r)
+{
+ r->seed = r->seed * ACC_UINT64_C(25214903917) + 11;
+ r->seed &= ACC_UINT64_C(0xffffffffffff);
+ return (acc_uint32l_t) (r->seed >> 16);
+}
+#endif
+#if defined(acc_int64l_t)
+ACCLIB_PUBLIC(void, acc_srand64) (acc_rand64_p r, acc_uint64l_t seed)
+{
+ r->seed = seed & ACC_UINT64_C(0xffffffffffffffff);
+}
+ACCLIB_PUBLIC(acc_uint32l_t, acc_rand64) (acc_rand64_p r)
+{
+ r->seed = r->seed * ACC_UINT64_C(6364136223846793005) + 1;
+#if (ACC_SIZEOF_ACC_INT64L_T > 8)
+ r->seed &= ACC_UINT64_C(0xffffffffffffffff);
+#endif
+ return (acc_uint32l_t) (r->seed >> 33);
+}
+ACCLIB_PUBLIC(acc_uint32l_t, acc_rand64_r32) (acc_rand64_p r)
+{
+ r->seed = r->seed * ACC_UINT64_C(6364136223846793005) + 1;
+#if (ACC_SIZEOF_ACC_INT64L_T > 8)
+ r->seed &= ACC_UINT64_C(0xffffffffffffffff);
+#endif
+ return (acc_uint32l_t) (r->seed >> 32);
+}
+#endif
+ACCLIB_PUBLIC(void, acc_srandmt) (acc_randmt_p r, acc_uint32l_t seed)
+{
+ unsigned i = 0;
+ do {
+ r->s[i++] = (seed &= ACC_UINT32_C(0xffffffff));
+ seed ^= seed >> 30;
+ seed = seed * ACC_UINT32_C(0x6c078965) + i;
+ } while (i != 624);
+ r->n = i;
+}
+ACCLIB_PUBLIC(acc_uint32l_t, acc_randmt) (acc_randmt_p r)
+{
+ return (__ACCLIB_FUNCNAME(acc_randmt_r32)(r)) >> 1;
+}
+ACCLIB_PUBLIC(acc_uint32l_t, acc_randmt_r32) (acc_randmt_p r)
+{
+ acc_uint32l_t v;
+ if __acc_unlikely(r->n == 624) {
+ int i = 0, j;
+ r->n = 0;
+ do {
+ j = i - 623; if (j < 0) j += 624;
+ v = (r->s[i] & ACC_UINT32_C(0x80000000)) ^ (r->s[j] & ACC_UINT32_C(0x7fffffff));
+ j = i - 227; if (j < 0) j += 624;
+ r->s[i] = r->s[j] ^ (v >> 1);
+ if (v & 1) r->s[i] ^= ACC_UINT32_C(0x9908b0df);
+ } while (++i != 624);
+ }
+ v = r->s[r->n++];
+ v ^= v >> 11; v ^= (v & ACC_UINT32_C(0x013a58ad)) << 7;
+ v ^= (v & ACC_UINT32_C(0x0001df8c)) << 15; v ^= v >> 18;
+ return v;
+}
+#if defined(acc_int64l_t)
+ACCLIB_PUBLIC(void, acc_srandmt64) (acc_randmt64_p r, acc_uint64l_t seed)
+{
+ unsigned i = 0;
+ do {
+ r->s[i++] = (seed &= ACC_UINT64_C(0xffffffffffffffff));
+ seed ^= seed >> 62;
+ seed = seed * ACC_UINT64_C(0x5851f42d4c957f2d) + i;
+ } while (i != 312);
+ r->n = i;
+}
+#if 0
+ACCLIB_PUBLIC(acc_uint32l_t, acc_randmt64) (acc_randmt64_p r)
+{
+ acc_uint64l_t v;
+ v = (__ACCLIB_FUNCNAME(acc_randmt64_r64)(r)) >> 33;
+ return (acc_uint32l_t) v;
+}
+#endif
+ACCLIB_PUBLIC(acc_uint64l_t, acc_randmt64_r64) (acc_randmt64_p r)
+{
+ acc_uint64l_t v;
+ if __acc_unlikely(r->n == 312) {
+ int i = 0, j;
+ r->n = 0;
+ do {
+ j = i - 311; if (j < 0) j += 312;
+ v = (r->s[i] & ACC_UINT64_C(0xffffffff80000000)) ^ (r->s[j] & ACC_UINT64_C(0x7fffffff));
+ j = i - 156; if (j < 0) j += 312;
+ r->s[i] = r->s[j] ^ (v >> 1);
+ if (v & 1) r->s[i] ^= ACC_UINT64_C(0xb5026f5aa96619e9);
+ } while (++i != 312);
+ }
+ v = r->s[r->n++];
+ v ^= (v & ACC_UINT64_C(0xaaaaaaaaa0000000)) >> 29;
+ v ^= (v & ACC_UINT64_C(0x38eb3ffff6d3)) << 17;
+ v ^= (v & ACC_UINT64_C(0x7ffbf77)) << 37;
+ return v ^ (v >> 43);
+}
+#endif
+#endif
+#if defined(ACC_WANT_ACCLIB_RDTSC)
+# undef ACC_WANT_ACCLIB_RDTSC
+#define __ACCLIB_RDTSC_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+#if defined(acc_int32e_t)
+#if (ACC_OS_WIN32 && ACC_CC_PELLESC && (__POCC__ >= 290))
+# pragma warn(push)
+# pragma warn(disable:2007)
+#endif
+#if (ACC_ARCH_AMD64 || ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)
+#if (ACC_ARCH_AMD64 && ACC_CC_PATHSCALE)
+# define __ACCLIB_RDTSC_REGS : : "c" (t) : "cc", "memory", "rax", "rdx"
+#elif (ACC_ARCH_AMD64 && ACC_CC_INTELC)
+# define __ACCLIB_RDTSC_REGS : : "r" (t) : "memory", "rax", "rdx"
+#elif (ACC_ARCH_AMD64)
+# define __ACCLIB_RDTSC_REGS : : "r" (t) : "cc", "memory", "rax", "rdx"
+#elif (ACC_ARCH_I386 && ACC_CC_GNUC && (ACC_CC_GNUC < 0x020000ul))
+# define __ACCLIB_RDTSC_REGS : : "r" (t) : "ax", "dx"
+#elif (ACC_ARCH_I386 && ACC_CC_INTELC)
+# define __ACCLIB_RDTSC_REGS : : "r" (t) : "memory", "eax", "edx"
+#elif (ACC_ARCH_I386 && ACC_CC_PATHSCALE)
+# define __ACCLIB_RDTSC_REGS : : "c" (t) : "memory", "eax", "edx"
+#else
+# define __ACCLIB_RDTSC_REGS : : "r" (t) : "cc", "memory", "eax", "edx"
+#endif
+#endif
+ACCLIB_PUBLIC(int, acc_tsc_read) (acc_uint32e_t* t)
+{
+#if (ACC_ARCH_AMD64 || ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)
+ __asm__ __volatile__(
+ "clc \n" ".byte 0x0f,0x31\n"
+ "movl %%eax,(%0)\n" "movl %%edx,4(%0)\n"
+ __ACCLIB_RDTSC_REGS
+ );
+ return 0;
+#elif (ACC_ARCH_I386) && (ACC_ASM_SYNTAX_MSC)
+ ACC_UNUSED(t);
+ __asm {
+ mov ecx, t
+ clc
+# if (ACC_CC_MSC && (_MSC_VER < 1200))
+ _emit 0x0f
+ _emit 0x31
+# else
+ rdtsc
+# endif
+ mov [ecx], eax
+ mov [ecx+4], edx
+ }
+ return 0;
+#else
+ t[0] = t[1] = 0; return -1;
+#endif
+}
+#if (ACC_OS_WIN32 && ACC_CC_PELLESC && (__POCC__ >= 290))
+# pragma warn(pop)
+#endif
+#endif
+#endif
+#if defined(ACC_WANT_ACCLIB_DOSALLOC)
+# undef ACC_WANT_ACCLIB_DOSALLOC
+#define __ACCLIB_DOSALLOC_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+#if (ACC_OS_OS216)
+ACC_EXTERN_C unsigned short __far __pascal DosAllocHuge(unsigned short, unsigned short, unsigned short __far *, unsigned short, unsigned short);
+ACC_EXTERN_C unsigned short __far __pascal DosFreeSeg(unsigned short);
+#endif
+#if (ACC_OS_DOS16 || ACC_OS_WIN16)
+#if !defined(ACC_CC_AZTECC)
+ACCLIB_PUBLIC(void __far*, acc_dos_alloc) (unsigned long size)
+{
+ void __far* p = 0;
+ union REGS ri, ro;
+ if ((long)size <= 0)
+ return p;
+ size = (size + 15) >> 4;
+ if (size > 0xffffu)
+ return p;
+ ri.x.ax = 0x4800;
+ ri.x.bx = (unsigned short) size;
+ int86(0x21, &ri, &ro);
+ if ((ro.x.cflag & 1) == 0)
+ p = (void __far*) ACC_PTR_MK_FP(ro.x.ax, 0);
+ return p;
+}
+ACCLIB_PUBLIC(int, acc_dos_free) (void __far* p)
+{
+ union REGS ri, ro;
+ struct SREGS rs;
+ if (!p)
+ return 0;
+ if (ACC_PTR_FP_OFF(p) != 0)
+ return -1;
+ segread(&rs);
+ ri.x.ax = 0x4900;
+ rs.es = ACC_PTR_FP_SEG(p);
+ int86x(0x21, &ri, &ro, &rs);
+ if (ro.x.cflag & 1)
+ return -1;
+ return 0;
+}
+#endif
+#endif
+#if (ACC_OS_OS216)
+ACCLIB_PUBLIC(void __far*, acc_dos_alloc) (unsigned long size)
+{
+ void __far* p = 0;
+ unsigned short sel = 0;
+ if ((long)size <= 0)
+ return p;
+ if (DosAllocHuge((unsigned short)(size >> 16), (unsigned short)size, &sel, 0, 0) == 0)
+ p = (void __far*) ACC_PTR_MK_FP(sel, 0);
+ return p;
+}
+ACCLIB_PUBLIC(int, acc_dos_free) (void __far* p)
+{
+ if (!p)
+ return 0;
+ if (ACC_PTR_FP_OFF(p) != 0)
+ return -1;
+ if (DosFreeSeg(ACC_PTR_FP_SEG(p)) != 0)
+ return -1;
+ return 0;
+}
+#endif
+#endif
+#if defined(ACC_WANT_ACCLIB_HALLOC)
+# undef ACC_WANT_ACCLIB_HALLOC
+#define __ACCLIB_HALLOC_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+#if (ACC_HAVE_MM_HUGE_PTR)
+#if 1 && (ACC_OS_DOS16 && defined(BLX286))
+# define __ACCLIB_HALLOC_USE_DAH 1
+#elif 1 && (ACC_OS_DOS16 && defined(DOSX286))
+# define __ACCLIB_HALLOC_USE_DAH 1
+#elif 1 && (ACC_OS_OS216)
+# define __ACCLIB_HALLOC_USE_DAH 1
+#elif 1 && (ACC_OS_WIN16)
+# define __ACCLIB_HALLOC_USE_GA 1
+#elif 1 && (ACC_OS_DOS16) && (ACC_CC_BORLANDC) && defined(__DPMI16__)
+# define __ACCLIB_HALLOC_USE_GA 1
+#endif
+#endif
+#if (__ACCLIB_HALLOC_USE_DAH)
+#if 0 && (ACC_OS_OS216)
+#include <os2.h>
+#else
+ACC_EXTERN_C unsigned short __far __pascal DosAllocHuge(unsigned short, unsigned short, unsigned short __far *, unsigned short, unsigned short);
+ACC_EXTERN_C unsigned short __far __pascal DosFreeSeg(unsigned short);
+#endif
+#endif
+#if (__ACCLIB_HALLOC_USE_GA)
+#if 0
+#define STRICT 1
+#include <windows.h>
+#else
+ACC_EXTERN_C const void __near* __far __pascal GlobalAlloc(unsigned, unsigned long);
+ACC_EXTERN_C const void __near* __far __pascal GlobalFree(const void __near*);
+ACC_EXTERN_C unsigned long __far __pascal GlobalHandle(unsigned);
+ACC_EXTERN_C void __far* __far __pascal GlobalLock(const void __near*);
+ACC_EXTERN_C int __far __pascal GlobalUnlock(const void __near*);
+#endif
+#endif
+ACCLIB_PUBLIC(acc_hvoid_p, acc_halloc) (acc_hsize_t size)
+{
+ acc_hvoid_p p = 0;
+ if (!(size > 0))
+ return p;
+#if 0 && defined(__palmos__)
+ p = MemPtrNew(size);
+#elif !defined(ACC_HAVE_MM_HUGE_PTR)
+ if (size < (size_t) -1)
+ p = malloc((size_t) size);
+#else
+ if ((long)size <= 0)
+ return p;
+{
+#if (__ACCLIB_HALLOC_USE_DAH)
+ unsigned short sel = 0;
+ if (DosAllocHuge((unsigned short)(size >> 16), (unsigned short)size, &sel, 0, 0) == 0)
+ p = (acc_hvoid_p) ACC_PTR_MK_FP(sel, 0);
+#elif (__ACCLIB_HALLOC_USE_GA)
+ const void __near* h = GlobalAlloc(2, size);
+ if (h) {
+ p = GlobalLock(h);
+ if (p && ACC_PTR_FP_OFF(p) != 0) {
+ GlobalUnlock(h);
+ p = 0;
+ }
+ if (!p)
+ GlobalFree(h);
+ }
+#elif (ACC_CC_MSC && (_MSC_VER >= 700))
+ p = _halloc(size, 1);
+#elif (ACC_CC_MSC || ACC_CC_WATCOMC)
+ p = halloc(size, 1);
+#elif (ACC_CC_DMC || ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)
+ p = farmalloc(size);
+#elif (ACC_CC_BORLANDC || ACC_CC_TURBOC)
+ p = farmalloc(size);
+#elif defined(ACC_CC_AZTECC)
+ p = lmalloc(size);
+#else
+ if (size < (size_t) -1)
+ p = malloc((size_t) size);
+#endif
+}
+#endif
+ return p;
+}
+ACCLIB_PUBLIC(void, acc_hfree) (acc_hvoid_p p)
+{
+ if (!p)
+ return;
+#if 0 && defined(__palmos__)
+ MemPtrFree(p);
+#elif !defined(ACC_HAVE_MM_HUGE_PTR)
+ free(p);
+#else
+#if (__ACCLIB_HALLOC_USE_DAH)
+ if (ACC_PTR_FP_OFF(p) == 0)
+ DosFreeSeg((unsigned short) ACC_PTR_FP_SEG(p));
+#elif (__ACCLIB_HALLOC_USE_GA)
+ if (ACC_PTR_FP_OFF(p) == 0) {
+ const void __near* h = (const void __near*) (unsigned) GlobalHandle(ACC_PTR_FP_SEG(p));
+ if (h) {
+ GlobalUnlock(h);
+ GlobalFree(h);
+ }
+ }
+#elif (ACC_CC_MSC && (_MSC_VER >= 700))
+ _hfree(p);
+#elif (ACC_CC_MSC || ACC_CC_WATCOMC)
+ hfree(p);
+#elif (ACC_CC_DMC || ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)
+ farfree((void __far*) p);
+#elif (ACC_CC_BORLANDC || ACC_CC_TURBOC)
+ farfree((void __far*) p);
+#elif defined(ACC_CC_AZTECC)
+ lfree(p);
+#else
+ free(p);
+#endif
+#endif
+}
+#endif
+#if defined(ACC_WANT_ACCLIB_HFREAD)
+# undef ACC_WANT_ACCLIB_HFREAD
+#define __ACCLIB_HFREAD_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+ACCLIB_PUBLIC(acc_hsize_t, acc_hfread) (void* vfp, acc_hvoid_p buf, acc_hsize_t size)
+{
+ FILE* fp = (FILE *) vfp;
+#if (ACC_HAVE_MM_HUGE_PTR)
+#if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM)
+#define __ACCLIB_REQUIRE_HMEMCPY_CH 1
+ unsigned char tmp[512];
+ acc_hsize_t l = 0;
+ while (l < size)
+ {
+ size_t n = size - l > sizeof(tmp) ? sizeof(tmp) : (size_t) (size - l);
+ n = fread(tmp, 1, n, fp);
+ if (n == 0)
+ break;
+ __ACCLIB_FUNCNAME(acc_hmemcpy)((acc_hbyte_p)buf + l, tmp, (acc_hsize_t)n);
+ l += n;
+ }
+ return l;
+#elif (ACC_MM_COMPACT || ACC_MM_LARGE || ACC_MM_HUGE)
+ acc_hbyte_p b = (acc_hbyte_p) buf;
+ acc_hsize_t l = 0;
+ while (l < size)
+ {
+ size_t n;
+ n = ACC_PTR_FP_OFF(b); n = (n <= 1) ? 0x8000u : (0u - n);
+ if ((acc_hsize_t) n > size - l)
+ n = (size_t) (size - l);
+ n = fread((void __far*)b, 1, n, fp);
+ if (n == 0)
+ break;
+ b += n; l += n;
+ }
+ return l;
+#else
+# error "unknown memory model"
+#endif
+#else
+ return fread(buf, 1, size, fp);
+#endif
+}
+ACCLIB_PUBLIC(acc_hsize_t, acc_hfwrite) (void* vfp, const acc_hvoid_p buf, acc_hsize_t size)
+{
+ FILE* fp = (FILE *) vfp;
+#if (ACC_HAVE_MM_HUGE_PTR)
+#if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM)
+#define __ACCLIB_REQUIRE_HMEMCPY_CH 1
+ unsigned char tmp[512];
+ acc_hsize_t l = 0;
+ while (l < size)
+ {
+ size_t n = size - l > sizeof(tmp) ? sizeof(tmp) : (size_t) (size - l);
+ __ACCLIB_FUNCNAME(acc_hmemcpy)(tmp, (const acc_hbyte_p)buf + l, (acc_hsize_t)n);
+ n = fwrite(tmp, 1, n, fp);
+ if (n == 0)
+ break;
+ l += n;
+ }
+ return l;
+#elif (ACC_MM_COMPACT || ACC_MM_LARGE || ACC_MM_HUGE)
+ const acc_hbyte_p b = (const acc_hbyte_p) buf;
+ acc_hsize_t l = 0;
+ while (l < size)
+ {
+ size_t n;
+ n = ACC_PTR_FP_OFF(b); n = (n <= 1) ? 0x8000u : (0u - n);
+ if ((acc_hsize_t) n > size - l)
+ n = (size_t) (size - l);
+ n = fwrite((void __far*)b, 1, n, fp);
+ if (n == 0)
+ break;
+ b += n; l += n;
+ }
+ return l;
+#else
+# error "unknown memory model"
+#endif
+#else
+ return fwrite(buf, 1, size, fp);
+#endif
+}
+#endif
+#if defined(ACC_WANT_ACCLIB_HSREAD)
+# undef ACC_WANT_ACCLIB_HSREAD
+#define __ACCLIB_HSREAD_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+ACCLIB_PUBLIC(long, acc_safe_hread) (int fd, acc_hvoid_p buf, long size)
+{
+ acc_hbyte_p b = (acc_hbyte_p) buf;
+ long l = 0;
+ int saved_errno;
+ saved_errno = errno;
+ while (l < size)
+ {
+ long n = size - l;
+#if (ACC_HAVE_MM_HUGE_PTR)
+# define __ACCLIB_REQUIRE_HREAD_CH 1
+ errno = 0; n = acc_hread(fd, b, n);
+#elif (ACC_OS_DOS32) && defined(__DJGPP__)
+ errno = 0; n = _read(fd, b, n);
+#else
+ errno = 0; n = read(fd, b, n);
+#endif
+ if (n == 0)
+ break;
+ if (n < 0) {
+#if defined(EAGAIN)
+ if (errno == (EAGAIN)) continue;
+#endif
+#if defined(EINTR)
+ if (errno == (EINTR)) continue;
+#endif
+ if (errno == 0) errno = 1;
+ return l;
+ }
+ b += n; l += n;
+ }
+ errno = saved_errno;
+ return l;
+}
+ACCLIB_PUBLIC(long, acc_safe_hwrite) (int fd, const acc_hvoid_p buf, long size)
+{
+ const acc_hbyte_p b = (const acc_hbyte_p) buf;
+ long l = 0;
+ int saved_errno;
+ saved_errno = errno;
+ while (l < size)
+ {
+ long n = size - l;
+#if (ACC_HAVE_MM_HUGE_PTR)
+# define __ACCLIB_REQUIRE_HREAD_CH 1
+ errno = 0; n = acc_hwrite(fd, b, n);
+#elif (ACC_OS_DOS32) && defined(__DJGPP__)
+ errno = 0; n = _write(fd, b, n);
+#else
+ errno = 0; n = write(fd, b, n);
+#endif
+ if (n == 0)
+ break;
+ if (n < 0) {
+#if defined(EAGAIN)
+ if (errno == (EAGAIN)) continue;
+#endif
+#if defined(EINTR)
+ if (errno == (EINTR)) continue;
+#endif
+ if (errno == 0) errno = 1;
+ return l;
+ }
+ b += n; l += n;
+ }
+ errno = saved_errno;
+ return l;
+}
+#endif
+#if defined(ACC_WANT_ACCLIB_PCLOCK)
+# undef ACC_WANT_ACCLIB_PCLOCK
+#define __ACCLIB_PCLOCK_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+#if defined(HAVE_GETTIMEOFDAY)
+#ifndef acc_pclock_read_gettimeofday
+#define acc_pclock_read_gettimeofday acc_pclock_read_gettimeofday
+#endif
+static int acc_pclock_read_gettimeofday(acc_pclock_handle_p h, acc_pclock_p c)
+{
+ struct timeval tv;
+ if (gettimeofday(&tv, 0) != 0)
+ return -1;
+#if defined(acc_int64l_t)
+ c->tv_sec = tv.tv_sec;
+#else
+ c->tv_sec_high = 0;
+ c->tv_sec_low = tv.tv_sec;
+#endif
+ c->tv_nsec = (acc_uint32l_t) (tv.tv_usec * 1000u);
+ ACC_UNUSED(h); return 0;
+}
+#endif
+#if defined(CLOCKS_PER_SEC)
+#ifndef acc_pclock_read_clock
+#define acc_pclock_read_clock acc_pclock_read_clock
+#endif
+static int acc_pclock_read_clock(acc_pclock_handle_p h, acc_pclock_p c)
+{
+ clock_t ticks;
+ double secs;
+#if defined(acc_int64l_t)
+ acc_uint64l_t nsecs;
+ ticks = clock();
+ secs = (double)ticks / (CLOCKS_PER_SEC);
+ nsecs = (acc_uint64l_t) (secs * 1000000000.0);
+ c->tv_sec = (acc_int64l_t) (nsecs / 1000000000ul);
+ c->tv_nsec = (acc_uint32l_t) (nsecs % 1000000000ul);
+#else
+ ticks = clock();
+ secs = (double)ticks / (CLOCKS_PER_SEC);
+ c->tv_sec_high = 0;
+ c->tv_sec_low = (acc_uint32l_t) (secs + 0.5);
+ c->tv_nsec = 0;
+#endif
+ ACC_UNUSED(h); return 0;
+}
+#endif
+#if (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__) && defined(UCLOCKS_PER_SEC)
+#ifndef acc_pclock_read_uclock
+#define acc_pclock_read_uclock acc_pclock_read_uclock
+#endif
+static int acc_pclock_read_uclock(acc_pclock_handle_p h, acc_pclock_p c)
+{
+ acc_uint64l_t ticks;
+ double secs;
+ acc_uint64l_t nsecs;
+ ticks = uclock();
+ secs = (double)ticks / (UCLOCKS_PER_SEC);
+ nsecs = (acc_uint64l_t) (secs * 1000000000.0);
+ c->tv_sec = nsecs / 1000000000ul;
+ c->tv_nsec = (acc_uint32l_t) (nsecs % 1000000000ul);
+ ACC_UNUSED(h); return 0;
+}
+#endif
+#if 0 && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) && defined(acc_int64l_t)
+#ifndef acc_pclock_read_clock_gettime_p
+#define acc_pclock_read_clock_gettime_p acc_pclock_read_clock_gettime_p
+#endif
+static int acc_pclock_read_clock_gettime_p(acc_pclock_handle_p h, acc_pclock_p c)
+{
+ struct timespec ts;
+ if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) != 0)
+ return -1;
+ c->tv_sec = ts.tv_sec;
+ c->tv_nsec = ts.tv_nsec;
+ ACC_UNUSED(h); return 0;
+}
+#endif
+#if (ACC_OS_CYGWIN || ACC_OS_WIN32 || ACC_OS_WIN64) && (ACC_HAVE_WINDOWS_H) && defined(acc_int64l_t)
+#ifndef acc_pclock_read_getprocesstimes
+#define acc_pclock_read_getprocesstimes acc_pclock_read_getprocesstimes
+#endif
+static int acc_pclock_read_getprocesstimes(acc_pclock_handle_p h, acc_pclock_p c)
+{
+ FILETIME ct, et, kt, ut;
+ acc_uint64l_t ticks;
+ if (GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut) == 0)
+ return -1;
+ ticks = ((acc_uint64l_t)ut.dwHighDateTime << 32) | ut.dwLowDateTime;
+ if __acc_unlikely(h->ticks_base == 0)
+ h->ticks_base = ticks;
+ else
+ ticks -= h->ticks_base;
+ c->tv_sec = (acc_int64l_t) (ticks / 10000000ul);
+ c->tv_nsec = (acc_uint32l_t)(ticks % 10000000ul) * 100u;
+ ACC_UNUSED(h); return 0;
+}
+#endif
+#if defined(HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
+#ifndef acc_pclock_read_getrusage
+#define acc_pclock_read_getrusage acc_pclock_read_getrusage
+#endif
+static int acc_pclock_read_getrusage(acc_pclock_handle_p h, acc_pclock_p c)
+{
+ struct rusage ru;
+ if (getrusage(RUSAGE_SELF, &ru) != 0)
+ return -1;
+#if defined(acc_int64l_t)
+ c->tv_sec = ru.ru_utime.tv_sec;
+#else
+ c->tv_sec_high = 0;
+ c->tv_sec_low = ru.ru_utime.tv_sec;
+#endif
+ c->tv_nsec = (acc_uint32l_t) (ru.ru_utime.tv_usec * 1000u);
+ ACC_UNUSED(h); return 0;
+}
+#endif
+#if (__ACCLIB_PCLOCK_USE_PERFCTR)
+#ifndef acc_pclock_read_perfctr
+#define acc_pclock_read_perfctr acc_pclock_read_perfctr
+#endif
+static int acc_pclock_read_perfctr(acc_pclock_handle_p h, acc_pclock_p c)
+{
+ acc_perfctr_clock_t pcc;
+ double secs;
+ acc_uint64l_t nsecs;
+ acc_perfctr_read(&h->pch, &pcc);
+ if __acc_unlikely(h->ticks_base == 0)
+ h->ticks_base = pcc.tsc;
+ else
+ pcc.tsc -= h->ticks_base;
+ secs = pcc.tsc * h->pch.tsc_to_seconds;
+ nsecs = (acc_uint64l_t) (secs * 1000000000.0);
+ c->tv_sec = nsecs / 1000000000ul;
+ c->tv_nsec = (acc_uint32l_t) (nsecs % 1000000000ul);
+ ACC_UNUSED(h); return 0;
+}
+#endif
+#if 0 && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_THREAD_CPUTIME_ID) && defined(acc_int64l_t)
+#ifndef acc_pclock_read_clock_gettime_t
+#define acc_pclock_read_clock_gettime_t acc_pclock_read_clock_gettime_t
+#endif
+static int acc_pclock_read_clock_gettime_t(acc_pclock_handle_p h, acc_pclock_p c)
+{
+ struct timespec ts;
+ if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0)
+ return -1;
+ c->tv_sec = ts.tv_sec;
+ c->tv_nsec = ts.tv_nsec;
+ ACC_UNUSED(h); return 0;
+}
+#endif
+#if (ACC_OS_CYGWIN || ACC_OS_WIN32 || ACC_OS_WIN64) && (ACC_HAVE_WINDOWS_H) && defined(acc_int64l_t)
+#ifndef acc_pclock_read_getthreadtimes
+#define acc_pclock_read_getthreadtimes acc_pclock_read_getthreadtimes
+#endif
+static int acc_pclock_read_getthreadtimes(acc_pclock_handle_p h, acc_pclock_p c)
+{
+ FILETIME ct, et, kt, ut;
+ acc_uint64l_t ticks;
+ if (GetThreadTimes(GetCurrentThread(), &ct, &et, &kt, &ut) == 0)
+ return -1;
+ ticks = ((acc_uint64l_t)ut.dwHighDateTime << 32) | ut.dwLowDateTime;
+ if __acc_unlikely(h->ticks_base == 0)
+ h->ticks_base = ticks;
+ else
+ ticks -= h->ticks_base;
+ c->tv_sec = (acc_int64l_t) (ticks / 10000000ul);
+ c->tv_nsec = (acc_uint32l_t)(ticks % 10000000ul) * 100;
+ ACC_UNUSED(h); return 0;
+}
+#endif
+ACCLIB_PUBLIC(int, acc_pclock_open) (acc_pclock_handle_p h, int mode)
+{
+ acc_pclock_t c;
+ int i;
+ h->h = (acclib_handle_t) 0;
+ h->mode = -1;
+ h->name = NULL;
+ h->gettime = 0;
+#if defined(acc_int64l_t)
+ h->ticks_base = 0;
+#endif
+ switch (mode)
+ {
+ case ACC_PCLOCK_REALTIME_HR:
+# if defined(acc_pclock_read_gettimeofday)
+ h->gettime = acc_pclock_read_gettimeofday;
+ h->name = "gettimeofday";
+# endif
+ break;
+ case ACC_PCLOCK_REALTIME:
+# if defined(acc_pclock_read_gettimeofday)
+ h->gettime = acc_pclock_read_gettimeofday;
+ h->name = "gettimeofday";
+# endif
+ break;
+ case ACC_PCLOCK_MONOTONIC_HR:
+# if defined(acc_pclock_read_uclock)
+ h->gettime = acc_pclock_read_uclock;
+ h->name = "uclock";
+# endif
+ break;
+ case ACC_PCLOCK_MONOTONIC:
+# if defined(acc_pclock_read_clock)
+ if (!h->gettime) {
+ h->gettime = acc_pclock_read_clock;
+ h->name = "clock";
+ }
+# endif
+ break;
+ case ACC_PCLOCK_PROCESS_CPUTIME_ID:
+# if defined(acc_pclock_read_perfctr)
+ if (acc_perfctr_open(&h->pch) == 0) {
+ h->gettime = acc_pclock_read_perfctr;
+ h->name = "perfctr";
+ break;
+ }
+# endif
+# if defined(acc_pclock_read_getprocesstimes)
+ if (!h->gettime && acc_pclock_read_getprocesstimes(h, &c) == 0) {
+ h->gettime = acc_pclock_read_getprocesstimes;
+ h->name = "GetProcessTimes";
+ break;
+ }
+# endif
+# if defined(acc_pclock_read_clock_gettime_p)
+ if (!h->gettime && acc_pclock_read_clock_gettime_p(h, &c) == 0) {
+ h->gettime = acc_pclock_read_clock_gettime_p;
+ h->name = "CLOCK_PROCESS_CPUTIME_ID";
+ break;
+ }
+# endif
+# if defined(acc_pclock_read_getrusage)
+ h->gettime = acc_pclock_read_getrusage;
+ h->name = "getrusage";
+# endif
+ break;
+ case ACC_PCLOCK_THREAD_CPUTIME_ID:
+# if defined(acc_pclock_read_getthreadtimes)
+ if (!h->gettime && acc_pclock_read_getthreadtimes(h, &c) == 0) {
+ h->gettime = acc_pclock_read_getthreadtimes;
+ h->name = "GetThreadTimes";
+ }
+# endif
+# if defined(acc_pclock_read_clock_gettime_t)
+ if (!h->gettime && acc_pclock_read_clock_gettime_t(h, &c) == 0) {
+ h->gettime = acc_pclock_read_clock_gettime_t;
+ h->name = "CLOCK_THREAD_CPUTIME_ID";
+ break;
+ }
+# endif
+ break;
+ }
+ if (!h->gettime)
+ return -1;
+ if (!h->h)
+ h->h = (acclib_handle_t) 1;
+ h->mode = mode;
+ if (!h->name)
+ h->name = "unknown";
+ for (i = 0; i < 10; i++) {
+ acc_pclock_read(h, &c);
+ }
+ return 0;
+}
+ACCLIB_PUBLIC(int, acc_pclock_open_default) (acc_pclock_handle_p h)
+{
+ if (acc_pclock_open(h, ACC_PCLOCK_PROCESS_CPUTIME_ID) == 0)
+ return 0;
+ if (acc_pclock_open(h, ACC_PCLOCK_MONOTONIC_HR) == 0)
+ return 0;
+ if (acc_pclock_open(h, ACC_PCLOCK_REALTIME_HR) == 0)
+ return 0;
+ if (acc_pclock_open(h, ACC_PCLOCK_MONOTONIC) == 0)
+ return 0;
+ if (acc_pclock_open(h, ACC_PCLOCK_REALTIME) == 0)
+ return 0;
+ if (acc_pclock_open(h, ACC_PCLOCK_THREAD_CPUTIME_ID) == 0)
+ return 0;
+ return -1;
+}
+ACCLIB_PUBLIC(int, acc_pclock_close) (acc_pclock_handle_p h)
+{
+ h->h = (acclib_handle_t) 0;
+ h->mode = -1;
+ h->name = NULL;
+ h->gettime = 0;
+#if (__ACCLIB_PCLOCK_USE_PERFCTR)
+ acc_perfctr_close(&h->pch);
+#endif
+ return 0;
+}
+ACCLIB_PUBLIC(void, acc_pclock_read) (acc_pclock_handle_p h, acc_pclock_p c)
+{
+ if (h->gettime) {
+ if (h->gettime(h, c) == 0)
+ return;
+ }
+#if defined(acc_int64l_t)
+ c->tv_sec = 0;
+#else
+ c->tv_sec_high = 0;
+ c->tv_sec_low = 0;
+#endif
+ c->tv_nsec = 0;
+}
+#if !defined(ACC_CFG_NO_DOUBLE)
+ACCLIB_PUBLIC(double, acc_pclock_get_elapsed) (acc_pclock_handle_p h, const acc_pclock_p start, const acc_pclock_p stop)
+{
+ double tstop, tstart;
+ if (!h->h) {
+ h->mode = -1;
+ return 0.0;
+ }
+#if defined(acc_int64l_t)
+ tstop = stop->tv_sec + stop->tv_nsec / 1000000000.0;
+ tstart = start->tv_sec + start->tv_nsec / 1000000000.0;
+#else
+ tstop = stop->tv_sec_low + stop->tv_nsec / 1000000000.0;
+ tstart = start->tv_sec_low + start->tv_nsec / 1000000000.0;
+#endif
+ return tstop - tstart;
+}
+#endif
+ACCLIB_PUBLIC(int, acc_pclock_flush_cpu_cache) (acc_pclock_handle_p h, unsigned flags)
+{
+ if (h->h) {
+#if (__ACCLIB_PCLOCK_USE_PERFCTR)
+ return acc_perfctr_flush_cpu_cache(&h->pch, flags);
+#endif
+ }
+ ACC_UNUSED(h); ACC_UNUSED(flags);
+ return -1;
+}
+#if defined(__ACCLIB_PCLOCK_NEED_WARN_POP)
+# if (ACC_CC_MSC && (_MSC_VER >= 1200))
+# pragma warning(pop)
+# else
+# error "__ACCLIB_PCLOCK_NEED_WARN_POP"
+# endif
+# undef __ACCLIB_PCLOCK_NEED_WARN_POP
+#endif
+#endif
+#if defined(ACC_WANT_ACCLIB_UCLOCK)
+# undef ACC_WANT_ACCLIB_UCLOCK
+#define __ACCLIB_UCLOCK_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+#if (ACC_OS_DOS16 || ACC_OS_WIN16)
+#elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)
+#elif (ACC_OS_CYGWIN || ACC_OS_WIN32 || ACC_OS_WIN64) && (ACC_HAVE_WINDOWS_H)
+# if ((ACC_CC_DMC && (__DMC__ < 0x838)) || ACC_CC_LCCWIN32)
+# define __ACCLIB_UCLOCK_USE_CLOCK 1
+# else
+# define __ACCLIB_UCLOCK_USE_WINMM 1
+# if (ACC_CC_MSC && (_MSC_VER >= 1200))
+# pragma warning(push)
+# define __ACCLIB_UCLOCK_NEED_WARN_POP 1
+# endif
+# if (ACC_CC_MSC && (_MSC_VER >= 900))
+# pragma warning(disable: 4201)
+# elif (ACC_CC_MWERKS)
+# define LPUINT __ACC_MMSYSTEM_H_LPUINT
+# endif
+# if 1
+# include <mmsystem.h>
+# else
+# if (ACC_CC_INTELC || ACC_CC_MSC || ACC_CC_PELLESC)
+ ACC_EXTERN_C __declspec(dllimport) unsigned long __stdcall timeGetTime(void);
+# else
+ ACC_EXTERN_C unsigned long __stdcall timeGetTime(void);
+# endif
+# endif
+# if (ACC_CC_DMC)
+# pragma DMC includelib "winmm.lib"
+# elif (ACC_CC_INTELC || ACC_CC_MSC || ACC_CC_PELLESC)
+# pragma comment(lib, "winmm.lib")
+# elif (ACC_CC_MWERKS && (__MWERKS__ >= 0x3000))
+# pragma comment(lib, "winmm.lib")
+# elif (ACC_CC_SYMANTECC)
+# pragma SC includelib "winmm.lib"
+# elif (ACC_CC_WATCOMC && (__WATCOMC__ >= 1050))
+# pragma library("winmm.lib")
+# endif
+# endif
+#elif (ACC_OS_CYGWIN || ACC_OS_DOS32 || ACC_OS_EMX || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_TOS || ACC_OS_WIN32 || ACC_OS_WIN64)
+# define __ACCLIB_UCLOCK_USE_CLOCK 1
+#elif (ACC_OS_CONSOLE) && defined(CLOCKS_PER_SEC)
+# define __ACCLIB_UCLOCK_USE_CLOCK 1
+#elif (ACC_LIBC_ISOC90 || ACC_LIBC_ISOC99) && defined(CLOCKS_PER_SEC)
+# define __ACCLIB_UCLOCK_USE_CLOCK 1
+#endif
+#if (__ACCLIB_UCLOCK_USE_CLOCK) && !defined(CLOCKS_PER_SEC)
+# if defined(CLK_TCK)
+# define CLOCKS_PER_SEC CLK_TCK
+# else
+# undef __ACCLIB_UCLOCK_USE_CLOCK
+# endif
+#endif
+#if (__ACCLIB_UCLOCK_USE_GETRUSAGE)
+# if !defined(RUSAGE_SELF)
+# undef __ACCLIB_UCLOCK_USE_GETRUSAGE
+# endif
+#endif
+ACCLIB_PUBLIC(int, acc_uclock_open) (acc_uclock_handle_p h)
+{
+ int i;
+#if (__ACCLIB_UCLOCK_USE_QPC)
+ LARGE_INTEGER li;
+#endif
+ h->h = (acclib_handle_t) 1;
+ h->mode = 0;
+ h->name = NULL;
+#if (__ACCLIB_UCLOCK_USE_PERFCTR)
+ h->pch.h = 0;
+ if (h->mode == 0 && acc_perfctr_open(&h->pch) == 0)
+ h->mode = 2;
+#endif
+#if (__ACCLIB_UCLOCK_USE_QPC)
+ h->qpf = 0.0;
+ if (h->mode == 0 && QueryPerformanceFrequency(&li) != 0) {
+ double d = (double) li.QuadPart;
+ if (d > 0.0 && QueryPerformanceCounter(&li) != 0) {
+ h->mode = 3;
+ h->qpf = d;
+ }
+ }
+#endif
+ for (i = 0; i < 10; i++) {
+ acc_uclock_t c;
+ acc_uclock_read(h, &c);
+ }
+ return 0;
+}
+ACCLIB_PUBLIC(int, acc_uclock_close) (acc_uclock_handle_p h)
+{
+ h->h = (acclib_handle_t) 0;
+ h->mode = -1;
+ h->name = NULL;
+#if (__ACCLIB_UCLOCK_USE_PERFCTR)
+ acc_perfctr_close(&h->pch);
+#endif
+ return 0;
+}
+ACCLIB_PUBLIC(void, acc_uclock_read) (acc_uclock_handle_p h, acc_uclock_p c)
+{
+#if (__ACCLIB_UCLOCK_USE_RDTSC)
+ acc_tsc_read((acc_uint32e_t*) (void*) &c->tsc);
+#endif
+#if (__ACCLIB_UCLOCK_USE_PERFCTR)
+ if (h->pch.h) {
+ acc_perfctr_read(&h->pch, &c->pcc);
+ if (h->mode > 0 && h->mode <= 2)
+ return;
+ }
+#endif
+#if (__ACCLIB_UCLOCK_USE_QPC)
+ if (h->qpf > 0.0) {
+ LARGE_INTEGER li;
+ if (QueryPerformanceCounter(&li) != 0) {
+ c->qpc = (acc_int64l_t) li.QuadPart;
+ if (h->mode > 0 && h->mode <= 3)
+ return;
+ } else {
+ h->mode = 0; h->qpf = 0.0; c->qpc = 0;
+ }
+ }
+#endif
+ {
+#if (ACC_OS_DOS16 || ACC_OS_WIN16)
+# if (ACC_CC_AZTECC)
+ c->ticks.t32 = 0;
+# else
+ union REGS ri, ro;
+ ri.x.ax = 0x2c00; int86(0x21, &ri, &ro);
+ c->ticks.t32 = ro.h.ch*60UL*60UL*100UL + ro.h.cl*60UL*100UL + ro.h.dh*100UL + ro.h.dl;
+# endif
+#elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)
+ c->ticks.t64 = uclock();
+#elif (__ACCLIB_UCLOCK_USE_CLOCK) && defined(acc_int64l_t)
+ c->ticks.t64 = clock();
+#elif (__ACCLIB_UCLOCK_USE_CLOCK)
+ c->ticks.t32 = clock();
+#elif (__ACCLIB_UCLOCK_USE_WINMM)
+ c->ticks.t32 = timeGetTime();
+#elif (__ACCLIB_UCLOCK_USE_GETRUSAGE)
+ struct rusage ru;
+ if (getrusage(RUSAGE_SELF, &ru) != 0) c->ticks.td = 0;
+ else c->ticks.td = ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1000000.0;
+#elif (HAVE_GETTIMEOFDAY)
+ struct timeval tv;
+ if (gettimeofday(&tv, 0) != 0) c->ticks.td = 0;
+ else c->ticks.td = tv.tv_sec + tv.tv_usec / 1000000.0;
+#else
+ ACC_UNUSED(c);
+#endif
+ }
+ ACC_UNUSED(h);
+}
+ACCLIB_PUBLIC(double, acc_uclock_get_elapsed) (acc_uclock_handle_p h, const acc_uclock_p start, const acc_uclock_p stop)
+{
+ double d;
+ if (!h->h) {
+ h->mode = -1;
+ return 0.0;
+ }
+#if (__ACCLIB_UCLOCK_USE_RDTSC)
+ if (h->mode == 1) {
+ if (!h->name) h->name = "rdtsc";
+ d = (double) ((acc_int64l_t)stop->tsc - (acc_int64l_t)start->tsc);
+ return d / 1000000000.0;
+ }
+#endif
+#if (__ACCLIB_UCLOCK_USE_PERFCTR)
+ if (h->pch.h && h->mode == 2) {
+ if (!h->name) h->name = "perfctr";
+ return acc_perfctr_get_elapsed(&h->pch, &start->pcc, &stop->pcc);
+ }
+#endif
+#if (__ACCLIB_UCLOCK_USE_QPC)
+ if (h->qpf > 0.0 && h->mode == 3) {
+ if (!h->name) h->name = "qpc";
+ if (start->qpc == 0 || stop->qpc == 0) return 0.0;
+ return (double) (stop->qpc - start->qpc) / h->qpf;
+ }
+#endif
+#if (ACC_OS_DOS16 || ACC_OS_WIN16)
+ h->mode = 11;
+ if (!h->name) h->name = "uclock";
+ d = (double) (stop->ticks.t32 - start->ticks.t32) / 100.0;
+ if (d < 0.0) d += 86400.0;
+#elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)
+ h->mode = 12;
+ if (!h->name) h->name = "uclock";
+ d = (double) (stop->ticks.t64 - start->ticks.t64) / (UCLOCKS_PER_SEC);
+#elif (__ACCLIB_UCLOCK_USE_CLOCK) && defined(acc_int64l_t)
+ h->mode = 13;
+ if (!h->name) h->name = "clock";
+ {
+ acc_int64l_t t;
+ t = stop->ticks.t64 - start->ticks.t64;
+ if (t < 0)
+ t += sizeof(clock_t) == 4 ? ACC_INT64_C(0x100000000) : ACC_INT64_C(0);
+ d = (double) t / (CLOCKS_PER_SEC);
+ }
+#elif (__ACCLIB_UCLOCK_USE_CLOCK)
+ h->mode = 14;
+ if (!h->name) h->name = "clock";
+ d = (double) (stop->ticks.t32 - start->ticks.t32) / (CLOCKS_PER_SEC);
+#elif (__ACCLIB_UCLOCK_USE_WINMM)
+ h->mode = 15;
+ if (!h->name) h->name = "timeGetTime";
+ d = (double) (stop->ticks.t32 - start->ticks.t32) / 1000.0;
+#elif (__ACCLIB_UCLOCK_USE_GETRUSAGE)
+ h->mode = 16;
+ if (!h->name) h->name = "getrusage";
+ d = stop->ticks.td - start->ticks.td;
+#elif (HAVE_GETTIMEOFDAY)
+ h->mode = 17;
+ if (!h->name) h->name = "gettimeofday";
+ d = stop->ticks.td - start->ticks.td;
+#else
+ h->mode = 0;
+ d = 0.0;
+#endif
+ return d;
+}
+ACCLIB_PUBLIC(int, acc_uclock_flush_cpu_cache) (acc_uclock_handle_p h, unsigned flags)
+{
+ if (h->h) {
+#if (__ACCLIB_UCLOCK_USE_PERFCTR)
+ return acc_perfctr_flush_cpu_cache(&h->pch, flags);
+#endif
+ }
+ ACC_UNUSED(h); ACC_UNUSED(flags);
+ return -1;
+}
+#if defined(__ACCLIB_UCLOCK_NEED_WARN_POP)
+# if (ACC_CC_MSC && (_MSC_VER >= 1200))
+# pragma warning(pop)
+# else
+# error "__ACCLIB_UCLOCK_NEED_WARN_POP"
+# endif
+# undef __ACCLIB_UCLOCK_NEED_WARN_POP
+#endif
+#endif
+#if defined(ACC_WANT_ACCLIB_MISC)
+# undef ACC_WANT_ACCLIB_MISC
+#define __ACCLIB_MISC_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+#if !defined(ACCLIB_PUBLIC_NOINLINE)
+# if !defined(__acc_noinline)
+# define ACCLIB_PUBLIC_NOINLINE(r,f) r __ACCLIB_FUNCNAME(f)
+# elif (ACC_CC_GNUC >= 0x030400ul) || (ACC_CC_LLVM)
+# define ACCLIB_PUBLIC_NOINLINE(r,f) __acc_noinline __attribute__((__used__)) r __ACCLIB_FUNCNAME(f)
+# else
+# define ACCLIB_PUBLIC_NOINLINE(r,f) __acc_noinline r __ACCLIB_FUNCNAME(f)
+# endif
+#endif
+#if (ACC_OS_WIN32 && ACC_CC_PELLESC && (__POCC__ >= 290))
+# pragma warn(push)
+# pragma warn(disable:2007)
+#endif
+ACCLIB_PUBLIC(const char *, acc_getenv) (const char *s)
+{
+#if defined(HAVE_GETENV)
+ return getenv(s);
+#else
+ ACC_UNUSED(s); return (const char *) 0;
+#endif
+}
+ACCLIB_PUBLIC(acclib_handle_t, acc_get_osfhandle) (int fd)
+{
+ if (fd < 0)
+ return -1;
+#if (ACC_OS_CYGWIN)
+ return get_osfhandle(fd);
+#elif (ACC_OS_EMX && defined(__RSXNT__))
+ return -1;
+#elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)
+ return -1;
+#elif (ACC_OS_WIN32 || ACC_OS_WIN64)
+# if (ACC_CC_PELLESC && (__POCC__ < 280))
+ return -1;
+# elif (ACC_CC_WATCOMC && (__WATCOMC__ < 1000))
+ return -1;
+# elif (ACC_CC_WATCOMC && (__WATCOMC__ < 1100))
+ return _os_handle(fd);
+# else
+ return _get_osfhandle(fd);
+# endif
+#else
+ return fd;
+#endif
+}
+ACCLIB_PUBLIC(int, acc_set_binmode) (int fd, int binary)
+{
+#if (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__)
+ FILE* fp; int old_binary;
+ if (fd == STDIN_FILENO) fp = stdin;
+ else if (fd == STDOUT_FILENO) fp = stdout;
+ else if (fd == STDERR_FILENO) fp = stderr;
+ else return -1;
+ old_binary = fp->__mode.__binary;
+ __set_binmode(fp, binary ? 1 : 0);
+ return old_binary ? 1 : 0;
+#elif (ACC_ARCH_M68K && ACC_OS_TOS)
+ ACC_UNUSED(fd); ACC_UNUSED(binary);
+ return -1;
+#elif (ACC_OS_DOS16 && (ACC_CC_AZTECC || ACC_CC_PACIFICC))
+ ACC_UNUSED(fd); ACC_UNUSED(binary);
+ return -1;
+#elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)
+ int r; unsigned old_flags = __djgpp_hwint_flags;
+ ACC_COMPILE_TIME_ASSERT(O_BINARY > 0)
+ ACC_COMPILE_TIME_ASSERT(O_TEXT > 0)
+ if (fd < 0) return -1;
+ r = setmode(fd, binary ? O_BINARY : O_TEXT);
+ if ((old_flags & 1u) != (__djgpp_hwint_flags & 1u))
+ __djgpp_set_ctrl_c(!(old_flags & 1));
+ if (r == -1) return -1;
+ return (r & O_TEXT) ? 0 : 1;
+#elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)
+ if (fd < 0) return -1;
+ ACC_UNUSED(binary);
+ return 1;
+#elif (ACC_OS_DOS32 && ACC_CC_HIGHC)
+ FILE* fp; int r;
+ if (fd == fileno(stdin)) fp = stdin;
+ else if (fd == fileno(stdout)) fp = stdout;
+ else if (fd == fileno(stderr)) fp = stderr;
+ else return -1;
+ r = _setmode(fp, binary ? _BINARY : _TEXT);
+ if (r == -1) return -1;
+ return (r & _BINARY) ? 1 : 0;
+#elif (ACC_OS_WIN32 && ACC_CC_MWERKS) && defined(__MSL__)
+ ACC_UNUSED(fd); ACC_UNUSED(binary);
+ return -1;
+#elif (ACC_OS_CYGWIN && (ACC_CC_GNUC < 0x025a00ul))
+ ACC_UNUSED(fd); ACC_UNUSED(binary);
+ return -1;
+#elif (ACC_OS_CYGWIN || ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_EMX || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
+ int r;
+#if !defined(ACC_CC_ZORTECHC)
+ ACC_COMPILE_TIME_ASSERT(O_BINARY > 0)
+#endif
+ ACC_COMPILE_TIME_ASSERT(O_TEXT > 0)
+ if (fd < 0) return -1;
+ r = setmode(fd, binary ? O_BINARY : O_TEXT);
+ if (r == -1) return -1;
+ return (r & O_TEXT) ? 0 : 1;
+#else
+ if (fd < 0) return -1;
+ ACC_UNUSED(binary);
+ return 1;
+#endif
+}
+ACCLIB_PUBLIC(int, acc_isatty) (int fd)
+{
+ if (fd < 0)
+ return 0;
+#if (ACC_OS_DOS16 && !defined(ACC_CC_AZTECC))
+ {
+ union REGS ri, ro;
+ ri.x.ax = 0x4400; ri.x.bx = fd;
+ int86(0x21, &ri, &ro);
+ if ((ro.x.cflag & 1) == 0)
+ if ((ro.x.ax & 0x83) != 0x83)
+ return 0;
+ }
+#elif (ACC_OS_DOS32 && ACC_CC_WATCOMC)
+ {
+ union REGS ri, ro;
+ ri.w.ax = 0x4400; ri.w.bx = (unsigned short) fd;
+ int386(0x21, &ri, &ro);
+ if ((ro.w.cflag & 1) == 0)
+ if ((ro.w.ax & 0x83) != 0x83)
+ return 0;
+ }
+#elif (ACC_HAVE_WINDOWS_H)
+ {
+ acclib_handle_t h = __ACCLIB_FUNCNAME(acc_get_osfhandle)(fd);
+ if ((HANDLE)h != INVALID_HANDLE_VALUE)
+ {
+ DWORD d = 0;
+ if (GetConsoleMode((HANDLE)h, &d) == 0)
+ return 0;
+ }
+ }
+#endif
+#if defined(HAVE_ISATTY)
+ return (isatty(fd)) ? 1 : 0;
+#else
+ return 0;
+#endif
+}
+ACCLIB_PUBLIC(int, acc_mkdir) (const char* name, unsigned mode)
+{
+#if !defined(HAVE_MKDIR)
+ ACC_UNUSED(name); ACC_UNUSED(mode);
+ return -1;
+#elif (ACC_ARCH_M68K && ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))
+ ACC_UNUSED(mode);
+ return Dcreate(name);
+#elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)
+ return mkdir(name, mode);
+#elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)
+ return mkdir(name, mode);
+#elif (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
+ ACC_UNUSED(mode);
+# if (ACC_CC_HIGHC || ACC_CC_PACIFICC)
+ return mkdir((char*) name);
+# else
+ return mkdir(name);
+# endif
+#else
+ return mkdir(name, mode);
+#endif
+}
+ACCLIB_PUBLIC(int, acc_rmdir) (const char* name)
+{
+#if !defined(HAVE_RMDIR)
+ ACC_UNUSED(name);
+ return -1;
+#elif ((ACC_OS_DOS16 || ACC_OS_DOS32) && (ACC_CC_HIGHC || ACC_CC_PACIFICC))
+ return rmdir((char *) name);
+#else
+ return rmdir(name);
+#endif
+}
+#if defined(acc_int32e_t)
+ACCLIB_PUBLIC(acc_int32e_t, acc_muldiv32s) (acc_int32e_t a, acc_int32e_t b, acc_int32e_t x)
+{
+ acc_int32e_t r = 0;
+ if __acc_likely(x != 0)
+ {
+#if defined(acc_int64l_t)
+ r = (acc_int32e_t) (((acc_int64l_t) a * b) / x);
+#else
+ ACC_UNUSED(a); ACC_UNUSED(b);
+#endif
+ }
+ return r;
+}
+ACCLIB_PUBLIC(acc_uint32e_t, acc_muldiv32u) (acc_uint32e_t a, acc_uint32e_t b, acc_uint32e_t x)
+{
+ acc_uint32e_t r = 0;
+ if __acc_likely(x != 0)
+ {
+#if defined(acc_int64l_t)
+ r = (acc_uint32e_t) (((acc_uint64l_t) a * b) / x);
+#else
+ ACC_UNUSED(a); ACC_UNUSED(b);
+#endif
+ }
+ return r;
+}
+#endif
+#if 0
+ACCLIB_PUBLIC_NOINLINE(int, acc_syscall_clock_gettime) (int c)
+{
+}
+#endif
+#if (ACC_OS_WIN16)
+ACC_EXTERN_C void __far __pascal DebugBreak(void);
+#endif
+ACCLIB_PUBLIC_NOINLINE(void, acc_debug_break) (void)
+{
+#if (ACC_OS_WIN16)
+ DebugBreak();
+#elif (ACC_ARCH_I086)
+#elif (ACC_OS_WIN64) && (ACC_HAVE_WINDOWS_H)
+ DebugBreak();
+#elif defined(ACC_CFG_NO_INLINE_ASM) && (ACC_OS_WIN32) && (ACC_HAVE_WINDOWS_H)
+ DebugBreak();
+#elif (ACC_ARCH_AMD64 || ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)
+ __asm__ __volatile__("int $3\n" : : : __ACC_ASM_CLOBBER);
+#elif (ACC_ARCH_I386) && (ACC_ASM_SYNTAX_MSC)
+ __asm { int 3 }
+#elif (ACC_OS_WIN32) && (ACC_HAVE_WINDOWS_H)
+ DebugBreak();
+#else
+ * (volatile int *) 0x1 = -1;
+#endif
+}
+ACCLIB_PUBLIC_NOINLINE(void, acc_debug_nop) (void)
+{
+}
+ACCLIB_PUBLIC_NOINLINE(int, acc_debug_align_check_query) (void)
+{
+#if (ACC_ARCH_AMD64 || ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)
+ size_t r;
+ __asm__ __volatile__("pushf\n pop %0\n" : "=a" (r) : : __ACC_ASM_CLOBBER);
+ return (int)(r >> 18) & 1;
+#elif (ACC_ARCH_I386) && (ACC_ASM_SYNTAX_MSC)
+ unsigned long r;
+ __asm {
+ pushf
+ pop eax
+ mov r,eax
+ }
+ return (int)(r >> 18) & 1;
+#else
+ return -1;
+#endif
+}
+ACCLIB_PUBLIC_NOINLINE(int, acc_debug_align_check_enable) (int v)
+{
+ int r;
+#if (ACC_ARCH_AMD64) && (ACC_ASM_SYNTAX_GNUC)
+ if (v) {
+ __asm__ __volatile__("pushf\n orl $262144,(%%rsp)\n popf\n" : : : __ACC_ASM_CLOBBER);
+ } else {
+ __asm__ __volatile__("pushf\n andl $-262145,(%%rsp)\n popf\n" : : : __ACC_ASM_CLOBBER);
+ }
+ r = 0;
+#elif (ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)
+ if (v) {
+ __asm__ __volatile__("pushf\n orl $262144,(%%esp)\n popf\n" : : : __ACC_ASM_CLOBBER);
+ } else {
+ __asm__ __volatile__("pushf\n andl $-262145,(%%esp)\n popf\n" : : : __ACC_ASM_CLOBBER);
+ }
+ r = 0;
+#elif (ACC_ARCH_I386) && (ACC_ASM_SYNTAX_MSC)
+ if (v) { __asm {
+ pushf
+ or dword ptr [esp],262144
+ popf
+ }} else { __asm {
+ pushf
+ and dword ptr [esp],-262145
+ popf
+ }}
+ r = 0;
+#else
+ r = -1;
+#endif
+ ACC_UNUSED(v); return r;
+}
+ACCLIB_PUBLIC_NOINLINE(unsigned, acc_debug_running_on_qemu) (void)
+{
+ unsigned r = 0;
+#if (ACC_OS_POSIX_LINUX || ACC_OS_WIN32 || ACC_OS_WIN64)
+ const char* p;
+ p = acc_getenv("ACC_ENV_RUNNING_ON_QEMU");
+ if (p) {
+ if (p[0] == 0) r = 0;
+ else if ((p[0] >= '0' && p[0] <= '9') && p[1] == 0) r = p[0] - '0';
+ else r = 1;
+ }
+#endif
+ return r;
+}
+ACCLIB_PUBLIC_NOINLINE(unsigned, acc_debug_running_on_valgrind) (void)
+{
+#if (ACC_ARCH_AMD64 || ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)
+ volatile unsigned long args[5] = { 0x1001, 0, 0, 0, 0 };
+ unsigned long r = 0;
+ __asm__ __volatile__(".byte 0xc1,0xc0,0x1d,0xc1,0xc0,0x03,0xc1,0xc8,0x1b,0xc1,0xc8,0x05,0xc1,0xc0,0x0d,0xc1,0xc0,0x13\n" : "=d" (r) : "a" (&args[0]), "d" (r) : __ACC_ASM_CLOBBER);
+ return (unsigned) r;
+#else
+ return 0;
+#endif
+}
+#if (ACC_OS_WIN32 && ACC_CC_PELLESC && (__POCC__ >= 290))
+# pragma warn(pop)
+#endif
+#endif
+#if defined(ACC_WANT_ACCLIB_WILDARGV)
+# undef ACC_WANT_ACCLIB_WILDARGV
+#define __ACCLIB_WILDARGV_CH_INCLUDED 1
+#if !defined(ACCLIB_PUBLIC)
+# define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f)
+#endif
+#if (ACC_OS_DOS16 || ACC_OS216 || ACC_OS_WIN16)
+#if 0 && (ACC_CC_MSC)
+ACC_EXTERN_C int __acc_cdecl __setargv(void);
+ACC_EXTERN_C int __acc_cdecl _setargv(void);
+ACC_EXTERN_C int __acc_cdecl _setargv(void) { return __setargv(); }
+#endif
+#endif
+#if (ACC_OS_WIN32 || ACC_OS_WIN64)
+#if (ACC_CC_INTELC || ACC_CC_MSC)
+ACC_EXTERN_C int __acc_cdecl __setargv(void);
+ACC_EXTERN_C int __acc_cdecl _setargv(void);
+ACC_EXTERN_C int __acc_cdecl _setargv(void) { return __setargv(); }
+#endif
+#endif
+#if (ACC_OS_EMX)
+#define __ACCLIB_HAVE_ACC_WILDARGV 1
+ACCLIB_PUBLIC(void, acc_wildargv) (int* argc, char*** argv)
+{
+ if (argc && argv) {
+ _response(argc, argv);
+ _wildcard(argc, argv);
+ }
+}
+#endif
+#if (ACC_OS_CONSOLE_PSP) && defined(__PSPSDK_DEBUG__)
+#define __ACCLIB_HAVE_ACC_WILDARGV 1
+ACC_EXTERN_C int acc_psp_init_module(int*, char***, int);
+ACCLIB_PUBLIC(void, acc_wildargv) (int* argc, char*** argv)
+{
+ acc_psp_init_module(argc, argv, -1);
+}
+#endif
+#if !defined(__ACCLIB_HAVE_ACC_WILDARGV)
+#define __ACCLIB_HAVE_ACC_WILDARGV 1
+ACCLIB_PUBLIC(void, acc_wildargv) (int* argc, char*** argv)
+{
+#if 1 && (ACC_ARCH_I086PM)
+ if (ACC_MM_AHSHIFT != 3) { exit(1); }
+#elif 1 && (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__)
+ __binmode(1);
+ if (isatty(1)) __set_binmode(stdout, 0);
+ if (isatty(2)) __set_binmode(stderr, 0);
+#endif
+ ACC_UNUSED(argc); ACC_UNUSED(argv);
+}
+#endif
+#endif
+
+/* vim:set ts=4 et: */
diff --git a/lzo/src/stats1a.h b/lzo/src/stats1a.h
new file mode 100644
index 00000000..5116f80b
--- /dev/null
+++ b/lzo/src/stats1a.h
@@ -0,0 +1,137 @@
+/* stats1a.h -- statistics for the the LZO1A algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the LZO package and is subject
+ to change.
+ */
+
+
+#ifndef __LZO_STATS1A_H
+#define __LZO_STATS1A_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+/***********************************************************************
+// collect statistical information when compressing
+// used for finetuning, view with a debugger
+************************************************************************/
+
+#if defined(LZO_COLLECT_STATS)
+# define LZO_STATS(expr) expr
+#else
+# define LZO_STATS(expr) ((void) 0)
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+typedef struct {
+
+/* configuration */
+ unsigned rbits;
+ unsigned clevel;
+
+/* internal configuration */
+ unsigned dbits;
+ unsigned lbits;
+
+/* constants */
+ unsigned min_match_short;
+ unsigned max_match_short;
+ unsigned min_match_long;
+ unsigned max_match_long;
+ unsigned min_offset;
+ unsigned max_offset;
+ unsigned r0min;
+ unsigned r0fast;
+ unsigned r0max;
+
+/* counts */
+ long short_matches;
+ long long_matches;
+ long r1_matches;
+ long lit_runs;
+ long lit_runs_after_long_match;
+ long r0short_runs;
+ long r0fast_runs;
+ long r0long_runs;
+
+/* */
+ long lit_run[RSIZE];
+ long lit_run_after_long_match[RSIZE];
+ long short_match[MAX_MATCH_SHORT + 1];
+ long long_match[MAX_MATCH_LONG + 1];
+ long marker[256];
+
+/* these could prove useful for further optimizations */
+ long short_match_offset_osize[MAX_MATCH_SHORT + 1];
+ long short_match_offset_256[MAX_MATCH_SHORT + 1];
+ long short_match_offset_1024[MAX_MATCH_SHORT + 1];
+ long matches_out_of_range;
+ long matches_out_of_range_2;
+ long matches_out_of_range_4;
+ long match_out_of_range[MAX_MATCH_SHORT + 1];
+
+/* */
+ long in_len;
+ long out_len;
+}
+lzo1a_stats_t;
+
+extern lzo1a_stats_t *lzo1a_stats;
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+/*
+vi:ts=4:et
+*/
diff --git a/lzo/src/stats1b.h b/lzo/src/stats1b.h
new file mode 100644
index 00000000..b24f71ed
--- /dev/null
+++ b/lzo/src/stats1b.h
@@ -0,0 +1,142 @@
+/* stats1b.h -- statistics for the the LZO library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the library and is subject
+ to change.
+ */
+
+
+#ifndef __LZO_STATS1B_H
+#define __LZO_STATS1B_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+// Collect statistical information when compressing.
+// Useful for finetuning the compression algorithm.
+// Examine the symbol 'lzo1b_stats' with a debugger.
+************************************************************************/
+
+#if defined(LZO_COLLECT_STATS)
+# define LZO_STATS(expr) expr
+#else
+# define LZO_STATS(expr) ((void) 0)
+#endif
+
+
+#if defined(LZO_COLLECT_STATS)
+
+typedef struct
+{
+/* algorithm configuration */
+ unsigned r_bits;
+ unsigned m3o_bits;
+ unsigned dd_bits;
+ unsigned clevel;
+
+/* internal configuration */
+ unsigned d_bits;
+ long min_lookahead;
+ long max_lookbehind;
+ const char *compress_id;
+
+/* counts */
+ long lit_runs;
+ long r0short_runs;
+ long r0fast_runs;
+ long r0long_runs;
+ long m1_matches;
+ long m2_matches;
+ long m3_matches;
+ long m4_matches;
+ long r1_matches;
+
+/* */
+ long lit_run[R0MIN];
+ long m2_match[M2_MAX_LEN + 1];
+ long m3_match[M3_MAX_LEN + 1];
+#if (M3O_BITS < 8)
+ long lit_runs_after_m3_match;
+ long lit_run_after_m3_match[LZO_SIZE(8-M3O_BITS)];
+#endif
+
+/* */
+ long matches;
+ long match_bytes;
+ long literals;
+ long literal_overhead;
+ long literal_bytes;
+ double literal_overhead_percent;
+
+/* */
+ long unused_dict_entries;
+ double unused_dict_entries_percent;
+
+/* */
+ long in_len;
+ long out_len;
+}
+lzo1b_stats_t;
+
+
+void _lzo1b_stats_init(lzo1b_stats_t *lzo_stats);
+void _lzo1b_stats_calc(lzo1b_stats_t *lzo_stats);
+
+extern lzo1b_stats_t * const lzo1b_stats;
+
+#define lzo_stats_t lzo1b_stats_t
+#define lzo_stats lzo1b_stats
+
+#endif
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+/*
+vi:ts=4:et
+*/
diff --git a/lzo/src/stats1c.h b/lzo/src/stats1c.h
new file mode 100644
index 00000000..8d261e78
--- /dev/null
+++ b/lzo/src/stats1c.h
@@ -0,0 +1,61 @@
+/* stats1c.h -- statistics for the the LZO library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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; either version 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the library and is subject
+ to change.
+ */
+
+
+#ifndef __LZO_STATS1C_H
+#define __LZO_STATS1C_H
+
+#define lzo1b_stats_t lzo1c_stats_t
+#define lzo1b_stats lzo1c_stats
+#define _lzo1b_stats_init _lzo1c_stats_init
+#define _lzo1b_stats_calc _lzo1c_stats_calc
+
+#include "stats1b.h"
+
+#endif /* already included */
+
+/*
+vi:ts=4:et
+*/
diff --git a/mtools/syslinux.c b/mtools/syslinux.c
index 3d55616d..aca24c92 100644
--- a/mtools/syslinux.c
+++ b/mtools/syslinux.c
@@ -125,7 +125,7 @@ int libfat_xpread(intptr_t pp, void *buf, size_t secsize,
int main(int argc, char *argv[])
{
- static unsigned char sectbuf[512];
+ static unsigned char sectbuf[SECTOR_SIZE];
int dev_fd;
struct stat st;
int status;
@@ -135,10 +135,13 @@ int main(int argc, char *argv[])
int mtc_fd;
FILE *mtc, *mtp;
struct libfat_filesystem *fs;
- libfat_sector_t s, *secp, sectors[65]; /* 65 is maximum possible */
+ libfat_sector_t s, *secp;
+ libfat_sector_t *sectors;
int32_t ldlinux_cluster;
int nsectors;
const char *errmsg;
+ int ldlinux_sectors, patch_sectors;
+ int i;
int force = 0; /* -f (force) option */
int stupid = 0; /* -s (stupid) option */
@@ -200,7 +203,7 @@ int main(int argc, char *argv[])
exit(1);
}
- xpread(dev_fd, sectbuf, 512, filesystem_offset);
+ xpread(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset);
/*
* Check to see that what we got was indeed an MS-DOS boot sector/superblock
@@ -248,12 +251,14 @@ int main(int argc, char *argv[])
/*
* Now, use libfat to create a block map
*/
+ ldlinux_sectors = (syslinux_ldlinux_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
+ sectors = calloc(ldlinux_sectors, sizeof *sectors);
fs = libfat_open(libfat_xpread, dev_fd);
ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL);
secp = sectors;
nsectors = 0;
s = libfat_clustertosector(fs, ldlinux_cluster);
- while (s && nsectors < 65) {
+ while (s && nsectors < ldlinux_sectors) {
*secp++ = s;
nsectors++;
s = libfat_nextsector(fs, s);
@@ -261,11 +266,14 @@ int main(int argc, char *argv[])
libfat_close(fs);
/* Patch ldlinux.sys and the boot sector */
- syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ i = syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ patch_sectors = (i + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
- /* Write the now-patched first sector of ldlinux.sys */
- xpwrite(dev_fd, syslinux_ldlinux, 512,
- filesystem_offset + ((off_t) sectors[0] << 9));
+ /* Write the now-patched first sectors of ldlinux.sys */
+ for (i = 0; i < patch_sectors; i++) {
+ xpwrite(dev_fd, syslinux_ldlinux + i * SECTOR_SIZE, SECTOR_SIZE,
+ filesystem_offset + ((off_t) sectors[i] << SECTOR_SHIFT));
+ }
/* Move ldlinux.sys to the desired location */
if (subdir) {
@@ -338,13 +346,13 @@ int main(int argc, char *argv[])
*/
/* Read the superblock again since it might have changed while mounted */
- xpread(dev_fd, sectbuf, 512, filesystem_offset);
+ xpread(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset);
/* Copy the syslinux code into the boot sector */
syslinux_make_bootsect(sectbuf);
/* Write new boot sector */
- xpwrite(dev_fd, sectbuf, 512, filesystem_offset);
+ xpwrite(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset);
close(dev_fd);
sync();
diff --git a/version b/version
index 5487373a..5be9d7ed 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-3.85 2010
+4.00 2010
diff --git a/win32/syslinux.c b/win32/syslinux.c
index 3e73952f..d8c6c82b 100644
--- a/win32/syslinux.c
+++ b/win32/syslinux.c
@@ -36,7 +36,6 @@ void error(char *msg);
#include <winioctl.h>
-#define SECTOR_SIZE 512
#define PART_TABLE 0x1be
#define PART_SIZE 0x10
#define PART_COUNT 4
@@ -244,14 +243,16 @@ int main(int argc, char *argv[])
DWORD drives;
UINT drive_type;
- static unsigned char sectbuf[512];
+ static unsigned char sectbuf[SECTOR_SIZE];
char **argp, *opt;
static char drive_name[] = "\\\\.\\?:";
static char drive_root[] = "?:\\";
static char ldlinux_name[] = "?:\\ldlinux.sys";
const char *errmsg;
struct libfat_filesystem *fs;
- libfat_sector_t s, *secp, sectors[65]; /* 65 is maximum possible */
+ libfat_sector_t s, *secp;
+ libfat_sector_t *sectors;
+ int ldlinux_sectors;
uint32_t ldlinux_cluster;
int nsectors;
const char *bootsecfile = NULL;
@@ -360,11 +361,11 @@ int main(int argc, char *argv[])
/*
* Make sure we can read the boot sector
*/
- if (!ReadFile(d_handle, sectbuf, 512, &bytes_read, NULL)) {
+ if (!ReadFile(d_handle, sectbuf, SECTOR_SIZE, &bytes_read, NULL)) {
error("Reading boot sector");
exit(1);
}
- if (bytes_read != 512) {
+ if (bytes_read != SECTOR_SIZE) {
fprintf(stderr, "Could not read the whole boot sector\n");
exit(1);
}
@@ -415,12 +416,14 @@ int main(int argc, char *argv[])
}
/* Map the file (is there a better way to do this?) */
+ ldlinux_sectors = (syslinux_ldlinux_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
+ sectors = calloc(ldlinux_sectors, sizeof *sectors);
fs = libfat_open(libfat_readfile, (intptr_t) d_handle);
ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL);
secp = sectors;
nsectors = 0;
s = libfat_clustertosector(fs, ldlinux_cluster);
- while (s && nsectors < 65) {
+ while (s && nsectors < ldlinux_sectors) {
*secp++ = s;
nsectors++;
s = libfat_nextsector(fs, s);
@@ -520,17 +523,17 @@ int main(int argc, char *argv[])
error("Unable to create bootsector file");
exit(1);
}
- if (!WriteFile(f_handle, sectbuf, 512, &bytes_written, NULL)) {
+ if (!WriteFile(f_handle, sectbuf, SECTOR_SIZE, &bytes_written, NULL)) {
error("Could not write boot sector file");
exit(1);
}
CloseHandle(f_handle);
} else {
SetFilePointer(d_handle, 0, NULL, FILE_BEGIN);
- WriteFile(d_handle, sectbuf, 512, &bytes_written, NULL);
+ WriteFile(d_handle, sectbuf, SECTOR_SIZE, &bytes_written, NULL);
}
- if (bytes_written != 512) {
+ if (bytes_written != SECTOR_SIZE) {
fprintf(stderr, "Could not write the whole boot sector\n");
exit(1);
}