Imported Upstream version 23.1 upstream/23.1
authorJoachim Wiedorn <ad_debian@joonet.de>
Wed, 10 Nov 2010 15:54:07 +0000 (16:54 +0100)
committerJoachim Wiedorn <ad_debian@joonet.de>
Wed, 10 Nov 2010 15:54:07 +0000 (16:54 +0100)
139 files changed:
CHANGELOG [new file with mode: 0644]
CHANGELOG_old [new file with mode: 0644]
COPYING [new file with mode: 0644]
Makefile [new file with mode: 0644]
NEWS [new file with mode: 0644]
QuickInst [new file with mode: 0755]
README [new file with mode: 0644]
TODO [new file with mode: 0644]
TOOLS [new file with mode: 0644]
checkit [new file with mode: 0755]
diagnose/GPLicence [new file with mode: 0644]
diagnose/LGPLicence [new file with mode: 0644]
diagnose/Makefile [new file with mode: 0644]
diagnose/README [new file with mode: 0644]
diagnose/README.diagnostic [new file with mode: 0644]
diagnose/bios.c [new file with mode: 0644]
diagnose/cprintf.c [new file with mode: 0644]
diagnose/sector.S [new file with mode: 0644]
diagnose/test4.c [new file with mode: 0644]
diagnose/test5.c [new file with mode: 0644]
doc/Makefile [new file with mode: 0644]
doc/README [new file with mode: 0644]
doc/bootloader.fig [new file with mode: 0644]
doc/bootloader.tex [new file with mode: 0644]
doc/fullpage.sty [new file with mode: 0644]
doc/image.fig [new file with mode: 0644]
doc/image.tex [new file with mode: 0644]
doc/map.fig [new file with mode: 0644]
doc/map.tex [new file with mode: 0644]
doc/other.fig [new file with mode: 0644]
doc/other.tex [new file with mode: 0644]
doc/parameter.fig [new file with mode: 0644]
doc/parameter.tex [new file with mode: 0644]
doc/rlatex [new file with mode: 0755]
doc/t2a.pl [new file with mode: 0644]
doc/tech.tex [new file with mode: 0644]
doc/user.tex [new file with mode: 0644]
dos/Makefile [new file with mode: 0644]
dos/README [new file with mode: 0644]
hooks/Makefile [new file with mode: 0644]
hooks/initramfs/post-update.d/runlilo [new file with mode: 0644]
hooks/kernel/postinst.d/zz-runlilo [new file with mode: 0644]
hooks/kernel/postrm.d/zz-runlilo [new file with mode: 0644]
images/Makefile [new file with mode: 0644]
images/README [new file with mode: 0644]
images/coffee_256c.dat [new file with mode: 0644]
images/coffee_256c.uu [new file with mode: 0644]
images/debian-de_16c.dat [new file with mode: 0644]
images/debian-de_16c.uu [new file with mode: 0644]
images/debian_16c.dat [new file with mode: 0644]
images/debian_16c.uu [new file with mode: 0644]
images/debianlilo_16c.dat [new file with mode: 0644]
images/debianlilo_16c.uu [new file with mode: 0644]
images/inside_16c.dat [new file with mode: 0644]
images/inside_16c.uu [new file with mode: 0644]
images/onlyblue_16c.dat [new file with mode: 0644]
images/onlyblue_16c.uu [new file with mode: 0644]
images/tuxlogo_16c.dat [new file with mode: 0644]
images/tuxlogo_16c.uu [new file with mode: 0644]
keytab-lilo.pl [new file with mode: 0755]
lilo.lsm [new file with mode: 0644]
make.vars [new file with mode: 0644]
man/Makefile [new file with mode: 0644]
man/keytab-lilo.8 [new file with mode: 0644]
man/lilo.8 [new file with mode: 0644]
man/lilo.conf.5 [new file with mode: 0644]
man/mkrescue.8 [new file with mode: 0644]
mkrescue [new file with mode: 0755]
readme/INCOMPAT [new file with mode: 0644]
readme/README [new file with mode: 0644]
readme/README.bitmaps [new file with mode: 0644]
readme/README.common.problems [new file with mode: 0644]
readme/README.disk [new file with mode: 0644]
readme/README.nokeyboard [new file with mode: 0644]
readme/README.pseudo [new file with mode: 0644]
readme/README.raid1 [new file with mode: 0644]
readme/README.volumeID [new file with mode: 0644]
sample/Makefile [new file with mode: 0644]
sample/lilo.example.conf [new file with mode: 0644]
sample/lilo.old-raid.conf [new file with mode: 0644]
sample/lilo.old-special.conf [new file with mode: 0644]
src/Makefile [new file with mode: 0644]
src/bdata.h [new file with mode: 0644]
src/biosdata.S [new file with mode: 0644]
src/bitmap.S [new file with mode: 0644]
src/bitmap.h [new file with mode: 0644]
src/boot.c [new file with mode: 0644]
src/boot.h [new file with mode: 0644]
src/bootsect.S [new file with mode: 0644]
src/bsect.c [new file with mode: 0644]
src/bsect.h [new file with mode: 0644]
src/cfg.c [new file with mode: 0644]
src/cfg.h [new file with mode: 0644]
src/chain.S [new file with mode: 0644]
src/common.c [new file with mode: 0644]
src/common.h [new file with mode: 0644]
src/config.h [new file with mode: 0644]
src/crt.S [new file with mode: 0644]
src/device.c [new file with mode: 0644]
src/device.h [new file with mode: 0644]
src/disk.S [new file with mode: 0644]
src/display4.S [new file with mode: 0644]
src/dparam.S [new file with mode: 0644]
src/dump.S [new file with mode: 0644]
src/edit.c [new file with mode: 0644]
src/edit.h [new file with mode: 0644]
src/first.S [new file with mode: 0644]
src/geometry.c [new file with mode: 0644]
src/geometry.h [new file with mode: 0644]
src/graph.S [new file with mode: 0644]
src/identify.c [new file with mode: 0644]
src/identify.h [new file with mode: 0644]
src/lilo.c [new file with mode: 0644]
src/lilo.h [new file with mode: 0644]
src/loader.h [new file with mode: 0644]
src/map.c [new file with mode: 0644]
src/map.h [new file with mode: 0644]
src/mapper.S [new file with mode: 0644]
src/mbr.S [new file with mode: 0644]
src/md-int.h [new file with mode: 0644]
src/menu.S [new file with mode: 0644]
src/partition.c [new file with mode: 0644]
src/partition.h [new file with mode: 0644]
src/probe.c [new file with mode: 0644]
src/probe.h [new file with mode: 0644]
src/pseudo.S [new file with mode: 0644]
src/raid.c [new file with mode: 0644]
src/raid.h [new file with mode: 0644]
src/read.S [new file with mode: 0644]
src/second.S [new file with mode: 0644]
src/shs2.c [new file with mode: 0644]
src/shs2.h [new file with mode: 0644]
src/shs3.S [new file with mode: 0644]
src/strlen.S [new file with mode: 0644]
src/temp.c [new file with mode: 0644]
src/temp.h [new file with mode: 0644]
src/version.h [new file with mode: 0644]
src/vesainfo.h [new file with mode: 0644]
src/volume.S [new file with mode: 0644]

diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644 (file)
index 0000000..8f780a5
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,292 @@
+Changes for version 23.1 (04-Nov-2010) - Joachim Wiedorn
+
+  Documentations
+  --------------
+    - 'make clean' delete all created documentation files.
+    - many small typos in manpages.
+    - Remove obsolete ifpdf definition.
+
+  Sources
+  -------
+    - Optimize and update menue header line.  (src/crt.S)
+    - Fix some typos in sources.  (src/bsect.c, src/raid.c)
+    - LVM volume as root device.  (src/bsect.c)
+    - Remove patch for inaccessible disks (src/geometry.c)
+        and add remarks in README file.
+    - Better computing size of uncompressed kernel. (src/boot.c)
+    - Working on degraded RAID device.      (src/raid.c)
+        (thanks to Christian Schöninger)
+    - Use for MD RAID newer 1.0 specification. (src/geometry.c)
+        (thanks to Robert de Bath)             (src/raid.c)
+
+  General
+  -------
+    - Use better 'checkit' for newer gcc.  (checkit)
+    - Remove very old scripts.      (mkbdist,mksdist,QuickInst)
+    - Create new makefile-based script QuickInst.
+    - Create new hook scripts for kernel and initramfs.
+    - Add new target 'uninstall' for src, man, hooks.
+    - Recreate and add background images as uuencoded files and
+        move images + config files into new 'image' directory.
+    - Add new file TOOLS listing needed tools / packages.
+    - Remove all unneeded stuff with old /boot/boot-* files.
+    - Add new example file for lilo.conf for newer lilo.
+
+
+Changes for version 23.0 (28-June-2010) - Joachim Wiedorn
+
+  Documentations
+  --------------
+    - Move very old file INCOMPAT into readme/.
+    - Update file COPYING with copyrights and license.
+    - Update copyrights in some file headers.
+    - Add new files README, TODO, NEWS.
+    - Fix for some typos in manpages.
+    - Update some old files in readme/ and docs/.
+    - Move to creating pdf instead of ps in /docs.
+    - Add found old manpage man/keytab-lilo.pl.
+    - Update additional informations  (lilo.lsm, sample/README).
+    - Set static manpage path to /usr/share/man (make.vars).
+    - Update of the program command logging header.
+
+  Sources
+  -------
+    - Fix error messages.           (script checkit)
+    - Allow spaces in boot menu.    (bsect.c)
+    - Workaround for buggy Bios.    (probe.c)
+    - Check for user root.          (script mkrescue)
+    - Use better temporary fifo's   (script mkrescue)
+    - Check for needed floppy space (script mkrescue)
+    - devmapper should use major/minor.  (geometry.c)
+    - Bios workarounds.             (second.S)
+    - Suppress error message if device does not exist. (geometry.c)
+    - Change 'map' to 'kmap'.       (keytab-lilo.pl)
+    - Add warnings for inaccessible disk (device.c, geometry.c)
+    - Modify script mkrescue for use of spaces in files.
+    - Speedup for geometry          (geometry.c)
+    - Add 'define' for lvm partition (lilo.h, partition.c)
+    - Don't scan '.udev' directory  (device.c)
+    - Use default size 'hdsize'     (script mkrescue)
+    - Move macro 'S' into 'SA' (crt.S, lilo.c, lilo.h, probe.c, second.S)
+    - Update min. versions of bcc and gcc.  (script checkit)
+    - Add new option 'small-memory' (cfg.c)
+    - Differentiate small-memory/large-memory (bsect.c, boot.c)
+    - Optimize standard logging     (bsect.c)
+    - Update install paths and names for some binaries. (src/Makefile)
+    - Move the environment variable ROOT to DESTDIR.    (src/Makefile)
+    - Deactivate very old scripts   (mkbdist, mksdist, QuickInst)
+
+  General
+  -------
+    - Remove link 'COPYRIGHT' to file COPYING.
+    - Move alle README files into new directory 'readme'.
+    - Move all source code files into new directory 'src'.
+    - Split file CHANGES into CHANGELOG and CHANGELOG_old.
+    - Better check for tool 'mkfs.msdos', for with you must be root.
+
+    - Create new main Makefile.
+    - Move target 'spotless' to 'distclean' in concerned files.
+    - Move src/Makefile header into extra file make.vars.
+    - Remove old comments in src/Makefile.
+    - Displacement from src/Makefile into new man/Makefile.
+    - Displacement from src/Makefile into dos/Makefile.
+    - Delete displaced make commands in src/Makefile.
+    - Update script paths in src/Makefile.
+    - Update path to bdata.h in files of directoy diagnose.
+
+    - Move more variables into make.vars.
+    - Move target 'test' into main Makefile.
+    - Update paths in dos/Makefile.
+    - Displace floppy targets in main and src Makefiles.
+    - Update paths to files in directory diagnose.
+    - Better checks in diagnose/Makefile.
+    - Remove old program 'activate'.
+
+    - Use correct path for script mkrescue.
+    - Target 'all' now without run of 'diagnostic' and 'dosexe'.
+    - Optimize warnings while running target 'diagnostic'.
+    - Renumber the pseudo targets.
+    - Move commands for target 'diagnostic' into src/Makefile.
+
+
+Changes from version 22.7.3 to 22.8 (16-Feb-2007) John Coffman
+
+  Boot Installer
+  --------------
+    - Move configuration information (-X) to a separate procedure.  
+        (lilo.c)
+    - Fix type decl problem in LVM _IOR/RW macros.  (geometry.c)
+    - Add  DEV_DISK_DIR  and edit source to use it.  (config.h, 
+        device.c, geometry.c)
+    - Change handling of 'device-mapper' depending upon DEVMAPPER 
+        option.   (device.c, geometry.c)
+    - Modify 'scan_dir' to stay out of hidden directories.  (device.c)
+    - Add 'nodevcache' option to configuration file.  (cfg.c, lilo.c)
+    - Add sync() before boot sector write to compensate for 2.6 kernel
+        bug in partition buffering code.  (bsect.c)
+    - Allow 'root="UUID=xyz"' syntax.  (bsect.c)
+
+  Boot Loader
+  -----------
+    - Add compilation switch 'NOVGA' to the Makefile.
+
+
+Changes from version 22.7.2 to 22.7.3 (11-Aug-2006) John Coffman
+
+  Boot Installer
+  --------------
+    - Make with changed compile-time options does not affect source
+      checksums. (Makefile)
+    - Remove device 253 from max_partitions[].  (device.c, 22.7.2.1)
+    - Install device-mapper patches. (geometry.c, Makefile)
+    - Correct setting of the VIRTUAL & NOKBD flags.  (bsect.c)
+
+
+Changes from version 22.7.1 to 22.7.2 (05-Jul-2006) John Coffman
+
+  Boot Installer
+  --------------
+    - Add "noraid" keyword to suppress automatic marking of members
+      of a full-disk RAID array as "inaccessible".
+    - Add '-H' switch to override abort on RAID1 install to a failed
+      array.  (raid.c, lilo.c, common.c, common.h)
+    - Add check for DM_RAID (aka ATA_RAID); warn about manual marking
+      of disk drives as "inaccessible".  (device.c)
+    - Add 'geo_query_dev' support for 31-partition devices.  (geometry.c)
+    - Add "Warning:'s" counter.  (common.c, common.h, & *.c)
+    - Disable 'nowarn' when verbose >= 3.   (lilo.c)
+    - Davide BIOS bug (sectors [1..63] -> [1..64])  (probe.c)
+    - Add keywords 'nokbdefault' & 'nokbdisable' on compilation switch
+      based upon input from Alberto Mardegan <mardy@users.sourceforge.net>.
+      (cfg.c, bsect.c, lilo.h)
+    - Add second stage flags:  VIRTUAL & NOKBD whenever any 'virtual' or
+      'nokeyboard' keyword is used.  (lilo.h, bsect.c)
+
+  Boot Loader
+  -----------
+    - Davide BIOS bug (sectors [1..63] -> [1..64])  (first.S, read.S)
+    - Implement 'nokbdefault' & 'nokbdisable' (second.S)
+    - Add cli/sti to keyboard detection code  (second.S)
+    - Fix timeout bug if 'ONE_SHOT' compile option is omitted.  (second.S)
+    - Add marker (space) between initrd/kernel loading dots.  (second.S)
+    - Observe second stage flags: VIRTUAL & NOKBD.  Do not touch hardware
+      unless corresponding flag is set.  (second.S)
+    - Allow DEBUG_NEW version to compile READONLY.  (read.S)
+    - Increase kernel command line to 512 bytes.  (bsect.c, probe.c, lilo.h,
+      second.S)
+
+  Utilities
+  ---------
+    - Add check of FS register to Diagnostic 2 (diagnose/test4.c)
+    - Change 'master' determination for --iso; log config file
+      with --debug  (mkrescue)
+    - Create 'checkit' script to check for versions of gcc, as86,
+      ld86, and bcc.  (checkit)
+    - Davide BIOS bug (sectors [1..63] -> [1..64])  (disk.S, test4.c)
+
+
+Changes from version 22.7 to 22.7.1 (17-Sep-2005) John Coffman
+
+  Boot Installer
+  --------------
+    - Add check that "vmdefault" image does exist.  (bsect.c, lilo.c)
+    - Use 512/4095 major devices (up from 255).  (geometry.c, device.c,
+      geometry.h)
+
+  Boot Loader
+  -----------
+    - Fix "vmdefault=" bug in MENU and BITMAP interfaces. (second.S)
+    - Allow any keyboard strike (not just Shift) to escape from
+      command line, or to display boot menu.  (second.S)
+
+  Utilities
+  ---------
+    - Apply security patch for temp files to  mkrescue & QuickInst
+    - Compensate for missing <msdos/stat.h> in BCC
+
+
+Changes from version 22.6.1 to 22.7 (12-Apr-2005) John Coffman
+
+  Boot Installer
+  --------------
+    - Fix reporting of NULL stored default boot command.  (lilo.c)
+    - Allow "unsafe" on partitions specified by "other=".  (boot.c)
+    - Handle RAID-1 arrays with a failed disk.  (raid.c, geometry.c)
+
+  Boot Loader
+  -----------
+    - Rearrange code in first.S to shorten by 3 (to 0x1B2).  (first.S)
+    - Fix "lock" bug on default image.  (second.S)
+    - Descriptor selection (find_image) based on partial command
+      line.  (second.S, crt.S, bitmap.S)
+    - Improve "unattended":  no selection on partial command; CR can't
+      stop timeout.  (second.S)
+
+  Utilities
+  ---------
+    - New DOS utility:  LILO.COM implements -q -R -V (-C -m) switches.
+
+
+Changes from version 22.6 to 22.6.1 (17-Nov-2004) John Coffman
+
+  Boot Installer
+  --------------
+    - Check command line options for CL_LENGTH max (256).  (bsect.c)
+    - Get '-I' switch to recognize 'addappend='.  (identify.c)
+    - Add 'R' flag to '-I' switch to get root.  (identify.c)
+
+  Boot Loader
+  -----------
+    - Enable read-ahead on EDD drives that support the function.
+      Now a Makefile switch (READAHEAD)  (volume.S, Makefile)
+    - Support BUG_SI_EBDA bugfix for SI controllers that don't properly
+      allocate the EBDA that they use.  (Makefile, second.S, chain.S)
+    - Correct El-Torito CD emulation termination to use HD/FD device
+      code.  (second.S)
+
+  Utilities
+  ---------
+    - Update diagnostic 2.2.4 to 2.3; check EDD fn 4Eh subfunctions.
+      (diagnose/test4.c)
+    - Update 'mkrescue' (2.5) to get root filesystem from /etc/fstab.
+    - Update 'mkrescue --iso --size HD' to create a bootable El Torito
+      format using hard disk emulation.  (mkrescue 3.0)
+    - Add --image option to mkrescue.  (mkrescue 3.0)
+
+
+Changes from version 22.5.9 to 22.6 (01-Sep-2004) John Coffman
+
+  Boot Installer
+  --------------
+    - Correct check of "append=" substring coincidence.  (bsect.c/
+      check_options)
+    - add keyword "unattended" to alter timeout operation. (cfg.c,
+      bsect.c, second.S)
+    - allow 'timeout' & 'delay' to be specified in 's', 'm', or 'h'.
+      (lilo.c, common.c)
+    - change #include <asm/unistd.h> to <linux/unistd.h> (partition.c)
+    - alter 'new_serial' to seed from time & /dev/urandom  (device.c)
+    - address compilation issues with 2.6 kernels (2.6.6) and glibc
+      versions 2.0 and 2.1++ (2.3.3).  (config.h, partition.h,
+      partition.c)
+    - fix "long" -> "int" for compilation on 64-bit systems. (*.h, *.c)
+    - use "mkloader" so compilation does not depend on NASM. (temp.c)
+    - add new block devices:  emd, sata, scsi9-15. (lilo.h, geometry.c)
+    - Check 'other=' for a file that is really an image.  (boot.c)
+    - Allow 'root = "LABEL=label"' in config file.  (bsect.c)
+    - Allow -P parameter to contain '='.  (lilo.c)
+    - Add 'addappend=' specification of local kernel parameters
+      to 'image=' sections.  (bsect.c, cfg.c)
+    - Automatically treat disks beyond the 16th as INACCESSIBLE.
+      (device.c)
+
+  Boot Loader
+  -----------
+    - Modify first-stage loader for BIOS that clobbers BX. (first.S)
+
+  Utilities
+  ---------
+    - Update diagnostic 2.2.4 to to check int 13, fn 8, for register
+      clobbers.  (diagnose/test4.c)
+    - Change regular expression in 'keytab-lilo.pl' (Debian patch)
+
diff --git a/CHANGELOG_old b/CHANGELOG_old
new file mode 100644 (file)
index 0000000..a129b4c
--- /dev/null
@@ -0,0 +1,1668 @@
+Changes from version 22.5.8 to 22.5.9 (08-Apr-2004) John Coffman
+
+  Boot Installer
+  --------------
+    - Alter NT check for invalid volume ID -- no change on single disk
+      systems.  (device.c)
+    - Make 'prompt' a word.  (common.h, first.S)
+    - Add 'bmp-retain' local & global option.  (bsect.c, cfg.c, second.S)
+      Retains bitmap after booting.
+    - Add Makefile option "lilo-static:"  -- must specifically make it.
+    - Fix setting of "map==boot" for RAID installs.  (bsect.c, raid.c)
+
+  Boot Loader
+  -----------
+    - Skip duplicate VolumeIDs in second stage, in case a disk has been
+      added to the system.  (volume.S)
+
+  Utilities
+  ---------
+    - Update QuickInst to reflect absence of 'activate', using lilo -A
+
+
+Changes from version 22.5.7.2 to 22.5.8 (09-Oct-2003) John Coffman
+
+  Boot Installer
+  --------------
+    - Add "max-partitions=" to the "disk=" section to enable support
+      for user-defined devices.   (geometry.c)
+    - Color range extended to 0-255 (from 0-15) for 256 color bitmaps.
+      (bsect.c, edit.c, common.c)
+    - Make VolumeID scan skip INACCESSIBLE drives (device.c)
+    - Automatically skip ATARAID drives with "ataraid" keyword and
+      mark all underlying drives INACCESSIBLE.  (device.c, cfg.c)
+
+    - REMOVE the above ATARAID stuff.
+
+    - Add "static-BIOS-codes" to bypass VolumeID booting.  (bsect.c,
+       device.c)
+    - Add test for setup > MAX_SETUPSECS.    (boot.c)
+    - Open '/proc/partitions' before 'chroot' with -r flag  (lilo.c)
+
+
+Changes from version 22.5.7 to 22.5.7.2 (20-Aug-2003) John Coffman
+
+  Boot Installer
+  --------------
+    - Eliminate f2.S; combine all into first.S.   (loader.S, Makefile)
+    - Fix -I to work with "change automatic".   (partition.c)
+    - Correct warning message condition in pf_hard_disk_scan.  (device.c)
+    - Modify warning message condition: unknown video adapter.  (bsect.c)
+    - Fix problem with "devfs" in 'cache_scsi'.  (device.c)  (22.5.7.1)
+
+
+Changes from version 22.5.6 to 22.5.7 (10-Aug-2003) John Coffman
+
+  Boot Installer
+  --------------
+    - Int 13h, fn 08h/48h differing geometries depends on LBA32 & 
+      verbosity level   (probe.c)
+    - Bug fix for geo_query_dev uninited geo->device  (geometry.c)
+    - preload_dev_cache is now sensitive to devfs present  (device.c)
+    - Alter lookup_dev to not check for existence of device; just
+      return the name if it is in the cache   (device.c)
+    - PROBE_VERSION==6 always report fn 48h parameters; print nicer
+      output for "-T geom" switch   (probe.c)
+    - Account for drive mapping in volume.S so that multiple chain's
+      will operate correctly on RAID1 installations.
+    - Experiment:  sort MAJOR_HPT370 (114) as (2)   (device.c)
+    - Raid install:  suppress warning if 'mbr-only' or 'mbr'   (raid.c)
+
+  Boot Loader
+  -----------
+    - First stage uses rewritten I/O routine & processed disk addresses
+      (6 bytes); now enough space for VE call; no FF   (f2.S, first.S)
+
+  Utilities
+  ---------
+    - Update 'mkrescue' to dynamically determine the loopback device;
+      makes it devfs-friendly   (mkrescue 2.3)
+    - mbr & mbr2 will pass lilo parameters through to destination  (mbr.S)
+
+
+Changes from version 22.5.5 to 22.5.6 (29-Jun-2003) John Coffman
+
+  Boot Loader
+  -----------
+    - Strict limit on PARMLINE to 255 characters + NUL  (second.S)
+    - Move 'volume.S' and 'shs3.S' variables to .bss  after PARMLINE.
+    - Use DL from first stage on raid reads  (volume.S)
+
+  Boot Installer
+  --------------
+    - Generate 'version' information to track changes  (common.c)
+    - Eliminate raid assigning all devices to the same device code (raid.c)
+
+
+Changes from version 22.5.4 to 22.5.5 (16-Jun-2003) John Coffman
+
+  Boot Installer
+  --------------
+    - Improve fetch() to avoid redundant reads on failure  (probe.c)
+    - Add 'el-torito-bootable-cd' switch   (cfg.c, bsect.c)
+    - Check for initial ramdisks too big to fit between 4M-15M (boot.c)
+    - Enhanced '-A' (activate) works for extended part. (partition.c)
+    - Separate PT check & S/N check in 'bios_dev'   (probe.c)
+    - Allow chain loader > 3 sectors  (boot.c)
+    - Attach -P switch to universal cfg_set()      (lilo.c)
+    - Check for active partition (part_verify, partition.c)
+
+  Boot Loader
+  -----------
+    - Terminate floppy emulation on boot from El Torito CD  (second.S)
+    - Complain of possible kernel overwrite if initrd loads below 4M
+
+  Chain Loader
+  ------------
+    - Merges second stage drive map with any existing drive map; then
+      merges its own drive map (chain.S)
+
+  Utilities
+  ---------
+    - Enhanced 'mbr.S' will look at extended partitions
+    - Compensate in 'mbr.S' for AHA-2940 bios bug (ES:BX needed)
+
+
+Changes from version 22.5.3.1 to 22.5.4 (25-May-2003) John Coffman
+
+  Boot Installer
+  --------------
+    - Remove all references to FLAG_RAID_NOWRITE (lilo.h, raid.c)
+    - Add flags to -I option:  D (default), a (append)  (identify.c)
+    - Add warning about initial RAM disks too big for 15M  (boot.c)
+    - Check specifically for switches which take no args  (lilo.c)
+    - Sorted assignment of BIOS device codes if no BIOS data (device.c)
+    - Fix serial number naming bug  (device.c)
+
+  Boot Loader
+  -----------
+    - Remove all references to FLAG_RAID_NOWRITE (second.S)
+    - Allow '-DSUSPEND=0xNN' to specify a primary partition, which, if
+      active, indicates a virtual boot; for DELL suspend option (second.S)
+
+  Utilities
+  ---------
+    - Get 'mkrescue' to use the -I 'D' and 'a' flags  (mkrescue)
+    - Add  --iso  option to 'mkrescue'  (mkrescue 2.0)
+
+
+Changes from version 22.5.3 to 22.5.3.1 (12-May-2003) John Coffman
+
+  Boot Installer
+  --------------
+    - Update to fix Segmentation fault in "lilo -T geom" (probe.c)
+
+
+Changes from version 22.5.2 to 22.5.3 (10-May-2003) John Coffman
+
+  Boot Installer
+  --------------
+    - Update smart_cache to account for DEVFS irregularities (device.c)
+    - Call smart_cache from lilo.c, not within preload_dev_cache (lilo.c)
+    - Add FLAG_BD_OKAY to suppress the writing to the map file if previous
+      BIOS data collection worked okay (bsect.c)
+
+  Utilities
+  ---------
+    - Update mkrescue to 1.3 to suppress spruious messages with 22.5.2
+      due to smart_cache scan of hard disks (mkrescue), and add --size
+      argument for making 1.2M floppy, instead of 1.44M floppy
+
+
+Changes from version 22.5.1 to 22.5.2 (01-May-2003) John Coffman
+
+  Boot Installer
+  --------------
+    - Compilation fix for lilo.c  (printf macro, again)
+    - Updates to handle reiser4.  (geometry.c)
+    - Smart device caching if "/proc/partitions" is present. (device.c)
+    - '-M' switch creates a backup file subject to '-s' & '-S' (partition.c)
+    - Fix "raid-extra-boot=" for devices outside of the raid set (bsect.c)
+
+  Boot Loader
+  -----------
+    - Fix calls to get number of hard disk devices (first.S & mbr.S)
+
+
+Changes from version 22.5 to 22.5.1 (28-Mar-2003) John Coffman
+
+  Boot Installer
+  --------------
+    - Put all backups and force-backups on the same footing.
+    - Allow only 1 backup file per major/minor device code, in case
+      a volume id is written, then the sector is backed up again.
+    - Fix bug in 'do_table' error reporting "Not a device". (probe.c)
+    - 'lilo -T video' will now check for Enable Screen Refresh bios bug.
+    - Added 'boot-as=' as global and other= option; 'master-boot' now
+      global option, too. (boot.c, chain.S)
+    - Add additional parameter to 'raid-extra-boot=mbr'; like 'mbr-only'
+      but writes boot record to RAID1 partition, too.
+    - Set 'bios-passes-dl=DL_GOOD' on '-x none' or '-x auto' with no
+      partitions other than primary.  Issue warning message. (raid.c)
+    - Fix problems when 'boot=' is omitted. (raid.c, bsect.c)
+
+  Boot Loader
+  -----------
+    - Protect DL against video BIOS clobbering it.
+    - Load second stage at 0880:0000, unconditionally. It will move
+      itself to where it wants to run. (first.S)
+    - Verify DL device code passed from BIOS into first stage. Verify
+      failure causes bypass of FLAG_MAP_ON_BOOT check. (first.S)
+    - Reconfigure headers of first & second stages for string compare
+      for verification that second stage is loaded. (first.S)
+    - Update bios data check to collect boot DX & enable screen refresh
+      registers for check for state of BIOS (PROBE_VERSION 5).
+    - Allow "mem=<size>#<start>" and "mem=<size>$<start>" to pass to
+      2.5 kernels. (second.S)
+
+  Utilities
+  ---------
+    - Incorporate protection for DX in master boot record. (mbr.S)
+
+
+Changes from version 22.4.1 to 22.5 (04-Mar-2003) John Coffman
+
+  Boot Installer
+  --------------
+    - Add timestamp to boot sector for this unique LILO installation;
+      use the map creation time (bsect.c).
+    - Allow 0 as a parameter to the '-A' switch, to indicate deactivation
+      of all partitions (partition.c).
+    - Meaning of '-w' flag expanded:  '-w+' turns on warnings, even if
+      configuration file says 'nowarn'.
+    - Create 32-bit volume labels on all hard disks.
+    - Mark boot sector if map file is on same disk as boot sector.
+    - Backup options -s & -S may specify directory or filename template,
+      in addition to existing filename.
+    - Update bitmap editor to handle 256 color bitmap files.
+    - For 'other=', add the flag 'master-boot' to indicate an OS which
+      is required to boot from drive 0x80.
+    - Check boot loader selected against video adapter; issue warnings.
+
+  Boot Loader
+  -----------
+    - Move two disk addresses (dflcmd, message/bitmap) to keytable area
+      to diminish size of First Stage loader.
+    - Fix RAID bug on writes to arrays with 3 or more active disks.
+    - Boot by volume label, not BIOS device code.
+    - If map file marked on same vol as boot sector, use boot BIOS device
+      code to access secondary loader in map file (UNIFY compile option
+      is mandatory).
+    - RAID1 uses volume labels for lock, fallback, cmdline rewrites.
+    - Update 'bmp' loader to allow 640x480x256 color bitmaps on adapters
+      which support VESA mode 0x101.
+    - Fix the nagging Passed Boot Command line *Interrupt* bug.
+    - Extend timestamp to the second stage loader (mapstamp).
+
+  Chain Loader
+  ------------
+    - Chain loader will pass command line to relocated boot record.
+    - Add support to dynamically add drive swapping for 'master-boot'
+      flag:  swap boot BIOS device code with 0x80 (or 0).
+
+  Utilities
+  ---------
+    - Master Boot Record (mbr.S) exits to BIOS on error (int 0x18).
+
+
+Changes from version 22.4 to 22.4.1 (27-Jan-2003) John Coffman
+
+  Boot Loader
+  -----------
+    - Fix compilation typos
+
+
+Changes from version 22.3.4 to 22.4 (24-Jan-2003) John Coffman
+
+  Boot Installer
+  --------------
+    - Add keywords vmdefault, vmdisable, vmwarn.
+    - Print volume serial numbers with "-T geom".
+
+  Boot Loader
+  -----------
+    - Add support for keywords vmdefault, vmdisable, vmwarn.
+    - First stage loader exits to BIOS on error (int 0x18).
+
+  Chain Loader
+  ------------
+    - Change pause requiring user input to delay (in debugging mode).
+
+
+Changes from version 22.3.3 to 22.3.4 (01-Nov-2002) John Coffman
+
+  Boot Installer
+  --------------
+    - Remove exit() call from unbootable() (bsect.c) so die() displays
+      error message.
+    - Fix boot errors when boot record relocation occurs in a RAID1
+      installation.  (bsect.c)
+    - Fix Failsafe partition table overwrite check.  (bsect.c)
+
+  Boot Loader
+  -----------
+    - Recognize command line "mem=<size>@<start>" for the 2.4 kernels.
+
+
+Changes from version 22.3.2 to 22.3.3 (30-Aug-2002) John Coffman
+
+  Boot Installer
+  --------------
+    - Suppress warning message about .shs file older than config file,
+      if '-p' is already specified.
+    - Change FLAG_SAVE to really be complement of FLAG_RAID_xxx.
+    - Add EVMS patches from Kevin Corry <corryk@us.ibm.com> 
+      Enterprise Volume Management Project <evms-devel@lists.sf.net>
+    - get UNSAFE to work on hard disks, too (geometry.c) with 
+      "disk=/dev/hdXX  bios=0x8X  inaccessible"
+    - allow BIOS_MAX_HEADS to be 256; 255 is the REAL max, but there
+      are some oddball BIOS's which allow 256
+
+
+Changes from version 22.3.1 to 22.3.2 (11-Jul-2002) John Coffman
+
+  Utilities
+  ---------
+    - Fix bug in 'mbr.S' to correctly use 'lba32' on large disks
+
+
+Changes from version 22.3 to 22.3.1 (16-Jun-2002) John Coffman
+
+  Boot Installer
+  --------------
+    - Correct reporting of command line segment (probe.c).
+    - Correct check for Bitmap table image_menu_space exceeded.
+    - Output actual geometry when Kernel/BIOS differ, or int 13h, functions
+      08h/48h differ (probe.c).
+    - 'bios_dev' changes to cope with kernel 2.4.18 returning different
+      disk geometry than previous kernels.  Use int 13h/fn 8h disk
+      geometry, where possible (probe.c).
+    - Add "k" option to -I flag to support mkrescue 1.2.
+
+  Boot Loader
+  -----------
+    - Bug fix for FF in text in 'say:' routine (save/restore BX).
+
+  Utilities
+  ---------
+    - Create 'pseudo.b' -- a pseudo kernel header for loading arbitrary
+      binaries at 1000:0000.  See 'README.pseudo' for details.
+    - Change "make floppy" to create both 1.5.4 and 2.1.1 diagnostics.
+    - 'mkrescue' now handles keytable translations with --keymap (1.2).
+
+
+Changes from version 22.2 to 22.3 (19-May-2002) John Coffman
+
+  Utilities
+  ---------
+    - Update 'mkrescue' to work with 22.3
+    - Integate bitmap file header Editor with 'lilo -E'
+    - Upgrade boot diagnostic to check for memory area overlap in
+      int 15h, function E820h, bios call, and to check for 24-bit
+      moves to high memory, when a 32-bit address is used.
+
+  Boot Installer
+  --------------
+    - Try again to fix the CRC/SHS compilation problem for gcc 3.XX
+      in bsect.c
+    - Resolve links in verbose bootloader output from boot.c (patch
+      from R. Coker) + extend to RAM disk, message, & bitmap files.
+      Essentially superseded by BUILTIN option.
+    - Fix minor -I bug when change rules repeat in another 'other='
+    - Implement UNIFY (copy 2nd stage loader, bitmap, and/or message
+      file into the map file).
+    - Implement BUILTIN - first and second stage loaders, chain loaders,
+      and mbr loader is built into the /sbin/lilo executable.  No more
+      file incompatibilities.
+    - Fill in bitmap file Location, Color, and Timer parameters from
+      a header in the bitmap file; config file overrides; add utilities
+      on the -E switch to manipulate parameters in the BM file header.
+    - Pass size of 2nd stage loader to 1st stage; probe reflects proper
+      memory size.
+    - Fatal error if any of "lock", "nobd", "vga=", and "kbd=" are in an
+      append= or literal= in the config file.
+    - "optional" now will skip an image if the initrd is not present,
+      just as it will now skip if the kernel is not present.
+    - Eliminate 'start_page' from the image descriptor.
+    - Correct and beautify output from verify_partition in partition.c.
+    - Issue warning when BIOS geometry and kernel geometry differ.
+    - Add '-E' switch for handling bitmap file LILO headers.
+    - Interactive password input is no longer echoed.
+    - Add '-F' flag to override XFS, swap, NTFS partition checks.
+    - DOS paritions will cause boot loader relocation.
+    - Add '-B' flag to specify bitmap file on command line.
+    - Modify bsect.c(bsect_common) to use 'image' flag.
+    - Check for space/control-char in image name, label, alias.
+    - Implement 'large-memory' flag in the prompt variable.
+    - Report change rules (-q) without stopping on 0 offset in PT.
+
+  Chain Loader
+  ------------
+    - Now sensitive to command line in ES:DI; will pass it on if there
+      are args after the 'BOOT_IMAGE=xxxxx' prefix.
+    - Limit command line passing to boot sectors having the 'LILO' sig-
+      nature only.  (Will miss relocated boot sectors, however.)
+    - Fix 'revmap1' to save SI, so partition change rules are okay.
+
+  Boot Loader
+  -----------
+    - First stage now verifies signatures in second stage loader
+      and its index map.
+    - Fix bugs in bitmap display when there is a locked command line
+      and it is interrupted:  cmdline clobbered, descr selection,
+      and top line lowlite display.
+    - Bitmap display dynamically computes number of rows in selection
+      menu -- just like the menu interface.
+    - Memory allocation by 1st stage for the 2nd is now variable, rather
+      than fixed at the largest (boot-bmp.b).
+    - Issue "BIOS data check successful/bypassed" message.
+    - First stage loader begins with short jmp, and still allows relocation
+    - 'map_create' checks 'extra' on a RAID installation
+    - Load initrd AFTER the kernel: supports boot protocol 0203h and
+      "mem=" within an append=XXX. "mem=" on command line replaces "mem="
+      from any append=XXX.
+    - Load sequence:  kernel header, initrd (alt. map), kernel proper
+    - "vga=" on command line now allows any radix input; viz., 0xHHHH
+    - With no 'start_page', the high starting address is obtained from
+      the kernel header directly.
+    - Add INITRDLOW compilation switch, and add check for bios that mucks
+      with high byte of 386 address (int 15h, fn 87h).
+    - Only use 32-bit move address with 'large-memory' flag in prompt
+      variable, otherwise sitck with 24-bit address (<15M).
+    - Compensate for buggy BIOS in int 15h, fn E820h call to avoid
+      overlapping memory areas
+
+
+Changes from version 22.1 to 22.2 (05-Feb-2002) John Coffman
+
+  Boot Installer
+  --------------
+    - Fix bsect.c compilation problem (l.241) on newer GCC libraries
+    - Add "suppress-boot-time-BIOS-data" flag to config file
+    - Add LVM support patches, courtesy of Andreas Dilger:
+      <adilger@users.sourceforge.net>
+    - Make sure image descriptor is zeroed to start
+    - Fix 'lilo -p' segfault with password=explicit
+    - Fix 'lilo -q' to handle relocated boot sectors on floppies
+
+  Boot Loader
+  -----------
+    - Add a video mode set to mbr.S and first.S to accomodate Dell/
+      Windows XP disabled video on startup
+    - Add mt_flag to KEYTABLE menu area for automatic suppression
+      of bios data collection in case of failure
+    - Vary placement of initrd:  (memory <= 64M) ==> load below 15M,
+      whereas (memory > 64M) load just above 64M; use int 15h, fn's
+      E820 & E801 to determine memory size > 64M
+    - DELL_DIRTY_HACK enables video with int 10h, fn=12h, subfn=36h
+    - Shorten read.S by making 1 mov AX into mov AH
+    - Fix first.S pread to use index buffer at 0x7E00, not 0x0200
+    - Limit BIOS data collection for HD to # drives returned by
+      fn 8, dev 80h (in DL)
+
+  Chain Loader
+  ------------
+    - Fix bug in CHANGE / MAP-DRIVE interaction when change is to
+      other than boot drive
+
+  Utilities
+  ---------
+    - Add a video mode set to disk.S to accomodate Dell/Windows XP
+      disabled video on startup
+    - Add pauses between stages of output to make reading easier
+    - Add "$(OBJS): mylilo.h" dependency to Makefile
+    - Add 'diagnose' directory with version 2 of the disk diagnostic
+    - Add LGPLicence for Robert de Bath's code
+    - Limit diagnostic 2.0 probe for HD to # drives returned by int 13h
+      fn 8, dev 80h (in DL)
+
+
+Changes from version 22.0.2 to 22.1 (31-Oct-2001) John Coffman
+
+  Utilities
+  ---------
+    - Add version 1.0 of 'mkrescue'
+
+  Boot Installer
+  --------------
+    - Support 4 more SCSI controllers & IBM iSeries v.disk.
+    - Add M-Systems Disk-On-Chip devices 62(?) and 93
+    - Fix bug in 'part_verify' to correct partition mask.
+    - Passwords use SHS (FIPS PUB 180-1) 160-bit hash or 64-bit CRC-32
+    - RAID1 relocations now check for files within the boot Raid
+      partition.
+    - Correct operation of -I flag; add option "r" (now "i" & "r")
+    - Strengthen "part_verify" to disallow installing on secondary 
+      partitions (in addition to primary partitions) other than Linux
+      partitions
+
+  Boot Loader
+  -----------
+    - Allow variable number of Descriptor Sectors (DSECS=n)
+    - Load second-stage loader using single sector map segment; removes
+      size constraint on second-stage loader (15->~100 sectors).
+    - First-stage loader avoids BPB area -- doesn't clobber FAT16 --
+      unless DSECS>5.
+    - RAID1 sector address relocation performed only if flagged.
+
+
+Changes from version 22.0.1 to 22.0.2 (13-Oct-2001) John Coffman
+
+  Compilation
+  -----------
+    - Fix 'partition.c' to compile with 2.4.12 kernel headers
+    - Fix compilation bug to allow omission of -DBDATA from Makefile
+
+  DISK.COM utility
+  ----------------
+    - Add BIOS data collection VERBOSE diagnostic.
+
+
+Changes from version 22.0 to 22.0.1 (02-Oct-2001) John Coffman
+
+  Boot Installer
+  --------------
+    - Fixed password security hole to create 'lilo.conf.crc' with
+      mode 0600 (not 0644).
+
+
+Changes from version 21.7.5 to 22.0 (29-Aug-2001) John Coffman   [released 9/27]
+
+  Boot Installer
+  --------------
+    - Passwords are now hashed using a CRC-32 checksum.  Allows
+      for a full pass-PHRASE
+    - Using password="" (null string) will trigger interactive pass-
+      phrase input; such passphrases persist until -p switch is used
+      to force re-creation of CRC save file:  'lilo.conf.crc'
+    - Password options expanded.  Now there are 'mandatory', 're-
+      stricted', and 'bypass', strongest to weakest.  'mandatory'
+      remains the default.
+    - The config file parser now handles garbage input with a good
+      diagnostic, rather than an unexpected parse.
+    - RAID installations now create a single map file, install the
+      boot record on the RAID partition, install auxiliary boot
+      records only on MBRs if needed, except BIOS device 0x80.  Back-
+      ward compatibility is possible with new config-file and command
+      line options (raid-extra-boot= or '-x' switch).  Even with
+      stored boot command lines ('-R', lock, fallback), RAID set
+      coherency can be maintained.
+    - Add the '-A' switch to activate a partition.  Replaces activate.c.
+    - Add the '-M' switch to allow restoration of a Master Boot Record.
+    - Allow 'loader=' in the global section of config file.
+    - Add 'bitmap=' to specify a 640x480x16 bitmap file to be used as 
+      a splash screen upon booting.  RGB (uncompressed) and RLE (com-
+      pressed) Windows/OS2 bitmaps are supported.
+    - Add 'bmp-table=', 'bmp-colors=', and 'bmp-timer=' to support posi-
+      tioning and color specification for bitmap screens.
+    - Modify 'bmp-X' input routines to allow pixel addressing (in addition
+      to the character addressing).
+    - Use bios data from boot-time to help identify bios device codes.
+    - Add 'geometric' and the '-g' switch to specify sector/head/cylinder
+      disk addressing.
+    - Add LBA32 compile switch, and make it the default:  'lba32' is now
+      assumed, unless 'geometric' or 'linear' is specified.
+    - Raid scans 'raid_disks + spare_disks'
+    - Add HPT370 controller (major device 114)
+
+  Boot Loader
+  -----------
+    - os2_d.b may now be obsolete with extensive checking added
+      to chain.b to see if it should fill in bytes 24 & 25 in the
+      boot record
+    - boot-bmp.b generated to display bitmapped boot screen
+    - read.S updated to allow #heads==256 (bios not IBM-compliant)
+    - disk.S updated to 1.4 to account for #heads==256 (hosed bios)
+    - second.S updated to allow for EBDA > 64k
+
+
+Changes from version 21.7.4 to 21.7.5 (26-Apr-2001) John Coffman
+
+  Boot Installer
+  --------------
+    - Correct DAC960 partition mask -- again.
+
+  Chain Loader
+  ------------
+    - Reverse map device code if "map-drive" is in effect
+
+
+Changes from version 21.7.3 to 21.7.4 (10-Apr-2001) John Coffman
+
+  Boot Installer
+  --------------
+    - Issue warning when CHANGE AUTOMATIC is to be inserted.
+    - Correct DAC960 partition mask.
+
+  Boot Loader
+  -----------
+    - Fix password timeout security hole which allowed booting with-
+      out entering a password.
+
+
+Changes from version 21.7.1 to 21.7.2 (20-Mar-2001) John Coffman
+  (issued as "patch-21.7.1-to-21.7.2-diff.txt)
+
+  Boot Installer
+  --------------
+    - Add several devices supported by the 2.4.2 kernel only
+    - Bugfix for -I switch
+
+
+Changes from version 21.7 to 21.7-1 (08-Mar-2001) John Coffman
+  (issued as "patch-21.7-to-21.7.1-diff.txt")
+
+  Boot Installer
+  --------------
+    - Makefile is simplified to remove 'filesize.c'
+    - New devices are added (Compaq), and ide5 is made to work
+    - A new diagnostic is added for when the '-r' switch is used
+    - Raid update for devfs support
+
+
+Changes from version 21.6.1 to 21.7 (24-Feb-2001) John Coffman
+
+  Boot Installer
+  --------------
+    - Added code to 'do_cr_auto' to account for 'devfs' specifications
+    - Corrected code for -u/-U switches to make argument optional
+    - Fix for I2O major block device (SCSI raid)
+    - Expanded 'default=' error message
+    - Fix to strip <cr> from 'lilo.conf' to accomodate DOS text files
+    - Changed & expanded setup of serial line parameter specifier
+
+  Boot Loader
+  -----------
+    - Accepts new serial line parameter and supports higher baud rates
+
+
+Changes from version 21.6 to 21.6.1 (16-Dec-2000) John Coffman
+
+  Boot Installer
+  --------------
+    - Bug fix to make '-r' and '-s' swithes work correctly.
+    - Bug fix for automatic change-rules to work correctly.
+    - Re-order some includes for glibc-2.2 compilation.
+
+  Boot Loader
+  -----------
+    - Added compile time option 'HP_TTRC' to add a 150ms delay
+      to boot process to accomodate HP TTRC card.
+
+
+Changes from version 21.5.1 to 21.6 (01-Oct-2000) John Coffman
+
+  License
+  -------
+    - Corrects license wording problems by issuing all code and
+      documentation under a BSD license.
+
+  Boot Installer
+  --------------
+    - Supports booting from Reiser FileSystem 3.6.18 and later,
+      without the need to mount 'notail'.
+    - Added -T diagnostic capability, which includes real-mode
+      bios tests.  "make floppy" is still supported for patho-
+      logical installations.
+    - Updated default change-rules.  Added "change/automatic"
+      facility, as well as automatic generation of change-rules in
+      the abscence of "change" keyword.
+
+  Boot Loader
+  -----------
+    - Dynamically determines where second-stage loader is loaded,
+      thus allowing maximum room for kernel setup.S real-mode
+      code.
+    - First-stage loader no longer relocates itself.
+
+
+Changes from version 21.5 to 21.5.1 (24-Aug-2000) John Coffman
+
+  Boot Loader
+  -----------
+    - Perl script keytab-lilo.pl updated for problem static decls
+    - Corrected assertion of DTR/RTS at all serial bitrates
+
+  Boot Installer
+  --------------
+    - Fix for RAID segmentation fault if boot= is not specified
+    - Fix for RAID to allow enough characters in expanded names
+
+
+Changes from version 21.4.4 to 21.5 (17-Jul-2000) John Coffman
+
+  Boot Installer
+  --------------
+    - Now recognizes the option `table=<letter>' to support
+      booting OS/2 or DOS-like systems from a secondary partition.
+    - Supports `menu-title=<string>' and `menu-scheme=<color-spec>'
+      to all customization of the Boot Loader menu-driven user
+      interface (see Boot Loader, below).
+    - Updated man-pages (lilo and lilo.conf) for all new features
+      (and even some older ones).
+
+  Boot Loader
+  -----------
+    - Completely new menu-driven user interface.  Preserves backward
+      compatibility with command line interface on console or serial
+      terminal.  Menu title may be specified in 'lilo.conf'.  Menu
+      color scheme may be customized on VGA, but is fixed on MDA.
+    - Passes cmdline to kernel in Setup.S, not bootsect.S, if kernel
+      header is 0x0202 or greater.  Uses old bootsect.S method for
+      0x0201 kernels and earlier
+    - Uses significatly less memory, none above 0x099200, to account
+      for large Extended BIOS Data Areas of up to 27K.  Allows for
+      considerable growth in kernel's Setup.S code.
+    - Default compile is without LARGE_EBDA, so zImages up to 512k
+      may be loaded.
+
+  Chain Loader
+  ------------
+    - The OS/2 chain loader, `os2_d.b', now correctly sets parameters
+      for booting OS/2 from an extended partition.  This requires use
+      of a new form of the `table=' option.
+
+  DISK.COM utility
+  ----------------
+    - The .asciz pseudo-op has been removed so that the utility will
+      assemble under earlier versions of the as86 assembler.
+    - Now reports EBDA information.
+
+
+Changes from version 21.4.3 to 21.4.4 (10-Jun-2000) John Coffman
+
+  Map Installer
+  -------------
+    - Added a minor RAID patch from Richard Bollinger: 'lilo-21_4_3.also'
+      http://www.elliott-turbo.com/lilo/
+    - Expand COMPACT/LINEAR warning message to include COMPACT/LBA32
+
+  Boot Loader
+  -----------
+    - LARGE_EBDA option now loads second stage loader at 800:0000, and
+      position of command line is changed; makes room for 512K kernels
+      to be loaded low.
+    - Minor optimizations when ES is reloaded (PUSH/POP) vs (mov thru AX)
+    - Serial line now turns on DTR/RTS at initialization
+    - Minor bugfix in numeric conversion (k/K-suffix)
+
+  DISK.COM utility
+  ----------------
+    - The disk.com utility no longer requires 'nasm' to assemble.  The
+      source code now makes the diagnostic floppy with "make floppy".
+
+
+Changes from version 21.4.2 to 21.4.3 (06-May-2000) John Coffman
+
+  Map Installer
+  -------------
+    - Added RAID patches from 'lilo.raid1.also' from Richard Bollinger
+      http://www.elliott-turbo.com/lilo/lilo.raid1.also
+
+
+Changes from version 21-3 to 21.4.2 (12-Apr-2000) -- John Coffman
+
+  Boot loader
+  -----------
+    - bugfix in 'read.S' that disabled the combination 'linear' with
+      'compact' ( '-l' and '-c' together).
+    - fixed numeric convesions; kernel accepts octal, decimal, and hex, so 
+      octal is now recognized by the boot loader.
+    - bugfix patch where ES segment prefix was ommitted (RHL 'second.patch')
+    - bugfix for compilation with 'LARGE_EBDA' option which caused command
+      line passed to the kernel to be truncated at 78 characters
+    
+  Map installer
+  -------------
+    - RHL6.2 loopdev updates added
+      
+      
+Changes from version 21 to 21-3 (24-FEB-2000)  -- John Coffman 
+-----------------------------                  <johninsd@san.rr.com>
+
+  Boot loader
+  -----------
+  
+    - will boot from disks up to 2048Gb in size, as long as the BIOS allows
+      the Enhanced BIOS calls for 32-bit sector addressing using packet calls.
+    - checks if BIOS supports packet calls (int 0x13, AH=0x42), and uses
+      these calls if 'lba32' was specified.  Otherwise, it uses
+      the C:H:S addressing scheme of the original IBM-PC BIOS.
+    - the disk read routine is separated into its own source file, "read.S",
+      which is included in the first-stage, and second-stage loader codes.
+      The first stage loader uses a very stripped down read routine, since it
+      only deals in single sector transfers.
+    - if BIOS does not support 32-bit packet calls, and the cylinder address
+      overflows when the 32-bit address is converted to C:H:S, then a "9f"
+      error code is issued.
+
+  Map installer
+  -------------
+  
+    - added the '-L' command line switch and 'lba32' configuration file 
+      global option.  
+    - map compaction of 'lba32' addresses is supported with the existing
+      '-c' switch (or 'compact' configuration file global option).
+    - floppy disks now will always fall back to C:H:S addressing.
+    - changed the -v option to now accept a single digit to set the verbosity
+      level; e.g., 'lilo -v 5 ...' replaces 'lilo -v -v -v -v -v ...'
+      for maximum diagnostic output.
+    - LILO version information is moved to the file 'version.h', and VERSION
+      is now deleted.  This allows for tracking of VERSION_MAJOR (=21) and
+      VERSION_MINOR (=3) for this and future code paths.
+      
+  BIOS tester
+  -----------
+  
+    - Inspired by 'dparam.com', a much more extensive BIOS test program is
+      included with this version.  Called 'disk.com', it was developed 
+      under DOS, and requires 'nasm' to be assembled.
+    - DISK.COM will probe the BIOS for disks supported by the BIOS, and report
+      on their CHS geometry.  If EDD is supported, the EDD geometry is also
+      reported.  If disks with cylinder numbers of 1024 or above are detected,
+      it will issue a recommendation to use LILO with the 'lba32' option.
+    - Creation of the bootable floppy image version of this utility is in-
+      complete at this time.
+      
+    
+Changes from version 20 to 21 (5-DEC-1998)
+-----------------------------
+
+  Boot loader
+  -----------
+
+    - cylinder calculation could overflow when using LINEAR (fix by Jonas
+      Aaberg and an anonymous contributor)
+    - first-stage loader code begins with the byte 0xFA (a CLI instruction).
+      This works around the "INACCESSIBLE_BOOT_DEVICE" blue screen bug of
+      Windows NT 4 (reported by too many people to mention)
+    - new build-time option LARGE_EBDA to load boot loader in the 0x8xxxx area
+      instead of the 0x9xxxx area (disabled by default; problem reported by
+      Josef Moellers)
+
+  Map installer
+  -------------
+
+    - new build-time option USE_TMPDIR to honor TMPDIR when creating temporary
+      devices (disabled by default)
+    - now only 0x1b6 bytes of the boot sector are overwritten, which preserves
+      the passwords DR DOS stores there (fixed by Roy Millar)
+    - -u and -U accidently implied -v
+    - "BIOS drive 0xNN may not be accessible" warning was printed in cases
+       where the drive code was never used (fixed by Andries Brouwer)
+    - change rule for DOS16_big incorrectly used DOS16_small_hidden when
+      hiding (fixed by Anthony Richardson)
+    - RESET in CHANGE-RULES did not remove default rules (fixed by Kurt
+      Garloff)
+    - added support for Mylex DAC960 PCI RAID controllers (by Leonard Zubkoff)
+    - added support for third to sixth IDE interface
+    - build-time option READONLY was not used properly
+    - fixed a few harmless compiler warnings
+
+  Documentation and installation
+  ------------------------------
+
+    - user's guide claimed that partitions are hidden by setting the highest
+      bit in the type (i.e. 0x80). The correct value is 0x10, which is also
+      what is used in the code.
+    - removed useless (and potentially harmful) DEFAULT_PATH from
+      keytab-lilo.pl (fixed by Andries Brouwer)
+    - consistency of build-time options is now checked before build starts
+    - QuickInst has now limited knowledge of multi-disk configurations
+    - doc/Makefile: added targets user.ps and tech.ps
+    - user's guide still claimed that kernels can't be larger than 512 kB
+      (reported by Jean-Albert Ferrez)
+    - weird description of the purpose of option BEEP (reported by Tom Toffoli)
+
+
+Changes from version 19 to 20 (20-JUN-1997)
+-----------------------------
+
+  Boot loader
+  -----------
+
+    - now supports 19200 bps and 38400 bps on the serial line (UNTESTED)
+    - when reaching the end of the command line buffer, input is ignored
+      instead of being treated like [Enter] (by Martin Mares)
+    - fixed numerous bugs in patching of heap end pointer in setup.S (by Martin
+      Mares)
+    - images can now optionally be launched with a single keystroke (no [Enter]
+      required)
+    - now supports non-US keyboard layouts
+
+  Map installer
+  -------------
+
+    - DISK sections may now also define non-disk devices, e.g. /dev/ram
+    - increased debug level for the "Caching device ..." message
+    - changed the chain loader format to allow sizes > 512 Bytes
+    - chain loader now supports arbitrary drive mappings (option MAP-DRIVE)
+    - chain loader now supports arbitrary partition table modifications (option
+      CHANGE)
+    - removed the configuration option REWRITE-TABLE
+    - removed the build-time options FIX_TABLE and HIDE_DOS
+    - added the global configuration option CHANGE-RULES plus sub-options
+      RESET, TYPE, NORMAL, and HIDDEN
+    - OTHER sections have new configuration option CHANGE plus sub-options
+      PARTITION, SET, ACTIVATE, and DEACTIVATE
+    - OTHER sections have new configuration option MAP-DRIVE with sub-option TO
+    - now only 0x1b8 bytes of the boot sector are overwritten, which preserves
+      some magic numbers NT stores there
+    - compiles with 2.1 kernels (asm/boot.h problem - reported by many people)
+    - should also compile under 0.93 or such again (required NORMAL_VGA etc.,
+      which didn't exist back then)
+    - lilo -q  now prints unknown VGA modes also in hex (by Martin Mares)
+    - option SINGLE-KEY to allow single-key activation
+    - -Wno-parentheses  is no longer needed
+    - didn't complain if image label was equal to alias
+    - removed some ancient dead code
+    - new option KEYTABLE to specify non-standard keyboard mappings
+    - PS/2 ESDI disk (/dev/eda and /dev/edb) support (by Andrew Kroll)
+    - geometry.c:last_dev now only probes for the first two IDE disks
+    - because chain.b is used for everything anyway, specifying the chain
+      loader when booting from a driver other than the first one is no longer
+      mandatory
+
+  Documentation and installation
+  ------------------------------
+
+    - changed all references to nic.funet.fi to ftp.funet.fi
+    - updated the user's guide and did some restructuring (many changes)
+    - QuickInst no longer puts ramdisk=0 into lilo.conf
+    - QuickInst now consistently checks for LILO >= version 15
+    - make clean  and  make spotless  now also remove dump.s and dump.b (by
+      Martin Mares)
+    - changed package names from lilo[.part].<version> to
+      lilo[-part]-<version> for compatibility with sunsite's archive
+      maintenance scripts
+    - new tool keytab-lilo.pl to generate LILO keyboard tables
+    - updated t2a.pl to a version compatible with Perl 5
+    - READONLY implicitly turns off REWRITE_TABLE
+
+
+Changes from version 18 to 19 (21-MAY-1996)
+-----------------------------
+
+  Boot loader
+  -----------
+
+    - new compile-time option to beep after displaying "LILO"
+
+  Map installer
+  -------------
+
+    - common.h broke compilation if CONFIG_BSD_DISKLABEL is enabled
+    - no longer tries to interpret dollar signs and such in comments
+    - check for too many images didn't work (patch by Andries Brouwer)
+
+  Documentation and installation
+  ------------------------------
+
+    - removed some "dead" targets in Makefile
+    - stopped using -N, because recent binutils link statically then
+    - INCOMPAT no longer promises that REWRITE_TABLE will be fixed in
+      version 19
+
+
+Changes from version 17 to 18 (16-MAY-1996)
+-----------------------------
+
+  Boot loader
+  -----------
+
+    - added ability to load data (e.g. kernels) at addresses >= 0x100000
+    - added support for loading an initial RAM disk
+    - any_*.b became too big when using REWRITE_TABLE
+    - included trimmed sector read function for first.S by Ted Ts'o
+    - now prints spaces before error codes
+    - temporarily removed support for REWRITE_TABLE
+    - added support for heap size indication to kernel setup.S
+    - added compile-time option XL_SECS for extra large disks
+
+  Map installer
+  -------------
+
+    - new option INITRD to load an initial RAM disk
+    - added support for "big" kernels (> 0.5 MB compressed), which are loaded
+      directly at 0x100000
+    - long quoted strings can now be distributed over several lines using
+      a backslash
+    - environment variables are accessible in lilo.conf with $name or ${name}
+    - now properly identifies attempts to map from NFS and such
+    - refuses to overwrite unsuitable partitions
+    - caches device names and numbers, thereby significantly reducing the
+      number of readdir and stat system calls (typically, the total number of
+      system call decreases by about 80%)
+    - temporarily removed support for REWRITE_TABLE
+    - geometry.c:exists now opens devices read-write in order to avoid
+      reading from CD-ROM devices (patch by Alain Knaff)
+    - added a warning if COMPACT is used with LINEAR
+
+  Documentation and installation
+  ------------------------------
+
+    - documentation, QuickInst, and on-line usage information no longer mention
+      the disktab file (a DISK section should be used instead)
+    - mkdist now uses the VERSION file
+    - distribution now includes .lsm file
+    - LILO is now compiled without -O2
+    - updated FTP references and rewrote them to conform to RFC1738
+
+
+Changes from version 16 to 17 (19-DEC-1995)
+-----------------------------
+
+  Boot loader
+  -----------
+
+    - changes for FALLBACK and new map section structure (see below)
+    - LCF_READONLY now disables the LOCK option (and FALLBACK too)
+    - added command-line option  kbd  to preload keyboard buffer
+    - write errors are now reported (Wxx)
+    - chain loaders now support changing the active partition (enabled with
+      REWRITE-TABLE)
+    - chain loader can also "un-hide" a DOS partition if its partition type
+      has been changed by OS/2 BM (build-time option FIX_TYPE)
+    - when enabling HIDE_DOS in addition to FIX_TYPE, DOS partitions (except
+      for the one being booted) are hidden, just like OS/2 BM does (build-time
+      option HIDE_DOS)
+
+  Map installer
+  -------------
+
+    - added FALLBACK option to change default command line before booting
+      the current image
+    - added REWRITE-TABLE option to patch partition table at boot time
+    - added REWRITE_TABLE build-time option to enable REWRITE-TABLE
+    - added DISK section flag INACCESSIBLE to mark disk as inaccessible for
+      the BIOS so that the map installer can refuse bad mappings
+    - options and fallback sectors are now at the beginning of map sections
+    - -q and -R were accidentially marked as optional in usage
+    - fixed incorrect partition check for  other = <non-root>
+
+  Documentation and installation
+  ------------------------------
+
+    - changed LILO version numbers to always be of the form <number> instead
+      of 0.<number>
+    - README now also contains the version number
+    - make install  now strips /sbin/lilo instead of trying to strip /sbin
+    - various bug fixes in QuickInst
+    - added file VERSION containing the current version number and new
+      make target  version  to rename ../lilo to ../lilo-<version>
+    - changed a footnote which yielded an asterisk at the end of a command
+      line in the ASCII README
+    - -q and -R were accidentally marked as optional in command-line
+      descriptions
+    - mentioned -D option in command line description
+    - new section "System overview" in the user's manual and several minor
+      additions
+    - a few minor corrections and addition of unusual error messages
+    - the last traces of "old-style" configuration have been removed
+
+
+Changes from version 15 to 16 (26-FEB-1995)
+-----------------------------
+
+  Boot loader
+  -----------
+
+    - added register dump boot sector (dump.S) for debugging
+    - chain loaders now clear BP. This might help in some cases where DOS
+      refused to boot.
+
+  Map installer
+  -------------
+
+    - really fixed -R this time
+    - now suggests to "use a DISK section" (instead of disktab) if HDIO_REQ
+      fails
+    - removed incorrect error message when using a disktab
+    - added check to detect CD-ROMs with major numbers of hard disks
+    - no longer complains about corrupt partition table if 3D address is
+      smaller than linear address and (3D) cylinder is 1023  (OS/2 does
+      is this way)
+    - LOADER is now required when booting an operating system from any device
+      than the first hard or floppy disk
+    - changed header protection macros from _xxx_H_ to xxx_H
+    - added (untested) support for 2nd IDE controller (major 22)
+
+  Documentation and installation
+  ------------------------------
+
+    - user.tex is now compatible with LaTeX 2e (\textfont0 problem)
+    - tech.tex now avoids \SetFigFont (LaTeX 2e again)
+    - /sbin/lilo is now optimized and stripped when installing
+    - ASCIIfied "Booting basics" section
+    - removed all references to the old directory structure
+    - added description of LOCK in config file
+    - updated FD TMC-1680 warning
+    - added reminder to re-run /sbin/lilo when modifying partition tables
+    - updated list of kernel options
+    - added detailed description of >2 disks and >1024 cylinders
+    - added description of putting /boot on a DOS partition
+    - reordered sections in "Installation and updates"
+    - updated tech.tex
+
+
+Changes from version 14 to 15 (23-OCT-1994)
+-----------------------------
+
+  General
+  -------
+
+    - upon popular demand, a copyright notice has been added
+
+  Boot loader
+  -----------
+
+    - now also drains the keyboard type-ahead buffer
+    - new command-line option "lock" to make the specified command line the
+      default for the following boots too
+    - default command line execution can now be interrupted in prompt mode too
+
+  Map installer
+  -------------
+
+    - fixed -R arguments handling bug
+    - fixed -P argument handling bug
+    - fixed yet another recursion problem with /dev/fd -> /proc/self/fd
+    - added option -D and configuration variable DEFAULT to specify the
+      default image without changing the oder of entries in /etc/lilo.conf
+    - added configuration variable LOCK to make the specified command line the
+      default for the following boots too
+    - added disk geometry configuration in the general configuration file.
+      /etc/disktab is now considered obsolete.
+    - added option -w and configuration variable NOWARN to disable some
+      warnings
+    - added warning when putting the boot sector on a non-boot disk
+    - added warning for possibly inaccessible devices (e.g. third disk)
+    - added warning for disks/partitions with more than 1024 cylinders
+    - added warnings for bad permissions of the configuration file
+    - fixed handling of floppies in geo_open_boot
+    - removed erroneous call to part_verify when booting other systems
+      from files
+    - added support for variable-size setup segments as supported by kernels
+      >= 1.1.43
+    - restructured verbosity levels
+    - allowed escaping of backslashes in quoted strings (/etc/lilo.conf)
+    - /sbin/lilo -q -v  now displays all settings
+
+  Documentation and installation
+  ------------------------------
+
+    - lots of things have been restructured
+    - many changes to describe the current Linux environment
+    - "new" directory structure is now the default
+    - README is now generated from user.tex by a Perl script
+    - lots of minor corrections and clarifications
+    - added a copyright notice and adapted several comments
+    - QuickInst: updated default kernel names
+    - QuickInst: now runs  /sbin/lilo -t  before trying to install
+    - doc/Makefile: removed extra "Label(s) may have changed" output
+    - disktab: changed header comment and added second example line
+    - /etc/disktab is no longer automatically created by  make install
+    - linking /etc/lilo/install -> /sbin/lilo is no longer suggested
+    - removed mkbindist. I don't think anybody used it anyway.
+
+
+Changes from version 13 to 14
+-----------------------------
+
+  Map installer
+  -------------
+
+    - added a few missing closedirs to device.c:scan_dir
+    - added detection of directory loops to device.c:scan_dir and
+      geometry.c:last_dev
+    - fixed handling of dangling links in /dev
+    - new option -u [ device ] to restore boot sector. Unsafe mode with -U
+    - fixed/improved usage message
+
+  Documentation and installation
+  ------------------------------
+
+    - QuickInst: did not write "other" sections to configuration file
+    - QuickInst.new: improved handling of disks without active partitions
+    - QuickInst.new now knows about /etc/disktab (relict from Shoelace,
+      still in some distributions)
+    - QuickInst.new now uses *_d.b chain loaders when configuring non-Linux
+      systems on the second disk
+
+
+Changes from version 12 to 13
+-----------------------------
+
+  General
+  -------
+
+    - BSS is no longer cleared by LILO, because the kernel itself does
+      that now.
+    - added support for the new directory structure. Makefile and QuickInst
+      come in .old and .new versions. See INCOMPAT for details.
+    - removed support for unstripped kernels. Therefore, mkck is no longer
+      part of the distribution.
+
+  Boot loader
+  -----------
+
+    - added missing  seg es  override to UI_MAGIC check at "input".
+
+  Map installer
+  -------------
+
+    - new options LITERAL and APPEND.
+    - the root setting is no longer being shown on -q -v
+    - the configuration file may now contain quoted strings in which spaces
+      and equal signs do not have to be escaped.
+
+  Documentation and installation
+  ------------------------------
+
+    - fixed bug in QuickInst that prevented correct renaming of the config
+      file when ROOT is set.
+    - added comment to disktab indicating that it is typically not needed.
+    - distributed files are now readable for group and other.
+    - mkdist is now included in the distribution.
+    - changed the name of kernels from "(traditional) boot image" to
+      "kernel image".
+    - changed the name of the string passed to the kernel from "command
+      line" to "parameter line".
+    - removed obsolescent terms "rootimage" and "bootimage".
+    - fixed documentation bug claiming only kernels can be protected by
+      passwords.
+    - fixed some additional minor documentation errors.
+
+
+Changes from version 11 to 12
+-----------------------------
+
+  Boot loader
+  ----------
+
+    - removed accidential swapping of A:/B: when swapping C:/D: from
+      the chain loader.
+    - added new chain loader any_b.b (swaps A:/B:)
+    - fixed incorrect handling of drive number resetting in swapping
+      versions of the chain loader.
+    - now generates diagnostics when failing to load the second stage
+      loader.
+    - new compile-time option NO1STDIAG to disable these diagnostics.
+
+  Map installer
+  -------------
+
+    - fixed stat/fstat when creating temporary devices.
+    - subdirectories of /dev are now recursively searched for disk devices
+      in addition to /dev
+    - devices are now counted by highest device number, not by name.
+    - some minor fixes.
+
+  Documentation and installation
+  ------------------------------
+
+    - QuickInst now warns if there is an obsolete LILO boot sector on
+      the MBR.
+    - QuickInst is now prepared to handle symbolic links hda -> sda
+    - other minor fixes to QuickInst.
+    - removed all references to compound unstripped kernels from the
+      user's guide.
+    - activate is now compiled as a stripped, statically linked, impure
+      executable.
+    - fixed a few minor omissions in the technical overview.
+
+
+Changes from version 10 to 11
+-----------------------------
+
+  Boot loader
+  -----------
+
+    - added on the fly patching of the BIOS disk parameter table to
+      fix the "Error 0x04" observed on some systems.
+
+  Map installer
+  -------------
+
+    - floppy devices are no longer opened at all when using the UNSAFE
+      option in OTHER.
+    - fixed partition table checking.
+    - new option -V to display the version number.
+    - INSTALL = /etc/lilo/boot.b  is now the default if INSTALL is
+      omitted.
+    - new compile-time configuration option NOINSTDEF to restore the old
+      semantics of INSTALL.
+
+  Documentation and installation
+  ------------------------------
+
+    - QuickInst no longer asks whether to change the active partition if
+      installing LILO as the MBR.
+    - QuickInst now suggests configuring other operating systems if
+      installing LILO as the MBR.
+    - added a version check to QuickInst.
+    - added de-installation instructions.
+    - fixed a few minor documentation bugs.
+    - added script mkbindist that generates a minimal binary distribution
+      of LILO.
+
+
+Changes from version 9 to 10
+----------------------------
+
+  Boot loader
+  -----------
+
+    - added support for read-only setting of root.
+    - new chain loader os2.b to load OS/2 from the second disk.
+    - new chain loader any_d.b to load BIOS-based operating systems
+      (e.g. PC/MS-DOS) from the second disk.
+
+  Map installer
+  -------------
+
+    - removed support for old-style configuration.
+    - removed the dump option -D
+    - removed support for not-compound unstripped kernels.
+    - limited partition checking to hard disks and primary partitions.
+    - -C now accepts - for standard input.
+    - -P now has sub-options "fix" and "ignore". New configuration
+      variable "ignore-table" coresponds to "-P ignore"
+    - added automatic backup of the partition table when fixing it.
+    - new configuration variables "readonly" and "read-write" to change
+      read-only mounting of root.
+    - made partition offset field in /etc/lilo/disktab optional.
+    - added tentative support for XT-type hard disks.
+    - improved some error messages.
+    - some minor fixes.
+
+  Documentation and installation
+  ------------------------------
+
+    - changed many "echo"s in QuickInst to "cat"s.
+    - suggesting using a symbolic link to lilo for /etc/lilo/install.
+    - removed the configuration option NOAUTO.
+    - split the documentation in a user's guide and the technical
+      overview.
+    - removed all references to older versions of LILO, the kernel or
+      other programs.
+    - removed all references to old-style configuration and not-compound
+      unstripped kernels.
+    - using the fullpage style.
+    - removed and "ascified" anew the shared sections of README and the
+      LaTeX documentation.
+    - some minor corrections.
+
+
+Changes from version 8 to 9
+---------------------------
+
+  Boot sector
+  -----------
+
+    - can now get the command line from the map file and overwrite
+      that sector.
+    - passes the word "auto" on the command line if booting after a
+      timeout.
+    - new command-line option vga={ask,normal,ext,extended,<number>}
+      to alter the VGA mode on the fly.
+    - image name matching can now be made case-insensitive (default)
+    - added sanity checks for the second stage loader and the
+      descriptor tables.
+
+  Map installer
+  -------------
+
+    - added new compound unstripped kernel format.
+    - -r is now implied if the environment variable ROOT is set.
+    - new option -I to translate a label name (e.g. obtained from
+      BOOT_IMAGE) to the path of the kernel image.
+    - new variable MESSAGE to define a startup message.
+    - new variable UNSAFE to bypass sanity checks and floppy spin-up
+      when defining other operating systems.
+    - new variable ALIAS to define a second label name.
+    - new variable RESTRICTED to confine password protection to
+      invocations with parameters.
+    - added a missing #include <sys/stat.h> to map.c
+    - fixed the BIOS_MAX_* parameters in lilo.h
+    - removed too restrictive cylinder number check.
+    - new option -R to set/clear the default command line in the
+      map file.
+    - added verification of 3D and linear address equality of
+      partition starts (in the partition table).
+    - suppressed outputting the version string when using -D with -v
+    - "vga=extended" can now be abbreviated to "vga=ext".
+
+  Documentation and installation
+  ------------------------------
+
+    - added a test for broken regexp in sed, grep and egrep to
+      QuickInst. Other minor improvements.
+    - now uses build-time configuration variables in Makefile or
+      /etc/lilo/config.defines
+    - copied section "LILO start messages" from doc.tex to README
+    - removed the description of a floppy test installation from
+      README. (doc.tex never contained that part.)
+    - fixed some minor documentation errors and omissions.
+    - fixed some minor Makefile bugs.
+    - included the LaTeX translations of the FIG files.
+    - moved the "Technical overview" to the end.
+
+
+Changes from version 7 to 8
+---------------------------
+
+  Boot sector
+  -----------
+
+    - now supports password protection for boot images.
+    - fixed occasional omission of delays.
+    - passes the name of the boot image to the kernel, which stores
+      it in the environment variable BOOT_IMAGE.
+    - parameters are now preserved when trying to boot the same
+      image again after a media error.
+    - the command line is preserved on error.
+    - can be operated from a serial line.
+    - made timeout handling interrupt-driven to fix time-wrap problems
+      at midnight.
+    - now clears all bytes after text and data of traditional boot
+      images booted from a file.
+
+  Map installer
+  -------------
+
+    - added detection of missing HDIO_REQ support.
+    - added sanity checking for disk parameters.
+    - fixed BIOS code computation for SCSI disks.
+    - command-line settings can now override /etc/lilo/config
+    - defaults for ROOT, VGA, RAMDISK, PASSWORD and OPTIONAL can be set
+      in the options section.
+    - new option PROMPT to unconditionally enter the boot prompt.
+    - new option TIMEOUT to specify an input timeout.
+    - new flag OPTIONAL to specify that an image can be omitted if it
+      isn't present.
+    - new value CURRENT for ROOT to specify the "current" root device.
+    - special characters are now correctly escaped in dumps.
+    - temporary files are now removed on error.
+    - updated the usage output to reflect the changes since 0.6.
+    - added a missing closedir to device.c
+
+  Documentation and installation
+  ------------------------------
+
+    - wrote a quick installation script.
+    - fixed many small documentation errors.
+    - wrote a README for the doc directory.
+    - added descriptions of the configuration parameters passed in
+      the boot sector and of the kernel's command-line interface.
+    - Makefile now explicitly uses /bin/sh
+    - changed echo \c to echo -n in the Makefile
+    - added ability to print the name of the active partition to
+      activate.
+
+
+Changes from version 6 to 7
+---------------------------
+
+  Boot sector
+  -----------
+
+    - supports video mode and RAM disk size settings.
+    - loads original boot sector to make possible additional settings
+      available.
+    - now uses defaults from the boot sector even if the boot sector
+      has been changed after map creation.
+
+  Map installer
+  -------------
+
+    - new configuration based on /etc/lilo/config
+    - can get SCSI geometry without using /etc/lilo/disktab (doesn't
+      work with 0.98pl6)
+    - removed support for BIOS codes (name:code)
+    - removed support for setting the swap device.
+    - new command-line options: -q, -C and -D
+
+  Documentation
+  -------------
+
+    - updated to cover new-style configuration
+    - extended the plain-ASCII README
+
+
+Changes from version 5 to 6
+---------------------------
+
+  Boot sector
+  -----------
+
+    - added command-line argument passing.
+    - now clears BSS of traditional images too.
+    - chain.b is now more careful about register values when invoking
+      the boot sector of the other OS.
+    - added an interface for externally provided command lines.
+    - added experimental recognition of linear addresses.
+
+  Map installer
+  -------------
+
+    - fixed opening the disktab file. (Using -f didn't work.)
+    - fixed use of BIOS codes for the map file: the tilde is now appended
+      before the BIOS code.
+    - added a chdir("/") when using -r
+    - added more sanity checks.
+    - added generation of linear addresses.
+
+  Documentation
+  -------------
+
+    - removed all references to swap device settings in the kernel because
+      recent kernels don't support that any longer.
+    - added a troubleshooting section.
+    - several minor fixes and improvements.
+
+
+Changes from version 4 to 5
+---------------------------
+
+  Map installer
+  -------------
+
+    - added automatic boot sector backup.
+    - fixed variable block size detection. (Didn't work with the 0.97-pl2
+      kernel.)
+    - added the chroot (-r) option.
+    - made the partition table part of a foreign OS boot descriptor
+      optional.
+
+  Documentation and installation
+  ------------------------------
+
+    - most of README has moved into doc.tex (LaTeX)
+    - added a utility to activate a partition.
+    - make install  now reminds the user to update the map.
+    - dd is now used in a more efficient way in the Makefile.
+      (Fewer subshells, etc.)
+
+
+Changes from version 3 to 4
+---------------------------
+
+  Boot sector
+  -----------
+
+    - added a configurable delay.
+    - added a diagnostic title message.
+
+  Map installer
+  -------------
+
+    - fixed all known include file conflicts.
+    - added support for variable block sizes. (Not used yet.)
+    - added some more sanity checks.
+    - added a tool to determine SCSI disk parameters.
+
+  Documentation and installation
+  ------------------------------
+
+    - extended coverage of SCSI disks.
+    - make install  now backs up chain.b and boot.b of any older LILO
+      installation. (To say: your system remains bootable even if you
+      forget to run /etc/lilo/install after the update or if this fails
+      for some reason.)
+    - moved the changes section from README into CHANGES.
+    - a set of pre-compiled executables of lilo, boot.b, chain.b and
+      dparam.com is available too.
+
+
+Changes from version 2 to 3
+---------------------------
+
+  Boot sector
+  -----------
+
+    - can initialize BSS of unstripped kernels.
+    - also accepts [Tab] to show the list of known images.
+
+  Map installer
+  -------------
+
+    - fixed parsing of the root device specification.
+    - fixed setting of the root device when the boot image doesn't
+      define it.
+    - reduced the number of installable images from 19 to 16. (Because the
+      descriptors have grown.)
+
+  Documentation
+  -------------
+
+    - added a booting basics section.
+    - many minor changes.
+
+
+Changes from version 1 to 2
+---------------------------
+
+  Boot sector
+  -----------
+
+    - added command-line editing.
+    - added debugging support (-DDEBUG).
+    - added support for compacted maps.
+    - some cosmetic changes.
+
+  Map installer
+  -------------
+
+    - major rewrite.
+    - files that contain "holes" are now handled properly.
+    - added map compaction.
+    - devices are now created on the fly only if they can't be found in /dev.
+    - improved sanity checking.
+    - can now boot other operating systems.
+    - can now boot unstripped kernel executables.
+    - added support for a disk parameter file.
+    - reduced the number of installable images from 21 to 19.
+    - changed the command-line syntax.
+    - root and boot can now be specified on the command line.
+
+  Documentation
+  -------------
+
+    - many changes, including correction of some minor errors.
+
+
+Changes from version 0 to 1
+---------------------------
+
+  Boot sector
+  -----------
+
+    - tested as master boot record.
+    - improved the boot prompt invocation method.
+    - increased the number of installable images to 21.
+    - added a help facility.
+    - improved read error handling and error reporting in the boot loader.
+    - added a second stage boot loader.
+
+  Map installer
+  -------------
+
+    - fixed some minor bugs in the map installer. Removed all compiler
+      warnings.
+    - added labeling of images.
+    - added version checking for the boot sector.
+    - replaced option -r by -m. -r will be available for a while for
+      compatibility.
+    - added booting from device files (that have boot images written on them).
+    - BIOS device codes can now be specified for boot image files too.
+    - added concatenation of images. (This is a test feature that will be
+      changed in the future.)
+
+  Documentation
+  -------------
+
+    - some minor documentation errors have been corrected.
+    - the README now warns that the map has to be rebuilt after the images are
+      replaced or moved.
+    - added a files, a hints and an examples section.
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..af53737
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,43 @@
+LInux LOader (LILO) program code, documentation, and auxiliary programs:
+
+Copyright 1992-1998 Werner Almesberger
+Copyright 1999-2007 John Coffman
+Copyright 2009-2010 Joachim Wiedorn
+All rights reserved.
+
+
+License
+-------
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are 
+met:
+
+ * Redistributions of source code must retain the above copyright notice, 
+   this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright 
+   notice, this list of conditions and the following disclaimer in the 
+   documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the authors nor the names of other contributors 
+   may be used to endorse or promote products derived from this software 
+   without specific prior written permission. 
+
+
+Disclaimer
+----------
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+POSSIBILITY OF SUCH DAMAGE.
+
+
+(Note: The above license is based on the BSD License at:
+       http://www.opensource.org/licenses/bsd-license.html)
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..442e943
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,132 @@
+# -*- makefile -*-
+
+#
+#  make help
+#
+help:
+       @echo ""
+       @echo "Targets:"
+       @echo "  make all         # binaries (without dosexe, diag.)"
+       @echo "  make dosexe      # DOS lilo.com utility"
+       @echo "  make diagnostic  # standalone diagnostics"
+       @echo "  make alles       # all above + static binary"
+       @echo "  make docs        # doc/[user,tech].[ps,dvi] docs"
+       @echo "  make floppy      # 2 standalone bootable diagnostic floppies"
+       @echo ""
+       @echo "  make install     # install binaries++ into root directory"
+       @echo "  make install DESTDIR=<dir>  # install binaries++ into directory"
+       @echo ""
+       @echo "  make uninstall     # remove binaries++ from root directory"
+       @echo "  make uninstall DESTDIR=<dir>  # rmove binaries++ from directory"
+       @echo ""
+       @echo "Maintenance:"
+       @echo "  make test        # test for all needed utilities (as86, ld86, etc.)"
+       @echo "  make tidy        # remove listings & other unnecessary files"
+       @echo "  make clean       # remove objects & ready for a fresh 'make all'"
+       @echo "  make distclean   # remove editor temps, & all of the above"
+       @echo ""
+
+#
+# everything needed to run, just short of installation
+#
+all: test
+       make -C src all
+       make -C images all
+
+#
+# everything above plus the statically linked version
+#
+alles: test
+       make -C src alles
+       make -C images all
+
+#
+# documentation files
+#
+docs:
+       make -C doc all
+
+#
+# if you have the 'bcc' compiler, then you can make the diagnostics, too
+# bcc = Bruce Evans’ C 16bit compiler (also for BIOS- and DOS code)
+#
+it:    docs alles diagnostic dosexe
+
+#
+# make the bootable diagnostic floppies
+#
+floppy: test
+       @echo
+       @echo Make sure you have 2 blank, formatted, 1.44Mb floppies
+       @echo before you proceed from this point.
+       @echo "Press <Enter> to continue, <^C> to abort ..."
+       @read
+       @make -C src floppy1
+       @echo Done.
+       @echo
+       @echo Remove the floppy from the drive.  Label it "\"1.6\""
+       @echo "Press <Enter> to continue, <^C> to abort ..."
+       @read
+       @make -C src floppy2
+       @echo Done.
+       @echo
+       @echo Remove the floppy from the drive.  Label it "\"2.4\""
+       @echo
+
+diagnostic: test
+       make -C src diagnostic
+
+dosexe: test
+       make -C dos lilo
+
+#
+# test for compilers & utilities
+#
+test: test.img
+test.img:
+       ./checkit
+       echo Tested >test.img   
+
+#
+# shorthand install, if one knows that one has the 'bcc' compiler
+#
+ins:
+       make -C src ins
+
+#
+#  normal install, but doesn't make the diagnostic binaries
+#
+install:  all
+       make -C src install
+       make -C images install
+       make -C hooks install
+       make -C sample install
+       make -C man install
+       make -C dos install
+
+tidy:
+       make -C src tidy
+       make -C diagnose tidy
+       make -C dos tidy
+       make -C doc tidy
+
+clean: tidy
+       rm -f test.img
+       make -C src clean
+       make -C images clean
+       make -C diagnose clean
+       make -C dos clean
+       make -C doc clean
+
+spotless: distclean
+distclean: clean
+       make -C src distclean
+       make -C diagnose distclean
+       make -C dos distclean
+
+uninstall:
+       make -C src uninstall
+       make -C images uninstall
+       make -C hooks uninstall
+       make -C sample uninstall
+       make -C man uninstall
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..bb51f5e
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,70 @@
+NEWS about project LILO
+=======================
+(For details see file 'CHANGELOG' in the source directory)
+
+
+Version 23.1  (major and bugfix update of 23.0)
+
+ o Many fixes of typos in sources and documentation.
+ o LVM volumes can now be used as root device.
+ o Better computing of (uncompressed) vmlinux size.
+ o Better working on degraded RAID devices.
+ o Update to newer MD RAID 1.0 specification.
+ o Substituted QuickInst script (mkbdist, mksdist removed).
+ o Added new hook scripts for newer kernel support.
+ o Updated and added new menu background images.
+ o Added new TOOLS file for overview of needed tools / packages.
+ o Added new example of lilo.conf with many comments.
+
+
+Version 23.0  (major and bugfix update of 22.8)
+
+ o Major code reorganisation and code cleaning.
+ o Add new option 'small-memory' and modify option 'large-memory'.
+ o Configuration without memory option set to auto-memory, which
+   mean a automatic decision: small initrd will be load <15M, 
+   large initrd will be load >16M.
+ o Now need an absolute path for the installation path DESTDIR,
+   in the past named as ROOT.
+ o Many bugfixes and sensible updates (most from Debian).
+ o Remove obsolete program 'activate'. Instead use 'lilo -A'.
+
+
+Version 22.8  (minor update of 22.7.3)
+
+ o Compile with DEVMAPPER (device-mapper or LVM2) if library is present.
+ o Add 'nodevcache' configuration file keyword.
+ o Allow root device specification with UUID in addition to LABEL.
+
+
+Version 22.7.3  (bugfix update of 22.7.2)
+
+ o Correct table entry for experimental major device 253.
+ o Correct PC/AT keyboard check when NOKEYBOARD compile option is used.
+
+
+Version 22.7.2  (minor update of 22.7.1)
+
+ o Keywords "noraid", "nokbdefault", "nokbdisable" are added.
+ o Compensate for common BIOS bug (sectors==0) on USB disk drives.  
+ o Increase kernel command line to 512 bytes.
+
+
+Version 22.7.1  (minor update of 22.7)
+
+ o Expand device major/minor numbers to more than 8 bits.
+ o Apply security updates to 'mkrescue' & 'QuickInst'.
+ o Allow any keystrike (not just Shift) to display 'boot:' menu, or to 
+   escape from stored command line.
+
+
+Version 22.7  (minor update of 22.6.1)
+
+ o Add the DOS/Windows utility 'lilo.com' which implements the -q -R -V 
+   (-C -m) switches. This utility may be used to set the boot command 
+   line if the sector map file is on a DOS/Windows partition.
+ o Add bulletproofing for "unattended" so that a spurious <CR> character 
+   can be ignored.
+ o Select boot descriptors based upon partially typed names in all 
+   situations except "unattended".
+
diff --git a/QuickInst b/QuickInst
new file mode 100755 (executable)
index 0000000..2aabccf
--- /dev/null
+++ b/QuickInst
@@ -0,0 +1,72 @@
+#!/bin/sh
+#
+#  QuickInst - script for quick installation of lilo
+#
+#  Copyright 2010 Joachim Wiedorn
+#  All rights reserved.
+#
+#  Licensed under the terms contained in the file 'COPYING'
+#  in the source directory.
+#
+
+set -e
+
+if [ ! -f "./src/lilo.c" ]; then
+  echo "You are not in the main source directory of LILO - Abort!"
+  exit 1
+fi
+
+if [ -z "$1" ]; then
+
+  if [ "$UID" != "0" ]; then
+    echo "For installing LILO you must be ROOT - Abort!"
+    exit 1
+  fi
+
+else
+  ADIR=`pwd`
+
+  # absolute path to directory ?
+  if [ `echo "$1" | sed 's#^\/##g'` = "$1" ]; then
+    # path is relative
+    BDIR=`echo "${ADIR}/${1}" | sed 's#\/\/#\/#g'`
+  else
+    BDIR=`echo "/${1}" | sed 's#\/\/#\/#g'`
+  fi  
+
+  # existing directory ?
+  if [ -e "${BDIR}" ]; then
+    DDIR="${BDIR}"
+  else
+    # try to create directory
+    mkdir -p ${BDIR} 2>/dev/null || true
+    if [ -e "$BDIR" ]; then
+      DDIR=$BDIR
+    else
+      echo "Cannot create directory ${1} - Abort!"
+      exit 1
+    fi
+  fi
+
+  # writeable directory ?
+  if [ ! -w "$DDIR" ]; then
+    echo "Cannot write to directory $DDIR - Abort!"
+    exit 1
+  fi
+
+fi
+
+echo "~~~~~~~~~~~~ make all ~~~~~~~~~~~~"
+make all
+
+echo "~~~~~~~~~~ make install ~~~~~~~~~~"
+if [ -n "$DDIR" ]; then
+  make install DESTDIR="$DDIR"
+  DDTEXT=" to ${DDIR}"
+else
+  make install
+fi
+
+echo
+echo "LILO installed${DDTEXT}."
+echo
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..ca26cbb
--- /dev/null
+++ b/README
@@ -0,0 +1,119 @@
+README for project LILO
+=======================
+
+
+Versoin 23.1 (release) -- Joachim Wiedorn <ad_debian@joonet.de>
+---------------------------------------------------------------
+
+Option 'inaccessible':
+
+  The patch in 23.0 for better support for inaccessible disks based
+  on problems with usb sticks. But this option 'inaccessible' is only 
+  usable, if hard disks can not be accessed by the BIOS, but always 
+  by linux. This option does not concern usb sticks, which will always
+  bring failures if they are named in the lilo.conf. So I have removed
+  this patch from the new version.
+
+Computing vmlinux size:
+
+  From the compressed kernel vmlinuz the size of the uncompressed
+  file must be compute to decide whether the initrd can be copied
+  in the memory <15M. But with the newer 64bit kernels this factor
+  changed from nearly "3" to nearly "6". "6" is now default.
+
+Working on degraded RAID device:
+
+  If the first physical device of a RAID1 array is faulty or removed, 
+  lilo fails to install. It doesn't get valid informations about the 
+  device and didn't resume with the next disk. Lilo now loop through
+  all devices to get the disk geometry.
+
+Working with MD RAID 1.0 standard:
+
+  Turned off the error "Inconsistent Raid version information" for 
+  Version 1.0 MD RAID mirror pairs. It also corrects the error message,
+  as the version information is just incompatible not inconsistent.
+
+  No other charges are required as 1.0 devices have the same layout
+  as v0.90 devices except that they work with drives in excess of 2TB.
+  It does not update for version 1.2 raid superblocks, this would 
+  require a much more complex patch.
+
+  With the following lilo.conf the standard debian initrd and kernel 
+  boot off of an LVM logical drive on an MD RAID-1 array consisting of
+  two whole disk devices (e.g. /dev/sda & /dev/sdb). Now the array can
+  use version 1.0 superblocks, so these devices can be e.g. the new 
+  3 TByte Seagate drives.
+
+  Configuration example:
+
+       | boot=/dev/md0
+       | raid-extra-boot=mbr-only
+       | map=/boot/map
+       | delay=20
+       |
+       | default=Linux
+       | append="quiet root=/dev/mapper/vg0-root"
+       |
+       | image=/vmlinuz
+       |         label=Linux
+       |         read-only
+       |         initrd=/initrd.img
+
+
+Versoin 23.0 (release) -- Joachim Wiedorn <ad_debian@joonet.de>
+---------------------------------------------------------------
+
+Option 'small-memory':
+
+  New option to define, that kernel+initrd should always set into the
+  low memory under 15M. But if this is impossible, lilo try to use the
+  high memory above 16M for initrd and give you a warning.
+
+Option 'large-memory':
+
+  This option enables using memory above 16Mb for the initrd (up to a
+  kernel imposed limit of around 768Mb) which is usable on nearly all
+  newer systems with post-2000 BIOSes. Details can be found in manpage
+  lilo.conf(5).
+
+No option 'large-memory' or 'small-memory':
+
+  If no option is set in the configuration, then lilo will check the
+  needed memory space and give you some informations about the result
+  and its decision in verbose mode.
+  If you need the old behaviour, please use the option 'small-memory'.
+
+Installation into a subdirectory:
+
+  If you want to install all lilo files into a specific directory which 
+  is not the root directory "/", then use the shell variable DESTDIR to
+  set an absolut path for installation:
+
+      make install DESTDIR=/home/myself/test/lilo/
+  or
+      make install DESTDIR=`pwd`/test/
+
+  WARNING: You always need an absolute path! This behaviour have changed 
+  since version 22.x. The old variable ROOT is obsolete for installing.
+
+Using UUIDs for partitions:
+
+  In the configuration file of lilo all lines with 'root=' can be used
+  together with UUIDs. To extract your UUIDs let run the program blkid.
+  Here an example:
+
+      #OLD#root = /dev/hda6 = /dev/sda6
+      root  = "UUID=5472fd8e-9089-4256-bcaa-ceab4f01a439"
+
+  But then you should also use a similar expression for the 'boot=' line.
+  Unfortunately you cannot use UUIDs because devices haven't any UUIDs.
+  The solution is using the udev device names which can be found in 
+  /dev/disks/by-id/ i. e. for a PATA disk:
+  
+      boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999
+
+  or i. e. for a SATA disk :
+
+      boot = /dev/disk/by-id/ata-SAMSUNG_HD502HI_S1VZJ90S999999
+
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..97e0f03
--- /dev/null
+++ b/TODO
@@ -0,0 +1,13 @@
+TODO for project LILO
+=====================
+
+* update manpages with new option 'small-memory' and changed
+  behaviour of 'large-memory'.
+
+* patching sources because of some warnings while compiling
+  with gcc 4.3.x
+
+* Upgrade of all manpages.
+
+* Upgrade of all documentations.
+
diff --git a/TOOLS b/TOOLS
new file mode 100644 (file)
index 0000000..391117a
--- /dev/null
+++ b/TOOLS
@@ -0,0 +1,18 @@
+The following is a list of external tools and programs that
+are used within lilo makefiles and scripts. Along with the 
+RPMs or DEBs they can be found in:
+
+               at least       tested         programs
+package        version        until          inside
+-----------------------------------------------------------------
+coreutils      6.4.10         8.5            (general)
+                     
+bcc            0.16.14        0.16.17        bcc
+                     
+bin86          0.16.14        0.16.17        as86, ld86
+                     
+gcc            3.3.5          4.4.5          gcc
+                     
+sharutils      4.6.3          4.9            uuencode, uudecode
+                     
+texlive-latex-base  2007-01   2009-11        ifpdf.sty
diff --git a/checkit b/checkit
new file mode 100755 (executable)
index 0000000..5fb8afa
--- /dev/null
+++ b/checkit
@@ -0,0 +1,110 @@
+#! /bin/sh
+#
+#  checkit:    Test for correct versions of utilities
+#  (see the end of the file for bypassing these checks)
+#
+#  Copyright 2005-2007 John Coffman
+#  Copyright 2009-2010 Joachim Wiedorn
+#  All rights reserved.
+#
+#  Licensed under the terms contained in the file 'COPYING'
+#  in the source directory.
+#
+
+
+ret=0
+rc=0
+
+# min. version of BCC, AD86, LD86
+bccmin="0.16.14"
+
+# min. version of GCC, CPP
+gccmin="3.3.5"
+
+vers_min() {
+       local M m p N n r
+
+       rc=0
+# get our version major, minor, rev
+       M=`echo $1 | cut -d . -f 1`
+       m=`echo $1 | cut -d . -f 2`
+       p=`echo $1 | cut -d . -f 3`
+       if [ -z "$p" ]; then p=0; fi
+#echo vers_min1 $M $m $p
+       N=`echo $2 | cut -d . -f 1`
+       n=`echo $2 | cut -d . -f 2`
+       r=`echo $2 | cut -d . -f 3`
+#echo vers_min2 $N $n $r
+       if [ "$M" -lt "$N" ]; then rc=1
+       elif [ "$M" -gt "$N" ]; then rc=0
+       elif [ "$m" -lt "$n" ]; then rc=1
+       elif [ "$m" -gt "$n" ]; then rc=0
+       elif [ -z "$r" ]; then rc=0
+       elif [ "$p" -lt "$r" ]; then rc=1
+       fi
+#echo vers_min returns $rc
+       return $rc
+}
+
+#echo
+echo GCC version $gccmin or later is required
+gcc -v 1>foo1 2>foo2
+V=`cat foo1 foo2 | cut -d' ' -f1-3 | grep -i version | tr '-' ' ' | cut -d' ' -f 3`
+rm -f foo1 foo2
+if [ -z "$V" ]; then
+       echo gcc is not present
+       ret=1
+else
+       vers_min $V $gccmin
+       echo gcc version $V
+       if [ $rc = 0 ]; then echo OKAY; else echo ERROR; ret=1; fi
+fi
+
+echo
+echo AS86 version $bccmin or later is required
+as86 -v 1>foo1 2>foo2
+A=`cat foo1 foo2 | grep version | cut -d " " -f 3`
+rm -f foo1 foo2
+if [ -z "$A" ]; then
+       echo as86 is not present
+       ret=1
+else
+       vers_min $A $bccmin
+       echo as86 version $A
+       if [ $rc = 0 ]; then echo OKAY; else echo ERROR; ret=1; fi
+fi
+
+echo
+echo LD86 version $bccmin or later is required
+ld86 -v 1>foo1 2>foo2
+L=`cat foo1 foo2 | grep version | cut -d " " -f 3`
+rm -f foo1 foo2
+if [ -z "$L" ]; then
+       echo ld86 is not present
+       ret=1
+else
+       vers_min $L $bccmin
+       echo ld86 version $L
+       if [ $rc = 0 ]; then echo OKAY; else echo ERROR; ret=1; fi
+fi
+
+echo
+echo BCC version $bccmin or later is recommended
+bcc -v 1>foo1 2>foo2
+B=`cat foo1 foo2 | grep version | cut -d " " -f 3`
+rm -f foo1 foo2
+if [ -z "$B" ]; then
+       echo bcc is not present
+       echo You will not be able to make floppy2, diag2.img, or lilo.com
+else
+       vers_min $B $bccmin
+       echo bcc version $B
+       if [ $rc = 0 ]; then echo OKAY; else echo ERROR; fi
+fi
+echo
+
+#
+# Uncomment the line below to bypass all the checks
+#
+#exit 0
+exit $ret
diff --git a/diagnose/GPLicence b/diagnose/GPLicence
new file mode 100644 (file)
index 0000000..a43ea21
--- /dev/null
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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 program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/diagnose/LGPLicence b/diagnose/LGPLicence
new file mode 100644 (file)
index 0000000..482cd2b
--- /dev/null
@@ -0,0 +1,371 @@
+GNU Lesser Public License
+
+ Version 2.1, February 1999
+
+     Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+     Everyone is permitted to copy and distribute verbatim copies
+     of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+as the successor of the GNU Library Public License, version 2, hence
+the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your freedom to share and change it. By contrast, the
+ GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to
+ make sure the software is free for all its users. 
+
+ This license, the Lesser General Public License, applies to some specially designated software
+ packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use
+ it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is
+ the better strategy to use in any particular case, based on the explanations below. 
+
+ When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are
+ designed to make sure that you have the freedom to distribute copies of free software (and charge for this service
+ if you wish); that you receive source code or can get it if you want it; that you can change the software and use
+ pieces of it in new free programs; and that you are informed that you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to
+ surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the
+ library or if you modify it. 
+
+ For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the
+ rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other
+ code with the library, you must provide complete object files to the recipients, so that they can relink them with the
+ library after making changes to the library and recompiling it. And you must show them these terms so they know
+ their rights. 
+
+ We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which
+ gives you legal permission to copy, distribute and/or modify the library. 
+
+ To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the
+ library is modified by someone else and passed on, the recipients should know that what they have is not the
+ original version, so that the original author's reputation will not be affected by problems that might be introduced by
+ others. 
+
+ Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a
+ company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent
+ holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the
+ full freedom of use specified in this license. 
+
+ Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This
+ license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from
+ the ordinary General Public License. We use this license for certain libraries in order to permit linking those
+ libraries into non-free programs. 
+
+ When a program is linked with a library, whether statically or using a shared library, the combination of the two is
+ legally speaking a combined work, a derivative of the original library. The ordinary General Public License
+ therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public
+ License permits more lax criteria for linking other code with the library. 
+
+ We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than
+ the ordinary General Public License. It also provides other free software developers Less of an advantage over
+ competing non-free programs. These disadvantages are the reason we use the ordinary General Public License
+ for many libraries. However, the Lesser license provides advantages in certain special circumstances. 
+
+ For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain
+ library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the
+ library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case,
+ there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. 
+
+ In other cases, permission to use a particular library in non-free programs enables a greater number of people to
+ use a large body of free software. For example, permission to use the GNU C Library in non-free programs
+ enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating
+ system. 
+
+ Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user
+ of a program that is linked with the Library has the freedom and the wherewithal to run that program using a
+ modified version of the Library. 
+
+ The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the
+ difference between a "work based on the library" and a "work that uses the library". The former contains code
+ derived from the library, whereas the latter must be combined with the library in order to run. 
+
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
+ MODIFICATION
+
+ 0. This License Agreement applies to any software library or other program which contains a notice placed by the
+ copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General
+ Public License (also called "this License"). Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with
+ application programs (which use some of those functions and data) to form executables. 
+
+ The "Library", below, refers to any such software library or work which has been distributed under these terms. A
+ "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a
+ work containing the Library or a portion of it, either verbatim or with modifications and/or translated
+ straightforwardly into another language. (Hereinafter, translation is included without limitation in the term
+ "modification".) 
+
+ "Source code" for a work means the preferred form of the work for making modifications to it. For a library,
+ complete source code means all the source code for all modules it contains, plus any associated interface
+ definition files, plus the scripts used to control compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not covered by this License; they are outside its
+ scope. The act of running a program using the Library is not restricted, and output from such a program is covered
+ only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the program that uses the Library does. 
+
+ 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any
+ medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty;
+ and distribute a copy of this License along with the Library. 
+
+ You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty
+ protection in exchange for a fee. 
+
+ 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library,
+ and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also
+ meet all of these conditions: 
+
+     a) The modified work must itself be a software library. 
+
+     b) You must cause the files modified to carry prominent notices stating that you changed the files and
+     the date of any change.
+
+     c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms
+     of this License. 
+
+     d) If a facility in the modified Library refers to a function or a table of data to be supplied by an
+     application program that uses the facility, other than as an argument passed when the facility is
+     invoked, then you must make a good faith effort to ensure that, in the event an application does not
+     supply such function or table, the facility still operates, and performs whatever part of its purpose
+     remains meaningful. 
+
+     (For example, a function in a library to compute square roots has a purpose that is entirely well-defined
+     independent of the application. Therefore, Subsection 2d requires that any application-supplied
+     function or table used by this function must be optional: if the application does not supply it, the square
+     root function must still compute square roots.) 
+
+     These requirements apply to the modified work as a whole. If identifiable sections of that work are not
+     derived from the Library, and can be reasonably considered independent and separate works in
+     themselves, then this License, and its terms, do not apply to those sections when you distribute them as
+     separate works. But when you distribute the same sections as part of a whole which is a work based
+     on the Library, the distribution of the whole must be on the terms of this License, whose permissions for
+     other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. 
+
+     Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by
+     you; rather, the intent is to exercise the right to control the distribution of derivative or collective works
+     based on the Library. 
+
+     In addition, mere aggregation of another work not based on the Library with the Library (or with a work
+     based on the Library) on a volume of a storage or distribution medium does not bring the other work
+     under the scope of this License. 
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given
+ copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the
+ ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the
+ ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not
+ make any other change in these notices. 
+
+ Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public
+ License applies to all subsequent copies and derivative works made from that copy. 
+
+ This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 
+
+ 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or
+ executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete
+ corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange. 
+
+ If distribution of object code is made by offering access to copy from a designated place, then offering equivalent
+ access to copy the source code from the same place satisfies the requirement to distribute the source code, even
+ though third parties are not compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by
+ being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative
+ work of the Library, and therefore falls outside the scope of this License. 
+
+ However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the
+ Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is
+ therefore covered by this License. Section 6 states terms for distribution of such executables. 
+
+ When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for
+ the work may be a derivative work of the Library even though the source code is not. Whether this is true is
+ especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for
+ this to be true is not precisely defined by law. 
+
+ If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and
+ small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether
+ it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under
+ Section 6.) 
+
+ Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms
+ of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly
+ with the Library itself. 
+
+ 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the
+ Library to produce a work containing portions of the Library, and distribute that work under terms of your choice,
+ provided that the terms permit modification of the work for the customer's own use and reverse engineering for
+ debugging such modifications. 
+
+ You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its
+ use are covered by this License. You must supply a copy of this License. If the work during execution displays
+ copyright notices, you must include the copyright notice for the Library among them, as well as a reference
+ directing the user to the copy of this License. Also, you must do one of these things: 
+
+     a) Accompany the work with the complete corresponding machine-readable source code for the
+     Library including whatever changes were used in the work (which must be distributed under Sections 1
+     and 2 above); and, if the work is an executable linked with the Library, with the complete
+     machine-readable "work that uses the Library", as object code and/or source code, so that the user
+     can modify the Library and then relink to produce a modified executable containing the modified
+     Library. (It is understood that the user who changes the contents of definitions files in the Library will not
+     necessarily be able to recompile the application to use the modified definitions.) 
+
+     b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one
+     that (1) uses at run time a copy of the library already present on the user's computer system, rather than
+     copying library functions into the executable, and (2) will operate properly with a modified version of the
+     library, if the user installs one, as long as the modified version is interface-compatible with the version
+     that the work was made with. 
+
+     c) Accompany the work with a written offer, valid for at least three years, to give the same user the
+     materials specified in Subsection 6a, above, for a charge no more than the cost of performing this
+     distribution. 
+
+     d) If distribution of the work is made by offering access to copy from a designated place, offer
+     equivalent access to copy the above specified materials from the same place. 
+
+     e) Verify that the user has already received a copy of these materials or that you have already sent this
+     user a copy.
+
+ For an executable, the required form of the "work that uses the Library" must include any data and utility programs
+ needed for reproducing the executable from it. However, as a special exception, the materials to be distributed
+ need not include anything that is normally distributed (in either source or binary form) with the major components
+ (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself
+ accompanies the executable. 
+
+ It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not
+ normally accompany the operating system. Such a contradiction means you cannot use both them and the Library
+ together in an executable that you distribute. 
+
+ 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with
+ other library facilities not covered by this License, and distribute such a combined library, provided that the
+ separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and
+ provided that you do these two things: 
+
+     a) Accompany the combined library with a copy of the same work based on the Library, uncombined
+     with any other library facilities. This must be distributed under the terms of the Sections above. 
+
+     b) Give prominent notice with the combined library of the fact that part of it is a work based on the
+     Library, and explaining where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this
+ License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will
+ automatically terminate your rights under this License. However, parties who have received copies, or rights, from
+ you under this License will not have their licenses terminated so long as such parties remain in full compliance. 
+
+ 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you
+ permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do
+ not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you
+ indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or
+ modifying the Library or works based on it. 
+
+ 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a
+ license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and
+ conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You
+ are not responsible for enforcing compliance by third parties with this License. 
+
+ 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited
+ to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict
+ the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so
+ as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free
+ redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you
+ could satisfy both it and this License would be to refrain entirely from distribution of the Library. 
+
+ If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the
+ section is intended to apply, and the section as a whole is intended to apply in other circumstances. 
+
+ It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest
+ validity of any such claims; this section has the sole purpose of protecting the integrity of the free software
+ distribution system which is implemented by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that system in reliance on consistent application of
+ that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other
+ system and a licensee cannot impose that choice. 
+
+ This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 
+
+ 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Library under this License may add an explicit geographical
+ distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus
+ excluded. In such case, this License incorporates the limitation as if written in the body of this License. 
+
+ 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License
+ from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to
+ address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the Library specifies a version number of this License
+ which applies to it and "any later version", you have the option of following the terms and conditions either of that
+ version or of any later version published by the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free Software Foundation. 
+
+ 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are
+ incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free
+ Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of
+ promoting the sharing and reuse of software generally. 
+
+ NO WARRANTY 
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE
+ LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN
+ WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE
+ LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+ CORRECTION. 
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
+ COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY
+ AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
+ INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE
+ OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH
+ ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGES. 
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making
+ it free software that everyone can redistribute and change. You can do so by permitting redistribution under these
+ terms (or, alternatively, under the terms of the ordinary General Public License). 
+
+ To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source
+ file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a
+ pointer to where the full notice is found. 
+
+     one line to give the library's name and an idea of what it does.
+     Copyright (C) year name of author 
+
+     This library is free software; you can redistribute it and/or
+     modify it under the terms of the GNU Lesser General Public
+     License as published by the Free Software Foundation; either
+     version 2.1 of the License, or (at your option) any later version.
+
+     This 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
+     Lesser General Public License for more details.
+
+     You should have received a copy of the GNU Lesser General Public
+     License along with this library; if not, write to the Free Software
+     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Also add information on how to contact you by electronic and paper mail. 
+
+ You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright
+ disclaimer" for the library, if necessary. Here is a sample; alter the names: 
+
+     Yoyodyne, Inc., hereby disclaims all copyright interest in
+     the library `Frob' (a library for tweaking knobs) written
+     by James Random Hacker.
+
+     signature of Ty Coon, 1 April 1990
+     Ty Coon, President of Vice
+
+ That's all there is to it! 
\ No newline at end of file
diff --git a/diagnose/Makefile b/diagnose/Makefile
new file mode 100644 (file)
index 0000000..1139e20
--- /dev/null
@@ -0,0 +1,118 @@
+# -*- makefile -*-
+# Makefile for BCC tests
+
+# adding variables
+include ../make.vars
+
+MODEL=s
+CC = bcc -M$(MODEL)
+CPP = gcc -E
+CINCL = /usr/lib/bcc/include
+AS = as86
+LINK = $(CC) -v
+COPT = -ansi -I$(CINCL) -c -O -DDEBUG=0
+LOPT = -m >$*.map -M -d
+AOPT = -0 -a -w
+FD = msdos.b
+FDSIZE = 1440
+MFILE=/tmp/liloboot
+LOOP=/dev/loop5
+
+.SUFFIXES:  .com .S
+
+.c.o:
+       $(CC) $(COPT) -o $@ $< -A-l -A$*.lis
+
+.o.com:
+       $(LINK) $(LOPT) -o $@ $^
+
+.s.o:
+       $(AS) $(AOPT) -l $*.lis -o $@ $<
+
+all:  check test4d.com test4.com test5.com bootdiagnostic.b.gz
+
+check:
+       # You need the bcc compiler for some steps!
+       @if [ -x /usr/bin/bcc -o -x /usr/local/bin/bcc ]; then echo Okay; \
+       else echo "*** WARNING ***"; \
+               echo "You don't seem to have the 'bcc' compiler from the 'dev86' package. "; \
+               echo "***************"; exit 1; \
+       fi
+
+floppy:  bootdiagnostic.b.gz
+       @echo
+       @echo Insert a blank, formatted, floppy into drive 0
+       @echo "Press <Enter> to continue, <^C> to abort ..."
+       @read
+       gzip -d <bootdiagnostic.b.gz | dd of=/dev/fd0 bs=1024
+
+bootdiagnostic.b.gz:  check2 sector.b test4.com test4d.com
+       rm -rf $(MFILE) bootdiagnostic.b
+       mkdir $(MFILE)
+       dd if=/dev/zero of=bootdiagnostic.b bs=1024 count=$(FDSIZE)
+       mkfs.msdos bootdiagnostic.b
+       dd if=sector.b bs=2 count=1 of=floppy.b
+       dd if=bootdiagnostic.b bs=2 skip=1 count=30 >>floppy.b
+       dd if=sector.b bs=2 skip=31 count=225 >>floppy.b
+       mount -t msdos -o loop=$(LOOP) bootdiagnostic.b $(MFILE)
+       dd if=floppy.b of=$(LOOP) bs=512
+       chown 0.0 *.com
+       cp -ufv ../COPYING $(MFILE)
+       cp -ufv test4.com $(MFILE)/hipboot.sys
+       cp -ufv test4.com $(MFILE)/diag2sa.com
+       cp -ufv test4d.com $(MFILE)/diag2.com
+       if [ -f ../disk.b ]; then cp -ufv ../disk.b $(MFILE)/diag1.com; fi
+       umount $(MFILE)
+       rm -rf $(MFILE)
+       gzip -9 <bootdiagnostic.b >bootdiagnostic.b.gz
+       rm -f bootdiagnostic.b
+
+check2:
+       # You need root permissions for some steps! (Test with mkfs.msdos)
+       @if [ `which mkfs.msdos | grep -c mkfs` -eq 1 ]; then echo Okay; \
+       else echo "*** WARNING ***"; \
+               echo -n "You don't seem to have the commands 'mkfs.msdos'. "; \
+               echo "Perhaps you are not ROOT ?"; \
+               echo "***************"; exit 1; \
+       fi
+
+test4.com:     test4.o bios_start.o cprintf.o
+
+test5.com:     test5.o bios_start.o cprintf.o
+
+sector.o:      sector.s
+test4.o:       test4.c ../src/bdata.h
+test5.o:       test5.c ../src/bdata.h
+cprintf.o:     cprintf.c
+bios_start.o:  bios.c
+       bcc -c -u -I$(CINCL) -DL_bios_start -D__AS386_16__ -D__STANDALONE__ -o bios_start.o bios.c -v
+
+test4d.o:      test4.c ../src/bdata.h
+       bcc -Md $(COPT) -o $@ $<
+
+test4d.com:    test4d.o
+       bcc -Md $(LOPT) -o $@ $^
+
+sector.s:      sector.S
+       $(CPP) -traditional -o $@ $<
+
+sector.img:    sector.o
+       ld86 -0 -s -o $@ $<
+
+sector.b:      sector.img
+       dd if=$< of=$@ bs=32 skip=1
+
+floppy.b:      sector.b
+       dd if=sector.b bs=2 count=1 of=floppy.b
+       dd if=$(FD) bs=2 skip=1 count=30 >>floppy.b
+       dd if=sector.b bs=2 skip=31 count=225 >>floppy.b
+       
+tidy:
+       rm -f *.map *.lis core
+
+clean:
+       rm -f *.o *.s *.img *.b *.com *.gz
+
+distclean:  clean
+       rm -f *~
+
diff --git a/diagnose/README b/diagnose/README
new file mode 100644 (file)
index 0000000..d1fe4f0
--- /dev/null
@@ -0,0 +1,30 @@
+This directory contains the files for making the bootable diagnostic
+diskette, version 2.  They are released under the terms of the BSD licence,
+contained in the file COPYING in the root LILO source directory.
+
+       sector.S -- the MSDOS boot code which boots HIPBOOT.SYS
+       test4.c -- the actual diagnostic
+
+
+Robert de Bath's "dev-0.16.0" package is REQUIRED to correctly make the
+programs in this directory.  The following sources are derived from his
+package, are his property, and are released under the 'LGPLicence' contained 
+in this directory.
+
+       bios.c -- modified source for the bios_start.o program
+       cprintf.c -- modified source for the standalone print routine
+
+
+The files placed on the MSDOS floppy are as follows:
+
+       test4d.com -- DOS version 2 of the diagnostic, runs under MSDOS;
+                       useful for capturing output to a file, BUT output is
+                       not guaranteed to be the same as the standalone
+                       version 2 program
+       test4.com -- standalone version 2 of the diagnostic, bootable if
+                       copied to 'hipboot.sys'
+       disk.com -- version 1 of the disk diagnostic, bootable if copied
+                       to 'hipboot.sys'
+
+
+(14-Jan-2002) -- jrc
diff --git a/diagnose/README.diagnostic b/diagnose/README.diagnostic
new file mode 100644 (file)
index 0000000..600168e
--- /dev/null
@@ -0,0 +1,38 @@
+               Notes for "bootdiagnostic.b.gz" 
+                       03-May-2002
+
+
+The lilo boot disk diagnostic (version 2.1) is distributed in binary
+form in the file:  bootdiagnostic.b.gz
+
+In order to create the bootable diagnostic floppy from this file, issue the
+following commands:
+
+       gunzip bootdiagnostic.b.gz
+       dd if=bootdiagnostic.b of=/dev/fd0
+
+The entire 1.44M floppy disk will be written.  This is an msdos filesystem
+diskette with the files:
+
+       disk.com                version 1 of the bootable lilo diagnostic
+       test4.com               version 2
+       test4d.com              version 2, MSDOS executable
+       hipboot.sys             copy of test4.com
+
+Whichever file is copied to 'hipboot.sys' will be booted by the special
+bootloader on the floppy.  As distributed, version 2, or 'test4.com' is
+the file copied to 'hipboot.sys'.
+
+The MSDOS executable is of some use if you can boot a bare DOS system.  It
+may be executed from the DOS prompt to capture the output to a file; viz.,
+
+       A> test4d.com >log.txt
+
+(you'll have to hit a lot of CR's to get past all the pauses)
+
+The output from test4d.com is not necessarily the same as from the booted
+file 'test4.com', since MSDOS intercepts and modifies the responses to
+certain bios calls.  User beware.
+
+--John Coffman
+<johninsd@san.rr.com>
diff --git a/diagnose/bios.c b/diagnose/bios.c
new file mode 100644 (file)
index 0000000..05d929d
--- /dev/null
@@ -0,0 +1,289 @@
+/* Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/* Modified 14-Jan-2002 by John Coffman <johninsd@san.rr.com> for inclusion
+ * in the set of LILO diagnostics.  This code is the property of Robert
+ * de Bath, and is used with his permission.
+ */
+#define MSDOS_TOO 1
+#define SAVE_SP 1
+
+
+#if !__FIRST_ARG_IN_AX__
+#ifdef __AS386_16__
+#ifdef __STANDALONE__
+
+#include <bios.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#ifdef L_bios_start
+
+char ** environ = { 0 };
+int errno;
+
+void (*__cleanup)() = 0;
+
+#asm
+  .data
+export ___argr
+___argr:
+  .word 0,0,0,0,0,0,0,0        ! A struct REGS
+export ___argseg
+___argseg:
+  .word 0,0,0,0                ! A struct SREGS
+___argr_end:
+defarg:
+  .word boot_str, 0
+boot_str:
+  .asciz "boot"
+loop_save:
+  .word 0
+
+  .text
+#if SAVE_SP
+sssp_save:
+  .word 0,0            ! dirty area if startup SS & SP are to be seen
+#endif
+export ___cstartup     ! Crt0 startup
+___cstartup:
+  cli
+#if MSDOS_TOO
+  seg es
+  cmp  word ptr [0],#$20CD     ! "int 20h" at psp:  ES:0000
+  jne  not_dos
+  push ax                      ! DOS provides us a stack
+  mov  ax,cs
+  add  ax,#$10                 ! bump CS by 0x10 
+  push ax
+  mov  ax,#is_dos              ! resume address
+  push ax
+  retf                         ! continue at next instruction
+is_dos:
+  pop  ax                      ! restore saved AX
+  seg cs
+  mov  word ptr [iret_ins-2],es  ! patch return to int 20h exit
+not_dos:
+#endif
+#if SAVE_SP
+  seg cs
+  mov  [sssp_save],sp
+  seg cs
+  mov  [sssp_save+2],ss        ! save startup SS:SP
+#endif
+  mov  sp,cs
+  add  sp,#__segoff
+  mov  ss,sp
+  mov  sp,#___argr_end
+
+  push ds
+#if SAVE_SP
+  seg cs
+  push [sssp_save+2]   ! startup SS
+#else
+  push ss
+#endif
+  push cs  
+  push es
+
+#if SAVE_SP
+  seg cs
+  push [sssp_save]     ! startup SP to flags
+#else
+  pushf                ! to flags, but why?
+#endif
+  push bp      ! to cflags
+  
+  push di      ! save the startup registers
+  push si      ! pushes are shorter than  mov  mem,reg
+  push dx
+  push cx
+  push bx
+  push ax
+  
+  xor  sp,sp   ! maximum stack
+  push bp      ! perhaps bp should be zeroed first
+  sti          ! now turn on interrupts
+
+  push ss              ! set up the ES and DS
+  pop  ds              ! equal to the SS
+  
+zap_bss:               ! Clear the BSS
+  push ds
+  pop  es              ! ES now = DS
+  mov  di,#__edata
+  mov  cx,#__end
+  sub  cx,di
+  xor  ax,ax
+  cld
+  rep
+   stosb
+
+  push [_environ]
+  mov  ax,#defarg      ! Don`t define __mkargv, standalone programs don`t
+  push ax              ! get any arguments.
+  mov  ax,#1
+  push ax
+
+  mov  bx,#auto_start  ! Pointer to first autostart function
+auto_run:
+  mov  [loop_save],bx
+  mov  bx,[bx]
+  test bx,bx
+  jz   no_entry
+  call bx              ! Call the function
+no_entry:
+  mov  bx,[loop_save]
+  inc  bx              ! next
+  inc  bx
+  jmp  auto_run        ! And round for the next.
+
+call_exit:             ! Last item called by above.
+  pop  bx              ! Be tidy.
+  push ax              ! At the end the last called was main() push it`s
+  call _exit           ! return val and call exit();
+bad_exit:
+  jmp  bad_exit        ! Exit returned !!
+
+  loc  2
+  .word _main          ! Segment 2 is the trailing pointers, main and the
+  .word        call_exit       ! routine to call exit.
+data_start:
+
+  .text
+export _exit
+_exit:                 ! exit(rv) function
+  mov  bx,sp
+  push [bx+2]          ! Copy the `rv` for the exit fuctions.
+  mov  bx,[___cleanup] ! Call exit, normally this is `__do_exit`
+  test bx,bx
+  je   no_clean        ! But it`s default is null
+  call bx
+no_clean:
+  inc  sp
+  inc  sp
+
+export __exit
+__exit:
+  xor  ax,ax
+  mov  es,ax
+  seg  es
+  mov  [$E6*4+2],cs    !
+  seg  es
+  mov  [$E6*4],#iret_ins
+  dec  ax              ! AX = $FFFF
+  int  $E6             ! Try to exit DOSEMU
+                       ! If we get here we`re not in dosemu.
+  seg es
+  mov  [$472],#$1234   ! Warm reboot.
+  
+  jmpi $0000,$FFFF     ! DO NOT SEPARATE
+iret_ins:              ! THIS LABEL FROM THE  jmpi ...
+  iret                 ! interrupt return!! not  retf (==reti)
+
+export ___mkargv       ! must resolve this reference
+___mkargv:
+  ret
+
+#endasm
+
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_write
+write(fd,buf,len)
+int fd,len;
+char * buf;
+{
+   register int v, c;
+   if(fd == 1 || fd == 2)
+   {
+      for(v=len; v>0; v--)
+      {
+         c= *buf++;
+         if( c == '\n') bios_putc('\r');
+        bios_putc(c);
+      }
+      return len;
+   } 
+   return (*__files)(CMD_WRITE, fd, buf, len);
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_read
+read(fd,buf,len)
+int fd,len;
+char * buf;
+{
+   if(fd == 0) return bios_rdline(buf, len);
+   return (*__files)(CMD_READ, fd, buf, len);
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_lseek
+long
+lseek(fd, offt, whence)
+int fd, whence;
+long offt;
+{
+   if( fd >= 0 && fd <= 2 ) errno = ESPIPE;
+   else 
+   {
+      if( (*__files)(CMD_LSEEK, fd, &offt, whence) >= 0 )
+         return offt;
+   }
+   return -1L;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_close
+close(fd)
+int fd;
+{
+   if( fd >= 0 && fd <= 2 ) errno = ENOSYS;
+   else
+      return (*__files)(CMD_CLOSE, fd);
+   return -1;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_nofiles
+int (*__files)() = __nofiles;
+
+int __nofiles(cmd, fd, buf, len)
+int cmd, fd, len;
+char * buf;
+{ 
+   errno = EBADF;
+   return -1;
+}
+
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_isatty
+isatty(fd)
+int fd;
+{
+   if( fd >= 0 && fd <= 2 ) return 1;
+   return 0;
+}
+#endif
+
+/****************************************************************************/
+
+#endif
+#endif
+#endif
diff --git a/diagnose/cprintf.c b/diagnose/cprintf.c
new file mode 100644 (file)
index 0000000..f0b9f54
--- /dev/null
@@ -0,0 +1,248 @@
+/* Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/* Modified 14-Jan-2002 by John Coffman <johninsd@san.rr.com> for inclusion
+ * in the set of LILO diagnostics.  This code is the property of Robert
+ * de Bath, and is used with his permission.
+ */
+
+#include <stdarg.h>
+/* #include <conio.h> */
+#define ASM_CVT 1
+
+#if __MSDOS__
+#include <stdio.h>
+#define putch(ch) fputc(ch,stdout)
+#else
+#define putch(ch) bios_putc(ch)
+#endif
+
+static unsigned char * __numout(long i, int base);
+
+int cprintf(char * fmt, ...)
+{
+   register int c;
+   int count = 0;
+   int type, base;
+   long val;
+   char * cp;
+   char padch=' ';
+   int  minsize, maxsize;
+   va_list ap;
+
+   va_start(ap, fmt);
+
+   while(c=*fmt++)
+   {
+      count++;
+      if(c!='%')
+      {
+        if (c=='\n') putch('\r');
+        putch(c);
+      }
+      else
+      {
+        type=1;
+        padch = *fmt;
+        maxsize=minsize=0;
+        if(padch == '-') fmt++;
+
+        for(;;)
+        {
+           c=*fmt++;
+           if( c<'0' || c>'9' ) break;
+           minsize*=10; minsize+=c-'0';
+        }
+
+        if( c == '.' )
+           for(;;)
+           {
+              c=*fmt++;
+              if( c<'0' || c>'9' ) break;
+              maxsize*=10; maxsize+=c-'0';
+           }
+
+        if( padch == '-' ) minsize = -minsize;
+        else
+        if( padch != '0' ) padch=' ';
+
+        if( c == 0 ) break;
+        if(c=='h')
+        {
+           c=*fmt++;
+           type = 0;
+        }
+        else if(c=='l')
+        {
+           c=*fmt++;
+           type = 2;
+        }
+
+        switch(c)
+        {
+           case 'x': base=16; type |= 4;   if(0) {
+           case 'o': base= 8; type |= 4; } if(0) {
+           case 'u': base=10; type |= 4; } if(0) {
+           case 'd': base=-10; }
+              switch(type)
+              {
+                 case 0: val=va_arg(ap, short); break; 
+                 case 1: val=va_arg(ap, int);   break;
+                 case 2: val=va_arg(ap, long);  break;
+                 case 4: val=va_arg(ap, unsigned short); break; 
+                 case 5: val=va_arg(ap, unsigned int);   break;
+                 case 6: val=va_arg(ap, unsigned long);  break;
+                 default:val=0; break;
+              }
+              cp = __numout(val,base);
+              if(0) {
+           case 's':
+                 cp=va_arg(ap, char *);
+              }
+              count--;
+              c = strlen(cp);
+              if( !maxsize ) maxsize = c;
+              if( minsize > 0 )
+              {
+                 minsize -= c;
+                 while(minsize>0) { putch(padch); count++; minsize--; }
+                 minsize=0;
+              }
+              if( minsize < 0 ) minsize= -minsize-c;
+              while(*cp && maxsize-->0 )
+              {
+                 putch(*cp++);
+                 count++;
+              }
+              while(minsize>0) { putch(' '); count++; minsize--; }
+              break;
+           case 'c':
+              putch(va_arg(ap, int));
+              break;
+           default:
+              putch(c);
+              break;
+        }
+      }
+   }
+   va_end(ap);
+   return count;
+}
+
+static char nstring[]="0123456789ABCDEF";
+
+#if ASM_CVT==0
+#define NUMLTH 11
+
+static unsigned char *
+__numout(long i, int base)
+{
+   static unsigned char out[NUMLTH+1];
+   int n;
+   int flg = 0;
+   unsigned long val;
+
+   if (base<0)
+   {
+      base = -base;
+      if (i<0)
+      {
+        flg = 1;
+        i = -i;
+      }
+   }
+   val = i;
+
+   out[NUMLTH] = '\0';
+   n = NUMLTH-1;
+   do
+   {
+      out[n--] = nstring[val % base];
+      val /= base;
+   }
+   while(val);
+   if(flg) out[n--] = '-';
+   return &out[n+1];
+}
+#else
+
+#asm
+! numout.s
+!
+#if 0
+.data
+_nstring:
+.ascii "0123456789ABCDEF"
+.byte  0
+#endif
+
+.bss
+___out lcomm   $C
+
+.text
+___numout:
+push   bp
+mov    bp,sp
+push   di
+push   si
+add    sp,*-4
+mov    byte ptr -8[bp],*$0     ! flg = 0
+mov    si,4[bp]        ; i or val.lo
+mov    di,6[bp]        ; i or val.hi
+mov    cx,8[bp]        ; base
+test   cx,cx                   ! base < 0 ?
+jge    .3num
+neg  cx                                ! base = -base
+or     di,di                   ! i < 0 ?
+jns    .5num
+mov    byte ptr -8[bp],*1      ! flg = 1
+neg    di                      ! i = -i
+neg    si
+sbb    di,*0
+.5num:
+.3num:
+mov    byte ptr [___out+$B],*$0        ! out[11] = nul
+mov    -6[bp],*$A              ! n = 10
+
+.9num:
+!!!         out[n--] = nstring[val % base];
+xor  dx,dx
+xchg ax,di
+div  cx
+xchg ax,di
+xchg ax,si
+div  cx
+xchg ax,si                     ! val(new) = val / base
+
+mov  bx,dx                     ! dx = val % base
+
+mov    al,_nstring[bx]
+mov    bx,-6[bp]
+dec    word ptr -6[bp]
+mov    ___out[bx],al
+
+mov  ax,si
+or   ax,di                     ! while (val)
+jne    .9num
+
+cmp    byte ptr -8[bp],*$0     ! flg == 0 ?
+je     .Dnum
+
+mov    bx,-6[bp]
+dec    word ptr -6[bp]
+mov    byte ptr ___out[bx],*$2D        ! out[n--] = minus
+
+.Dnum:
+mov    ax,-6[bp]
+add    ax,#___out+1
+
+add    sp,*4
+pop    si
+pop    di
+pop    bp
+ret
+#endasm
+
+#endif
diff --git a/diagnose/sector.S b/diagnose/sector.S
new file mode 100644 (file)
index 0000000..f5baa98
--- /dev/null
@@ -0,0 +1,395 @@
+; sector.S -- boot program named:  HIPBOOT.SYS
+;             from any MSDOS floppy diskette
+;
+; Copyright 2001-2005 John Coffman.
+; All rights reserved.
+;
+; Licensed under the terms contained in the file 'COPYING' in the LILO
+; source directory.
+;
+#define DEBUG 0                /* enables loading .EXE for codeview debugging */
+#define OPTION 1       /* enables fast directory search exit */
+#define LARGE 0                /* enables loading code >32K */
+#define TESTFAT 0      /* enables testing for FAT12/FAT16 */
+#define SYSSEG 0x1000          /* load at a fixed address SYSSEG:0000 */
+
+;;directory_entry         
+                       block   0
+
+dir_filename:          .blkb   8
+dir_filename_ext:      .blkb   3
+dir_attribute:         .blkb   1
+dir_Reserved:          .blkb   10
+dir_time_updated:      .blkw   1
+dir_date_updated:      .blkw   1
+dir_cluster:           .blkw   1
+dir_file_size:         .blkw   2
+
+dir_entry_size:
+                       endb
+
+base    equ     0x7C00
+buffer  equ     0x0500          ;scratch disk buffer
+
+
+
+
+
+;contAddr  equ   SS:[bp-4]      ;dword     DO NOT MOVE
+;dataBase  equ   SS:[bp-8]       ;dword    DO NOT MOVE
+;FATshift  equ   SS:[bp-9]      ; byte 
+;diskNumber  equ SS:[bp-10]      ; byte    DO NOT MOVE
+;dirBase equ     SS:[bp-14]       ;dword
+;nDirSec equ     SS:[bp-16]      ;word
+;FATsector equ   SS:[bp-18]      ;word
+;FATnibbles  equ SS:[bp-20]      ;word
+
+
+stacksize      equ     20
+
+
+                       block   -stacksize
+
+FATnibbles:    .blkw   1
+FATsector:     .blkw   1
+nDirSec:       .blkw   1
+dirBase:       .blkw   2
+diskNumber:    .blkb   1       ; DO NOT MOVE
+FATshift:      .blkb   1
+dataBase:      .blkw   2       ; DO NOT MOVE
+contAddr:      .blkw   2       ; DO NOT MOVE
+
+stack: /* this had better be zero */
+
+               .blkb   3       ; jump instruction
+               .blkb   8       ; system ID string
+secSiz:                .blkw   1       ; bytes_per_sector
+secPerCl:      .blkb   1       ; sectors_per_cluster
+FATbase:       .blkw   1       ; reserved_sectors
+nFATs:         .blkb   1       ; FAT_copies
+nDirEnt:       .blkw   1       ; directory_entries
+totSec:                .blkw   1       ; total_sectors
+media:         .blkb   1       ; media_descriptor
+secPerFAT:     .blkw   1       ; sectors_per_FAT
+nSEC:          .blkw   1       ; sectors_per_track
+nSides:                .blkw   1       ; heads_per_cylinder
+hidSec:                .blkw   2       ; hidden_sectors
+               .blkb   22
+fs_id:         .blkb   8       ; filesystem_id
+
+                       endb
+
+.globl _main
+                       org     0
+; jump instruction
+_main:                 jmp     beginning
+                       nop
+
+system_id_string:      .ascii  "DISKBOOT"      ; 8 chars
+
+msdos_boot_data:
+
+bytes_per_sector:      dw      512
+sectors_per_cluster:   db      1
+reserved_sectors:      dw      1
+FAT_copies:            db      2
+directory_entries:     dw      224       ; 112 & 224 are typical
+total_sectors:         dw      2880
+media_descriptor:      db      0xf0      ; 0f9H, 0f0h, 0fAh, etc.
+sectors_per_FAT:       dw      9
+sectors_per_track:     dw      18
+heads_per_cylinder:    dw      2
+hidden_sectors:                dd      0       ; always zero for floppies
+total_sectors_2:       dd      0       ; actual value if 'total_sectors' is zero
+BPB_rsvd:              dw      0       ; reserved
+vol_id_marker:         db      0x29    ; marker? for volume ID
+serial_number:         dd      0       ; volume unique ID number
+
+volume_label:          .ascii  "NO NAME    "   ; 11 chars
+filesystem_id:         .ascii  "FAT12   "      ;  8 chars
+
+
+
+beginning:
+        xor     ax,ax
+        mov     bp,#base         ;origin at 7C00
+#if DEBUG
+        xor     dl,dl
+        mov     ax,ss
+#endif
+        cli
+        mov     ss,ax
+        lea     sp,(bp-stacksize)
+        sti
+
+        cld
+        mov     es,ax           ;both at zero
+        mov     ds,ax
+#if DEBUG
+        xor     ax,ax
+#endif
+        mov     diskNumber(bp),dl   ;save disk number
+        int     0x13             ;reset the disk system
+        jc      error
+noError:
+        mov     ax,#0x0403        ;shift=4, nibbles=3 -- FAT12
+fat12   equ     *-2
+#if TESTFAT
+        cmp     byte ptr fs_id+4(bp),#$36      ; '6'
+        jne     isFAT12
+        mov     ax,#0004        ;shift=0, nibbles=4 -- FAT16
+isFAT12:
+#endif
+        mov     FATshift(bp),ah     ;set shift count
+        cbw
+        mov     FATnibbles(bp),ax   ;set number of nibbles per FAT index entry
+
+        mov     al,nFATs(bp)        ;number of FATs
+;       cbw
+        mul     word ptr secPerFAT(bp)       ;* sectors per FAT
+        add     ax,FATbase(bp)      ;+ FAT base
+        adc     dx,#0            ; SI = 0
+        mov     dirBase(bp),ax
+        mov     dirBase+2(bp),dx    ;save directory base
+
+        mov     dataBase(bp),ax
+        mov     dataBase+2(bp),dx   ;still forming Data base 
+
+        mov     ax,#dir_entry_size
+        mul     word ptr nDirEnt(bp)
+        mov     bx,secSiz(bp)
+        add     ax,bx           
+        dec     ax
+        div     bx              ;get base of data
+#if DEBUG
+        add     bx,bx
+#endif
+#if SYSSEG
+        mov     contAddr(bp),ss            ; SS = 0
+        mov     word ptr contAddr+2(bp),#SYSSEG      ; begin at SYSSEG:0000
+#else
+        add     bx,#base
+        mov     contAddr(bp),bx     ;save continuation address
+        mov     contAddr+2(bp),es
+#endif
+        mov     nDirSec(bp),ax      ;save no. of Directory sectors
+        add     dataBase(bp),ax
+        adc     word ptr dataBase+2(bp),#0           ; SI = 0
+
+; scan the directory for the required bootstrap file
+
+        mov     ax,dirBase(bp)      ; starting disk block in DX:AX
+        mov     dx,dirBase+2(bp)
+dirscan:
+        mov     bx,#buffer        ; ES:BX points to buffer
+        call    ReadSector
+        mov     di,bx
+        mov     bx,secSiz(bp)
+dirscan1:
+        
+        call    S21
+tofind: .ascii "HIPBOOT SYS"
+
+error:
+        call    write
+        db      13,10,10
+       .ascii  'Non-SYSTEM disk or disk error'
+        db      13,10
+       .ascii  'Press any key to re-boot ...'
+       db      0
+done:
+        xor     ax,ax
+        int     0x16             ;wait for keypress
+        int     0x19             ;re-boot
+
+
+S21:    pop     si
+        push    di
+        mov     cx,#11           ;name length
+        rep     
+        seg cs
+         cmpsb    ;byte ptr CS:[si],ES:[di]
+        pop     di
+        je      hipboot
+#if OPTION
+        cmp     byte ptr (di),#0
+        je      endOfDirectory
+#endif
+        lea     di,dir_entry_size(di)
+        sub     bx,#dir_entry_size
+        jg      dirscan1
+
+        inc     ax
+        dec     word ptr nDirSec(bp)
+        jnz     dirscan
+endOfDirectory:
+error2:
+        jmp     error
+
+ReadSector:
+        push    dx              ;save registers
+        push    cx
+        push    ax
+        
+        add     ax,hidSec(bp)       ;+ Hidden Sectors
+        adc     dx,hidSec+2(bp)     ;
+        xchg    ax,dx
+        push    dx              ;AX=dividend-hi, DX=dividend-low
+        cwd
+        div     word ptr nSEC(bp)            ;DX=remainder, AX=quo-hi
+        
+        pop     cx
+        xchg    ax,cx           ;CX=quo-hi, DX:AX=dividend-low
+        div     word ptr nSEC(bp)            ;remainder is sector number, zero based
+        inc     dx              ;DX=sector#, CX:AX=quotient
+        push    dx              ;save sector number
+
+        mov     dx,cx           ;DX:AX=quotient
+        div     word ptr nSides(bp)          ;DX = side, AX = Cyl No.
+        mov     cl,#6
+        shl     ah,cl           ;AH is hi-bits of cyl no.
+        pop     cx              ;restore sector number
+        or      cl,ah
+        mov     ch,al
+        mov     dh,dl
+        mov     dl,diskNumber(bp)
+retry:
+        mov     ax,#0x0201        ;BIOS read 1 sector
+        int     0x13
+#if DEBUG
+        jnc     readcont
+        xor     ax,ax
+        int     0x13
+        jmp     retry
+readcont:
+#endif
+error3:
+        jc      error2
+        pop     ax
+        pop     cx
+        pop     dx
+        ret
+
+hipboot:
+        mov     cx,dir_cluster(di)
+        mov     word ptr FATsector(bp),#-1    ;no FAT sector present
+        les     bx,contAddr(bp)     ;get continue address
+nextCluster:
+        call    readCluster
+        push    es
+        push    bx
+        mov     ax,FATnibbles(bp)   ;get number of nibbles in a FAT entry
+        mul     cx              ;DX:AX is nibble index
+        shr     dx,1
+        rcr     ax,1            ;DX:AX is byte index, CF=odd/even
+        pushf                   ;save CF
+        mov     si,secSiz(bp)       ;sector size to SI
+        div     si              ;AX is rel. sector, DX is byte offset
+        mov     di,dx           ;DI is byte offset
+        push    ds
+        pop     es
+        mov     bx,#buffer
+        call    ForceFatSector  ;AX is rel. FATsector to force
+        mov     dl,(bx+di)   ;get low byte
+        dec     si
+        inc     di
+        and     di,si           ;mask DI byte offset
+        jnz     sameFATsec
+        inc     ax
+        call    ForceFatSector
+sameFATsec:
+        mov     dh,(bx+di)
+        popf                    ;restore shift flag
+        mov     cl,FATshift(bp)
+        jc      shiftIt
+        shl     dx,cl
+shiftIt:
+        shr     dx,cl
+        mov     si,#-1
+        shr     si,cl           ;si is EOF
+        and     si,#-8         ;0xFFF8
+        mov     cx,dx           ;CX is next cluster
+        pop     bx
+        pop     es
+
+        cmp     cx,si
+        jb      nextCluster
+
+        mov     ch,media(bp)        ;pass on media descriptor
+        lea     sp,diskNumber(bp)
+        pop     dx
+        pop     bx              ;low order start of data
+        pop     ax              ;high order start of data
+#if DEBUG
+        jmp     done
+#endif
+        retf
+
+
+readCluster:
+        push    cx
+        mov     al,secPerCl(bp)     ;sectors per cluster
+        cbw
+        xchg    ax,cx           ;AX=cluster #,  CX=# sectors per cluster
+        dec     ax
+        dec     ax              ;base it at 0, instead of 2
+        mul     cx
+        add     ax,dataBase(bp)     ;offset onto disk
+        adc     dx,dataBase+2(bp)
+readClus1:
+        call    ReadSector      ;read a sector
+        add     bx,secSiz(bp)       ;update address
+#if LARGE
+        jnc     readClus2
+        mov     si,es           ;get segment register
+        add     si,#0x1000        ;REAL mode increment
+        mov     es,si           ;update segment register
+#else
+        jc      error3          ;segment overflow
+#endif
+readClus2:
+        inc     ax              ;update sector number
+        jnz     readClus3
+        inc     dx
+readClus3:
+        loop    readClus1
+
+        pop     cx
+        ret
+
+
+ForceFatSector:
+        push    dx
+        cmp     ax,FATsector(bp)
+        je      gotFATsector
+        mov     FATsector(bp),ax
+        add     ax,FATbase(bp)
+        xor     dx,dx
+        call    ReadSector
+gotFATsector:
+        pop     dx
+        ret
+
+
+
+write:
+        pop     si              ;get character string pointer
+write1:
+       seg cs
+        lodsb   ;byte ptr CS:[si]
+        test    al,al
+        jz      return
+        mov     ah,#0x0e
+        mov     bx,#7
+        int     0x10
+        jmp     write1
+return:
+        jmp     si
+
+       org     510
+       dw      0xAA55          ; BOOT_SIGNATURE
+
+endup:
+theend:
+
+
diff --git a/diagnose/test4.c b/diagnose/test4.c
new file mode 100644 (file)
index 0000000..60383bc
--- /dev/null
@@ -0,0 +1,1255 @@
+/* test4.c */
+/*
+ Copyright 2001-2005 John Coffman.
+ All rights reserved.
+
+ Licensed under the terms contained in the file 'COPYING' in the LILO
+ source directory.
+
+*/
+#include <bios.h>
+#include "../src/bdata.h"
+
+#define DISK_VERSION "2.4"
+
+#if __MSDOS__==0
+#define putch bios_putc
+#define getch bios_getc
+#define printf cprintf
+#define CR 13
+#else
+#include <stdio.h>
+#define putch(c) fputc((c),stdout)
+#define getch getchar
+#define CR 10
+#endif
+
+#define CTRL_C 03
+#define SPACER "\f\n"
+#define SEQ 0x3C4
+
+#define FS_REG 0x80
+
+#ifndef EDD_SUBSET
+#define EDD_SUBSET 4
+#define EDD_LOCK 2
+#define EDD_PACKET 1
+#endif
+#ifndef SECTOR_SIZE
+#define SECTOR_SIZE 512
+#endif
+#define nelem(a) (sizeof(a)/sizeof((a)[0]))
+
+typedef unsigned char  byte;
+typedef unsigned short word;
+typedef unsigned long dword;
+
+extern union REGS   __argr;
+extern struct SREGS __argseg;
+
+union REGS reg, oreg;
+struct SREGS sreg;
+int last_good_disk;
+int video_1 = 0xF00;
+int fs_mod = 0;
+int num_hd = BD_MAX_HARD;
+int errno;
+dword hma;     /* highest memory address */
+struct {
+  long start, start_hi,
+       length, length_hi,
+       mtype;
+    } mem_map;
+#define E820_MAGIC 0x534D4150
+
+struct gdt_entry {
+       unsigned short limit;
+       unsigned short base01;
+       unsigned char  base2;
+       unsigned char  dtype;   /* 0x93 for data */
+       unsigned char  limit2;  /* limit in low nibble, granularity & 32-bit in high nibble */
+       unsigned char  base3;
+};
+
+struct gdt_entry gdt[6];
+
+static
+int get_fs(void)
+{
+#asm
+ mov ax,fs
+#endasm
+}
+
+static
+int set_fs(int val)
+{
+    int i = val;
+#asm
+ mov ax,4[bp]
+ mov fs,ax
+#endasm
+    return i;
+}
+
+static
+int check_fs(void)
+{
+    int ret = 0;
+
+#if DEBUG>=2    
+    printf("#");
+#endif    
+    if (get_fs() != FS_REG) {
+        fs_mod = ret = 1;
+        printf("\nThe FS register has been modified.\n");
+        set_fs(FS_REG);
+    }
+    return ret;
+}
+
+static
+int hicopy (unsigned long to, unsigned long from, int wcount)
+{
+    int status;
+    unsigned char save;
+    
+    memset(gdt, 0, sizeof(gdt));
+    gdt[2].limit = gdt[3].limit = 0xFFFF;
+    gdt[2].dtype = gdt[3].dtype = 0x93;
+    
+    gdt[2].base01 = from;
+    gdt[2].base2 = from>>16;
+    gdt[2].base3 = from>>24;
+    
+    gdt[3].base01 = to;
+    gdt[3].base2 = to>>16;
+    save = gdt[3].base3 = to>>24;
+    
+    segread(&sreg);
+    sreg.es = sreg.ds;
+    reg.h.ah = 0x87;
+    reg.x.cx = wcount;
+    reg.x.si = gdt;
+/***    gdt[3].base3 &= 0;   / crosstalk */
+    int86x(0x15, &reg, &oreg, &sreg);
+    
+    status = oreg.h.ah;
+    if (oreg.x.cflag) status |= 0x100;
+    if (save!=gdt[3].base3) status |= 0x200;
+    errno |= status;
+    return status;
+}
+
+unsigned long linear(void *ptr)
+{
+    segread(&sreg);
+    return ((unsigned long)sreg.ds<<4) + (unsigned int)ptr;
+}
+
+word hipeekw(long address)
+{
+    word temp;
+    hicopy(linear(&temp), address, 1);
+    return temp;
+}
+
+int hipokew(long address, word value)
+{
+    return hicopy(address, linear(&value), 1);
+}
+
+#if __MSDOS__==0
+static
+bios_putc0(int c)
+{
+    union REGS reg;
+    if (c=='\f') {
+#if 0
+       reg.h.ah = 0x0F;
+       int86(0x10, &reg, &reg);
+       reg.h.ah = 0;
+       int86(0x10, &reg, &reg);
+#else
+       static word upper = 0;
+       if (!upper) {
+           __set_es(0x40);     /* address BIOS data area */
+           upper = __peek_es(0x84);
+           if (upper < 24 || upper > 50) upper = 24;
+           upper <<= 8;
+           reg.h.ah = 0x0F;    /* get video mode */
+           int86(0x10, &reg, &reg);
+           upper |= (reg.h.ah-1);
+       }
+       reg.x.ax = 0x0600;      /* blank screen area */
+       reg.h.bh = 7;
+       reg.x.cx = 0x0000;
+       reg.x.dx = upper;
+       int86(0x10, &reg, &reg);
+       reg.h.ah = 2;           /* set cursor position */
+       reg.h.bh = 0;
+       reg.x.dx = 0x0000;
+       int86(0x10, &reg, &reg);
+#endif
+    } else {
+       reg.h.al = c;
+       reg.h.ah = 14;
+       reg.x.bx = 7;
+       int86(0x10, &reg, &reg);
+    }
+}
+
+void bios_putc(char c)
+{
+static int col;
+   
+    switch(c) {
+    case '\t':
+       do bios_putc(' '); while(col&7);
+       break;
+    case '\n':  bios_putc0('\r');
+       /* fall into CR */
+    case '\f':
+    case '\r': col=0;
+    default:
+        bios_putc0(c);
+       if (c>=' ' && c<0177) col++;
+    }
+}
+#endif
+
+static
+int a20(void)  /* Return 1 if a20 is enabled, 0 if disabled */
+{
+#asm
+ push  ds
+ push  es
+ xor   ax,ax
+ mov   es,ax
+ dec   ax
+ mov   ds,ax
+ cli
+ mov   al,[0x10]
+ mov   ah,al
+ seg es
+ cmp   al,[0]
+ jne   a20_8
+ xor   al,#0x5A
+ mov   [0x10],al
+ seg es
+ cmp   al,[0]
+ jne   a20_8
+ xor   al,al
+ jmp   a20_9
+a20_8:
+ mov   al,#1
+a20_9:
+ mov   [0x10],ah
+ cbw
+ sti
+ pop   es
+ pop   ds
+#endasm
+}
+
+static
+void sizeit(unsigned long sectors)
+{
+static char suf[] = "KMGT";
+    int fract;
+    char *cp;
+
+/* print disk size in K,M,G,T */
+    sectors /= 2;
+    cp = suf;
+    if (sectors <= 999) {
+       printf("%ld%c", sectors, *cp);
+       return;
+    }
+    cp++;
+    while (sectors > 999999) {
+       sectors /= 1000;
+       cp++;
+    }
+    if (sectors > 2999) {
+       sectors *= 1024;
+       sectors /= 1000;
+    }
+    sectors += 5;      /* round decimal part */
+    sectors /= 10;
+    fract = sectors % 100;
+    sectors /= 100;
+    printf("%ld.%02d%c", sectors, fract, *cp);
+}
+
+static
+void banner(char *version)
+{
+       printf( "\n\n\n"
+">>>> Disk Detection and Parameter Display <<<<\n\n\n"
+"Version %s, Copyright (C) 1999-2005  John Coffman <johninsd@san.rr.com>\n"
+"Portions Copyright (C) 1996-2001 Robert de Bath, used with permission\n"
+"Re-use and redistribution rights set forth in the file \"COPYING\".\n\n",
+        version);
+}
+
+static
+void testDX(void)
+{
+#if __MSDOS__==0
+   printf("Boot reported from DX = 0x%04x (boot device is 0x%02x in DL)\n", __argr.x.dx, __argr.h.dl);
+   if (__argr.h.dl == 0 || __argr.h.dl == 1) {
+       printf("If you booted from the %s floppy drive, then this is correct.",
+               __argr.h.dl ? "second" : "first");
+   } else if (__argr.h.dl >= 0x80 && __argr.h.dl <= 0x8f) {
+       printf("If you booted from %s hard drive, then this is correct.",
+               __argr.h.dl==0x80 ? "the first" :
+               __argr.h.dl==0x81 ? "the second" : "a" );
+   } else {
+       printf("It looks like the BIOS failed to report the boot device in DL.\n");
+   }
+#endif
+}
+
+
+
+static
+int smsw(void)
+{
+#asm
+  smsw ax
+#endasm
+}
+
+static
+long e820(long b)
+{
+#asm
+  push bp
+  mov  bp,sp
+  push ds
+  pop  es
+  mov  di,#_mem_map
+  mov  eax,#0xE820
+  mov  ebx,[bp+4]
+  mov  ecx,#20
+  mov  edx,#E820_MAGIC
+  stc
+  int  0x15
+  jc   e820_err
+  cmp  eax,#E820_MAGIC
+  mov  ax,#-2
+  jne  e820_exit
+  cmp  ecx,#20
+  mov  ax,#-3
+  jne  e820_exit
+  push ebx
+  pop  ax
+  pop  dx
+  jmp  e820_exit
+e820_err:
+  mov  ax,#-1
+e820_err2:
+  cwd
+e820_exit:
+  leave
+#endasm
+}
+
+static
+int inb(int port)
+{
+#asm
+  mov  bx,sp
+  mov  dx,[bx+2]
+  in   al,dx
+  xor  ah,ah
+#endasm
+}
+
+static
+int outb(int port, int data)
+{
+#asm
+  mov  bx,sp
+  mov  dx,[bx+2]
+  mov  ax,[bx+4]
+  out  dx,al
+#endasm
+}
+
+static
+void v86test(void)
+{
+static char s1[] = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
+
+    if (smsw()&1) {
+       printf(s1);
+       printf( "!!! ***  Warning:  DOS is not running in REAL mode  *** !!!\n"
+               "!!! ***     Reported results may not be accurate    *** !!!\n" );
+       printf(s1);
+    }
+}
+
+static
+void yesno(int i)
+{
+    printf("%s\n", i?"yes":"no");
+}
+
+static
+void decimal(unsigned long value)
+{
+    unsigned int v[4];
+    int i;
+    for (i=0; i<4; i++) {
+       v[i] = value % 1000;
+       value /= 1000;
+    }
+    if (v[3]) printf("%d,%03d,%03d,%03d", v[3], v[2], v[1], v[0]);
+    else if (v[2]) printf("%d,%03d,%03d", v[2], v[1], v[0]);
+    else if (v[1]) printf("%d,%03d", v[1], v[0]);
+    else printf("%d", v[0]);
+}
+
+static
+void print_regs(union REGS *reg) {
+    printf("AX=%04x  BX=%04x  CX=%04x  DX=%04x  SI=%04x  DI=%04x\n",
+    reg->x.ax, reg->x.bx, reg->x.cx, reg->x.dx, reg->x.si, reg->x.di);
+}
+
+static 
+void print_sregs(struct SREGS *sreg) {
+    printf("DS=%04x  ES=%04x  CS=%04x  SS=%04x\n",
+               sreg->ds, sreg->es, sreg->cs, sreg->ss);
+}
+
+static
+int is_msdos(void)
+{
+#if __MSDOS__
+    return 1;
+#else
+    return (__argseg.es+0x10 == __argseg.cs);
+#endif
+}
+
+static
+void pause(void)
+{
+       char ch;
+/* Must be standalone */
+        check_fs();
+       printf("\n\n\nHit <Enter> to continue, <^C> to quit ...");
+       do {
+           ch = getch();
+           if (ch==CTRL_C) exit(0);
+#if DEBUG>=1
+           if (ch != CR) printf(" %o", ch);
+#endif
+       } while (ch != CR);
+       printf("\n");
+}
+
+static
+void video_fix(void)
+{
+   outb(SEQ, 1);
+   video_1 = inb(SEQ+1);
+/* dirty hack for DELL Dimension 4300 computers */
+   printf("\f\n");
+}
+
+static void print_carry(int flag)
+{
+    printf("    Carry = %d\n", flag);
+}
+
+static
+void get_equip_cfg(void)
+{
+static char *vmode[4] = { "reserved", "40x25 color",
+               "80x25 color", "80x25 monochrome" };
+    word flag;
+    int n;
+    
+    pause();
+    printf(SPACER
+               "Int 11h\t\t\t\t[PC][AT][PS/2]\n"
+               "Get Equipment Configuration\n\n"
+               "Returns:\n    ");
+    flag = int86(0x11, &reg, &reg);
+    print_regs(&reg);
+    
+    printf("\nHas floppy drive(s): "); yesno(flag&1);
+    printf("Has math coprocessor: "); yesno(flag&2);
+    printf("Has pointing device: "); yesno(flag&4);
+    printf("Initial video mode: %s\n", vmode[(flag>>4)&3]);
+    n = flag&1 ? ((flag>>6)&3)+1 : 0;
+    if (n) printf("Floppy drives installed: %d\n", ((flag>>6)&3)+1 );
+    n = (flag>>9)&7;
+    printf("Serial interfaces: %d\n", n);
+    printf("Has game adapter: "); yesno(flag&4096);
+    n = (flag>>14)&3;
+    printf("Parallel interfaces: %d\n", n);
+}
+
+static
+void get_conv_mem(void)
+{
+    int mem;
+    
+    pause();
+    printf(SPACER
+               "Int 12h\t\t\t\t[PC][AT][PS/2]\n"
+               "Get Conventional Memory Size\n\n"
+               "Returns:\n    ");
+    mem = int86(0x12, &reg, &reg);
+    print_regs(&reg);
+    printf("\nThere is %dK of low memory.    EBDA size = %dK   EBDA starts at 0x%lx\n",
+       mem, 640-mem, (long)mem<<10 );
+    printf("\n(The A20 line is %sabled.)\n", a20() ? "en" : "dis");
+}
+
+static
+void mov_ext_mem(void)
+{
+    word status, temp, vtemp;
+    dword high, veryhigh;
+        
+    pause();
+    segread(&sreg);
+    sreg.es = sreg.ds;
+    printf(SPACER
+               "Int 15h  Function 87h\t\t[AT][PS/2]\n"
+               "Move Extended Memory Block\n\n"
+               "Call With:\n    ");
+               print_sregs(&sreg);
+               reg.x.ax = 0x8700;
+               reg.x.cx = 1;
+               reg.x.si = &gdt;
+               printf("    ");
+               print_regs(&reg);
+               
+       high = 1024L*(1024L+128)-2;     /* 1Mb + 128K */
+       veryhigh = high+16L*1024L*1024L;
+       if (veryhigh >= hma) veryhigh=0;
+#define WORDA 0xA5C6
+#define WORDB 0x6CA5
+
+       errno = 0;
+       temp = hipeekw(high);
+       status = hipokew(high, WORDA^temp);
+       printf("\nReturns:\n    ");
+       print_sregs(&sreg);
+       printf("    ");
+       print_regs(&oreg);
+       print_carry((status>>8) & 1);
+
+       printf("\nR/W test at address %08lx ", high);
+       if (hipeekw(high) != (WORDA^temp)) errno |= 0x400;
+       hipokew(high, temp);
+       if (hipeekw(high) != temp) errno |= 0x800;
+       printf("%ssuccessful\n", errno ? "un" : "");
+       if (errno) printf("Error code = 0x%04x\n", errno);
+       
+       if (veryhigh) {
+               printf("R/W test at address %08lx ", veryhigh);
+               vtemp = hipeekw(veryhigh);
+               hipokew(veryhigh, WORDB^vtemp);
+               if (hipeekw(high) != temp) errno |= 0x200;
+               if (hipeekw(veryhigh) != (WORDB^vtemp)) errno |= 0x400;
+               hipokew(veryhigh, vtemp);
+               if (hipeekw(high) != temp) errno |= 0x200;
+               if (hipeekw(veryhigh) != vtemp) errno |= 0x800;
+               printf("%ssuccessful\n", errno ? "un" : "");
+               if (errno) printf("Error code = 0x%04x\n", errno);
+       }
+       if (errno & 0xE00)
+           printf("\nThere is crosstalk between the two addresses\n"
+               "The function does not support full 386 32-bit addressing.\n");
+}
+
+#define NAREA 32
+
+static
+void get_ext_mem(void)
+{
+    long b, b1;
+    dword t;
+    int i;
+    
+    pause();
+    printf(SPACER
+               "Int 15h  Function E820h\t\t[EXT]\n"
+               "Get Memory Map\n\n"
+               "Call With:\n"
+               "    EAX=0000E820  EBX=00000000  ECX=00000014  EDX=%lx\n\n",
+               E820_MAGIC );
+
+    b = e820(b1=i=0);
+    if (b > 0) {
+       dword start[NAREA], length[NAREA];
+       int j, k, ovlap;
+
+    /*           00    000000000000   000000000000   (1) avail */
+       printf("EBX        Start         Length      Type\n\n");
+       do {
+           printf(" %02lx    %04hx%08lx   %04hx%08lx   (%d) %s\n", b1,
+               (short)mem_map.start_hi, mem_map.start,
+               (short)mem_map.length_hi, mem_map.length, (int)mem_map.mtype,
+               mem_map.mtype == 1 ? "available" :
+               mem_map.mtype == 2 ? "reserved"  :
+               mem_map.mtype == 3 ? "ACPI" :
+               mem_map.mtype == 4 ? "NVS"  :  "unknown-reserved");
+           if (mem_map.mtype==1 && mem_map.start_hi==0 && mem_map.start<=1024L*1024L) {
+               if (mem_map.length_hi==0) hma = mem_map.start+mem_map.length;
+               else hma = 0xFFF00000L;
+           }
+           if (i < NAREA) {
+               start[i] = *(dword*)(((char*)&mem_map.start)+1);
+               length[i] = *(dword*)(((char*)&mem_map.length)+1);
+           }
+           i++;
+           b = e820(b1=b);
+       } while (b1 > 0);
+       printf("\n");
+       if (i > NAREA) {
+           i = NAREA;
+       }
+       ovlap = 0;
+       for (k=0; k<i-1; k++) {
+           dword s, e;
+           s = start[k];
+           e = s + length[k];
+           for (j=k+1; j<i; j++) {
+               dword ss, ee;
+               ss = start[j];
+               ee = ss + length[j];
+               if (!(ss < s && ee <= s || ss >= e && ee > e)) {
+                   printf("*** Memory areas %d and %d overlap ***\n", k, j);
+                   ovlap++;
+               }
+           }
+       }
+       if (!ovlap) printf("No memory areas overlap\n");
+    } else {
+       printf("Returns:\n");
+       if (b==-1) print_carry(1);
+       else if (b==-2) printf("    EAX=<trash>\n");
+       else if (b==-3) printf("    EAX=%lx  EBX=********  ECX=<trash>\n", E820_MAGIC);
+       else printf("    EAX=%lx  EBX=00000000\n", E820_MAGIC);
+       printf("\nFunction is not supported.\n");
+    }
+
+
+    pause();
+    printf(SPACER
+               "Int 15h  Function E801h\t\t[EXT]\n"
+               "Get Extended Memory Blocks\n\n"
+               "Call With:\n    ");
+    reg.x.ax = 0xE801;
+    print_regs(&reg);
+    int86(0x15, &reg, &oreg);
+    printf("\nReturns:\n    ");
+    print_regs(&oreg);
+    print_carry(oreg.x.cflag);
+
+    if (!oreg.x.cflag) {
+       printf("\nNumber of 1K blocks between 1M and 16M:  %u\n", oreg.x.ax);
+       printf(  "Number of 64K blocks above 16M:  %u\n", oreg.x.bx);
+       t = 1024L*(oreg.x.ax+1024);
+       t += 64L*1024L*oreg.x.bx;
+       if (!hma) hma = t;
+       else if (hma!=t) printf("A different amount of memory is reported by this function\n");
+    }
+    else printf("\nFunction is not supported.\n");
+
+    pause();
+    printf(SPACER
+               "Int 15h  Function 88h\t\t[AT][PS/2]\n"
+               "Get Extended Memory Size\n\n"
+               "Call With:\n    ");
+    reg.x.ax = 0x8800;
+    print_regs(&reg);
+    int86(0x15, &reg, &reg);
+    printf("\nReturns:\n    ");
+    print_regs(&reg);
+    printf("\nThere is ");
+    decimal( (unsigned long)reg.x.ax );
+    printf("K of extended memory.\n");
+
+    t = (reg.x.ax + 1024L) * 1024L;
+    if (!hma) hma = t;
+}    
+    
+static
+int get_video_mode(void)
+{
+    int m, row, col;
+    
+    pause();
+    printf(SPACER
+               "Int 10h  Function 0Fh\t\t[MDA][CGA][PCjr]\n"
+               "Get Video Mode\t\t\t[EGA][MCGA][VGA]\n\n"
+               "Call With:\n    ");
+    reg.x.ax = 0x0F00;
+    reg.x.bx = -1;
+    print_regs(&reg);
+    int86(0x10, &reg, &reg);
+    printf("\nReturns:\n    ");
+    print_regs(&reg);
+    m = reg.h.al;
+    __set_es(0x40);            /* address BIOS data area */
+    reg.h.bl = row = __peek_es(0x84);
+    printf("Fetch 0040:0084 (rows-1) to BL\n"
+       "--> ");
+    print_regs(&reg);
+    col = reg.h.ah;
+    printf("\nVideo mode = 0x%02x (%dx%d %s)\n", m, col, row+1,
+       m==7 ? "monochrome" : m==3 ? "color" : "unknown");
+    printf("Active display page = %d\n", (int)reg.h.bh);
+    
+    return !(m==7 || col<80);
+}
+
+static
+int get_cfg_info(void)
+{
+    pause();
+    printf(SPACER
+               "Int 10h  Function 12h\t\t[EGA][VGA]\n"
+               "Subfunction 10h\n"
+               "Get Configuration Information\n\n"
+               "Call With:\n    ");
+    reg.x.ax = 0x1200;
+    reg.x.bx = 0xFF10;
+    print_regs(&reg);
+    int86(0x10, &reg, &reg);
+    printf("\nReturns:\n    ");
+    print_regs(&reg);
+    if (reg.h.bh > 1) return 0;
+    
+    printf("\n%s display\n", reg.h.bh==0 ? "Color" : reg.h.bh==1 ? "Monochrome" : "Unknown");
+    printf("EGA memory = %dK\n", reg.h.bl <= 3 ? (reg.h.bl+1)*64 : 0);
+    printf("Feature bits = 0x%02x\n", (int)reg.h.ch);
+    printf("Configuration switch = 0x%02x\n", (int)reg.h.cl);
+    
+    return 1;
+}
+
+static
+int enable_refresh(void)
+{
+    pause();
+    printf(SPACER
+               "Int 10h  Function 12h\t\t[VGA]\n"
+               "Subfunction 36h\n"
+               "Enable Screen Refresh\n\n"
+               "Call With:\n    ");
+    reg.x.ax = 0x1200;
+    reg.x.bx = 0x0036;
+    reg.x.cx = 0;
+    reg.x.dx = 0x80;
+    print_regs(&reg);
+    int86(0x10, &reg, &oreg);
+    printf("\nReturns:\n    ");
+    print_regs(&oreg);
+    
+    printf("\n");
+    printf("Function is %ssupported.\n", oreg.h.al==0x12 ? "" : "NOT ");
+    if (oreg.x.dx != reg.x.dx || oreg.x.cx != reg.x.cx || oreg.x.si != reg.x.si
+               || oreg.x.di != reg.x.di)
+       printf("Error: Register(s) are not preserved.\n");
+    reg.x.dx = 0;
+    
+    return 1;
+}
+
+static
+int get_comb_code(void)
+{
+static char *dcode[] = { "none", "Monochrome", "CGA", "reserved",
+  "EGA (color)", "EGA (mono)", "PGA", "VGA (monochrome)", "VGA (color)",
+  "reserved", "MCGA (digital color)", "MCGA (monochrome)", "MCGA (color)",
+  "UNKNOWN" };
+    int code;
+    
+    pause();
+    printf(SPACER
+               "Int 10h  Function 1Ah\t\t[PS/2]\n"
+               "Subfunction 00h\n"
+               "Get Display Combination Code\n\n"
+               "Call With:\n    ");
+    reg.x.ax = 0x1A00;
+    reg.x.bx = reg.x.cx = 0;
+    print_regs(&reg);
+    int86(0x10, &reg, &reg);
+    printf("\nReturns:\n    ");
+    print_regs(&reg);
+    if (reg.h.al != 0x1A) return 0;
+    
+    code = reg.h.bl <= 12 ? reg.h.bl : 13;
+    printf("\nActive display: %s\n", dcode[code]);
+    code = reg.h.bh <= 12 ? reg.h.bh : 13;
+    printf("Inactive display: %s\n", dcode[code]);
+
+    return (reg.h.bl>=4);
+}
+
+static void print_io_status(int status)
+{
+static char *errmsg[] = {"no error", "invalid command",                /* 0-1 */
+       "address mark not found", "disk write-protected",       /* 2-3 */
+       "sector not found", "reset failed", "floppy disk removed", /* 4-6 */
+       "bad parameter table", "DMA overrun",                   /* 7-8 */
+       "DMA crossed 64k boundary", "bad sector flag",          /* 9-A */
+       "bad track flag", "media type not found",               /* B-C */
+       "invalid number of sectors on format",                  /* D */
+       "control data address mark detected",                   /* E */
+       "DMA arbitration level out of range",                   /* F */
+       "uncorrectable CRC or ECC data error",                  /* 10 */
+       "ECC corrected data error"                              /* 11 */
+                       };
+    char *err;
+                       
+    if (status <= 0x11) err = errmsg[status];
+    else switch(status) {
+       case 0x20: err = "controller failure"; break;
+       case 0x40: err = "seek failed"; break;
+       case 0x80: err = "disk timeout (failed to respond)"; break;
+       case 0xAA: err = "drive not ready"; break;
+       case 0xBB: err = "undefined error"; break;
+       case 0xCC: err = "write fault"; break;
+       case 0xE0: err = "status register error"; break;
+       case 0xFF: err = "sense operation failed"; break;
+       default:   err = "???";
+    }
+    printf("    BIOS error code = 0x%02x  (%s)\n", status, err);
+}
+
+static
+void do_edd(int dev)
+{
+    int m, subset;
+    
+    pause();
+    printf(SPACER
+               "Int 13h  Function 41h\t\t[EDD]\n"
+               "Check EDD Extensions Present (device %02xh)\n\n"
+               "Call With:\n    ", dev);
+    reg.x.ax = 0x41ED;
+    reg.x.bx = 0x55AA;
+    reg.x.dx = dev;
+    print_regs(&reg);
+    int86(0x13, &reg, &oreg);
+    printf("\nReturns:\n    ");
+    print_regs(&oreg);
+    print_carry(oreg.x.cflag);
+    m = 0;
+    if (oreg.x.cflag) print_io_status(oreg.h.ah);
+    else if (oreg.x.bx == 0xAA55 && (oreg.x.cx&EDD_SUBSET+EDD_LOCK+EDD_PACKET)) {
+       m = 1;
+       printf("\nEnhanced Disk Drive support: "); yesno(subset=oreg.x.cx&EDD_SUBSET);
+       printf("Drive locking and ejecting: "); yesno(oreg.x.cx&EDD_LOCK);
+       printf("Device access using packet calls: "); yesno(oreg.x.cx&EDD_PACKET);
+       printf("EDD extensions version%s (hex code %02xh)\n",
+               oreg.h.ah==0x30 ? " 3.0" : oreg.h.ah==0x21 ? " 1.1" : "" ,oreg.h.ah);
+    }
+    
+    if (m) {
+       struct EDDparam {
+           short size;         /* size of this structure */
+           short flags;        /* information flags */
+           long pcyls;         /* number of physical cylinders */
+           long pheads;        /* number of physical heads/cylinder */
+           long psects;        /* number of physical sectors/track */
+           unsigned            /* number of physical sectors on volume */
+           long sectors_lo, sectors_hi;        /* this is 8 bytes long */
+           short sec_size;     /* number of bytes per sector */
+           unsigned
+           long params;        /* EDD config params (valid only if EDD_SUBSET) */
+       } eddparam;
+
+       pause();
+       m = !!(oreg.x.cx&EDD_SUBSET)  &&  oreg.h.ah>=0x21;
+       printf(SPACER
+               "Int 13h  Function 48h\t\t[EDD]\n"
+               "EDD Get Drive Parameters (device %02xh)\n\n"
+               "Call With:\n    ", dev);
+       eddparam.size = sizeof(eddparam);
+       reg.x.si = &eddparam;   /* DS:SI points to buffer */
+       reg.x.ax =0x48C6;
+       segread(&sreg);
+       print_sregs(&sreg);
+       printf("    ");
+       print_regs(&reg);
+       int86x(0x13, &reg, &reg, &sreg);
+       printf("\nReturns:\n    ");
+       print_sregs(&sreg);
+       printf("    ");
+       print_regs(&reg);
+       print_carry(reg.x.cflag);
+#define fl eddparam.flags      
+       printf("\nDMA boundary errors handled transparently: "); yesno(fl&1);
+       printf("Geometry supplied: "); yesno(fl&2);
+       printf("Device is removable: "); yesno(fl&4);
+       printf("Device supports write with verify: "); yesno(fl&8);
+       if (fl&4) {
+           printf("Device has change-line support: "); yesno(fl&16);
+           printf("Device is lockable: "); yesno(fl&32);
+           printf("No media present; geometry is set to maximum: "); yesno(fl&64);
+       }
+       printf("Disk geometry (");
+       if (fl&2) {
+           printf("C:H:S) = %ld:%ld:%ld (", eddparam.pcyls, eddparam.pheads,
+                               eddparam.psects);
+       }
+       if (eddparam.sectors_hi == 0) 
+           decimal(eddparam.sectors_lo);
+       else printf("0x%x%08x", eddparam.sectors_hi, eddparam.sectors_lo);
+       printf(" sectors)\n");
+#undef fl
+       m=1;
+       if (m) {
+           static char *cfunc[] = {
+               "Enable Prefetch",
+               "Disable Prefetch",
+               "Set Maximum PIO Mode",
+               "Set PIO Mode 0",
+               "Set Default PIO Mode",
+               "Enable DMA Maximum Mode",
+               "Disable DMA"
+           };
+           m = 0;              /* start with subfn 0 */
+           pause();
+           printf(SPACER
+               "Int 13h  Function 4Eh\t\t[EDD]\n"
+               "Subfunction 0?h\n"
+               "EDD Set Hardware Configuration (device %02xh)\n\n"
+               "Call With:\n    ", dev);
+           reg.x.ax = 0x4E00;
+           reg.h.dl = dev;
+           print_regs(&reg);
+           int86(0x13, &reg, &reg);
+           printf("\nReturns:\n    ");
+           print_regs(&reg);
+           print_carry(reg.x.cflag);
+           printf("\n");
+           
+           for (m=0; m<nelem(cfunc); m++) {
+               reg.x.ax = 0x4E00 + m;
+               reg.h.dl = dev;
+               int86(0x13, &reg, &reg);
+               printf("Subfn(%d):  %s  <--  ", m, cfunc[m]);
+               if (reg.x.cflag || reg.h.ah) {
+                   printf("is not supported.\n");
+               }
+               else {
+                   printf("%s other drives on controller.\n",
+                       reg.h.al ? "affects" : "does not affect");
+               }
+           } /* for */
+           
+       } /* if (m) */
+       
+    } /* if (m) */
+}
+
+static
+int do_disk(int dev)
+{
+static char *drvtyp[] = {"No drive present", "Floppy w/o change-line support",
+       "Floppy with change-line support"};
+static char *dt[] = {  "5.25\", 40 track, 360K",
+                       "5.25\", 80 track, 1.2M",
+                       "3.5\", 80 track, 720K",
+                       "3.5\", 80 track, 1.44M" };
+    int m, mm;
+    int c,h,s;
+    unsigned long sect;
+    
+    pause();
+    printf(SPACER
+               "Int 13h  Function 15h\t\t[AT][PS/2]\n"
+               "Get Disk Type  (device %02xh)\n\n"
+               "Call With:\n    ", dev);
+    reg.x.ax = 0x1500;
+    reg.x.bx = 0;
+    reg.x.dx = dev;
+    print_regs(&reg);
+    int86(0x13, &reg, &oreg);
+    printf("\nReturns:\n    ");
+    print_regs(&oreg);
+    print_carry(oreg.x.cflag);
+    mm = (oreg.x.cflag==0 && oreg.h.ah!=0);
+    m = mm || (dev&0x80)==0;
+    if (oreg.x.cflag) print_io_status((int)oreg.h.ah);
+    else {
+       printf("\n%s",
+           oreg.h.ah < 3 ? drvtyp[oreg.h.ah] :
+           oreg.h.ah != 3 ? "unknown drive type" : "");
+       if (oreg.h.ah == 3) {
+           printf("Fixed disk with ");
+           sect = (long)oreg.x.cx<<16 | oreg.x.dx;
+           decimal(sect);
+           printf(" sectors = ");
+           sizeit(sect);
+       }
+       printf("\n");
+    }
+
+    if (m) {
+       pause();
+       printf(SPACER
+                       "Int 13h  Function 08h\t\t[PC][AT][PS/2]\n"
+                       "Get Drive Parameters  (device %02xh)\n\n"
+                       "Call With:\n    ", dev);
+       reg.x.ax = 0x0800;
+       reg.x.dx = dev;
+       reg.x.di = 0x4321;
+       reg.x.bx = 0x1234;
+       segread(&sreg);
+       sreg.es = 0;
+       print_sregs(&sreg);
+       printf("    ");
+       print_regs(&reg);
+       int86x(0x13, &reg, &oreg, &sreg);
+       printf("\nReturns:\n    ");
+       print_sregs(&sreg);
+       printf("    ");
+       print_regs(&oreg);
+       print_carry(oreg.x.cflag);
+       if (oreg.x.cflag) print_io_status((int)oreg.h.ah);
+       else {
+           last_good_disk = dev;
+           if (mm) {
+               printf("\n");
+               if (!(dev&0x80)) {
+                   printf("Disk type %d = %s\n", (int)oreg.h.bl,
+                                       dt[(oreg.h.bl-1)&3] );
+                   printf("Parameter table at %04x:%04x\n",
+                                       sreg.es, oreg.x.di);
+               }
+               else {
+                   if (oreg.x.bx != reg.x.bx)
+                       printf("Error:  Hard disk BIOS should not touch BX\n");
+                   if (sreg.es != 0  ||  oreg.x.di != reg.x.di)
+                       printf("Error:  Hard disk BIOS should not touch ES:DI\n");
+               }
+               s = (oreg.h.cl & 0x3F);         /* sectors 1..63 */
+               if (s == 0) s = 64;
+               h = (int)oreg.h.dh + 1;         /* heads 0..254 */
+               c = (((oreg.h.cl & 0xC0)<<2) | oreg.h.ch) + 1;
+               printf("Disk geometry (C:H:S) = %d:%d:%d (", c, h, s);
+               decimal( sect=(long)c*h*s );
+               printf(" sectors) = ");
+               sizeit(sect);
+               printf("\n%s disks on system = %d\n",
+                       dev&0x80 ? "Fixed" : "Floppy", oreg.h.dl);
+                if (s > 63)  printf("BIOS BUG!!!  sectors returned as zero; 64 assumed\n");
+                if (h > 255) printf("BIOS BUG!!!  heads > 255; BIOS is not IBM compatible\n");
+               if (dev & 0x80) {
+                   if (dev == 0x80) num_hd = oreg.h.dl;
+                   do_edd(dev);
+               }
+           }
+       }
+    }
+    
+    return m;
+}
+
+static
+int do_rw(int tries)
+{
+    int code;
+    
+    while (tries--) {
+       int86x(0x13, &reg, &oreg, &sreg);
+       if (oreg.x.cflag == 0 && oreg.x.ax == 0x0001) return 0;
+       code = oreg.h.ah;
+       oreg.x.ax = 0;
+       int86(0x13, &oreg, &oreg);
+    }
+    return code;
+}
+
+static
+void do_get_pt(int dev)
+{
+    int m;
+    char buf[SECTOR_SIZE];
+    
+    printf("Get partition table (device = 0x%x): ", dev);
+    segread(&sreg);
+    sreg.es = sreg.ss;
+    reg.x.ax = 0x0201;
+    reg.x.bx = buf;
+    reg.x.cx = 1;
+    reg.x.dx = dev & 0xFF;
+    m = do_rw(5);
+    if (m) print_io_status(m);
+    else printf("  okay");
+    printf("\n");
+    check_fs();
+}
+
+static
+void do_vesa(void)
+{
+    int i;
+    char vesa[512];
+    
+    pause();
+    printf(SPACER
+               "Int 10h  Function 4Fh\t\t[VESA]\n"
+               "Subfunction 00h\n"
+               "Check VESA Extensions Present\n\n"
+               "Call With:\n    ");
+    reg.x.ax = 0x4F00;
+    reg.x.bx = 0;
+    segread(&sreg);
+    sreg.es = sreg.ss;
+    reg.x.di = &vesa[0];
+    print_sregs(&sreg);
+    printf("    ");
+    print_regs(&reg);
+    int86x(0x10, &reg, &oreg, &sreg);
+    printf("\nReturns:\n    ");
+    print_sregs(&sreg);
+    printf("    ");
+    print_regs(&oreg);
+    if (oreg.x.ax != 0x004F) {
+       printf("\nVESA BIOS extensions not present\n");
+       return;
+    }
+    if (strncmp(vesa, "VESA", 4)) {
+       printf("\nVESA signature not found\n");
+       return;
+    }
+    vesa[4] = 0;
+    printf("\n\"%s\" BIOS extensions present\n", vesa);
+
+    pause();
+    printf(SPACER
+               "Int 10h  Function 4Fh\t\t[VESA]\n"
+               "Subfunction 01h\n"
+               "Get VESA Mode Information 1\n\n"
+               "Call With:\n    ");
+    reg.x.ax = 0x4F01;
+    reg.x.cx = 0x101;
+    segread(&sreg);
+    sreg.es = sreg.ss;
+    reg.x.di = &vesa[0];
+    print_sregs(&sreg);
+    printf("    ");
+    print_regs(&reg);
+    int86x(0x10, &reg, &oreg, &sreg);
+    printf("\nReturns:\n    ");
+    print_sregs(&sreg);
+    printf("    ");
+    print_regs(&oreg);
+    i = *(int*)vesa;   /* get mode bits */
+    printf("\nMode bits:  0x%04x\n", i);
+    printf("640x480x256 mode supported: ");
+    yesno(!(0x19 & ~i));
+    
+    pause();
+    printf(SPACER
+               "Int 10h  Function 4Fh\t\t[VESA]\n"
+               "Subfunction 01h\n"
+               "Get VESA Mode Information 3\n\n"
+               "Call With:\n    ");
+    reg.x.ax = 0x4F01;
+    reg.x.cx = 0x103;
+    segread(&sreg);
+    sreg.es = sreg.ss;
+    reg.x.di = &vesa[0];
+    print_sregs(&sreg);
+    printf("    ");
+    print_regs(&reg);
+    int86x(0x10, &reg, &oreg, &sreg);
+    printf("\nReturns:\n    ");
+    print_sregs(&sreg);
+    printf("    ");
+    print_regs(&oreg);
+    i = *(int*)vesa;   /* get mode bits */
+    printf("\nMode bits:  0x%04x\n", i);
+    printf("800x600x256 mode supported: ");
+    yesno(!(0x19 & ~i));
+}
+
+void main(void)
+{
+    int m, i, dev;
+    
+    set_fs(FS_REG);
+#if DEBUG>=1
+    printf("FS=%04x\n", get_fs());
+    pause();
+#endif
+    
+    if (!is_msdos()) {
+/**    atexit(pause);  **/
+       video_fix();    /* for Dumb DELL computers */
+    }
+#if DEBUG>=1 && __MSDOS__==0
+    printf("Beginning of '___cstartup'\n");
+    print_regs(&__argr);
+    printf("DS=%04x  ES=%04x  CS=%04x  SS=%04x  SP=%04x  BP=%04x\n",
+       __argseg.ds, __argseg.es, __argseg.cs, __argseg.ss,
+       __argr.x.flags, __argr.x.cflag);
+        
+    segread(&sreg);
+    printf("\nBeginning of '_main'\n");
+    check_fs();
+    print_sregs(&sreg);
+#endif
+    check_fs();
+    banner(DISK_VERSION);
+    check_fs();
+    v86test();
+    testDX();
+#if DEBUG>=2
+    sizeit((long)40*2*9);  putch('\n');
+    sizeit((long)80*2*15);  putch('\n');
+    sizeit((long)80*2*18);  putch('\n');
+    sizeit((long)80*2*36);  putch('\n');
+    sizeit((long)1024*255*63);  putch('\n');
+    sizeit((long)24000*512);  putch('\n');
+#endif
+    get_equip_cfg();
+    get_conv_mem();
+    hma = 0;
+    get_ext_mem();
+    if (hma>1024L*1024L) mov_ext_mem();
+    m = get_video_mode();
+    if (m) m = get_cfg_info();
+    if (m) m = enable_refresh();
+    if (m) m = get_comb_code();
+    if (m) do_vesa();
+#if DEBUG>=3
+    printf("\n\nm=%x\n", m);
+#endif
+    dev = 0; m = 1;
+    for (i=BD_MAX_FLOPPY; i && m;) {
+       m = do_disk(dev);
+       ++dev;
+       if (--i == 0  &&  (dev & 0x80)==0) {
+           dev = 0x80;
+           i = BD_MAX_HARD;
+       }
+       if ((dev & 0x7F) >= num_hd) m = 0;
+    }
+    pause();
+    printf(SPACER);
+    for (dev = 0x80; dev <= last_good_disk; dev++) do_get_pt(dev);
+    
+    if (!is_msdos()) {
+       printf("\n\nInitial SEQ reg 1:  0x%02x\n", video_1);
+    }
+    printf("The FS register was %smodified during the tests.\n",
+           fs_mod ? "" : "NOT ");
+    pause();
+}
diff --git a/diagnose/test5.c b/diagnose/test5.c
new file mode 100644 (file)
index 0000000..d285187
--- /dev/null
@@ -0,0 +1,366 @@
+/* test5.c */
+/*
+ Copyright (C) 2004 John Coffman.
+ All rights reserved.
+
+ Licensed under the terms contained in the file 'COPYING' in the LILO
+ source directory.
+
+*/
+#include <bios.h>
+#include <time.h>
+#include "../src/bdata.h"
+
+#define DISK_VERSION "3.0"
+
+#if __MSDOS__==0
+#define putch bios_putc
+#define getch bios_getc
+#define printf cprintf
+#define CR 13
+#else
+#include <stdio.h>
+#define putch(c) fputc((c),stdout)
+#define getch getchar
+#define CR 10
+#endif
+
+#define CTRL_C 03
+#define SPACER "\f\n"
+
+
+#ifndef EDD_SUBSET
+#define EDD_SUBSET 4
+#define EDD_LOCK 2
+#define EDD_PACKET 1
+#endif
+#ifndef SECTOR_SIZE
+#define SECTOR_SIZE 512
+#endif
+
+#define CL_MAGIC_ADDR 0x20
+#define CL_MAGIC 0xa33f
+#define CL_OFFSET 0x22
+#define CL_LENGTH 256
+
+typedef unsigned char  byte;
+typedef unsigned short word;
+typedef unsigned long dword;
+
+extern union REGS   __argr;
+extern struct SREGS __argseg;
+
+union REGS reg, oreg;
+struct SREGS sreg;
+
+int num_hd = BD_MAX_HARD;
+int errno;
+enum {RD=0, WR=1};
+
+struct Buffer {
+    int dirty, device;
+    union {
+       byte sector[SECTOR_SIZE];
+       word wsector[SECTOR_SIZE/2];
+       dword dsector[SECTOR_SIZE/4];
+    } x;
+} buffer;
+
+unsigned long linear(void *ptr)
+{
+    segread(&sreg);
+    return ((unsigned long)sreg.ds<<4) + (unsigned int)ptr;
+}
+
+
+#if __MSDOS__==0
+static
+bios_putc0(int c)
+{
+    union REGS reg;
+    if (c=='\f') {
+       reg.h.ah = 0x0F;
+       int86(0x10, &reg, &reg);
+       reg.h.ah = 0;
+       int86(0x10, &reg, &reg);
+    } else {
+       reg.h.al = c;
+       reg.h.ah = 14;
+       reg.x.bx = 7;
+       int86(0x10, &reg, &reg);
+    }
+}
+
+void bios_putc(char c)
+{
+static int col;
+   
+    switch(c) {
+    case '\t':
+       do bios_putc(' '); while(col&7);
+       break;
+    case '\n':  bios_putc0('\r');
+       /* fall into CR */
+    case '\f':
+    case '\r': col=0;
+    default:
+        bios_putc0(c);
+       if (c>=' ' && c<0177) col++;
+    }
+}
+#endif
+
+static
+void sizeit(unsigned long sectors)
+{
+static char suf[] = "KMGT";
+    int fract;
+    char *cp;
+
+/* print disk size in K,M,G,T */
+    sectors /= 2;
+    cp = suf;
+    if (sectors <= 999) {
+       printf("%ld%c", sectors, *cp);
+       return;
+    }
+    cp++;
+    while (sectors > 999999) {
+       sectors /= 1000;
+       cp++;
+    }
+    if (sectors > 2999) {
+       sectors *= 1024;
+       sectors /= 1000;
+    }
+    sectors += 5;      /* round decimal part */
+    sectors /= 10;
+    fract = sectors % 100;
+    sectors /= 100;
+    printf("%ld.%02d%c", sectors, fract, *cp);
+}
+
+static
+void banner(char *version)
+{
+       printf( "\n\n\n"
+">>>> Disk Maintenance Tools <<<<\n\n\n"
+"Version %s, Copyright (C) 2004  John Coffman <johninsd@san.rr.com>\n"
+"Portions Copyright (C) 1996-2001 Robert de Bath, used with permission\n"
+"Re-use and redistribution rights set forth in the file \"COPYING\".\n\n",
+        version);
+}
+
+
+
+static
+int inb(int port)
+{
+#asm
+  mov  bx,sp
+  mov  dx,[bx+2]
+  in   al,dx
+  xor  ah,ah
+#endasm
+}
+
+static
+int outb(int port, int data)
+{
+#asm
+  mov  bx,sp
+  mov  dx,[bx+2]
+  mov  ax,[bx+4]
+  out  dx,al
+#endasm
+}
+
+static
+void yesno(int i)
+{
+    printf("%s\n", i?"yes":"no");
+}
+
+static
+void decimal(unsigned long value)
+{
+    unsigned int v[4];
+    int i;
+    for (i=0; i<4; i++) {
+       v[i] = value % 1000;
+       value /= 1000;
+    }
+    if (v[3]) printf("%d,%03d,%03d,%03d", v[3], v[2], v[1], v[0]);
+    else if (v[2]) printf("%d,%03d,%03d", v[2], v[1], v[0]);
+    else if (v[1]) printf("%d,%03d", v[1], v[0]);
+    else printf("%d", v[0]);
+}
+
+static
+void print_regs(union REGS *reg) {
+    printf("AX=%04x  BX=%04x  CX=%04x  DX=%04x  SI=%04x  DI=%04x\n",
+    reg->x.ax, reg->x.bx, reg->x.cx, reg->x.dx, reg->x.si, reg->x.di);
+}
+
+static 
+void print_sregs(struct SREGS *sreg) {
+    printf("DS=%04x  ES=%04x  CS=%04x  SS=%04x\n",
+               sreg->ds, sreg->es, sreg->cs, sreg->ss);
+}
+
+static
+int is_msdos(void)
+{
+#if __MSDOS__
+    return 1;
+#else
+    return (__argseg.es+0x10 == __argseg.cs);
+#endif
+}
+
+static
+void pause(void)
+{
+       char ch;
+/* Must be standalone */    
+       printf("\n\n\nHit <Enter> to continue, <^C> to quit ...");
+       do {
+           ch = getch();
+           if (ch==CTRL_C) exit(0);
+#if DEBUG>=1
+           if (ch != CR) printf(" %o", ch);
+#endif
+       } while (ch != CR);
+       printf("\n");
+}
+
+static
+void video_fix(void)
+{
+/* dirty hack for DELL Dimension 4300 computers */
+   printf("\f\n");
+}
+
+
+static
+void setup(int rval)
+{
+    segread(&sreg);
+    sreg.es = sreg.ds;         /* as a general rule */
+    memset(&reg,rval,sizeof(reg));
+    memset(&oreg,rval,sizeof(oreg));
+}
+
+
+
+
+static
+int peekw_es(int addr)
+{
+    union {
+       char ch[2];
+       int  w;
+       } tem;
+    tem.ch[0] = __peek_es(addr);
+    tem.ch[1] = __peek_es(addr+1);
+    return tem.w;
+}
+
+
+static void get_cmdline(char *cp)
+{
+    word addr;
+    int ch;
+    
+    __set_es(__argseg.ds);
+    if (peekw_es(CL_MAGIC_ADDR) == CL_MAGIC) {
+       addr = peekw_es(CL_OFFSET);
+       do {
+           ch = __peek_es(addr++);
+       } while (ch && ch != '=');
+       do {
+           *cp++ = ch = __peek_es(addr++);
+       } while (ch);
+    }
+    else *cp = 0;
+}
+
+static
+int num_hard_disks(void)
+{
+    setup(0);
+    reg.h.ah = 8;
+    reg.h.dl = 0x80;
+    int86(0x13, &reg, &oreg);
+    return oreg.x.cflag ? 0 : (int)oreg.h.dl;
+}
+
+static
+int disk_rw0(int bios, int rw, void *buffer)
+{
+    int err = 1;
+    int errcnt = 5;
+    int code;
+    while (err && errcnt) {
+       setup(0);
+       reg.h.ah = 2 + (rw & !DEBUG);
+       reg.h.al = 1;
+       reg.x.cx = 1;   /* sector=0  is  sect=1, hd=0, cyl=0 */
+       reg.h.dh = 0;
+       reg.h.dl = bios;
+       reg.x.bx = (word)buffer;
+       /* ES is set == DS */
+       int86x(0x13, &reg, &oreg, &sreg);
+       code = oreg.h.ah;
+       if ((err = (oreg.x.cflag || oreg.h.ah))) {
+           setup(0);
+           reg.h.dl = bios;
+           if (bios & 0x80) reg.h.ah = 0x0D;
+           int86(0x13, &reg, &oreg);
+           --errcnt;
+       }
+    } /* while (err && errcnt) */
+    if (err) {
+       printf("Disk error on 0x%02x, AH = 0x%02x\n", bios, code);
+       exit(1);
+    }
+    return code;
+}
+
+void disk_data(int bios)
+{
+    if (!disk_rw0(bios, RD, buffer.x.sector)) {
+       printf("   %02x   %08lx\n", bios, buffer.x.dsector[110]);
+    }
+}
+
+void main(void)
+{
+    int m, i, dev;
+    char cp[CL_LENGTH];
+    
+    if (!is_msdos()) {
+       video_fix();    /* for Dumb DELL computers */
+    }
+#if DEBUG>=1 && __MSDOS__==0
+    printf("Beginning of '___cstartup'\n");
+    print_regs(&__argr);
+    printf("DS=%04x  ES=%04x  CS=%04x  SS=%04x  SP=%04x  BP=%04x\n",
+       __argseg.ds, __argseg.es, __argseg.cs, __argseg.ss,
+       __argr.x.flags, __argr.x.cflag);
+        
+    segread(&sreg);
+    printf("\nBeginning of '_main'\n");
+    print_sregs(&sreg);
+#endif
+    banner(DISK_VERSION);
+    get_cmdline(cp);
+    printf("Command line: '%s'   time=%ld\n", cp, time(NULL));   
+    num_hd = num_hard_disks();
+    printf("The BIOS reports %d hard disks.\n", num_hd);
+    for (i=0; i<num_hd; i++) disk_data(0x80+i);
+    
+    if (!is_msdos()) {
+       pause();
+    }
+}
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644 (file)
index 0000000..88690e3
--- /dev/null
@@ -0,0 +1,61 @@
+# -*- makefile -*-
+
+LATEX=latex
+PDFLATEX=pdflatex
+RLATEX=./rlatex
+FIG2DEV=fig2dev
+SHELL=/bin/sh
+
+IMAGES=bootloader.tex map.tex image.tex parameter.tex other.tex
+
+.SUFFIXES:     .fig .tex .dvi .ps
+
+.fig.tex:
+               $(FIG2DEV) -L latex $*.fig $*.tex
+
+.tex.dvi:
+               $(RLATEX) $*
+
+all:           user.dvi tech.dvi user.pdf tech.pdf
+
+user.ps:       user.dvi
+               dvips -o user.ps user.dvi
+
+tech.ps:       tech.dvi
+               dvips -o tech.ps tech.dvi
+
+user.dvi:      user.tex
+
+tech.dvi:      tech.tex $(IMAGES)
+
+user.pdf:      user.dvi
+               $(PDFLATEX) user
+               $(PDFLATEX) user
+
+tech.pdf:      tech.dvi
+               $(PDFLATEX) tech
+               $(PDFLATEX) tech
+
+../doc/README: user.tex
+               perl t2a.pl <user.tex >../doc/README || { rm -f ../doc/README; exit 1; }
+
+html:          user.ps tech.ps
+               latex2html -split 2 -link 2 -toc_depth 2 user
+               latex2html -split 1 -link 1 -toc_depth 1 tech
+
+again:
+               $(PDFLATEX) user
+               $(PDFLATEX) tech
+
+tidy:
+               rm -f *~ *.toc *.aux *.log *.out
+
+clean:         tidy
+               rm -f *.ps *.dvi *.pdf
+               rm -Rf user tech
+
+distclean:     clean
+
+
+dummies:
+               for n in $(IMAGES); do echo '(omitted)' >$$n; done
diff --git a/doc/README b/doc/README
new file mode 100644 (file)
index 0000000..31b5ec7
--- /dev/null
@@ -0,0 +1,56 @@
+Generating the README
+=====================
+
+In order to (re)generate the plain ASCII documentation that is found in
+lilo/README, Perl 4 or 5 must be installed on your system.
+Just type
+
+make ../README
+
+to perform the conversion. Note that fairly large amounts of virtual memory
+(16 MB or more) are allocated during the process.
+
+
+Printing the documentation
+==========================
+
+You need the following programs to generate a printable file from the
+LaTeX and FIG sources:
+
+  - LaTeX
+  - fig2dev from the transfig package (optional)
+
+The LaTeX translations of the FIG files are already included in the
+distribution, so you can print the documentation without fig2dev.
+WARNING: 'make distclean'  removes those pre-built LaTeX files.
+
+You can also omit all drawings by typing  make dummies . The drawings
+are only necessary when processing the technical overview document.
+
+To run LaTeX just type
+
+make
+
+LaTeX issues many "Overfull \hbox" warnings. They can be safely ignored.
+LaTeX will be run repeatedly until it stops issuing the message
+LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.
+
+Finally, you have to convert the device-independent file doc.dvi to
+something your printer understands. The actual command to perform this
+depends on your local installation. Example:
+
+dvips user | lpr
+
+(Another way is to use GhostScript. To generate HP DeskJet output by
+converting the DVI file to PostScript as an intermediate step, use this
+command
+
+dvips -r1 -f1 user | gs -q -sDEVICE=deskjet -sOutputFile=/dev/lp1 -
+
+gs -h  lists all configured drivers.)
+
+If you don't have access to LaTeX but if you can print PostScript, you
+should get the file(s) lilo.<part>.<version>.ps.gz from the same place
+where you've obtained lilo.<version>.tar.gz  That file contains the
+document user.tex (<part> = u) or tech.tex (<part> = t) already translated
+to PostScript.
diff --git a/doc/bootloader.fig b/doc/bootloader.fig
new file mode 100644 (file)
index 0000000..b6d2e44
--- /dev/null
@@ -0,0 +1,53 @@
+#FIG 2.1
+80 2
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        269 209 339 139 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        269 219 339 289 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        269 224 339 329 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        269 229 339 369 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        199 239 199 199 279 199 279 239 9999 9999
+2 1 1 1 -1 0 0 0 4.000 7 0 0
+        339 314 419 314 9999 9999
+2 1 1 1 -1 0 0 0 4.000 7 0 0
+        339 354 419 354 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        419 234 419 394 339 394 339 234 419 234 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        349 254 269 214 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        339 169 419 169 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        339 182 339 199 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        419 199 419 179 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        339 179 339 89 419 89 419 179 9999 9999
+2 1 0 1 -1 0 0 0 0.000 7 0 0
+        199 239 279 239 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        339 129 419 129 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        269 204 339 99 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        339 274 419 274 9999 9999
+4 0 5 10 0 -1 0 0.00000 0 7 36 354 409 boot.b\ 1
+4 0 1 10 0 -1 0 0.00000 0 9 34 359 249 Primary\ 1
+4 0 1 10 0 -1 0 0.00000 0 7 47 354 264 boot loader\ 1
+4 0 1 10 0 -1 0 0.00000 0 7 47 354 344 boot loader\ 1
+4 0 1 10 0 -1 0 0.00000 0 9 41 354 329 Secondary\ 1
+4 0 5 10 0 -1 0 0.00000 0 7 18 364 199 map\ 1
+4 0 1 10 0 -1 0 0.00000 0 9 25 359 144 Image\ 1
+4 0 1 10 0 -1 0 0.00000 0 9 46 349 159 descriptors\ 1
+4 0 1 10 0 -1 0 0.00000 0 7 57 344 119 command line\ 1
+4 0 1 10 0 -1 0 0.00000 0 7 32 359 104 Default\ 1
+4 0 1 10 0 -1 0 0.00000 0 7 47 204 219 Boot sector\ 1
diff --git a/doc/bootloader.tex b/doc/bootloader.tex
new file mode 100644 (file)
index 0000000..beb693e
--- /dev/null
@@ -0,0 +1,58 @@
+\setlength{\unitlength}{0.01250000in}%
+%
+\begingroup\makeatletter\ifx\SetFigFont\undefined
+% extract first six characters in \fmtname
+\def\x#1#2#3#4#5#6#7\relax{\def\x{#1#2#3#4#5#6}}%
+\expandafter\x\fmtname xxxxxx\relax \def\y{splain}%
+\ifx\x\y   % LaTeX or SliTeX?
+\gdef\SetFigFont#1#2#3{%
+  \ifnum #1<17\tiny\else \ifnum #1<20\small\else
+  \ifnum #1<24\normalsize\else \ifnum #1<29\large\else
+  \ifnum #1<34\Large\else \ifnum #1<41\LARGE\else
+     \huge\fi\fi\fi\fi\fi\fi
+  \csname #3\endcsname}%
+\else
+\gdef\SetFigFont#1#2#3{\begingroup
+  \count@#1\relax \ifnum 25<\count@\count@25\fi
+  \def\x{\endgroup\@setsize\SetFigFont{#2pt}}%
+  \expandafter\x
+    \csname \romannumeral\the\count@ pt\expandafter\endcsname
+    \csname @\romannumeral\the\count@ pt\endcsname
+  \csname #3\endcsname}%
+\fi
+\fi\endgroup
+\begin{picture}(224,323)(198,429)
+\thinlines
+\put(270,630){\vector( 1, 1){ 70}}
+\put(270,620){\vector( 1,-1){ 70}}
+\put(270,615){\vector( 2,-3){ 70}}
+\put(270,610){\vector( 1,-2){ 70}}
+\put(200,600){\line( 0, 1){ 40}}
+\put(200,640){\line( 1, 0){ 80}}
+\put(280,640){\line( 0,-1){ 40}}
+\multiput(340,525)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\multiput(340,485)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\put(340,445){\framebox(80,160){}}
+\put(350,585){\vector(-2, 1){ 80}}
+\multiput(340,670)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\multiput(340,657)(0.00000,-6.80000){3}{\line( 0,-1){  3.400}}
+\multiput(420,640)(0.00000,8.00000){3}{\line( 0, 1){  4.000}}
+\put(340,660){\line( 0, 1){ 90}}
+\put(340,750){\line( 1, 0){ 80}}
+\put(420,750){\line( 0,-1){ 90}}
+\put(200,600){\line( 1, 0){ 80}}
+\put(340,710){\line( 1, 0){ 80}}
+\put(270,635){\vector( 2, 3){ 70}}
+\put(340,565){\line( 1, 0){ 80}}
+\put(355,430){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}boot.b}}}
+\put(360,590){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Primary}}}
+\put(355,575){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}boot loader}}}
+\put(355,495){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}boot loader}}}
+\put(355,510){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Secondary}}}
+\put(365,640){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}map}}}
+\put(360,695){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Image}}}
+\put(350,680){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}descriptors}}}
+\put(345,720){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}command line}}}
+\put(360,735){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Default}}}
+\put(205,620){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Boot sector}}}
+\end{picture}
diff --git a/doc/fullpage.sty b/doc/fullpage.sty
new file mode 100644 (file)
index 0000000..67824e3
--- /dev/null
@@ -0,0 +1,29 @@
+% This is FULLPAGE.STY by H.Partl, Version 2 as of 15 Dec 1988.
+% Document Style Option to fill the paper just like Plain TeX.
+     
+\typeout{Style Option FULLPAGE Version 2 as of 15 Dec 1988}
+     
+\topmargin 0pt
+\advance \topmargin by -\headheight
+\advance \topmargin by -\headsep
+     
+\textheight 8.9in
+     
+\oddsidemargin 0pt
+\evensidemargin \oddsidemargin
+\marginparwidth 0.5in
+     
+\textwidth 6.5in
+     
+     
+% For users of A4 paper: The above values are suited for american 8.5x11in
+% paper. If your output driver performs a conversion for A4 paper, keep
+% those values. If your output driver conforms to the TeX standard (1in/1in),
+% then you should add the following commands to center the text on A4 paper:
+     
+% \advance\hoffset by -3mm  % A4 is narrower.
+% \advance\voffset by  8mm  % A4 is taller.
+     
+\endinput
+     
+     
diff --git a/doc/image.fig b/doc/image.fig
new file mode 100644 (file)
index 0000000..8cc4702
--- /dev/null
@@ -0,0 +1,95 @@
+#FIG 2.1
+80 2
+6 219 139 284 159
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        284 159 284 139 219 139 219 159 284 159 9999 9999
+4 0 1 10 0 -1 0 0.00000 0 9 44 224 154 Descriptor\ 1
+-6
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        369 329 414 349 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        369 274 414 204 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        369 284 413 227 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        369 264 414 164 9999 9999
+2 1 0 1 -1 0 0 0 0.000 7 0 0
+        414 269 414 139 494 139 494 264 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        414 259 494 259 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        414 219 494 219 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        414 179 494 179 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        414 329 414 379 494 379 494 329 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        414 339 494 339 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        414 309 414 329 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        494 309 494 329 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        494 269 494 289 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        379 519 379 439 299 439 299 519 379 519 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        414 489 414 439 494 439 494 489 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        414 269 414 289 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        414 489 414 509 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        494 489 494 509 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        414 549 414 599 494 599 494 549 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        414 529 414 549 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        494 529 494 549 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        414 479 494 479 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        414 559 494 559 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        299 479 379 479 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 1
+       0 0 1.000 4.000 8.000
+        299 189 269 159 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        259 159 299 279 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        299 259 379 259 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        359 294 319 304 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        379 339 379 179 299 179 299 339 379 339 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        299 299 379 299 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        299 219 379 219 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        359 474 319 484 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        369 444 414 444 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        369 509 414 569 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        234 159 304 439 9999 9999
+4 0 1 10 0 -1 0 0.00000 0 9 54 424 399 Kernel image\ 1
+4 0 1 10 0 -1 0 0.00000 0 9 50 309 359 Map section\ 1
+4 0 1 10 0 -1 0 0.00000 0 9 33 319 239 Options\ 1
+4 0 1 10 0 -1 0 0.00000 0 13 36 319 199 Fallback\ 1
+4 0 1 10 0 -1 0 0.00000 0 9 50 309 539 Map section\ 1
+4 0 1 10 0 -1 0 0.00000 0 9 35 239 404 optional\ 1
+4 0 1 10 0 -1 0 0.00000 0 7 73 409 619 Initial RAM disk\ 1
diff --git a/doc/image.tex b/doc/image.tex
new file mode 100644 (file)
index 0000000..ea272d5
--- /dev/null
@@ -0,0 +1,78 @@
+\setlength{\unitlength}{0.01250000in}%
+%
+\begingroup\makeatletter\ifx\SetFigFont\undefined
+% extract first six characters in \fmtname
+\def\x#1#2#3#4#5#6#7\relax{\def\x{#1#2#3#4#5#6}}%
+\expandafter\x\fmtname xxxxxx\relax \def\y{splain}%
+\ifx\x\y   % LaTeX or SliTeX?
+\gdef\SetFigFont#1#2#3{%
+  \ifnum #1<17\tiny\else \ifnum #1<20\small\else
+  \ifnum #1<24\normalsize\else \ifnum #1<29\large\else
+  \ifnum #1<34\Large\else \ifnum #1<41\LARGE\else
+     \huge\fi\fi\fi\fi\fi\fi
+  \csname #3\endcsname}%
+\else
+\gdef\SetFigFont#1#2#3{\begingroup
+  \count@#1\relax \ifnum 25<\count@\count@25\fi
+  \def\x{\endgroup\@setsize\SetFigFont{#2pt}}%
+  \expandafter\x
+    \csname \romannumeral\the\count@ pt\expandafter\endcsname
+    \csname @\romannumeral\the\count@ pt\endcsname
+  \csname #3\endcsname}%
+\fi
+\fi\endgroup
+\begin{picture}(279,483)(218,219)
+\thinlines
+\put(220,680){\framebox(65,20){}}
+\put(225,685){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Descriptor}}}
+\put(370,510){\vector( 2,-1){ 44}}
+\put(370,565){\vector( 2, 3){ 46.154}}
+\put(370,555){\vector( 3, 4){ 43.200}}
+\put(370,575){\vector( 1, 2){ 49}}
+\put(415,570){\line( 0, 1){130}}
+\put(415,700){\line( 1, 0){ 80}}
+\put(495,700){\line( 0,-1){125}}
+\multiput(415,580)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\multiput(415,620)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\multiput(415,660)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\put(415,510){\line( 0,-1){ 50}}
+\put(415,460){\line( 1, 0){ 80}}
+\put(495,460){\line( 0, 1){ 50}}
+\multiput(415,500)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\multiput(415,530)(0.00000,-8.00000){3}{\line( 0,-1){  4.000}}
+\multiput(495,530)(0.00000,-8.00000){3}{\line( 0,-1){  4.000}}
+\multiput(495,570)(0.00000,-8.00000){3}{\line( 0,-1){  4.000}}
+\put(300,320){\framebox(80,80){}}
+\put(415,350){\line( 0, 1){ 50}}
+\put(415,400){\line( 1, 0){ 80}}
+\put(495,400){\line( 0,-1){ 50}}
+\multiput(415,570)(0.00000,-8.00000){3}{\line( 0,-1){  4.000}}
+\multiput(415,350)(0.00000,-8.00000){3}{\line( 0,-1){  4.000}}
+\multiput(495,350)(0.00000,-8.00000){3}{\line( 0,-1){  4.000}}
+\put(415,290){\line( 0,-1){ 50}}
+\put(415,240){\line( 1, 0){ 80}}
+\put(495,240){\line( 0, 1){ 50}}
+\multiput(415,310)(0.00000,-8.00000){3}{\line( 0,-1){  4.000}}
+\multiput(495,310)(0.00000,-8.00000){3}{\line( 0,-1){  4.000}}
+\multiput(415,360)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\multiput(415,280)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\multiput(300,360)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\put(270,680){\vector( 1,-1){ 30}}
+\put(260,680){\vector( 1,-3){ 40}}
+\multiput(300,580)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\put(360,545){\vector(-4,-1){ 40}}
+\put(300,500){\framebox(80,160){}}
+\multiput(300,540)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\multiput(300,620)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\put(360,365){\vector(-4,-1){ 40}}
+\put(370,395){\vector( 1, 0){ 45}}
+\put(370,330){\vector( 3,-4){ 45}}
+\put(235,680){\vector( 1,-4){ 70}}
+\put(425,440){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Kernel image}}}
+\put(310,480){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Map section}}}
+\put(320,600){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Options}}}
+\put(320,640){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Fallback}}}
+\put(310,300){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Map section}}}
+\put(240,435){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}optional}}}
+\put(410,220){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Initial RAM disk}}}
+\end{picture}
diff --git a/doc/map.fig b/doc/map.fig
new file mode 100644 (file)
index 0000000..f7719fc
--- /dev/null
@@ -0,0 +1,39 @@
+#FIG 3.1
+Landscape
+Center
+Inches
+1200 2
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5
+        600 1800 1800 1800 1800 7200 600 7200 600 1800
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2
+        600 2400 1800 2400
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2
+        600 6600 1800 6600
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2
+        600 5400 1800 5400
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2
+        600 4800 1800 4800
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2
+        600 4200 1800 4200
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2
+        600 3600 1800 3600
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        1425 5925 975 6075
+2 1 1 1 -1 7 0 0 -1 4.000 0 0 -1 0 0 2
+        600 6000 1800 6000
+2 1 1 1 -1 7 0 0 -1 4.000 0 0 -1 0 0 2
+        600 3000 1800 3000
+4 1 -1 0 0 0 10 0.0000 4 105 480 1200 2025 Default\001
+4 1 -1 0 0 0 10 0.0000 4 105 855 1200 2250 command line\001
+4 1 -1 0 0 0 10 0.0000 4 135 690 1200 3300 descriptors\001
+4 1 -1 0 0 0 10 0.0000 4 105 690 1200 3900 Zero sector\001
+4 1 -1 0 0 0 10 0.0000 4 135 585 1200 4425 Keyboard\001
+4 1 -1 0 0 0 10 0.0000 4 105 705 1200 4650 trans. table\001
+4 1 -1 0 0 0 10 0.0000 4 105 315 1200 5025 First\001
+4 1 -1 0 0 0 10 0.0000 4 105 435 1200 5250 section\001
+4 1 -1 0 0 0 10 0.0000 4 105 420 1200 5775 Second\001
+4 1 -1 0 0 0 10 0.0000 4 135 375 1200 2775 Image\001
+4 1 -1 0 0 0 10 0.0000 4 105 435 1200 6300 section\001
+4 1 -1 0 0 0 10 0.0000 4 105 435 1200 7050 section\001
+4 1 -1 0 0 0 10 0.0000 4 105 345 1200 6825 Third\001
diff --git a/doc/map.tex b/doc/map.tex
new file mode 100644 (file)
index 0000000..c46f279
--- /dev/null
@@ -0,0 +1,49 @@
+\setlength{\unitlength}{0.00083300in}%
+%
+\begingroup\makeatletter\ifx\SetFigFont\undefined
+% extract first six characters in \fmtname
+\def\x#1#2#3#4#5#6#7\relax{\def\x{#1#2#3#4#5#6}}%
+\expandafter\x\fmtname xxxxxx\relax \def\y{splain}%
+\ifx\x\y   % LaTeX or SliTeX?
+\gdef\SetFigFont#1#2#3{%
+  \ifnum #1<17\tiny\else \ifnum #1<20\small\else
+  \ifnum #1<24\normalsize\else \ifnum #1<29\large\else
+  \ifnum #1<34\Large\else \ifnum #1<41\LARGE\else
+     \huge\fi\fi\fi\fi\fi\fi
+  \csname #3\endcsname}%
+\else
+\gdef\SetFigFont#1#2#3{\begingroup
+  \count@#1\relax \ifnum 25<\count@\count@25\fi
+  \def\x{\endgroup\@setsize\SetFigFont{#2pt}}%
+  \expandafter\x
+    \csname \romannumeral\the\count@ pt\expandafter\endcsname
+    \csname @\romannumeral\the\count@ pt\endcsname
+  \csname #3\endcsname}%
+\fi
+\fi\endgroup
+\begin{picture}(1224,5424)(589,-6373)
+\thicklines
+\put(601,-6361){\framebox(1200,5400){}}
+\put(601,-1561){\line( 1, 0){1200}}
+\put(601,-5761){\line( 1, 0){1200}}
+\put(601,-4561){\line( 1, 0){1200}}
+\put(601,-3961){\line( 1, 0){1200}}
+\put(601,-3361){\line( 1, 0){1200}}
+\put(601,-2761){\line( 1, 0){1200}}
+\put(1426,-5086){\vector(-3,-1){450}}
+\multiput(601,-5161)(7.97342,0.00000){151}{\line( 1, 0){  3.987}}
+\multiput(601,-2161)(7.97342,0.00000){151}{\line( 1, 0){  3.987}}
+\put(1201,-1186){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}Default}}}
+\put(1201,-1411){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}command line}}}
+\put(1201,-2461){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}descriptors}}}
+\put(1201,-3061){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}Zero sector}}}
+\put(1201,-3586){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}Keyboard}}}
+\put(1201,-3811){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}trans. table}}}
+\put(1201,-4186){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}First}}}
+\put(1201,-4411){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}section}}}
+\put(1201,-4936){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}Second}}}
+\put(1201,-1936){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}Image}}}
+\put(1201,-5461){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}section}}}
+\put(1201,-6211){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}section}}}
+\put(1201,-5986){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}Third}}}
+\end{picture}
diff --git a/doc/other.fig b/doc/other.fig
new file mode 100644 (file)
index 0000000..c30dc65
--- /dev/null
@@ -0,0 +1,49 @@
+#FIG 2.1
+80 2
+6 239 179 304 199
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        304 199 304 179 239 179 239 199 304 199 9999 9999
+4 0 1 10 0 -1 0 0.00000 0 9 44 244 194 Descriptor\ 1
+-6
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        299 339 379 339 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        369 359 389 349 399 334 399 319 379 309 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        274 199 299 224 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        369 369 439 369 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        519 389 519 349 439 349 439 389 519 389 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        369 349 384 349 9999 9999
+2 1 2 1 -1 0 0 0 3.000 -1 0 0
+        384 349 399 349 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        299 299 379 299 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        379 379 379 219 299 219 299 379 379 379 9999 9999
+2 1 1 1 -1 0 0 0 4.000 -1 0 0
+        299 259 379 259 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 1
+       0 0 1.000 4.000 8.000
+        359 304 436 168 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        539 169 364 309 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        399 179 399 139 479 139 479 179 399 179 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        614 179 614 139 534 139 534 179 614 179 9999 9999
+4 0 1 10 0 -1 0 0.00000 0 9 50 309 399 Map section\ 1
+4 0 1 10 0 -1 0 0.00000 0 7 47 444 369 Boot sector\ 1
+4 0 5 10 0 -1 0 0.00000 0 7 42 414 159 chain.b\ 1
+4 0 1 10 0 -1 0 0.00000 0 9 35 554 149 Original\ 1
+4 0 0 10 0 -1 0 0.00000 0 7 21 559 174 table\ 1
+4 0 1 10 0 -1 0 0.00000 0 9 37 554 162 partition\ 1
+4 0 1 10 0 -1 0 0.00000 0 13 41 319 284 (Options)\ 1
+4 0 1 10 0 -1 0 0.00000 0 13 36 319 244 Fallback\ 1
+4 0 1 10 0 -1 0 0.00000 0 7 52 309 324 Chain loader\ 1
diff --git a/doc/other.tex b/doc/other.tex
new file mode 100644 (file)
index 0000000..f30a8fc
--- /dev/null
@@ -0,0 +1,54 @@
+\setlength{\unitlength}{0.01250000in}%
+%
+\begingroup\makeatletter\ifx\SetFigFont\undefined
+% extract first six characters in \fmtname
+\def\x#1#2#3#4#5#6#7\relax{\def\x{#1#2#3#4#5#6}}%
+\expandafter\x\fmtname xxxxxx\relax \def\y{splain}%
+\ifx\x\y   % LaTeX or SliTeX?
+\gdef\SetFigFont#1#2#3{%
+  \ifnum #1<17\tiny\else \ifnum #1<20\small\else
+  \ifnum #1<24\normalsize\else \ifnum #1<29\large\else
+  \ifnum #1<34\Large\else \ifnum #1<41\LARGE\else
+     \huge\fi\fi\fi\fi\fi\fi
+  \csname #3\endcsname}%
+\else
+\gdef\SetFigFont#1#2#3{\begingroup
+  \count@#1\relax \ifnum 25<\count@\count@25\fi
+  \def\x{\endgroup\@setsize\SetFigFont{#2pt}}%
+  \expandafter\x
+    \csname \romannumeral\the\count@ pt\expandafter\endcsname
+    \csname @\romannumeral\the\count@ pt\endcsname
+  \csname #3\endcsname}%
+\fi
+\fi\endgroup
+\begin{picture}(379,263)(238,439)
+\thinlines
+\put(240,640){\framebox(65,20){}}
+\put(245,645){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Descriptor}}}
+\multiput(300,500)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\put(370,480){\line( 2, 1){ 20}}
+\put(390,490){\line( 2, 3){ 10}}
+\put(400,505){\line( 0, 1){ 15}}
+\put(400,520){\vector(-2, 1){ 20}}
+\put(275,640){\vector( 1,-1){ 25}}
+\put(370,470){\vector( 1, 0){ 70}}
+\put(440,450){\framebox(80,40){}}
+\put(370,490){\line( 1, 0){ 15}}
+\multiput(385,490)(7.50000,0.00000){3}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}}
+\multiput(300,540)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\put(300,460){\framebox(80,160){}}
+\multiput(300,580)(7.61905,0.00000){11}{\line( 1, 0){  3.810}}
+\put(430,675){\vector(-1,-2){ 69.800}}
+\put(540,670){\vector(-4,-3){179.200}}
+\put(400,660){\framebox(80,40){}}
+\put(535,660){\framebox(80,40){}}
+\put(310,440){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Map section}}}
+\put(445,470){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Boot sector}}}
+\put(415,680){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}chain.b}}}
+\put(555,690){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Original}}}
+\put(560,665){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}table}}}
+\put(555,677){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}partition}}}
+\put(320,555){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}(Options)}}}
+\put(320,595){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Fallback}}}
+\put(310,515){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Chain loader}}}
+\end{picture}
diff --git a/doc/parameter.fig b/doc/parameter.fig
new file mode 100644 (file)
index 0000000..8973c31
--- /dev/null
@@ -0,0 +1,39 @@
+#FIG 2.1
+80 2
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        239 299 239 334 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        299 299 299 334 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        619 334 619 299 199 299 199 334 619 334 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        459 299 459 334 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        269 234 269 299 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        379 399 379 334 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+       0 0 1.000 4.000 8.000
+        389 234 519 299 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 0 0
+        299 199 299 234 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        459 234 459 199 239 199 239 234 459 234 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+        459 434 459 399 299 399 299 434 459 434 9999 9999
+4 0 1 10 0 -1 0 0.000 0 7 21 209 314 Pre-\ 1
+4 0 1 10 0 -1 0 0.000 0 7 21 204 329 fixes\ 1
+4 0 1 10 0 -1 0 0.000 0 9 25 254 314 Image\ 1
+4 0 1 10 0 -1 0 0.000 0 5 21 254 329 name\ 1
+4 0 1 10 0 -1 0 0.000 0 9 98 489 319 Command-line options\ 1
+4 0 1 10 0 -1 0 0.000 0 9 57 344 319 Static options\ 1
+4 0 1 10 0 -1 0 0.000 0 9 69 139 354 Parameter string\ 1
+4 0 1 10 0 -1 0 0.000 0 9 80 139 369 passed to the kernel\ 1
+4 0 1 10 0 -1 0 0.000 0 9 25 254 214 Image\ 1
+4 0 1 10 0 -1 0 0.000 0 5 21 254 229 name\ 1
+4 0 1 10 0 -1 0 0.000 0 9 98 329 219 Command-line options\ 1
+4 0 1 10 0 -1 0 0.000 0 9 57 344 419 Static options\ 1
+4 0 1 10 0 -1 0 0.000 0 9 60 139 419 Options sector\ 1
+4 0 1 10 0 -1 0 0.000 0 7 60 139 219 Command line\ 1
diff --git a/doc/parameter.tex b/doc/parameter.tex
new file mode 100644 (file)
index 0000000..8f8ab45
--- /dev/null
@@ -0,0 +1,50 @@
+\setlength{\unitlength}{0.01250000in}%
+%
+\begingroup\makeatletter\ifx\SetFigFont\undefined
+% extract first six characters in \fmtname
+\def\x#1#2#3#4#5#6#7\relax{\def\x{#1#2#3#4#5#6}}%
+\expandafter\x\fmtname xxxxxx\relax \def\y{splain}%
+\ifx\x\y   % LaTeX or SliTeX?
+\gdef\SetFigFont#1#2#3{%
+  \ifnum #1<17\tiny\else \ifnum #1<20\small\else
+  \ifnum #1<24\normalsize\else \ifnum #1<29\large\else
+  \ifnum #1<34\Large\else \ifnum #1<41\LARGE\else
+     \huge\fi\fi\fi\fi\fi\fi
+  \csname #3\endcsname}%
+\else
+\gdef\SetFigFont#1#2#3{\begingroup
+  \count@#1\relax \ifnum 25<\count@\count@25\fi
+  \def\x{\endgroup\@setsize\SetFigFont{#2pt}}%
+  \expandafter\x
+    \csname \romannumeral\the\count@ pt\expandafter\endcsname
+    \csname @\romannumeral\the\count@ pt\endcsname
+  \csname #3\endcsname}%
+\fi
+\fi\endgroup
+\begin{picture}(482,239)(140,403)
+\thinlines
+\put(240,540){\line( 0,-1){ 35}}
+\put(300,540){\line( 0,-1){ 35}}
+\put(200,505){\framebox(420,35){}}
+\put(460,540){\line( 0,-1){ 35}}
+\put(270,605){\vector( 0,-1){ 65}}
+\put(380,440){\vector( 0, 1){ 65}}
+\put(390,605){\vector( 2,-1){130}}
+\put(300,640){\line( 0,-1){ 35}}
+\put(240,605){\framebox(220,35){}}
+\put(300,405){\framebox(160,35){}}
+\put(210,525){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Pre-}}}
+\put(205,510){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}fixes}}}
+\put(255,525){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Image}}}
+\put(255,510){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}name}}}
+\put(490,520){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Command-line options}}}
+\put(345,520){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Static options}}}
+\put(140,485){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Parameter string}}}
+\put(140,470){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}passed to the kernel}}}
+\put(255,625){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Image}}}
+\put(255,610){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}name}}}
+\put(330,620){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Command-line options}}}
+\put(345,420){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Static options}}}
+\put(140,420){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Options sector}}}
+\put(140,620){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Command line}}}
+\end{picture}
diff --git a/doc/rlatex b/doc/rlatex
new file mode 100755 (executable)
index 0000000..842359e
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh
+while true; do
+    pid=$$
+    export pid
+    rm -f /tmp/rlok$pid
+    (
+        if latex $*; then
+           touch /tmp/rlok$pid
+       fi
+    ) | tee /tmp/rlso$pid
+    if [ ! -f /tmp/rlok$pid ]; then
+       rm -f /tmp/rlso$pid
+       exit 1
+    fi
+    if grep '^LaTeX Warning: Label(s) may' /tmp/rlso$pid >/dev/null; then :
+    else
+       rm -f /tmp/rlso$pid
+       exit 0
+    fi
+    echo "Re-running LaTeX"
+done
diff --git a/doc/t2a.pl b/doc/t2a.pl
new file mode 100644 (file)
index 0000000..f733a55
--- /dev/null
@@ -0,0 +1,467 @@
+#!/usr/bin/perl
+#
+# Copyright 1994-1996 Werner Almesberger.
+# All rights reserved.
+#
+# See file COPYING for details.
+#
+#-----------------------------------------------------------------------------
+#
+# Known bugs:
+#
+#   Usually doesn't check for prepended backslashes, e.g. things like
+#   \\begin{verbatim} would be processed incorrectly.
+#
+#   Tokenization should be done once at the beginning, not on the fly
+#   with cleanup and check procedures at the end of each step.
+#
+#-----------------------------------------------------------------------------
+#
+$w = 75;
+#
+# default macros
+#
+$m{"\\\\ldots"} = "...";
+#
+# read the file
+#
+print STDERR "[".length($t)."] Reading the file\n";
+$/ = "\000";
+$t = "\n".<>."\n";
+#
+# universal markers
+#
+$N = "\000";   # non-character
+$X = "\007";   # generic marker
+$Y = "\010";   # another generic marker
+$Z = "\011";   # yet another generic marker
+$B = "\001";   # begin
+$E = "\002";   # end
+$BS = "\013";  # second begin
+$ES = "\014";  # second end
+$CO = "\003";  # curly open
+$CC = "\004";  # curly close
+#
+# commands to the output formatter
+#
+$SI = "\020";  # increase indentation by one
+$SO = "\021";  # decrease indentation by one
+$B1 = "\022";  # one blank line
+$B2 = "\023";  # two blank lines
+
+sub xlat
+{
+    local ($l) = @_;
+
+    $l =~ tr/~/ /;
+    $l =~ s/\\([_~&%^\$\#\[\]|\-])/\1/g;# unescape special characters
+    $l =~ s/\\,//g;                    # remove small spaces
+    $l =~ s/\\backslash */$X/g;                # \backslash ->\
+    if ($l =~ /\\([A-Za-z]+|.)/) {
+       warn "unrecognized command $& ($l)";
+       $l = $`."\n!!! UNRECOGNIZED COMMAND: $&\n$'";
+    }
+    $l =~ s/$X/\\/g;
+    $l =~ tr/{}//d;                    # delete stray curly braces
+    $l =~ s/$CO/{/g;                   # put escaped braces back
+    $l =~ s/$CC/}/g;
+    return $l;
+}
+
+
+#
+# load macros
+#
+print STDERR "[".length($t)."] Loading macros\n";
+while ($t =~ /\n%%(def|cmd)([^\n]*)\n/) {
+    $t = $`."\n".$';
+    $a = $1;
+    $2 =~ /([^\\])=/ || die "= missing in $2";
+    if ($a eq "def") {
+       $m{$`.$1} = $';
+       $c{$`.$1} = "";
+    }
+    else {
+       $m{$`.$1} = "";
+       $c{$`.$1} = $';
+    }
+}
+#
+# remove %%beginskip ... %%endskip pairs
+#
+print STDERR "[".length($t)."] Removing %%beginskip ... %%endskip pairs\n";
+while ($t =~ /\n%%beginskip\s*\n/) { $t = $`.$B.$'; }
+while ($t =~ /\n%%endskip\s*\n/) { $t = $`.$E.$'; }
+while ($t =~ /$B[^$B$E]*$E/) { $t = $`."\n".$'; }
+$t !~ /[$B$E]/ || die "%%beginskip/%%endskip mismatch";
+#
+#  process macros
+#
+print STDERR "[".length($t)."] Processing macros (may take a while)\n";
+while (1) {
+    $none = 1;
+    for (keys %m) {
+       while ($t =~ /$_/) {
+           $none = 0;
+           if ($c{$_} eq "") {
+               eval "\$t = \$`.\"$m{$_}\".\$';";
+           }
+           else {
+               eval "\$t = \$`.$c{$_}.\$';";
+           }
+           die "syntax error: $@" if $@;
+       }
+    }
+    last if $none;
+    print STDERR "[".length($t)."] "."  next pass\n";
+# perfectionist's approach:
+#    $l = 0;
+#    for (keys %m) {
+#      if ($t =~ /$_/) {
+#          if (length($&) > $l) {
+#              $i = $_;
+#              $l = length($&);
+#          }
+#      }
+#    }
+#    last if !$l;
+#    $t =~ /$i/ || die "internal error";
+#    eval "\$t = \$`.\"$m{$i}\".\$'";
+#    die "syntax error: $@" if $@;
+#    print STDERR "[".length($t)."] "."$i\n";
+}
+#
+# handle verbatim sections (we're not trying to be perfect here)
+#
+print STDERR "[".length($t)."] Handling verbatim sections\n";
+while ($t =~ /\\begin{verbatim}([ \t]*\n)?/) { $t = $`."\n\n".$B.$'; }
+while ($t =~ /\\end{verbatim}([ \t]*\n)?/) { $t = $`.$E."\n\n".$'; }
+while ($t =~ /\\verb([^a-zA-Z \t\n])/ && $t =~ /\\verb$1([^$1]*)$1/) {
+    $t = $`.$B.$1.$E.$';
+}
+while ($t =~ /$B([^$B$E]*)$E/) {
+    ($a,$b,$c) = ($`,$1,$');
+    die "no support for \\t yet, sorry" if $b =~ /\t/;
+    $b =~ s/\\/\\backslash /g;
+    $b =~ s/[~^_%#&{}\$\-]/\\$&/g;
+    $b =~ s/[`']/\\$&~/g;
+    $b =~ s/ /~/g;
+    $b =~ s/\n\n\n/$B2/g;
+    $b =~ s/\n\n/$B1/g;
+    $b =~ s/\n/\\\\/g;
+    $t = $a.$b.$c;
+}
+if ($t =~ /[$B$E]/) {
+    if ($t =~ /..........[$B$E]........../) { print STDERR "$&\n"; }
+    die "verbatim conflict";
+}
+#
+# hide escaped curly braces
+#
+print STDERR "[".length($t)."] Hiding escaped curly braces\n";
+$t =~ s/\\{/$CO/g;
+$t =~ s/\\}/$CC/g;
+#
+# discard comments and italic corrections
+#
+print STDERR "[".length($t)."] Discarding comments and italic corrections\n";
+while ($t =~ s/([^\\])%[^\n]*\n/$1/g) {};
+$t =~ s|\\/||g;
+#
+# no math mode
+#
+print STDERR "[".length($t)."] No math mode\n";
+while ($t =~ s/([^\\])\$/$1/g) {};
+#
+# remove tabs and massage blanks
+#
+print STDERR "[".length($t)."] Removing tabs and massaging blanks\n";
+$t =~ s/\\ / /g;       # \cmd\ blah
+$t =~ tr/ \t/ /s;
+#
+# various minor issues
+#
+print STDERR "[".length($t)."] Dealing with various minor issues\n";
+$t =~ s/\\rightarrow\s*/->/g;
+$t =~ s/\\quad\s*/~/g;
+$t =~ s/\\qquad\s*/~~/g;
+$t =~ s/\\vert/|/g;
+$t =~ s/\\TeX/TeX/g;
+$t =~ s/\\LaTeX/LaTeX/g;
+$t =~ s/\\rm\s*//g;
+$t =~ s/\\hbox{/{/g;
+$t =~ s/\\protect//g;
+$t =~ s/\\newpage\s*//g;
+$t =~ tr/-/-/s;
+$t =~ s/\n\n+/$B1/g;
+while ($t =~ /\\cite{([^}]+)}/) {
+    $t = $`."[";
+    $after = $';
+    for (split(",",$1)) {
+       if (defined $cite{$_}) { $t .= "$cite{$_},"; }
+       else {
+           $cite{$_} = ++$citation;
+           $bibref[$citation] = $_;
+           $t .= "$citation,";
+           die "unmatched ref $_" unless $after =~ /\\bibitem{$_}/;
+           $after = $`."\\item[\[$citation\]] ".$';
+       }
+    }
+    $t =~ s/,$//;
+    $t .= "]$after";
+}
+$t =~
+  s/\\begin{thebibliography}{[^}]*}/\\section{References}\\begin{description}/;
+$t =~ s/\\end{thebibliography/\\end{description}/;
+#
+# handle footnotes
+#
+print STDERR "[".length($t)."] Handling footnotes\n";
+$t =~ s/\\footnote{/\\footnotemark\\footnotetext{/g;
+$t =~ s/\\footnotemark/$X/g;
+$t =~ s/\\footnotetext{/$Y/g;
+while ($t =~ /$X([^$Y]*)$Y/) {
+    ($a,$b,$c) = ($`,$',$1);
+    $t =~ /^[^$Y]*$Y$B1/;
+    $d = $';
+    for ($s = "*"; $d =~ /$Z/; $d = $`.$Y.$') { $s .= "*"; }
+    $a = $a.$s.$c;
+    while ($b =~ /^([^}]*){([^{}]*)}/) { $b = $`.$1.$B.$2.$E.$'; }
+    $b =~ /^([^{}]*)}/ || die "{ } confusion";
+    ($b,$t) = ($1,$');
+    $b =~ s/$B/{/g;
+    $b =~ s/$E/}/g;
+    $d = "$B1$Z\\begin{description}\\item[$s] $b\\end{description}$B1";
+    if ($t =~ /$B1([^$Z][^$N]*)$/) { $t = $`.$d.$1; }
+    else { $t = $t.$d; }
+    $t = $a.$t;
+}
+$t =~ s/$Z//g;
+if ($t =~ /[$X$Y$Z$B$E]/) {
+    if ($t =~ /..............[$X$Y$Z$B$E]/) { print STDERR "HEY $&\n"; }
+    die "footnote confusion";
+}
+#
+# process simple tables ...
+#
+print STDERR "[".length($t)."] Processing simple tables\n";
+while ($t =~ /\\begin{tabular}/) { $t = $`.$B.$'; }
+while ($t =~ /\\end{tabular}/) { $t = $`.$E.$'; }
+while ($t =~ /$B\{([rlc|]+)\}([^$B$E]*)$E/) {
+    ($a,$b,$c,$d) = ($`,$',$2,$1);
+    $c =~ s/\\\\/&/g;
+    $c =~ s/[\s\n]*\\hline[\s\n]*/$X&/g;
+    ($e = $d) =~ tr/|//cd;
+    @d = ();
+    while ($d =~ /^(\|*)[a-z](\|*)/) {
+       push(@d,$&);
+       $d = $';
+    }
+    @f = ();
+    while ($c =~ /([^\\])&/) {
+       push(@f,$`.$1);
+       $c = $';
+    }
+    @w = ();
+    $d =~ tr/|//d;
+    $i = 0;
+    for (@f) {
+       next if $_ eq $X;
+       $f = $i % @d;
+       $_ = &xlat($_);
+       $_ =~ s/^[\s\n]*//g;
+       $_ =~ s/[\s\n]*$//g;
+       if ($w[$f] < length($_)) { $w[$f] = length($_); }
+       $i++;
+    }
+    $l = @d+2*length($e)-1;
+    for (@w) { $l += $_; }
+    $a .= "$B1";
+    $i = 0;
+    for (@f) {
+       if ($_ eq $X) { $a .= ("-" x $l)."\\\\"; }
+       else {
+           $f = $i % @d;
+           if ($d[$f] =~ /^\|/) { $a .= "| "; }
+           $g = $w[$f]-length($_);
+           if ($d[$f] =~ /l/) { $a .= $_.("~" x $g); }
+           if ($d[$f] =~ /c/) {
+               $a .= ("~" x int($g/2)).$_.("~" x ($g-int($g/2)));
+           }
+           if ($d[$f] =~ /r/) { $a .= ("~" x $g).$_; }
+           $a .= " ";
+           if ($d[$f] =~ /\|$/) { $a .= "| "; }
+           if ($f == $#d) { $a .= "\\\\"; }
+           $i++;
+       }
+    }
+    $t = $a.$b.$B1;
+}
+if ($t =~ /[$B$E$X]/) {
+    if ($t =~ /(.|\n)(.|\n)(.|\n)(.|\n)(.|\n)(.|\n)[$B$E$X](.|\n)(.|\n)(.|\n)(.|\n)(.|\n)(.|\n)/) { print STDERR "$&\n"; }
+    die "\\begin/end{tabular} mismatch";
+}
+#
+# process lists
+#
+print STDERR "[".length($t)."] Formatting lists\n";
+while ($t =~ /\\begin{itemize}\s*/) { $t = $`.$B.$'; }
+while ($t =~ /\\end{itemize}\s*/) { $t = $`.$E.$'; }
+while ($t =~ /$B[^$B$E]*$E/) {
+    ($a,$b,$c) = ($`,$&,$');
+    while ($b =~ /\\item\s*/) { $b = $`.$X.$'; }
+    while ($b =~ /$X([^$X]*)([$X$E])/) {
+       $b = $`."- ".$SI.$SI.$1.$SO.$SO."\\\\"."$2".$';
+    }
+    $b =~ /$B([^$B$E]*)$E/;
+    $t = $a.$SI.$SI.$B1.$1.$SO.$SO."$B1".$c;
+}
+$t !~ /[$B$E]/ || die "\\begin/\\end{itemize} mismatch";
+while ($t =~ /\\begin{description}\s*/) { $t = $`.$B.$'; }
+while ($t =~ /\\end{description}\s*/) { $t = $`.$E.$'; }
+while ($t =~ /$B[^$B$E]*$E/) {
+    ($a,$b,$c) = ($`,$&,$');
+    while ($b =~ /\\item\[/) { $b = $`.$X."[".$'; }
+    while ($b =~ /$X\[/) {
+       ($d,$e) = ($`,$');
+       while ($e =~ s/\[([^\[\]]*)\]/$BS$1$ES/g) {};
+       $e =~ /^([^\[\]]*)]\s*([^$X]*)([$X$E])/ || die "\item problem (1)";
+       $b = $d.$1."~~".$SI.$SI.$2.$SO.$SO."\\\\".$3.$';
+       $b =~ s/$BS/[/g;
+       $b =~ s/$ES/]/g;
+    }
+    $b =~ /$B([^$B$E]*)$E/;
+    $t = $a.$SI.$SI.$B1.$1.$SO.$SO.$B1.$c;
+}
+$t !~ /[$X]/ || die "\item problem (2)";
+$t !~ /[$B$E]/ || die "\\begin/\\end{description} mismatch";
+#
+# process figures
+#
+print STDERR "[".length($t)."] Removing figures\n";
+while ($t =~ /\\begin{figure}\s*/) { $t = $`.$B.$'; }
+while ($t =~ /\\end{figure}\s*/) { $t = $`.$E.$'; }
+while ($t =~ /$B[^$B$E]*$E/) {
+    ($a,$b,$c) = ($`,$&,$');
+    $t = $a."[ Figure";
+    if ($b =~ /\\label{([^}]*)}/) {
+       $l{$1} = ++$figref;
+       $t .= " $figref";
+    }
+    if ($b =~ /\\caption{([^}]*)}/) {
+       $t .= ": $1";
+    }
+    $t .= " ]".$c;
+}
+
+#
+# process sections and labels
+#
+print STDERR "[".length($t)."] Processing sections and labels\n";
+$t =~ s/\\begin{abstract}/\\section{Abstract}/g;
+$t =~ s/\\end{abstract}//g;
+$LB = "\005";  # they don't necessarily have to be unique
+$SC = "\006";
+while ($t =~ /\\label{/) { $t = $`.$LB."{".$'; }
+while ($t =~ /\\((sub)*)section\*?{/) { $t = $`.$SC.$1."{".$'; }
+$l = "";
+while (1) {
+    if ($t =~ /^([^$LB$SC]*)$LB\{([^{}]*)\}/) {
+       $l{$2} = '"'.$l.'"';
+       $t = $1.$';
+    }
+    if ($t =~ /$SC((sub)*){/) {
+       ($a,$b,$c) = ($`,$',$1);
+       while ($b =~ /^([^}]*){([^{}]*)}/) { $b = $`.$1.$B.$2.$E.$'; }
+       $b =~ /^([^{}]*)}\s*/ || die "{ } confusion";
+       ($b,$d) = ($1,$');
+       $b =~ s/$B/{/g;
+       $b =~ s/$E/}/g;
+       $l = $b;
+       $b = &xlat($b);
+       if (($u = ("=","-","- ","")[length($c)/3]) ne "") {
+           $u = "\\\\".substr($u x length($b),0,length($b));
+       }
+        $t = $a.$B2.$b.$u.$B1.$d;
+    }
+    else {
+       last;
+    }
+}
+#
+# handle references
+#
+print STDERR "[".length($t)."] Handling references\n";
+$t =~ s/[Pp]age \\pageref({[^{}]*})/\\ref$1/g;
+$t =~ s/\\pageref{[^{}]*}/???/g;
+while ($t =~ /\\ref{([^{}]*)}/) {
+    $t = $`.(defined($l{$1}) ? $l{$1} : "???").$';
+}
+#
+# collapse whitespace
+#
+print STDERR "[".length($t)."] Collapsing whitespace\n";
+$t =~ s/\\par\s*/\n\n/g;
+$t =~ s/ *(\n+) */$1/g;
+$t =~ tr/\n/ /;
+$t =~ tr/ \t/ /s;      # again
+#
+# handle line breaks
+#
+print STDERR "[".length($t)."] Handling line breaks\n";
+$t =~ tr/\n//d;
+$t =~ s/\\\\/\n/g;
+$t =~ s/\\par\s*/$B1/g;
+#
+# handle accents, umlauts, and double quotes
+#
+print STDERR "[".length($t)."] Handling accents, umlauts, double quotes ".
+  "and hyphens\n";
+$t =~ s/\\[`']([AEOUaeou])/$1/g;
+$t =~ s/\\([`'])~/$1/g;
+$t =~ s/\\"([AOUaou])/$1e/g;
+$t =~ s/``/"/g;
+$t =~ s/''/"/g;
+#
+# apply ultimate set of fixes to newlines
+#
+print STDERR "[".length($t)."] Applying ultimate set of fixes to newlines\n";
+while ($t =~ s/([\n$B1$B2]+)([$SI$SO])/$2$1/g) {};
+$t =~ s/([\n$B1$B2]*)\s+([\n$B1$B2]+)/$1$2/g;
+$t =~ s/\n+/\n/g;
+$t =~ s/\n?($B1)[\n$B1]*/\n\n/g;
+$t =~ s/\n*($B2)[\n$B2]*/\n\n\n/g;
+#
+# translate what's left
+#
+print STDERR "[".length($t)."] Final translation\n";
+$t = &xlat($t);
+$t =~ s/^\s*//;
+$t =~ s/\s*$//;
+$t .= "\n";
+#
+# okay, now format and print it
+#
+print STDERR "[".length($t)."] "."Formatting (may take a while)\n";
+$l = "";
+$m = 0;
+while ($t =~ /([$SI$SO\n]| +)/) {
+    if ($` ne "" || substr($1,0,1) eq " ") {
+       if (length($l)+length($`) > $w && $l ne "") {
+           print $l."\n";
+           $l = "";
+       }
+       if ($l eq "") { $l = " " x $m; }
+       $l = $l.$`.(substr($1,0,1) eq " " ? $1 : "");
+    }
+    $t = $';
+    if ($1 eq $SI) { $m++; }
+    if ($1 eq $SO) { $m--; }
+    if ($1 eq "\n") {
+       print $l."\n";
+       $l = "";
+#      $t = s/^ *(\S.*)/\1/;
+    }
+}
+print "$l\n" if $l ne "";
+print STDERR "Done\n";
diff --git a/doc/tech.tex b/doc/tech.tex
new file mode 100644 (file)
index 0000000..ca2892e
--- /dev/null
@@ -0,0 +1,359 @@
+%
+% Copyright 1992-1998 by Werner Almesberger.
+% All rights reserved.
+%
+% See file COPYING for details.
+%
+
+\documentclass[fullpage]{article}
+\usepackage{ae}
+\usepackage[bookmarks,%
+        pdftitle={Linux Loader (LILO) technical overview},%
+        pdfsubject={Booting on iA32 architecture},%
+        pdfkeywords={lilo, boot},%
+        pdfauthor={Werner Almesberger <Werner.Almesberger@epfl.ch>}]%
+        {hyperref}
+\usepackage{ifpdf}
+
+\parindent=0pt
+\parskip=4pt
+
+\hyphenation{hexa-decimal}
+
+\def\key#1{$[$#1$]$}
+\def\LILO{LILO}
+
+\def\SetFigFont#1#2#3{\tt}
+
+
+\begin{document}
+
+\title{\LILO \\
+  \Large
+  Generic boot loader for Linux \\
+  Version 21 \\ ~\\
+  \bf Technical overview}
+\author{Werner Almesberger \\
+  {\tt Werner.Almesberger@epfl.ch}}
+\date{December 4, 1998}
+
+\maketitle
+{
+  \parskip=-4pt
+  \setcounter{tocdepth}{1}
+  \tableofcontents
+}
+
+~\\
+This document describes internals of \LILO\ and related parts of its
+environment (kernel, etc.). It is not necessary to read or understand
+this document in order to install or use \LILO. A general introduction
+and installation instructions can be found in the user's guide.
+
+{\bf This document has only been partially updated and does not entirely
+reflect the current ('98) status of Linux or of \LILO\ (version 21).}
+
+
+\section{Load sequence}
+\label{load}
+
+The boot sector is loaded by the ROM-BIOS at address 0x07C00. It moves
+itself to address 0x96A00, sets up the stack (growing downwards from
+0x96A00 to 0x96800), loads the secondary boot loader at address
+0x96C00 and transfers control to it. It displays an ``L'' after moving
+itself and an ``I'' before starting the secondary boot loader. If a read
+error occurs when loading the secondary boot loader, a two-digit hex code
+is displayed after the ``L''. This results in an endless stream of error
+codes if the problem is permanent. Displaying these error codes is disabled
+if the build-time option {\tt NO1STDIAG} is set.
+
+The secondary boot loader loads the descriptor table at 0x98800 and the
+sector containing the default command line at 0x98C00. If the default command
+line is enabled, its magic number is invalidated and the sector is written
+back to disk. This potentially dangerous operation can be disabled by defining
+{\tt LCF\_READONLY} when passing {\tt second.S} through {\sf cpp}. Next, the
+secondary boot loader checks
+for user input. If either the default is used or if the user has specified
+an alternate image, the options sector is loaded at 0x98C00 and the parameter
+line is constructed at 0x99000. If the resulting line contains the option
+\verb"lock", the command line as entered by the user (it is saved before
+the final line is constructed) is written to the disk as the new default
+command line. Also, if a fallback command line is set, it is copied to the
+default command line sector.
+
+If the user has supplied an initial RAM disk image, this file is loaded
+below the end of physical memory or 16 MB, whichever is lower. The start
+address is lowered to the next page boundary so that the memory area
+occupied by the initial RAM disk can later be easily returned to the
+system's free memory pool. The 16 MB limit exists because the BIOS
+functions used to transfer data in memory are only specified for an 24 bit
+address space.
+
+Next, the floppy boot sector of that image is
+loaded at 0x90000\footnote{The floppy boot sector is only used as a source of
+setup information.},
+the setup part is loaded at 0x90200 and
+the kernel part is loaded at 0x10000, or, if the kernel has been compiled
+for being loaded ``high'' (i.e. with {\tt make bzImage}), it is loaded
+at 0x100000 instead. During the load operations, the sectors
+of the map file are loaded at 0x98600.
+
+If the loaded image is a kernel image, control is transferred to
+its setup code.
+If a different operating system is booted, things are a bit more difficult:
+the chain loader is loaded at 0x90200 and the boot sector of the other OS
+is loaded at 0x90400. The chain loader moves the partition table (loaded at
+0x903BE as part of the chain loader) to 0x00600 and the boot sector to
+0x07C00. After that, it passes control to the boot sector.
+
+Chain loaders that allow booting from a second drive (either floppy or hard
+disk) also install a small function to intercept BIOS calls and to swap
+the drive numbers at the top of available memory.
+
+The secondary boot loader displays an ``L'' after being started and an ``O''
+after loading the descriptor table and the default command line. Before
+loading the descriptor table, it checks, whether it has been loaded at the
+correct location and displays a question mark if it hasn't. If the
+descriptor table has an incorrect checksum, a minus sign is displayed.
+
+$$
+\begin{tabular}{l|c|l}
+  \cline{2-2}
+  \tt 0x00000 & & 1982 bytes \\
+  \cline{2-2}
+  \tt 0x007BE & Partition table & 64 bytes \\
+  \cline{2-2}
+  \tt 0x007FE & & 29 kB \\
+  \cline{2-2}
+  \tt 0x07C00 & Boot load area & 512 bytes \\
+  \cline{2-2}
+  \tt 0x07E00 & & 32.5 kB \\
+  \cline{2-2}
+  \tt 0x10000 & & 448 kB \\
+  & & \\
+  & Kernel & \\
+  & & \\
+  & & \\
+  \cline{2-2}
+  \tt 0x90000 & Floppy boot sector & 512 bytes \\
+  \cline{2-2}
+  \tt 0x90200 & Setup (kernel) & 39.5 kB (2 kB used) \\
+  \cline{2-2}
+  \tt 0x9A000 & Primary boot loader & 512 bytes \\
+  \cline{2-2}
+  \tt 0x9A200 & Stack & 3.5 kB \\
+  \cline{2-2}
+  \tt 0x9B000 & Secondary boot loader & 8 kB (3.5 kB used) \\
+  \cline{2-2}
+  \tt 0x9D000 & Map load area & 512 bytes \\
+  \cline{2-2}
+  \tt 0x9D200 & Descriptor table & 1 kB \\
+  \cline{2-2}
+  \tt 0x9D600 & Default command line, etc. & 512 bytes \\
+  \cline{2-2}
+  \tt 0x9D800 & Keyboard translation table & 512 bytes \\
+  \cline{2-2}
+  \tt 0x9DA00 & Parameter line construction area & 1 kB \\
+  \cline{2-2}
+  \tt 0x9DC00 & & 7.5 kB \\
+  & & \\
+  \cline{2-2}
+  & Drive swapper & 1 kB \\
+  \cline{2-2}
+  \multicolumn{3}{l}{\tt 0xA0000} \\
+\end{tabular}
+$$
+
+The area 0x90020-0x90023 is overlaid by a command-line descriptor while
+the secondary boot loader is running.
+
+
+
+\section{File references}
+
+This section describes the references among files involved in the boot
+procedures.
+
+$$
+  \input bootloader
+$$
+
+The boot sector contains the primary boot loader, the address of the default
+command line sector, the address of both
+descriptor table sectors and the addresses of the sectors of the secondary
+boot loader. The generic boot sector is copied from {\tt boot.b}.
+
+The primary boot loader can store up to eight sector addresses of the
+secondary boot loader.
+
+$$
+  \input map
+$$
+
+The map file consists of so-called sections and of special data sectors.
+Each section
+spans an integral number of disk sectors and contains addresses of sectors
+of other files.
+
+There are three exceptions: 1. If a ``hole'' is being
+covered or if the floppy boot sector of an unstripped kernel has been omitted,
+the address of the zero sector is used. This sector is part of the
+map file. 2. When booting a different operating system, the first sector is
+the merged chain loader that has been written to the map file before that
+section. 3. Each map section describing an image is followed by a sector
+containing the options line of that image.
+
+The last address slot of each map sector is either unused (if the map section
+ends in this sector) or contains the address of the next map sector in the
+section.
+
+The ifive sectors at the beginning of the map file are special: the first
+sector contains the default command line, the next
+two sectors contain the boot image descriptor table and the fourth sector
+is filled with zero bytes. This sector is mapped whenever a file contains
+a ``hole''. The fifth sector contains the keyboard translation table.
+
+$$
+  \input image
+$$
+
+A kernel image consists simply of a sequence of sectors being
+loaded. The map section also contains a sector with a fallback command line
+and a sector with parameter line options. Optionally, a RAM disk image,
+specified by a second map section, can be loaded.
+
+$$
+  \input other
+$$
+
+When booting another operating system, the chain loader ({\tt chain.b}) is
+merged with the patched partition table\footnote{If the partition table is
+omitted, that area is filled with zero bytes.} and written into the map file.
+The map section of this boot image starts after that sector and contains only
+the address of a dummy floppy boot sector (the zero sector, but its
+contents are irrelevant), the loader
+sector and the boot sector of the other operating system. Not that the
+map section also contains the fallback sector and a (useless) sector for
+options.
+
+
+\section{Configuration parameters}
+
+The boot sector of each kernel contains a set of configuration parameters
+that have to be available at boot time before the kernel can access
+file systems. These parameters can be set when the kernel is compiled and
+later be changed with programs like {\sf rdev}. \LILO\ can supersede
+the parameters (in memory) at boot time by placing the corresponding
+items on the parameter line passed to the kernel.
+
+The parameters are stored at the following (decimal) offsets:
+
+\begin{description}
+  \item[497] the size of the setup code in sectors (512 bytes). Older kernels
+    may put a zero at this place.
+  \item[498-499] is a flag specifying whether the root file system should be
+    mounted read-only (if non-zero) or read-write (if zero).
+  \item[500-501] the size of the kernel, counted in paragraphs (16 bytes).
+  \item[502-503] this parameter is currently unused.
+  \item[504-505] the size of the RAM disk in kilobytes. No RAM disk is
+    created if this parameter is set to zero.
+  \item[506-507] the text mode the VGA is set to.
+    \begin{description}
+      \item[0xFFFD] the user is asked to specify the VGA mode at boot time.
+      \item[0xFFFE] uses 80x50 (``extended'') mode.
+      \item[0xFFFF] uses 80x25 (``normal'') mode.
+    \end{description}
+    Any other value selects the corresponding mode as displayed in the
+    interactive VGA mode selection menu. This is the only option that is set
+    by LILO by patching the boot sector instead of passing it on the parameter
+    line.
+  \item[508] the minor number of the device that should be mounted as root.
+  \item[509] the major number of the device that should be mounted as root.
+\end{description}
+
+
+\section{Parameter line interface}
+
+The kernel supports processing of parameters that are
+provided by the boot loader. The parameter string is a NUL-terminated
+ASCII string that contains space-separated words or
+{\tt {\it variable\/}={\it value\/}} pairs. A description of how they are
+interpreted can be found in the section of the user's guide labeled
+``The boot prompt''.
+
+The following descriptor has to be set up to pass a parameter string to
+the kernel:
+
+\begin{description}
+  \item[0x90020] the magic number 0xA33F.
+  \item[0x90022] the offset of the first byte of the parameter line relative
+    to 0x90000.
+\end{description}
+
+The boot loader composes the parameter line from the command line, from
+the options sector and from some internally generated prefixes (typically
+\verb"auto" and \verb"BOOT_IMAGE="), as follows:
+
+$$
+  \input parameter
+$$
+
+Example: \\
+Command line: \verb"vmlinuz root=802"\\
+Options sector: \verb"root=801 ro"
+
+yields \verb"BOOT_IMAGE=vmlinuz root=801 ro root=802"
+
+Because parameter line options can typically be overridden, the first
+\verb"root" option is ignored by the kernel.
+
+
+\section{External interface}
+
+\LILO\ is able to receive its command line from a program that is booted
+before it. This externally provided command line is only used if the
+user does not use the normal mechanism to invoke the boot prompt.
+
+The following register contents are expected:
+
+\begin{description}
+  \item[\bf DL] contains the value 0xFE.
+  \item[\bf ES:SI] points to the string ``LILO''. The string must be in
+    upper case and no terminating character is needed. The string must not
+    cross segment boundaries, i.e. {\bf SI} must be below 0xFFFD.
+  \item[\bf ES:BX] points to a NUL-terminated string that is used as the
+    command line. This string has a maximum length of 78 characters (not
+    including the terminating NUL) and must not cross segment boundaries.
+\end{description}
+
+There are two values of the externally provided command line that have a
+special meaning:
+
+\begin{itemize}
+  \item an empty string ({\bf ES:BX} points to a NUL byte) is interpreted
+    as a request to enter the boot prompt and to accept keyboard input.
+  \item a string that consists only of blanks is interpreted as a request
+    to boot the default boot image.
+\end{itemize}
+
+\LILO\ can also obtain the default command line from the map file. It
+is only used if no externally provided command line is available.
+
+
+\section{Default command line in map file}
+
+The first sector of the map file is reserved for a default command line.
+Unless the user invokes the boot prompt by pressing a shift key or unless an
+externally provided command line is present, the command line in the map
+file is interpreted as if it had been typed on the keyboard.
+
+The first two bytes of the first sector of the map file have to contain
+the magic number {\tt DC\_MAGIC} (0xF4F2) in little-endian byte order.
+They are followed by a NUL-terminated string with a maximum length of
+510 bytes, including the NUL. Note that the boot loader limits command
+lines to 78 characters after removing duplicate spaces.
+
+The command line is disabled by either clobbering the magic number or
+by using an empty string (i.e. only a NUL byte) as the command line.
+
+\end{document}
diff --git a/doc/user.tex b/doc/user.tex
new file mode 100644 (file)
index 0000000..93e23f7
--- /dev/null
@@ -0,0 +1,3505 @@
+%
+% Copyright 1992-1998 by Werner Almesberger.
+% Copyright 1999-2000 by John R. Coffman (version 21-3)
+% All rights reserved.
+%
+% See file COPYING for details.
+%
+
+%%def%:=
+%:\begin{verbatim}
+%:LILO - Generic Boot Loader for Linux ("LInux LOader") by Werner Almesberger
+%:===========================================================================
+%:
+%:   NOTE:  This document is no longer maintained.  However, it is
+%:   still current.  Changes to LILO for versions 21.2 and later are
+%:   documented in detail in the 'man' pages for 'lilo' and 'lilo.conf'.
+%:   Refer to them first, then to this document.
+%:
+%:  
+%:Version 21-4 (release) -- John Coffman <johninsd@san.rr.com>
+%:
+%:Minor changes suggested by Werner to show that this release is derived
+%:from the source code to his version 21.  Added VERSION_MAJOR and 
+%:VERSION_MINOR to replace VERSION.  The file VERSION is replaced by 
+%:'version.h'.
+%:
+%:The first and second stage loaders have been modified so that ONLY
+%:'lba32' will use EDD packet calls.  'linear' will now always ask the
+%:BIOS for the disk geometry, and then use C:H:S addressing.
+%:
+%:
+%:Version 21-2  -- John Coffman <johninsd@san.rr.com>
+%:
+%:This version was created to allow booting on disks larger than 8.4Gb using
+%:the Enhanced BIOS call (int 0x13, AH=0x42) and the packet-call interface.
+%:These calls are supported on post-1998 systems, and through software BIOS
+%:extensions such as EZ-DRIVE(tm).  
+%:
+%:My primary objective in making these changes to LILO, is not to break any-
+%:thing.  Hence, the 32-bit direct addressing of sectors is supported by a
+%:new keyword in the 'lilo.conf' file:  "lba32".  This keyword is mutually
+%:exclusive with the keyword "linear".  On the command line, these options
+%:are invoked with the new "-L" switch, or the old "-l" switch, respectively.
+%:
+%:Apologies to Werner Almesberger for not communicating these changes/addi-
+%:tions to him directly; but I have not been able to contact him by e-mail
+%:at the address he provided in the latest 'lilo.lsm' file.  I do not want
+%:versions of LILO to get out-of-step.
+%:
+%:Disk sector addresses are conveyed from the Map Installer (lilo executable)
+%:to the boot loaders, first- and second-stages through a 5 byte structure:
+%:
+%:     sector    [1..63] plus 2 high bits of Cylinder
+%:     cylinder  [0..1023] low eight bits in this byte
+%:     device    [0..3] for floppies, [0x80..0x8F] for hard disks
+%:     head      [0..254] no, the max is 254, not 255
+%:     count     [1...] number of sectors to transfer
+%:     
+%:The first two bytes are normally loaded into the CX register, the second two
+%:bytes into the DX register, and the last byte into the AL register.  This is
+%:the call used for the C:H:S addressing scheme of the original IBM-PC BIOS.
+%:LILO checks that the 64Kb DMA boundary is never crossed by a call, and that
+%:the count never exceeds the sector count of one track on the disk.
+%:
+%:When 'linear' is specified, a 24-bit, 0 based addressing scheme is employed.
+%:The low 8 bits are in 'sector'; the middle 8 bits in 'cylinder'; and the high
+%:8 bits are in 'head'.  To flag this as a 'linear' address, the 'device' byte
+%:has bit 6 set (mask 0x40 or'ed in).  The count field is a maximum of 128,
+%:since anything greater would cross a 64Kb DMA boundary.  It is up to the 
+%:loader code (second stage only), to check that no track boundary is crossed.
+%:
+%:The situation is more complicated with 'lba32' addressing.  It is flagged with
+%:bit 5 of the 'device' byte being set (mask 0x20 or'ed in).  The 32-bit address
+%:is spread over the 'sector', 'cylinder', 'head', and 'count' fields, from low
+%:byte to high byte, respectively.  Whenever this full 32-bit address is
+%:specified explicitly, the actual sector count to transfer is implied to be
+%:one (1), and this fact is flagged in the 'device' byte by setting bit 5
+%:(mask 0x10 or'ed in).  When a multi-sector transfer is called for, the high
+%:8-bits of the address are NOT specified explicitly, but are assumed to be
+%:the same as the previous transfer, the 'count' of sectors to transfer will
+%:be in the range [2..127], and bit 5 (mask 0x10) of the 'device' byte will be
+%:clear.
+%:
+%:The first-stage loader uses single sector transfers only, so it uses a
+%:simplified disk read routine, always assumes a sector transfer count of 1,
+%:and always assumes that the full 32-bit address of the sector is specified
+%:when 'lba32' mode is detected in the 'device' byte.  However, the second-
+%:stage loader is capable of multi-sector transfers when map-compaction has
+%:been used (-c switch, or 'compact' global option), so it uses the fully
+%:capable read routine to load the -initrd- image, and the -kernel- image.
+%:
+%:Both 'linear' and 'lba32' will use the Enhanced BIOS packet calls, if they
+%:are available.  Otherwise, the disk address is converted to C:H:S, using the
+%:disk geometry returned by (int 0x13, AH=8).  If cylinder overflow occurs --
+%:i.e., cylinder > 1023, then error code '9f' is issued.
+%:
+%:The BIOS calls used to implement large disk booting conform to the Enhanced
+%:Disk Drive Specification, version 3.0, rev 0.8, dated March 12, 1998.  This
+%:document is available on-line from Phoenix Technologies Ltd., at:
+%:   
+%:   http://www.phoenix.com/products/specs.html
+%:
+%:Known bugs:
+%:   The chain loader, 'os2_d.b', still will not boot OS2 4.0 from a secondary
+%:   partition on my "D:" drive.  Boot Manager can, and I am still working on
+%:   the problem.
+%:----------------------------------------------------------------------------
+%:
+%:
+%:Version 21
+%:
+%:Important: The file INCOMPAT contains vital (in)compatibility information
+%:           for this release of LILO. Read it before proceeding.
+%:
+%:Installing boot loaders is inherently dangerous. Be sure to have some means
+%:to boot your system from a different media if you install LILO on your hard
+%:disk.
+%:
+%:
+%:There is also a LaTeX version of this document in the "doc" directory.
+%:It is much nicer to read than pure ASCII.
+%:
+%:
+%:Installation
+%:------------
+%:
+%:Please read the file INCOMPAT for compatibility notes.
+%:
+%:The installation procedure is described in the section "Normal first-time
+%:installation". Please read "Booting basics" for the whole story.
+%:
+%:*** QUICK INSTALLATION ***
+%:
+%:    If you want to install LILO on your hard disk and if you don't want
+%:    to use all its features, you can use the quick installation script.
+%:    Read QuickInst for details.
+%:
+%:
+%:\end{verbatim}
+
+%%beginskip
+
+\documentclass[fullpage]{article}
+\usepackage{ae}
+\usepackage[bookmarks,%
+        pdftitle={Linux Loader (LILO) user manual},%
+        pdfsubject={Booting on iA32 architecture},%
+        pdfkeywords={lilo, boot},%
+        pdfauthor={Werner Almesberger, John Coffman}]%
+        {hyperref}
+\usepackage{ifpdf}
+
+\parindent=0pt
+\parskip=4pt
+\tolerance=9000
+
+\hyphenation{hexa-decimal}
+
+% Okay, what follows is more TeX than LaTeX ...
+
+\def\hditem#1{\hbox to 1.2in{#1\hfil}}
+\def\boottwo#1{$$
+  \bf
+  \begin{tabular}{|ll|}
+    \hline
+    \hditem{\rm Master Boot Record} & \hditem{\rm Operating system} \\
+    \hline
+    #1 \\
+    \hline
+  \end{tabular}
+  $$}
+
+\def\bootthree#1{$$
+  \bf
+  \begin{tabular}{|lll|}
+    \hline
+    \hditem{\rm Master Boot Record} & \hditem{\rm Boot sector} &
+      \hditem{\rm Operating system} \\
+    \hline
+    #1 \\
+    \hline
+  \end{tabular}
+  $$}
+
+\def\bootfour#1{$$
+  \bf
+  \begin{tabular}{|llll|}
+    \hline
+    \hditem{\rm Master Boot Record} & \hbox to 1.1in{\rm Boot sector\hfil} &
+      \hditem{\rm Operating systems} & \hbox to 0.4in{\hfil} \\
+    \hline
+    #1 \\
+    \hline
+  \end{tabular}
+  $$}
+\def\sep{\rightarrowfill &}
+\def\emptys{&}
+\def\branch{\hfill$\longrightarrow$ &}
+\def\cont{---\,$\cdots$}
+\def\key#1{$[$#1$]$}
+\def\LILO{LILO}
+\def\meta#1{{\it #1\/}}        % ... <blah> ...
+\def\path#1{{\tt #1}}   % ... /foo/bar ...
+\def\raw#1{{\tt #1}}   % ...  raw output  ...
+\def\craw#1{{\tt #1}}  % ...  raw output  ...
+\def\name#1{{\sf #1}}  % ... FooBar ...
+\def\emphasize#1{{\bf #1}} % ... _don't_ ...
+\def\unit#1{\hbox{\tt #1}} % ... \unit{-x foo} ...
+%%def\\key{([^{}]*)}=[$1]
+%%def\\LILO=LILO
+%%def\\meta{([^{}]*)}=<$1>
+%%def\\path{([^{}]*)}=$1
+%%def\\raw{([^{}]*)}=~$1~
+%%cmd\\craw{([^{}]*)}=((($x = $1) =~ tr/a-z/A-Z/), $x)
+%%def\\name{={
+%%def\\emphasize{([^{}]*)}=\\_$1\\_
+%%def\\underline{([^{}]*)}=$1
+%%def\\begin{command}=\\raw{$SI$SI$SI$SI
+%%def\\end{command}=$SO$SO$SO$SO}
+%%def\\addtocounter{([^{}]*)}{([^{}]*)}=~
+%%def\\hbox{([^{}]*)}=$1
+%%def(\\unit{[^{} ]*) ([^{}]*})=$1~$2
+%%def\\unit{([^{} ]*)}=$1
+%%def{\$([^{}])\$}=$1
+%%def%4=    
+%      ^^^^
+%       four invisible spaces here
+%%def%;=        
+%      ^^^^^^^^
+%       eight invisible spaces here
+
+\newenvironment{command}{\def\[{$\bigl[$}\def\]{$\bigr]$}\def\|{$\big\vert$}%
+  \parindent=-2em\advance\leftskip by -\parindent\vskip -\parskip~\par
+  \begingroup\tt\textfont0=\font}{%
+  ~\endgroup\par\advance\hoffset by \parindent}
+
+\begin{document}
+
+\title{\LILO \\
+  \Large
+  Generic boot loader for Linux \\
+  Version 21 \\ ~\\
+  \bf User's guide}
+\author{Werner Almesberger \\
+  {\tt Werner.Almesberger@epfl.ch}}
+\date{December 4, 1998}
+
+\maketitle
+{
+  \parskip=-1pt
+  \setcounter{tocdepth}{2}
+  \tableofcontents
+}
+%%endskip
+
+~\\
+\LILO\ is a versatile boot loader for Linux. It does not depend on a specific
+file system, can boot Linux kernel images from
+floppy disks and from hard disks and can even act as a ``boot manager'' for
+other operating
+systems.\footnote{PC/MS-DOS, DR DOS, OS/2, Windows 95, Windows NT, 386BSD,
+SCO UNIX, Unixware, $\ldots$}
+
+One of up to sixteen different images can be selected at boot time.
+Various parameters, such as the root
+device, can be set independently for each kernel. \LILO\ can even be
+used as the master boot record.
+
+This document introduces the basics of disk organization and booting,
+continues with an overview of common boot techniques and finally describes
+installation and use of \LILO\ in greater detail. The troubleshooting
+section at the end describes diagnostic messages and contains suggestions
+for most problems that have been observed in the past.
+
+Please read at least the sections about installation and configuration if
+you're already using an older version of \LILO. This distribution is
+accompanied by a file named \path{INCOMPAT} that describes further
+incompatibilities to older versions.
+
+For the impatient: there is a quick-installation script to create
+a simple but quite usable installation. See section \ref{quickinst} for
+details.
+
+But wait $\ldots$ here are a few easy rules that will help you to avoid
+most problems people experience with \LILO:
+
+\begin{itemize}
+  \item \emphasize{Don't panic.} If something doesn't work, try to find
+    out what is wrong, try to verify your assumption and only then attempt
+    to fix it.
+  \item Read the documentation. Especially if what the system does doesn't
+    correspond to what you think it should do.
+  \item Make sure you have an emergency boot disk, that you know how to
+    use it, and that it is always kept up to date.
+  \item Run \path{/sbin/lilo} \emphasize{whenever} the kernel or any part
+    of \LILO, including its configuration file, has changed. When in doubt,
+    run it. You can't run \path{/sbin/lilo} too many times.
+  \item If performing a destructive upgrade and/or erasing your Linux
+    partitions, de-install \LILO\ \emphasize{before} that if using it as the
+    MBR.
+  \item Don't trust setup scripts. Always verify the \path{/etc/lilo.conf}
+    they create before booting.
+  \item If using a big disk, be prepared for inconveniences: you may have
+    to use the \craw{linear} option.
+\end{itemize}
+
+
+\newpage
+\subsection*{System overview}
+
+\LILO\ is a collection of several programs and other files:
+
+\begin{description}
+  \item[The map installer] is the program you run under Linux to put all
+    files belonging to \LILO\ at the appropriate places and to record
+    information about the location of data needed at boot time. This program
+    normally resides in \path{/sbin/lilo}. It has to be run to refresh that
+    information whenever any part of the system that \LILO\ knows about
+    changes, e.g. after installing a new kernel.
+  \item[Various files] contain data \LILO\ needs at boot time, e.g. the
+    boot loader. Those files normally reside in \path{/boot}. The most
+    important files are the boot loader (see below) and the map file
+    (\path{/boot/map}), where the map installer records the location of
+    the kernel(s).\footnote{\LILO\ does not know how to read a file system.
+    Instead, the map installer asks the kernel for the physical location of
+    files (e.g. the kernel image(s)) and records that information. This
+    allows \LILO\ to work with most file systems that are supported by
+    Linux.} Another important file is the configuration file, which is
+    normally called \path{/etc/lilo.conf}
+  \item[The boot loader] is the part of \LILO\ that is loaded by the BIOS
+    and that loads kernels or the boot sectors of other operating systems.
+    It also provides a simple command-line interface to interactively
+    select the item to boot and to add boot options.
+\end{description}
+
+\LILO\ primarily accesses the following parts of the system:
+
+\begin{description}
+  \item[The root file system partition] is important for two reasons: first,
+    \LILO\ sometimes has to tell the kernel where to look for it. Second, it
+    is frequently a convenient place for many other items \LILO\ uses, such
+    as the boot sector, the \path{/boot} directory, and the kernels.
+  \item[The boot sector] contains the first part of \LILO's boot loader. It
+    loads the much larger second-stage loader. Both loaders are typically
+    stored in the file \path{/boot/boot.b}
+  \item[The kernel] is loaded and started by the boot loader. Kernels
+    typically reside in the root directory or in \path{/boot}.
+\end{description}
+
+Note that many of the files \LILO\ needs at boot time have to be accessible
+with the BIOS. This creates certain restrictions, see section \ref{broken}.
+
+
+\newpage
+\section{Introduction}
+
+The following sections describe how PCs
+boot in general and what has to be known when booting Linux and using
+\LILO\ in particular.
+
+
+\subsection{Disk organization}
+\label{diskorg}
+
+When designing a boot concept, it is important to understand some of the
+subtleties of how PCs typically organize disks. The most simple case are
+floppy disks. They consist of a boot sector, some administrative
+data (FAT or super block, etc.) and the data area. Because that
+administrative data is irrelevant as far as booting is concerned, it is
+regarded as part of the data area for simplicity.
+
+%%beginskip
+$$
+\begin{tabular}{|c|c|}
+  \hline
+  Boot sector & \hbox to 1.5in{\hfil} \\
+  \cline{1-1}
+  \multicolumn{2}{|c|}{} \\
+  \multicolumn{2}{|c|}{Data area} \\
+  \multicolumn{2}{|c|}{} \\
+  \hline
+  \end{tabular}
+$$
+%%endskip
+%:\begin{verbatim}
+%;    +---------------------------+
+%;    |Boot sector|               |
+%;    |-----------+               |
+%;    |                           |
+%;    |         Data area         |
+%;    |                           |
+%;    |                           |
+%;    +---------------------------+
+%:\end{verbatim}
+
+The entire disk appears as one device (e.g. \path{/dev/fd0}) on Linux.
+
+The MS-DOS boot sector has the following structure:
+
+%%beginskip
+$$
+\begin{tabular}{r|c|}
+  \cline{2-2}
+  \tt 0x000 & Jump to the program code\\
+  \cline{2-2}
+  \tt 0x003 & \\
+  & Disk parameters \\
+  & \\
+  \cline{2-2}
+  \tt 0x02C/0x03E & \\
+  & Program code \\
+  & \\
+  & \\
+  \cline{2-2}
+  \tt 0x1FE & Magic number (0xAA55)\\
+  \cline{2-2}
+\end{tabular}
+$$
+%%endskip
+%:\begin{verbatim}
+%;            +------------------------+
+%;      0x000 |Jump to the program code|
+%;            |------------------------|
+%;      0x003 |                        |
+%;            |    Disk parameters     |
+%;            |                        |
+%;            |------------------------|
+%;0x02C/0x03E |                        |
+%;            |      Program code      |
+%;            |                        |
+%;            |                        |
+%;            |------------------------|
+%;      0x1FE | Magic number (0xAA55)  |
+%;            +------------------------+
+%:\end{verbatim}
+
+\LILO\ uses a similar boot sector, but it does not contain the disk
+parameters part. This is no problem for Minix, Ext2 or similar file systems,
+because
+they don't look at the boot sector, but putting a \LILO\ boot sector on an
+MS-DOS file system would make it inaccessible for MS-DOS.
+
+Hard disks are organized in a more complex way than floppy disks. They
+contain several data areas called partitions. Up to four so-called
+primary partitions can exist on an MS-DOS hard disk. If more partitions
+are needed, one primary partition is used as an extended partition that
+contains several logical partitions.
+
+The first sector of each hard disk contains a partition table, and an
+extended partition and \emphasize{each} logical partition contains a partition
+table too.
+
+%%beginskip
+$$
+\begin{tabular}{|l|l|l|}
+  \hline
+  \multicolumn{3}{|l|}{Partition table\hbox to 2in{\hfil\tt /dev/hda~}} \\
+  \cline{2-3}
+  & \multicolumn{2}{l|}{Partition 1\hfill {\tt /dev/hda1}} \\
+  & \multicolumn{2}{l|}{} \\
+  \cline{2-3}
+  & \multicolumn{2}{l|}{Partition 2\hfill {\tt /dev/hda2}} \\
+  & \multicolumn{2}{l|}{} \\
+  \hline
+\end{tabular}
+$$
+%%endskip
+%:\begin{verbatim}
+%;+--------------------------------------------+
+%;| Partition table                  /dev/hda  |
+%;| +------------------------------------------|
+%;| | Partition 1                    /dev/hda1 |
+%;| |                                          |
+%;| |------------------------------------------|
+%;| | Partition 2                    /dev/hda2 |
+%;| |                                          |
+%;+--------------------------------------------+
+%:\end{verbatim}
+
+The entire disk can be accessed as \path{/dev/hda}, \path{/dev/hdb},
+\path{/dev/sda}, etc. The primary partitions are \path{/dev/hda1 $\ldots$
+/dev/hda4}.
+
+%%beginskip
+$$
+\begin{tabular}{|l|l|l|}
+  \hline
+  \multicolumn{3}{|l|}{Partition table\hbox to 2in{\hfil\tt /dev/hda~}} \\
+  \cline{2-3}
+  & \multicolumn{2}{l|}{Partition 1\hfill {\tt /dev/hda1}} \\
+  & \multicolumn{2}{l|}{} \\
+  \cline{2-3}
+  & \multicolumn{2}{l|}{Partition 2\hfill {\tt /dev/hda2}} \\
+  & \multicolumn{2}{l|}{} \\
+  \cline{2-3}
+  & \multicolumn{2}{l|}{Extended partition\hfill {\tt /dev/hda3}} \\
+  \cline{3-3}
+  & & Extended partition table \\
+  \cline{3-3}
+  & & Partition 3\hfill {\tt /dev/hda5}\\
+  & & \\
+  \cline{3-3}
+  & & Extended partition table \\
+  \cline{3-3}
+& & Partition 4\hfill {\tt /dev/hda6}\\
+  & & \\
+  \hline
+\end{tabular}
+$$
+%%endskip
+%:\begin{verbatim}
+%;+--------------------------------------------+
+%;| Partition table                  /dev/hda  |
+%;| +------------------------------------------|
+%;| | Partition 1                    /dev/hda1 |
+%;| |                                          |
+%;| |------------------------------------------|
+%;| | Partition 2                    /dev/hda2 |
+%;| |                                          |
+%;| |------------------------------------------|
+%;| | Extended partition             /dev/hda3 |
+%;| | +----------------------------------------|
+%;| | | Extended partition table               |
+%;| | |----------------------------------------|
+%;| | | Partition 3                  /dev/hda5 |
+%;| | |                                        |
+%;| | |----------------------------------------|
+%;| | | Extended partition table               |
+%;| | |----------------------------------------|
+%;| | | Partition 4                  /dev/hda6 |
+%;| | |                                        |
+%;+--------------------------------------------+
+%:\end{verbatim}
+
+This hard disk has two primary partitions and an extended partition
+that contains two logical partitions. They are accessed as
+\path{/dev/hda5 $\ldots$}
+
+Note that the partition tables of logical partitions are not accessible
+as the first blocks of some devices, while the main partition table,
+all boot sectors and the partition tables of extended partitions are.
+
+Partition tables are stored in partition boot sectors. Normally, only the
+partition boot sector of the entire disk is used as a boot sector. It is
+also frequently called the master boot record (MBR). Its structure is as
+follows:
+
+%%beginskip
+$$
+\begin{tabular}{r|c|}
+  \cline{2-2}
+  \tt 0x000 & \\
+  & Program code \\
+  & \\
+  & \\
+  \cline{2-2}
+  \tt 0x1BE & Partition table \\
+  & \\
+  \cline{2-2}
+  \tt 0x1FE & Magic number (0xAA55) \\
+  \cline{2-2}
+\end{tabular}
+$$
+%%endskip
+%:\begin{verbatim}
+%;            +------------------------+
+%;      0x000 |                        |
+%;            |      Program code      |
+%;            |                        |
+%;            |                        |
+%;            |------------------------|
+%;      0x1BE |    Partition table     |
+%;            |                        |
+%;            |------------------------|
+%;      0x1FE | Magic number (0xAA55)  |
+%;            +------------------------+
+%:\end{verbatim}
+
+The \LILO\ boot sector is designed to be usable as a partition boot sector.
+(I.e. there is room for the partition table.)
+Therefore, the \LILO\ boot sector can be stored at the following locations:
+
+\begin{itemize}
+  \item boot sector of a Linux floppy disk. (\path{/dev/fd0}, $\ldots$)
+  \item MBR of the first hard disk. (\path{/dev/hda}, \path{/dev/sda}, $\ldots$)
+  \item boot sector of a primary Linux file system partition on the first hard
+    disk. (\path{/dev/hda1}, $\ldots$)
+  \item partition boot sector of an extended partition on the first hard disk.
+    (\path{/dev/hda1}, $\ldots$)\footnote{Most FDISK-type programs don't
+      believe in booting from an extended partition and refuse to
+      activate it. \LILO\ is accompanied by a simple program
+      (\name{activate}) that doesn't have this restriction. Linux \name{fdisk}
+      also supports activating extended partitions.}
+\end{itemize}
+
+It \emphasize{can't} be stored at any of the following locations:
+
+\begin{itemize}
+  \item boot sector of a non-Linux floppy disk or primary partition.
+  \item a Linux swap partition.
+  \item boot sector of a logical partition in an extended partition.%
+\footnote{\LILO\ can be forced to put the boot sector on such a
+ partition by using the \raw{-b} option or the \craw{boot} variable.
+ However, only few programs that operate as master boot records
+ support booting from a logical partition.}
+  \item on the second hard disk. (Unless for backup installations,
+    if the current first disk will be removed or disabled, or if some
+    other boot loader is used, that is capable of loading boot sectors from
+    other drives.)
+\end{itemize}
+
+Although \LILO\ tries to detect attempts to put its boot sector at an
+invalid location, you should not rely on that.
+
+
+\subsection{Booting basics}
+
+When booting from a floppy disk, the first sector of the disk, the so-called
+boot sector, is loaded. That boot sector contains a small program that loads
+the respective operating system. MS-DOS boot sectors also contain 
+a data area, where disk and file system parameters (cluster size, number of
+sectors, number of heads, etc.) are stored.
+
+When booting from a hard disk, the very first sector of that disk, the
+so-called master boot record (MBR) is loaded. This sector contains a
+loader program and the partition table of the disk. The loader program
+usually loads the boot sector, as if the system was booting from a floppy.
+
+Note that there is no functional difference between the MBR and the boot
+sector other than that the MBR contains the partition information but
+doesn't contain any file system-specific information (e.g. MS-DOS disk
+parameters).
+
+The first 446 (0x1BE) bytes of the MBR are used by the loader program.
+They are followed by the partition table, with a length of 64 (0x40)
+bytes. The last two bytes contain a magic number that is sometimes used to
+verify that a given sector really is a boot sector.
+
+There is a large number of possible boot configurations. The most common
+ones are described in the following sections.
+
+
+\subsubsection{MS-DOS alone}
+
+%%beginskip
+\bootthree{DOS-MBR \sep MS-DOS \sep COMMAND.COM}
+%%endskip
+%:\begin{verbatim}
+%;+-------------------------------------------------------+
+%;| Master Boot Record    Boot sector    Operating system |
+%;|-------------------------------------------------------|
+%;| DOS-MBR ------------> MS-DOS ------> COMMAND.COM      |
+%;+-------------------------------------------------------+
+%:\end{verbatim}
+
+This is what usually happens when MS-DOS boots from a hard disk: the DOS-MBR
+determines the active partition and loads the MS-DOS boot sector. This boot
+sector loads MS-DOS and finally passes control to \path{COMMAND.COM}. (This is
+greatly simplified.)
+
+
+\subsubsection{LOADLIN}
+
+%%beginskip
+\bootfour{DOS-MBR \sep MS-DOS \sep COMMAND.COM \emptys \\
+  \emptys \branch LOADLIN \sep Linux}
+%%endskip
+%:\begin{verbatim}
+%4+------------------------------------------------------------+
+%4| Master Boot Record    Boot sector    Operating system      |
+%4|------------------------------------------------------------|
+%4| DOS-MBR ------------> MS-DOS ------> COMMAND.COM           |
+%4|                                 ---> LOADLIN ------> Linux |
+%4+------------------------------------------------------------+
+%:\end{verbatim}
+
+A typical \name{LOADLIN} setup: everything happens like when booting MS-DOS,
+but in \path{CONFIG.SYS} or \path{AUTOEXEC.BAT}, LOADLIN is invoked. Typically,
+a program like \path{BOOT.SYS} is used to choose among configuration sections
+in \path{CONFIG.SYS} and \path{AUTOEXEC.BAT}.
+This approach has the pleasant property that no boot
+sectors have to be altered.
+
+Please refer to the documentation accompanying the LOADLIN package for
+installation instructions and further details.
+
+
+\subsubsection{\LILO\ started by DOS-MBR}
+
+%%beginskip
+\bootthree{DOS-MBR \sep LILO \sep Linux \\
+  \branch {\rm other OS} \emptys}
+%%endskip
+%:\begin{verbatim}
+%;+-------------------------------------------------------+
+%;| Master Boot Record    Boot sector    Operating system |
+%;|-------------------------------------------------------|
+%;| DOS-MBR ------------> LILO --------> Linux            |
+%;|                  ---> other OS                        |
+%;+-------------------------------------------------------+
+%:\end{verbatim}
+
+This is a ``safe'' \LILO\ setup: \LILO\ is booted by the DOS-MBR. No other boot
+sectors have to be touched. If the other OS (or one of them, if there are
+several other operating systems being used) should be booted without
+using \LILO, the other
+partition has to be marked ``active'' with \name{fdisk} or \name{activate}.
+
+Installation:
+\begin{itemize}
+  \item install \LILO\ with its boot sector on the Linux partition.
+  \item use \name{fdisk} or \name{activate} to make that partition active.
+  \item reboot.
+\end{itemize}
+
+Deinstallation:
+\begin{itemize}
+  \item make a different partition active.
+  \item install whatever should replace \LILO\ and/or Linux.
+\end{itemize}
+
+
+\subsubsection{Several alternate branches}
+
+%%beginskip
+\bootfour{DOS-MBR \sep MS-DOS \sep COMMAND.COM \emptys \\
+  \emptys \branch LOADLIN \sep Linux \\
+  \branch LILO \sep Linux \emptys \\
+  \emptys \branch MS-DOS \cont \emptys}
+%%endskip
+%:\begin{verbatim}
+%4+------------------------------------------------------------+
+%4| Master Boot Record    Boot sector    Operating system      |
+%4|------------------------------------------------------------|
+%4| DOS-MBR ------------> MS-DOS ------> COMMAND.COM           |
+%4|                                 ---> LOADLIN ------> Linux |
+%4|                  ---> LILO --------> Linux                 |
+%4|                                 ---> MS-DOS --- ...        |
+%4+------------------------------------------------------------+
+%:\end{verbatim}
+
+An extended form of the above setup: the MBR is not changed and both branches
+can either boot Linux or MS-DOS. (\LILO\ could also boot other
+operating systems.)
+
+
+\subsubsection{\LILO\ started by \name{BOOTACTV}\protect\footnotemark}
+\footnotetext{Other, possibly better known boot switchers, e.g. \name{OS/2
+BootManager} operate in a similar way. The installation procedures typically
+vary.}
+
+%%beginskip
+\bootthree{BOOTACTV \sep LILO \sep Linux \\
+  \branch {\rm other OS} \emptys}
+%%endskip
+%:\begin{verbatim}
+%;+-------------------------------------------------------+
+%;| Master Boot Record    Boot sector    Operating system |
+%;|-------------------------------------------------------|
+%;| BOOTACTV -----------> LILO --------> Linux            |
+%;|                  ---> other OS                        |
+%;+-------------------------------------------------------+
+%:\end{verbatim}
+
+Here, the MBR is replaced by \name{BOOTACTV} (or any other interactive boot
+partition selector) and the choice between Linux and the
+other operating system(s) can be made at boot time. This approach should be
+used if \LILO\ fails to boot the other operating system(s).\footnote{%
+And the author would like to be notified if booting the other operating
+system(s) doesn't work with \LILO, but if it works with an other boot partition
+selector.}
+
+Installation:
+\begin{itemize}
+  \item boot Linux.
+  \item make a backup copy of your MBR on a floppy disk, e.g. \\
+    \verb"dd if=/dev/hda of=/fd/MBR bs=512 count=1"
+  \item install \LILO\ with the boot sector on the Linux partition.
+  \item install \name{BOOTACTV} as the MBR, e.g. \\
+    \verb"dd if=bootactv.bin of=/dev/hda bs=446 count=1"
+  \item reboot.
+\end{itemize}
+
+Deinstallation:
+\begin{itemize}
+  \item boot Linux.
+  \item restore the old MBR, e.g. \\
+    \verb"dd if=/MBR of=/dev/hda bs=446 count=1" \\
+    or \verb"FDISK /MBR" under MS-DOS.
+\end{itemize}
+
+If replacing the MBR appears undesirable and if a second Linux partition
+exists (e.g. \path{/usr}, \emphasize{not} a swap partition), \name{BOOTACTV}
+can be merged with
+the partition table and stored as the ``boot sector'' of that partition.
+Then, the partition can be marked active to be booted by the DOS-MBR.
+
+Example:
+\begin{verbatim}
+# dd if=/dev/hda of=/dev/hda3 bs=512 count=1
+# dd if=bootactv.bin of=/dev/hda3 bs=446 count=1
+\end{verbatim}
+
+\emphasize{WARNING:} Whenever the disk is re-partitioned, the merged boot
+sector on that ``spare'' Linux partition has to be updated too.
+
+
+\subsubsection{\LILO\ alone}
+
+%%beginskip
+\boottwo{LILO \sep Linux \\
+  \branch {\rm other OS}}
+%%endskip
+%:\begin{verbatim}
+%;    +----------------------------------------+
+%;    | Master Boot Record    Operating system |
+%;    |----------------------------------------|
+%;    | LILO ---------------> Linux            |
+%;    |                  ---> other OS         |
+%;    +----------------------------------------+
+%:\end{verbatim}
+
+\LILO\ can also take over the entire boot procedure. If installed as the MBR,
+\LILO\ is responsible for either booting Linux or any other OS. This approach
+has the disadvantage, that the old MBR is overwritten and has to be restored
+(either from a backup copy, with \verb"FDISK /MBR" on recent versions of
+MS-DOS or by overwriting it with something like \name{BOOTACTV}) if Linux
+should ever be removed from the system.
+
+You should verify that \LILO\ is able to boot your other operating system(s)
+before relying on this method.
+
+Installation:
+\begin{itemize}
+  \item boot Linux.
+  \item make a backup copy of your MBR on a floppy disk, e.g. \\
+    \verb"dd if=/dev/hda of=/fd/MBR bs=512 count=1"
+  \item install \LILO\ with its boot sector as the MBR.
+  \item reboot.
+\end{itemize}
+
+Deinstallation:
+\begin{itemize}
+  \item boot Linux.
+  \item restore the old MBR, e.g. \\
+    \verb"dd if=/fd/MBR of=/dev/hda bs=446 count=1"
+\end{itemize}
+
+If you've installed \LILO\ as the master boot record, you have to
+explicitly specify the boot sector (configuration variable
+\craw{boot=}$\ldots$) when updating the map. Otherwise, it
+will try to use the boot sector of your current root partition, which
+will usually work, but it will probably leave your system unbootable.
+
+
+\subsubsection{Names}
+
+The following names have been used to describe boot sectors or parts of
+operating systems:
+
+\begin{description}
+  \item[``DOS-MBR''] is the original MS-DOS MBR. It scans the partition
+    table for a partition that is marked ``active'' and loads the boot
+    sector of that partition. Programs like MS-DOS' \name{FDISK}, Linux
+    \name{fdisk} or \name{activate} (accompanies \LILO)
+    can change the active marker in the partition table.
+  \item[``MS-DOS''] denotes the MS-DOS boot sector that loads the other parts
+    of the system (\path{IO.SYS}, etc.).
+  \item[``COMMAND.COM''] is the standard command interpreter of MS-DOS.
+  \item[``LOADLIN''] is a program that loads a Linux
+    kernel image from an
+    MS-DOS partition into memory and executes it. It is usually invoked
+    from \path{CONFIG.SYS} and is used in combination with a \path{CONFIG.SYS}
+    configuration switcher, like BOOT.SYS.\footnote{
+      \name{LOADLIN} is available for anonymous FTP from \\
+      \path{ftp://tsx-11.mit.edu/pub/linux/dos\_utils/lodlin\meta{n}.tar.gz} \\
+      \path{ftp://sunsite.unc.edu/pub/Linux/system/boot/dualboot/lodlin\meta{n}%
+.tgz} \\
+      \name{BOOT.SYS} is available for anonymous FTP from \\
+      \path{ftp://ftp.funet.fi/pub/Linux/tools/boot142.zip}}
+  \item[``LILO''] can either load a Linux kernel or the boot sector of any
+    other operating system. It has a first stage boot sector that
+    loads the remaining parts of \LILO\ from various locations.\footnote{%
+      \LILO\ can be found in \\
+      \path{ftp://tsx-11.mit.edu/pub/linux/packages/lilo/lilo-\meta{n}.tar.gz}
+       \\
+      \path{ftp://sunsite.unc.edu/pub/Linux/system/boot/lilo/lilo-%
+\meta{n}.tar.gz} \\
+      \path{ftp://lrcftp.epfl.ch/pub/linux/local/lilo/lilo-\meta{n}.tar.gz}}
+  \item[``BOOTACTV''] permits interactive selection of the partition from
+    which the boot sector should be read. If no key is pressed within a
+    given interval, the partition marked active is booted. \name{BOOTACTV} is
+    included in the \name{pfdisk} package. There are also several similar
+    programs, like PBOOT and OS-BS.\footnote{\name{pfdisk} is available for
+      anonymous FTP from \\
+      \path{ftp://sunsite.unc.edu/pub/Linux/utils/disk-management/pfdisk.tar.Z}
+       or \\
+      \path{ftp://ftp.funet.fi/pub/Linux/tools/pfdisk.tar.Z} \\
+      PBOOT can be found in \\
+      \path{ftp://ftp.funet.fi/pub/Linux/tools/pboot.zip}}
+\end{description}
+
+
+\subsection{Choosing the ``right'' boot concept}
+
+Although \LILO\ can be installed in many different ways, the choice is
+usually limited by the present setup and therefore,
+typically only a small number of configurations which fit naturally
+into an existing system remains. The following sections describe various
+possible cases. See also section \ref{broken}.
+
+The configuration file \path{/etc/lilo.conf} for the examples
+could look like this:
+
+\begin{verbatim}
+boot = /dev/hda2
+compact
+image = /vmlinuz
+image = /vmlinuz.old
+other = /dev/hda1
+  table = /dev/hda
+  label = msdos
+\end{verbatim}
+
+It installs a Linux kernel image (\path{/vmlinuz}),
+an alternate Linux kernel image (\path{/vmlinuz.old}) and
+a chain loader to boot MS-DOS from \path{/dev/hda1}. The option \craw{compact}
+on the second line instructs the map installer to optimize loading.
+
+In all examples, the names of the IDE-type hard disk devices
+(\path{/dev/hda$\ldots$}) are used. Everything applies to other disk types
+(e.g. SCSI disks; \path{/dev/sda$\ldots$}) too.
+
+
+\subsubsection{BIOS restrictions}
+\label{broken}
+
+Nowadays, an increasing number of systems is equipped with comparably large
+disks or even with multiple disks. At the time the disk interface of the
+standard PC BIOS has been designed (about 16 years ago), such configurations
+were apparently considered to be too unlikely to be worth supporting.
+
+The most common BIOS restrictions that affect \LILO\ are the limitation to
+two hard disks and the inability to access more than 1024 cylinders per
+disk. \LILO\ can detect both conditions, but in order to work around the
+underlying problems, manual intervention is necessary.
+
+The drive limit does not exist in every BIOS. Some modern motherboards
+and disk controllers are equipped with a BIOS that supports more (typically
+four) disk drives. When attempting to access the third, fourth, etc. drive,
+\LILO\ prints a warning message but continues. Unless the BIOS really
+supports more than two drives, the system will \emphasize{not} be able to
+boot in that case.\footnote{However, if only ``unimportant'' parts of the
+system are located on the ``high'' drives, some functionality may be
+available.}
+
+The cylinder limit is a very common problem with IDE disks. There, the
+number of cylinders may already exceed 1024 if the drive has a capacity
+of more than 504 MB. Many SCSI driver BIOSes present the disk geometry
+in a way that makes the limit occur near 1 GB. Modern disk controllers
+may even push the limit up to about 8 GB. All cylinders beyond the
+1024th are inaccessible for the BIOS. \LILO\ detects this problem and
+aborts the installation (unless the \craw{linear} option is used, see
+section \ref{cfgglo}).
+
+Note that large partitions that only partially extend into the ``forbidden
+zone'' are still in jeopardy even if they appear to work at first, because
+the file system does not know about the restrictions and may allocate
+disk space from the area beyond the 1024th cylinder when installing new
+kernels. \LILO\ therefore prints a warning message but continues as long
+as no imminent danger exists.
+
+There are four approaches of how such problems can be solved:
+\begin{itemize}
+  \item use of a different partition which is on an accessible disk and
+    which does not exceed the 1024 cylinder limit. If there is only a DOS
+    partition which fulfills all the criteria, that partition can be
+    used to store the relevant files. (See section \ref{viados}.)
+  \item rearranging partitions and disks. This is typically a destructive
+    operation, so extra care should be taken to make good backups.
+  \item if the system is running DOS or Windows 95, \name{LOADLIN} can be
+    used instead of \LILO.
+  \item if all else fails, installation of a more capable BIOS, a different
+    controller or a different disk configuration.
+\end{itemize}
+
+\LILO\ depends on the BIOS to load the following items:
+\begin{itemize}
+  \item \path{/boot/boot.b}
+  \item \path{/boot/map} (created when running \path{/sbin/lilo})
+  \item all kernels
+  \item the boot sectors of all other operating systems it boots
+  \item the startup message, if one has been defined
+\end{itemize}
+
+Normally, this implies that the Linux root file system should be in the
+``safe'' area. However, it is already sufficient to put all kernels into
+\path{/boot} and to either mount a ``good'' partition on \path{/boot} or
+to let \path{/boot} be a symbolic link pointing to or into such a
+partition.
+
+See also \path{/usr/src/linux/Documentation/ide.txt} (or
+\path{/usr/src/linux/drivers/block/README.ide} in older kernels) for a detailed
+description of problems with large disks.
+
+
+\subsubsection{One disk, Linux on a primary partition}
+
+If at least one primary partition of the first hard disk is used as a
+Linux file system (\path{/}, \path{/usr}, etc. but \emphasize{not} as a swap
+partition), the \LILO\ boot sector should be stored on that partition
+and it should be booted by the original master boot record or by a
+program like \name{BOOTACTV}.
+
+%%beginskip
+$$
+  \begin{tabular}{r|c|c|}
+    \cline{2-3}
+    & \multicolumn{2}{|l|}{MBR\hbox to 1.3in{\hfill\tt /dev/hda~}} \\
+    \cline{3-3}
+    & & MS-DOS\hfill\tt /dev/hda1 \\
+    \cline{3-3}
+    $\rightarrow$ & & Linux {\tt /}\hfill\tt /dev/hda2 \\
+    \cline{2-3}
+  \end{tabular}
+$$
+%%endskip
+%:\begin{verbatim}
+%;    +--------------------------+
+%;    | MBR            /dev/hda  |
+%;    | +------------------------|
+%;    | | MS-DOS       /dev/hda1 |
+%;    | |------------------------|
+%;--> | | Linux /      /dev/hda2 |
+%;    +--------------------------+
+%:\end{verbatim}
+
+In this example, the \craw{boot} variable could be omitted, because
+the boot sector is on the root partition.
+
+
+\subsubsection{One disk, Linux on a logical partition}
+
+If no primary partition is available for Linux, but at least one logical
+partition of an extended partition on the first hard disk contains a
+Linux file system, the \LILO\ boot sector should be stored in the partition
+sector of the extended partition and it should be booted by the original
+master boot record or by a program like \name{BOOTACTV}.
+
+%%beginskip
+$$
+  \begin{tabular}{r|c|c|c|}
+    \cline{2-4}
+    & \multicolumn{3}{|l|}{MBR\hbox to 1.3in{\hfill\tt /dev/hda~}} \\
+    \cline{3-4}
+    & & \multicolumn{2}{|l|}{MS-DOS\hfill\tt /dev/hda1} \\
+    \cline{3-4}
+    $\rightarrow$ & & \multicolumn{2}{|l|}{Extended\hfill\tt /dev/hda2} \\
+    \cline{4-4}
+    & & & Linux\hfill\tt /dev/hda5 \\
+    \cline{4-4}
+    & & & $\ldots$\hfill\tt /dev/hda6 \\
+    \cline{2-4}
+  \end{tabular}
+$$
+%%endskip
+%:\begin{verbatim}
+%;    +--------------------------+
+%;    | MBR            /dev/hda  |
+%;    | +------------------------|
+%;    | | MS-DOS       /dev/hda1 |
+%;    | |------------------------|
+%;--> | | Extended     /dev/hda2 |
+%;    | | +----------------------|
+%;    | | | Linux      /dev/hda5 |
+%;    | | |----------------------|
+%;    | | | ...        /dev/hda6 |
+%;    +--------------------------+
+%:\end{verbatim}
+
+Because many disk partitioning programs refuse to make an extended
+partition (in our example \path{/dev/hda2}) active, you might have to
+use \name{activate}, which comes with the \LILO\ distribution.
+
+OS/2 BootManager should be able to boot \LILO\ boot sectors from logical
+partitions. The installation on the extended partition itself is not
+necessary in this case.
+
+
+\subsubsection{Two disks, Linux (at least partially) on the first disk}
+
+This case is equivalent to the configurations where only one disk
+is in the system. The Linux boot sector resides on the first hard
+disk and the second disk is used later in the boot process.
+
+Only the location of the boot sector matters -- everything
+else (\path{/boot/boot.b},
+\path{/boot/map}, the root file system, a swap partition, other
+Linux file systems, etc.) can be located anywhere on the second disk,
+provided that the constraints described in section \ref{broken} are met.
+
+
+\subsubsection{Two disks, Linux on second disk, first disk has an extended
+  partition}
+
+If there is no Linux partition on the first disk, but there is an
+extended partition, the \LILO\ boot sector can be stored in the partition
+sector of the extended partition and it should be booted by the original
+master boot record or by a program like \name{BOOTACTV}.
+
+%%beginskip
+$$
+  \begin{tabular}{r|c|c|c|c|c|c|}
+    \multicolumn{1}{r}{}
+    & \multicolumn{3}{c}{\bf First disk} &
+      \multicolumn{1}{r}{\qquad}
+      & \multicolumn{2}{c}{\bf Second disk} \\
+    \cline{2-4}\cline{6-7}
+    & \multicolumn{3}{|l|}{MBR\hbox to 1.3in{\hfill\tt /dev/hda~}} &
+      & \multicolumn{2}{|l|}{MBR\hbox to 1.3in{\hfill\tt /dev/hdb~}} \\
+    \cline{3-4}\cline{7-7}
+    & & \multicolumn{2}{|l|}{MS-DOS\hfill\tt /dev/hda1} &
+      & & Linux\hfill\tt /dev/hdb1 \\
+    \cline{3-4}\cline{7-7}
+    $\rightarrow$ & & \multicolumn{2}{|l|}{Extended\hfill\tt /dev/hda2} &
+      & & $\ldots$\hfill\tt /dev/hdb2 \\
+    \cline{4-4}
+    & & & $\ldots$\hfill\tt /dev/hda5 & & & \\
+    \cline{4-4}
+    & & & $\ldots$\hfill\tt /dev/hda6 & & & \\
+    \cline{2-4}\cline{6-7}
+  \end{tabular}
+$$
+%%endskip
+%:\begin{verbatim}
+%4             FIRST DISK                     SECOND DISK
+%4    +--------------------------+    +--------------------------+
+%4    | MBR            /dev/hda  |    | MBR            /dev/hdb  |
+%4    | +------------------------|    | +------------------------|
+%4    | | MS-DOS       /dev/hda1 |    | | Linux        /dev/hdb1 |
+%4    | |------------------------|    | |------------------------|
+%4--> | | Extended     /dev/hda2 |    | | ...          /dev/hdb2 |
+%4    | | +----------------------|    | |                        |
+%4    | | | ...        /dev/hda5 |    | |                        |
+%4    | | |----------------------|    | |                        |
+%4    | | | ...        /dev/hda6 |    | |                        |
+%4    +--------------------------+    +--------------------------+
+%:\end{verbatim}
+
+The program \name{activate}, that accompanies \LILO, may have to be used to
+set the active marker on an extended partition, because MS-DOS' \name{FDISK}
+and some older version of Linux \name{fdisk} refuse to do that. (Which is
+generally a good idea.)
+
+
+\subsubsection{Two disks, Linux on second disk, first disk has no
+  extended partition}
+
+If there is neither a Linux partition nor an extended partition on the first
+disk, then there's only one place left, where a \LILO\ boot sector could be
+stored: the master boot record.
+
+In this configuration, \LILO\ is responsible for booting all other operating
+systems too.
+
+%%beginskip
+$$
+  \begin{tabular}{r|c|c|c|c|c|}
+    \multicolumn{1}{r}{}
+    & \multicolumn{2}{c}{\bf First disk} &
+      \multicolumn{1}{r}{\qquad}
+      & \multicolumn{2}{c}{\bf Second disk} \\
+    \cline{2-3}\cline{5-6}
+    $\rightarrow$ & \multicolumn{2}{|l|}{MBR\hbox to 1.3in{
+      \hfill\tt /dev/hda~}} &
+      & \multicolumn{2}{|l|}{MBR\hbox to 1.3in{\hfill\tt /dev/hdb~}} \\
+    \cline{3-3}\cline{6-6}
+    & & MS-DOS\hfill\tt /dev/hda1 &
+      & & Linux\hfill\tt /dev/hdb1 \\
+    \cline{3-3}\cline{6-6}
+    & & $\ldots$\hfill\tt /dev/hda2 &
+      & & $\ldots$\hfill\tt /dev/hdb2 \\
+    \cline{2-3}\cline{5-6}
+  \end{tabular}
+$$
+%%endskip
+%:\begin{verbatim}
+%4             FIRST DISK                     SECOND DISK
+%4    +--------------------------+    +--------------------------+
+%4--> | MBR            /dev/hda  |    | MBR            /dev/hdb  |
+%4    | +------------------------|    | +------------------------|
+%4    | | MS-DOS       /dev/hda1 |    | | Linux        /dev/hdb1 |
+%4    | |------------------------|    | |------------------------|
+%4    | | ...          /dev/hda2 |    | | ...          /dev/hdb2 |
+%4    +--------------------------+    +--------------------------+
+%:\end{verbatim}
+
+You should back up your old MBR before installing \LILO\ and verify that
+\LILO\ is able to boot your other operating system(s) before relying on
+this approach.
+
+The line \verb"boot = /dev/hda2" in \path{/etc/lilo.conf} would have to be
+changed to \verb"boot = /dev/hda" in this example.
+
+
+\subsubsection{More than two disks}
+
+On systems with more than two disks, typically only the first two can
+be accessed. The configuration choices are therefore the same as with
+two disks.
+
+When attempting to access one of the extra disks, \LILO\ displays a
+warning message (\raw{Warning: BIOS drive 0x\meta{number} may not be
+accessible}) but does not abort. This is done in order to allow
+the lucky few whose BIOS (or controller-BIOS) does support more than
+two drives to make use of this feature. By all others, this warning
+should be considered a fatal error.
+
+Note that the two disks restriction is only imposed by the BIOS.
+Linux normally has no problems using all disks once it is booted.
+
+
+\subsubsection{\path{/boot} on a DOS partition}
+\label{viados}
+
+Recent kernels support all the functions \LILO\ needs to map files also
+on MS-DOS (or UMSDOS) file systems. Since DOS partitions tend to occupy
+exactly the places where BIOS restrictions (see section \ref{broken})
+are invisible, they're an ideal location for \path{/boot} if the native
+Linux file systems can't be used because of BIOS problems.
+
+In order to accomplish this, the DOS partition is mounted read-write,
+a directory (e.g. \path{/dos/linux}) is created, all files from
+\path{/boot} are moved to that directory, \path{/boot} is replaced by
+a symbolic link to it, the kernels are also moved to the new directory,
+their new location is recorded in \path{/etc/lilo.conf}, and finally
+\path{/sbin/lilo} is run.
+
+From then on, new kernels must always be copied into that directory on
+the DOS partition before running \path{/sbin/lilo}, e.g. when recompiling
+a kernel, the standard procedure changes from
+
+\begin{verbatim}
+# make zlilo
+\end{verbatim}
+
+to
+
+\begin{verbatim}
+# make zImage
+# mv /dos/linux/vmlinuz /dos/linux/vmlinuz.old
+# mv arch/i386/boot/zImage /dos/linux/vmlinuz
+# /sbin/lilo
+\end{verbatim}
+
+\emphasize{WARNING:} De-fragmenting such a DOS partition is likely to
+make Linux or even the whole system unbootable. Therefore, the DOS
+partition should either not be de-fragmented, or a Linux boot disk
+should be prepared (and tested) to bring up Linux and to run
+\path{/sbin/lilo} after the de-fragmentation.\footnote{Setting the
+``system'' attribute from DOS on the critical files (e.g. everything
+in \path{C:$\backslash$LINUX}) may help to protect them from being
+rearranged. However, the boot floppy should still be ready, just in case.}
+
+
+\newpage
+\section{The boot prompt}
+\label{cmdopt}
+
+Immediately after it's loaded, \LILO\ checks whether one of the following
+is happening:
+
+\begin{itemize}
+  \item any of the \key{Shift}, \key{Control} or \key{Alt} keys is
+    pressed.
+  \item \key{CapsLock} or \key{ScrollLock} is set.
+\end{itemize}
+
+If this is the case, \LILO\ displays the \verb"boot:" prompt and waits for
+the name of a boot image (i.e. Linux kernel or other operating system).
+Otherwise, it boots the default boot image\footnote{%
+The default boot image is either the first boot image, the image specified
+with the \craw{default} variable, or the image that
+has been selected at the boot prompt.}
+or -- if a
+delay has been specified -- waits for one of the listed activities
+until that amount of time has passed.
+
+At the boot prompt, the name of the image to boot can be entered. Typing
+errors can be corrected with \key{BackSpace}, \key{Delete},
+\key{Ctrl U} and \key{Ctrl X}. A list of known images can be obtained by
+pressing \key{?} or \key{Tab}.
+
+If \key{Enter} is pressed and no file name has been entered, the default
+image is booted.
+
+
+\subsection{Boot command-line options}
+
+\LILO\ is also able to pass command-line options to the kernel.
+Command-line options are words that follow the name of the boot
+image and that are separated by spaces.
+
+Example:
+\begin{verbatim}
+boot: linux single root=200
+\end{verbatim}
+
+This document only gives an overview of boot options. Please consult Paul
+Gortmaker's BootPrompt-HOWTO for a more complete and more up to date list.
+You can get it from
+\path{ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/BootPrompt-HOWTO.gz}
+or from one of the many mirror sites.
+
+
+\subsubsection{Standard options}
+
+Recent kernels recognize a large number of options, among them are \raw{debug},
+\raw{no387}, \raw{no-hlt},
+\raw{ramdisk=\meta{size}}, \raw{reserve=\meta{base},\meta{size},$\ldots$},
+\raw{root=\meta{device}}, \raw{ro}, and \raw{rw}.
+All current \name{init} programs also recognize the option \raw{single}.
+The options \raw{lock} and \raw{vga} are processed by the boot loader itself.
+Boot command-line options are always case-sensitive.
+
+\raw{single} boots the system in single-user mode. This bypasses most
+system initialization procedures and directly starts a root shell on the
+console. Multi-user mode can typically be entered by exiting the single-user
+shell or by rebooting.
+
+\raw{root=\meta{device}} changes the root device. This overrides
+settings that may have been made in the boot image and on the
+\LILO\ command line. \meta{device} is either the hexadecimal device number
+%%beginskip
+\footnote{%
+This is a list of device numbers of some frequently used devices: \\
+\begin{tabular}{lllllll}
+\qquad
+& {\tt /dev/fd0} & 200\qquad & \tt /dev/hda1 & 301\qquad & /dev/sda1 & 801 \\
+& {\tt /dev/fd1} & 201 & \tt /dev/hda2 & 302 & /dev/sda2 & 802 \\
+& \multicolumn{2}{c}{$\cdots$} & \multicolumn{2}{c}{$\cdots$} &
+\multicolumn{2}{c}{$\cdots$} \\
+& & & \tt /dev/hdb1 & 341 & /dev/sdb1 & 811 \\
+& & & \tt /dev/hdb2 & 342 & /dev/sdb2 & 812 \\
+& \multicolumn{2}{c}{} & \multicolumn{2}{c}{$\cdots$} &
+\multicolumn{2}{c}{$\cdots$} \\
+\end{tabular}}
+%%endskip
+or the full path name of the device, e.g. \verb"/dev/hda3".%
+\footnote{The device names are hard-coded in the kernel. Therefore, only
+the ``standard'' names are supported and some less common devices may not
+be recognized. In those cases, only numbers can be used.}
+
+\raw{reserve=\meta{base},\meta{size},$\ldots$} reserves IO port regions.
+This can be used to prevent device drivers from auto-probing addresses
+where other devices are located, which get confused by the probing.
+
+\raw{ro} instructs the kernel to mount the root file system read-only.
+\raw{rw} mounts it read-write. If neither \raw{ro} nor \raw{rw} is
+specified, the setting from the boot image is used.
+
+\raw{no-hlt} avoids executing a \raw{HLT} instructions whenever the system
+is idle. \raw{HLT} normally significantly reduces power consumption and
+therefore also heat
+dissipation of the CPU, but may not work properly with some clone CPUs.
+\raw{no387} disables using the hardware FPU even if one is present.
+
+\raw{debug} enables more verbose console logging.
+
+Recent kernels also accept the options \raw{init=\meta{name}} and
+\raw{noinitrd}. \raw{init} specifies the name of the \name{init} program
+to execute. Therefore, if single mode cannot be entered because \name{init}
+is mis-configured, one may still be able to reach a shell using
+\verb"init=/bin/sh". \raw{noinitrd} disables automatic loading of the initial
+RAM disk. Instead, its content is then available on \path{/dev/initrd}.
+
+\raw{vga=\meta{mode}} alters the VGA mode set at startup. The values
+\raw{normal}, \raw{extended}, \raw{ask} or a decimal number are
+recognized. (See also page \pageref{vga}.)
+
+\raw{kbd=\meta{code},$\ldots$} preloads a sequence of keystrokes in the
+BIOS keyboard buffer. The keystrokes have to be entered as 16 bit hexadecimal
+numbers, with the upper byte containing the scan code and the lower byte
+containing the ASCII code. Note that most programs only use the ASCII
+code, so the scan code can frequently be omitted. Scan code tables can be
+found in many books on PC hardware. Note that scan codes depend on the
+keyboard layout.
+
+Finally, \raw{lock} stores the current command-line as the default
+command-line, so that \LILO\ boots the same image with the same options
+(including \raw{lock}) when invoked the next time.
+
+
+\subsubsection{Device-specific options}
+
+There is also a plethora of options to specify certain characteristics
+(e.g. IO and memory addresses) of devices. Some common ones are
+\raw{ether}, \raw{floppy}, \raw{hd}, \raw{bmouse}, and \raw{sound}.
+The usage of these options is \raw{\meta{option}=\meta{number},$\ldots$}.
+Please consult the corresponding FAQs and HOWTOs for details. For an overview
+of all available options, consult the file \path{init/main.c} in the kernel
+source tree.
+
+
+\subsubsection{Other options}
+
+Options of the type \raw{\meta{variable}=\meta{value}} which are neither
+standard options nor device-specific options,
+cause the respective variables to be set in the environment passed to
+\name{init}. The case of the variable name is preserved, i.e. it isn't
+automatically converted to upper case.
+
+Note that environment variables passed to \name{init} are typically
+available in system initialization scripts (e.g. \path{/etc/rc.local}),
+but they're not visible from ordinary login sessions, because the \name{login}
+program removes them from the user's environment.
+
+
+\subsubsection{Repeating options}
+
+The effect of repeating boot command-line options depends on the options.%
+\footnote{Options are frequently repeated when a string defined with
+\craw{append} or \craw{literal} is prepended to the parameters typed in by
+the user. Also, \LILO\ implicitly prepends the options \raw{ramdisk},
+\raw{ro}, \raw{root}, or \raw{rw} when \craw{ramdisk}, \craw{read-only},
+\craw{read-write}, or \craw{root}, respectively, are set in the configuration
+file.
+(\raw{lock} and \raw{vga} are handled by a different internal mechanism.)}
+There are three possible behaviours:
+
+Options that only enable or disable a certain functionality can be repeated
+any number of times. \raw{debug}, \raw{lock}, \raw{no-hlt}, and \raw{no387}
+fall into this category.
+
+Other options change a global setting whenever they appear, so only the
+value or presence of the last option matters. The antagonists \raw{ro} and
+\raw{rw} are such options. Also, \raw{ramdisk}, \raw{root}, and \raw{vga}
+work this way. Example: \raw{ro rw} would mount the root file system
+read-write.
+
+Finally, when \raw{reserve} and many device-specific options are repeated,
+each occurrence has its own meaning, e.g. \raw{hd=$\ldots$ hd=$\ldots$} would
+configure two hard disks, and \raw{reserve=0x300,8 reserve=0x5f0,16} would
+reserve the ranges 0x300 to 0x307 and 0x5f0 to 0x5ff (which is equivalent to
+writing \raw{reserve=0x300,8,0x5f0,16}).
+
+
+\subsubsection{Implicit options}
+
+\LILO\ always passes the string \raw{BOOT\_IMAGE=\meta{name}} to the
+kernel, where \meta{name} is the name by which the kernel is identified
+(e.g. the label). This variable can be used in \path{/etc/rc} to select
+a different behaviour, depending on the kernel.
+
+When booting automatically, i.e. without human intervention, the word
+\raw{auto} is also passed on
+the command line. This can be used by \name{init} to suppress interactive
+prompts in the boot phase.
+
+
+\subsection{Boot image selection}
+\label{bootsel}
+
+The details of selecting the boot image are somewhat complicated. The
+following tables illustrate them. First, if neither \craw{prompt} is
+set nor a shift key is being pressed:
+
+$$
+\begin{tabular}{cc|cl}
+  Externally & Command  & Auto- & Booted image \\
+  provided   & line in  & matic & \\
+  cmd. line\footnotemark
+  & map file\footnotemark
+  & boot\footnotemark
+  & \\
+  \hline
+  No  & No  & Yes & Default image \\
+  Yes & --- & Yes & Specified by external \\
+      &     &     & command line \\
+  No  & Yes & Yes & Specified by command line \\
+      &     &     & in map file \\
+\end{tabular}
+\addtocounter{footnote}{-2}
+\footnotetext{Externally provided command lines could be used to
+  add front-ends to \LILO. They would pass the respective command
+  string to LILO, which would then interpret it like keyboard input. This
+  feature is currently not used.}
+\addtocounter{footnote}{1}
+\footnotetext{This command line is set by invoking the map installer
+    with the \raw{-R} option, by using the boot command-line option
+    \raw{lock}, or if a fallback command line is set (with \craw{fallback}).}
+\addtocounter{footnote}{1}
+\footnotetext{I.e. the keyword \raw{auto} is added.}
+$$
+
+If \craw{prompt} is not set and a shift key is being pressed:
+$$
+\begin{tabular}{cccc|cl}
+  Input   & Empty  & Extern. & Cmd.l.  & Auto- & Booted image \\
+  timeout & cmd.l. & cmd.l.  & in map  & matic & \\
+          &        &         & file    & boot  & \\
+  \hline
+  No  & No  & --- & --- & No  & Specified by the user \\
+  No  & Yes & --- & --- & No  & Default image \\
+  Yes & n/a & --- & --- & Yes & Default image \\
+\end{tabular}
+$$
+
+Finally, if the configuration variable \craw{prompt} is set:
+$$
+\begin{tabular}{cccc|cl}
+  Input   & Empty  & Extern. & Cmd.l.  & Auto- & Booted image \\
+  timeout & cmd.l. & cmd.l.  & in map  & matic & \\
+          &        &         & file    & boot  & \\
+  \hline
+  No  & No  & No  & No  & No  & Specified by the user \\
+  No  & Yes & No  & No  & No  & Default image \\
+  Yes & n/a & No  & No  & Yes & Default image \\
+  n/a & n/a & Yes & --- & Yes & Specified by external \\
+      &     &     &     &     & command line \\
+  n/a & n/a & No  & Yes & Yes & Specified by command \\
+      &     &     &     &     & line in map file \\
+\end{tabular}
+$$
+
+Note that \LILO\ pauses for the amount of time specified in \craw{delay}
+when at the end of a default command line. The automatic boot can then
+be interrupted by pressing a modifier key (\key{Shift}, \key{Ctrl}, etc.).
+
+The default image is the first image in the map file or the image specified
+with the \craw{default} variable. However,
+after an unsuccessful boot attempt, the respective image becomes the
+default image.
+
+
+\newpage
+\section{Map installer}
+
+The map installer program \path{/sbin/lilo} updates the boot sector
+and creates the map file. If the map installer detects an error, it terminates
+immediately and does not touch the boot sector and the map file.
+
+Whenever the map installer updates a boot sector, the original boot
+sector is copied
+to \path{/boot/boot.\meta{number}}, where \meta{number} is the
+hexadecimal device number. If such a file already exists, no backup
+copy is made. Similarly, a file \raw{/boot/part.\meta{number}} is
+created if \LILO\ modifies the partition table. (See page \pageref{fix-table}.)
+
+
+\subsection{Command-line options}
+
+The \LILO\ map installer can be invoked in the following ways:
+
+
+%%beginskip
+\def\seealso{See also sections \ref{corropt} and \ref{cfgglo}.}
+%%def\\seealso=See also sections \\ref{corropt} and \\ref{cfgglo}.
+%%endskip
+
+\subsubsection{Show current installation}
+\label{invshow}
+
+The currently mapped files are listed. With \raw{-v}, also many parameters
+are shown.
+
+\begin{command}
+  /sbin/lilo
+    \unit{\[ -C \meta{config\_file} \]}
+    \unit{-q}
+    \unit{\[ -m \meta{map\_file} \]}
+    \unit{\[ -v $\ldots$ \]}
+\end{command}
+
+\begin{description}
+  \item[\raw{-C \meta{config\_file}}]~\\
+    Specifies the configuration file that is used by the map
+    installer (see section \ref{config}). If \raw{-C} is omitted,
+    \path{/etc/lilo.conf} is used.
+  \item[\raw{-m \meta{map\_file}}]~\\
+    Specifies an alternate map file. \seealso
+  \item[\raw{-q}]~ \\
+    Lists the currently mapped files.
+  \item[\raw{-v $\ldots$}]~\\
+    Increase verbosity. \seealso
+\end{description}
+
+
+\subsubsection{Create or update map}
+\label{creupd}
+
+A new map is created for the images described in the configuration file
+\path{/etc/lilo.conf} and they are registered in the boot sector.
+
+\begin{command}
+  /sbin/lilo
+    \unit{\[ -C \meta{config\_file} \]}
+    \unit{\[ -b \meta{boot\_device} \]}
+    \unit{\[ -c \]}
+    \unit{\[ -l \]}
+    \unit{\[ -i \meta{boot\_sector} \]}
+    \unit{\[ -f \meta{disk\_tab} \]}
+    \unit{\[ -m \meta{map\_file} \]}
+    \unit{\[ -d \meta{delay\/} \]}
+    \unit{\[ -v $\ldots$ \]}
+    \unit{\[ -t \]}
+    \unit{\[ -s \meta{save\_file} \|}
+    \unit{-S \meta{save\_file} \]}
+    \unit{\[ -P fix \|}
+    \unit{-P ignore \]}
+    \unit{\[ -r \meta{root\_dir} \]}
+\end{command}
+
+\begin{description}
+  \item[\raw{-b \meta{boot\_device}}]~\\
+    Specifies the boot device. \seealso
+  \item[\raw{-c}]~\\
+    Enables map compaction. \seealso
+  \item[\raw{-C \meta{config\_file}}]~\\
+    Specifies an alternate configuration file. See also section \ref{invshow}.
+  \item[\raw{-d \meta{delay}}]~\\
+    Sets the delay before \LILO\ boots the default image. Note that the
+    delay is specified in \emphasize{tenths} of a second. \seealso
+  \item[\raw{-D \meta{name}}]~\\
+    Specifies the default image. \seealso
+  \item[\raw{-f \meta{disk\_tab}}]~\\
+    Specifies a disk parameter table file. \seealso
+  \item[\raw{-i \meta{boot\_sector}}]~\\
+    Specifies an alternate boot file. \seealso
+  \item[\raw{-L}]~\\
+    Enables lba32 sector addresses. \seealso
+  \item[\raw{-l}]~\\
+    Enables linear sector addresses. \seealso
+  \item[\raw{-m \meta{map\_file}}]~\\
+    Specifies an alternate map file. \seealso
+  \item[\raw{-P \meta{mode}}]~\\
+    Specifies how invalid partition table entries should be handled. \seealso
+  \item[\raw{-r \meta{root\_directory}}]~ \\
+    Chroots to the specified directory before doing anything else. This is
+    useful when running the map installer while the normal root file system
+    is mounted somewhere else, e.g. when recovering from an installation
+    failure with a recovery disk. The \raw{-r} option is implied if
+    the environment variable \raw{ROOT} is set.\footnote{E.g. if your root
+      partition is mounted on \path{/mnt}, you can update the map by simply
+      running \raw{ROOT=/mnt /mnt/sbin/lilo}}
+    The current directory is changed to the new root directory, so using
+    relative paths may not work.
+  \item[\raw{-s \meta{save\_file}}]~\\
+    Specifies an alternate boot sector save file. \seealso
+  \item[\raw{-S \meta{save\_file}}]~\\
+    Like \raw{-s}, but overwrites old save files.
+  \item[\raw{-t}]~ \\
+    Test only. This performs the entire installation procedure except
+    replacing the map file, writing the modified boot sector and fixing
+    partition tables. This
+    can be used in conjunction with the \raw{-v} option to verify that
+    \LILO\ will use sane values.
+  \item[\raw{-v $\ldots$}]~\\
+    Increase verbosity. \seealso
+\end{description}
+
+
+\subsubsection{Change default command line}
+\label{invcmd}
+
+Changes \LILO's default command line. See also section \ref{bootsel}.
+
+\begin{command}
+  /sbin/lilo
+    \unit{\[ -C \meta{config\_file} \]}
+    \unit{\[ -m \meta{map\_file} \]}
+    \unit{-R \[ \meta{word} $\ldots$ \]}
+\end{command}
+
+\begin{description}
+  \item[\raw{-C \meta{config\_file}}]~\\
+    Specifies an alternate configuration file. See also section \ref{invshow}.
+  \item[\raw{-m \meta{map\_file}}]~\\
+    Specifies an alternate map file. \seealso
+  \item[\raw{-R \meta{word $\ldots$}}]~ \\
+    Stores the specified words in the map file. The boot loader uses those
+    words as the default command line when booting the next time. That command
+    line is removed from the map file by the boot loader by overwriting the
+    sector immediately after reading it. The first word has
+    to be the name of a boot image. If \raw{-R} is not followed by any words,
+    the current default command line in the map file is erased.\footnote{%
+      \raw{-R} is typically used in reboot scripts, e.g. \\
+%%beginskip
+\tt
+%%endskip
+\#!/bin/sh \\
+cd / \\
+/sbin/lilo -R "\$*" \&\& reboot}
+    If the command line isn't valid, the map installer issues an error
+    message and returns a non-zero exit code.
+\end{description}
+
+
+\subsubsection{Kernel name translation}
+
+Determines the path of the kernel.
+
+\begin{command}
+  /sbin/lilo
+    \unit{\[ -C \meta{config\_file} \]}
+    \unit{-I \meta{name}}
+    \unit{\[ \meta{options} \]}
+\end{command}
+
+\begin{description}
+  \item[\raw{-C \meta{config\_file}}]~\\
+    Specifies an alternate configuration file. See also section \ref{invshow}.
+  \item[\raw{-I \meta{name} {$[$} \meta{options} {$]$}}]~ \\
+    Translates the specified label name to the path of the corresponding kernel
+    image and prints that path on standard output. This can be used to
+    synchronize
+    files that depend on the kernel (e.g. the \name{ps} database). The image
+    name can be obtained from the environment variable \raw{BOOT\_IMAGE}. An
+    error message is issued and a non-zero exit code is returned if no
+    matching label name can be found. The existence of the image file is
+    verified if the option character \raw{v} is added.
+\end{description}
+
+
+\subsubsection{De-installation}
+
+Restores the boot sector that was used before the installation of \LILO.
+Note that this option only works properly if \LILO's directories (e.g.
+\path{/boot}) have not been touched since the first installation. See also
+section \ref{deinst}.
+
+\begin{command}
+  /sbin/lilo
+    \unit{\[ -C \meta{config\_file} \]}
+    \unit{\[ -s \meta{save\_file} \]}
+    \unit{-u \| -U}
+    \unit{\[ \meta{boot\_device} \]}
+\end{command}
+
+\begin{description}
+  \item[\raw{-C \meta{config\_file}}]~\\
+    Specifies an alternate configuration file. See also section \ref{invshow}.
+  \item[\raw{-s \meta{save\_file}}]~\\
+    Specifies an alternate boot sector save file. \seealso
+  \item[\raw{-u {$[$} \meta{device\_name} {$]$}}]~ \\
+    Restores the backup copy of the specified boot sector. If no device is
+    specified, the value of the \verb"boot" variable is used. If this one
+    is also unavailable, \LILO\ uses the current root device. The name of
+    the backup copy is derived from the device name. The \verb"-s" option
+    or the \verb"backup" variable can be used to override this.
+    \LILO\ validates the backup copy by checking a time stamp.
+  \item[\raw{-U {$[$} \meta{device\_name} {$]$}}]~ \\
+    Like \verb"-u", but does not check the time stamp.
+\end{description}
+
+
+\subsubsection{Print version number}
+
+\begin{command}
+  /sbin/lilo -V
+\end{command}
+
+\begin{description}
+  \item[\raw{-V}]~ \\
+    Print the version number and exit.
+\end{description}
+
+
+\subsubsection{Options corresponding to configuration variables}
+\label{corropt}
+
+There are also many command-line options that correspond to configuration
+variables. See section \ref{cfgglo} for a description.
+
+$$
+\begin{tabular}{l|l}
+  Command-line option          & Configuration variable \\
+  \hline
+  \raw{-b \meta{boot\_device}} & \raw{boot=\meta{boot\_device}} \\
+  \raw{-c}                     & \raw{compact} \\
+  \raw{-d \meta{tsecs}}                & \raw{delay=\meta{tsecs}} \\
+  \raw{-D \meta{name}}         & \raw{default=\meta{name}} \\
+  \raw{-i \meta{boot\_sector}} & \raw{install=\meta{boot\_sector}} \\
+  \raw{-L}                     & \raw{lba32} \\
+  \raw{-l}                     & \raw{linear} \\
+  \raw{-m \meta{map\_file}}    & \raw{map=\meta{map\_file}} \\
+  \raw{-P fix}                 & \raw{fix-table} \\
+  \raw{-P ignore}              & \raw{ignore-table} \\
+  \raw{-s \meta{backup\_file}} & \raw{backup=\meta{backup\_file}} \\
+  \raw{-S \meta{backup\_file}} & \raw{force-backup=\meta{backup\_file}} \\
+  \raw{-v $\ldots$}            & \raw{verbose=\meta{level}} \\
+\end{tabular}
+$$
+
+
+\subsection{Configuration}
+\label{config}
+
+The configuration information is stored in the file \path{/etc/lilo.conf}
+and consists of variable assignments.
+
+
+\subsubsection{Syntax}
+\label{syntax}
+
+The following syntax rules apply:
+
+\begin{itemize}
+  \item flag variables consist of a single word and are followed by
+    whitespace or the end of the file.
+  \item string variables consist of the variable name, optional whitespace,
+    an equal sign, optional whitespace, the value and required whitespace,
+    or the end of the file.
+  \item a non-empty sequence of blanks, tabs, newlines and comments counts
+    as whitespace.
+  \item variable names are case-insensitive. Values are usually case-sensitive,
+    but there are a few exceptions. (See below.)
+  \item tabs and newlines are special characters and may not be part of a
+    variable name or a value. The use of other control characters and
+    non-ASCII characters is discouraged.
+  \item blanks and equal signs may only be part of a variable name or a
+    value if they are escaped by a backslash or if the value is embedded in
+    double quotes. An equal sign may not be the only character in a name or
+    value.
+  \item an escaped tab is converted to an escaped blank. An escaped newline
+    is removed from the input stream. An escaped backslash (i.e. two
+    backslashes) is converted to a backslash. Inside quoted strings, only
+    double quotes, backslashes, dollar signs, and newlines can be escaped.
+  \item quoted strings can be continued over several lines by ending each
+    incomplete line with a backslash. A single space is inserted in the
+    string for the line end and all spaces or tabs that follow immediately
+    on the next line.
+  \item environment variables can be used by specifying them in the form
+    \verb"$"\meta{name} or \verb"${"\meta{name}\verb"}". Dollar signs can
+    be escaped.
+  \item comments begin with a number sign and end with the next newline.
+    All characters (including backslashes) until the newline are ignored.
+\end{itemize}
+
+Example:
+\begin{verbatim}
+boot = $FD
+install = menu
+map = $MNT/map
+compact
+read-only
+append = "nfsroot=/home/linux-install/root \
+  nfsaddrs=128.178.156.28:128.178.156.24::255.255.255.0:lrcinst"
+image = $MNT/zImage
+\end{verbatim}
+
+
+\subsubsection{Global options}
+\label{cfgglo}
+
+\path{/etc/lilo.conf} begins with a possibly empty global options section.
+Many global options can also be set from the command line, but storing
+permanent options in the configuration file is more convenient.
+
+The following global options are recognized:
+
+\begin{description}
+  \item[\craw{backup=}\meta{backup\_file}] Copy the original boot sector to
+    \meta{backup\_file} (which may also be a device, e.g. \path{/dev/null})
+    instead of \path{/boot/boot.\meta{number}}
+  \item[\craw{boot=}\meta{boot\_device}] Sets the name of the device (e.g.
+    a hard disk partition) that contains
+    the boot sector. If \craw{boot} is omitted, the boot sector is read from
+    (and possibly written to) the device that is currently mounted as root.
+  \item[\craw{change-rules}] Defines partition type numbers. See section
+    \ref{ptcr} for details.
+  \item[\craw{compact}] Tries to merge read requests for adjacent sectors into
+    a single read request. This drastically reduces load time and keeps the
+    map smaller. Using \craw{compact} is especially recommended when booting
+    from a floppy disk.
+    \craw{compact} may conflict with \craw{linear} or \craw{lba32}, see
+    section \ref{othpro}.
+  \item[\craw{default=}\meta{name}] Uses the specified image as the default
+    boot image. If \craw{default} is omitted, the image appearing first in the
+    configuration file is used.
+  \item[\craw{delay=}\meta{tsecs}] Specifies the number of \emphasize{tenths}
+    of a second
+    \LILO\ should wait before booting the first image. This is useful on
+    systems that immediately boot from the hard disk after enabling the
+    keyboard. \LILO\ doesn't wait if \craw{delay} is omitted or if \craw{delay}
+    is set to zero.
+  \item[\craw{disk=}\meta{device\_name}] Defines non-standard parameters
+    for the specified disk. See section \ref{diskgeo} for details.
+  \item[\craw{fix-table}]\label{fix-table}Allows \LILO\ to adjust 3D addresses
+    in partition
+    tables. Each partition entry contains a 3D (sector/head/cylinder) and a
+    linear 32-bit address of the first and the last sector of the partition.
+    If a
+    partition is not track-aligned and if certain other operating systems
+    (e.g. PC/MS-DOS or OS/2) are using the same disk, they may change the 3D
+    address. \LILO\ can store its boot sector only on partitions where both
+    address types correspond. \LILO\ re-adjusts incorrect 3D start addresses
+    if \craw{fix-table} is set.
+
+    \emphasize{WARNING:} This does not guarantee that other operating systems
+    may not attempt to reset the address later. It is also possible that this
+    change has other, unexpected side-effects. The correct fix is to
+    re-partition the drive with a program that does align partitions to tracks.
+    Also, with some disks (e.g. some large EIDE disks with address
+    translation enabled), under some circumstances, it may even be unavoidable
+    to have conflicting partition table entries.
+  \item[\craw{force-backup=}\meta{backup\_file}] Like \craw{backup}, but
+    overwrite an old backup copy if it exists.
+    \craw{backup=}\meta{backup\_file}
+    is ignored if \craw{force-backup} appears in the same configuration file.
+  \item[\craw{ignore-table}] Tells LILO to ignore corrupt partition tables and
+    to put the boot sector even on partitions that appear to be unsuitable for
+    that.
+  \item[\craw{install=}\meta{boot\_sector}] Install the specified file as the
+    new boot sector. If \craw{install} is omitted, \path{install=text} is used
+    as the default.
+  \item[\craw{keytable=}\meta{table\_file}] Re-map the keyboard as specified
+    in this file. See section \ref{keytab} for details.
+  \item[\craw{lba32}] Generate 32-bit Logical Block Addresses instead of 
+    sector/head/cylinder addresses. If the BIOS supports packet addressing, 
+    then packet calls will be used to access the disk. This allows booting 
+    from any partition on disks with more than 1024 cylinders. If the BIOS 
+    does not support packet addressing, then \craw{lba32} addresses are 
+    translated to C:H:S, just as for \craw{linear}. All floppy disk references 
+    are retained in C:H:S form.  Use of \craw{lba32} is recommended on all 
+    post-1998 systems.
+    \craw{lba32} may conflict with \craw{compact}, see section \ref{othpro}.
+  \item[\craw{linear}] Generate linear sector addresses instead of
+    sector/head/cylinder addresses. Linear addresses are translated at run
+    time and do not depend on disk geometry. Note that boot disks
+    may not be portable if \craw{linear} is used,
+    because the BIOS service to
+    determine the disk geometry does not work reliably for floppy disks.
+    When using \craw{linear} with large disks, \path{/sbin/lilo} may
+    generate references to inaccessible disk areas (see section \ref{broken}),
+    because 3D sector addresses are not known before boot time.
+    \craw{linear} may conflict with \craw{compact}, see section \ref{othpro}.
+  \item[\craw{map=}\meta{map\_file}] Specifies the location of the map file.
+    If \craw{map} is omitted, a file \path{/boot/map} is used.
+  \item[\craw{message=}\meta{message\_file}] Specifies a file containing a
+    message that is displayed before the boot prompt. No message is displayed
+    while waiting for a modifier key (\key{Shift}, etc.) after printing
+    ``LILO ''. In the message, the \raw{FF}
+    character (\hbox{\key{Ctrl L}}) clears the local screen. The size of the
+    message file is limited to 65535 bytes. The map file has to be rebuilt
+    if the message file is changed or moved.
+  \item[\craw{nowarn}] Disables warnings about possible future dangers.
+  \item[\craw{prompt}] Forces entering the boot prompt without expecting any
+    prior key-presses. Unattended reboots are impossible if \craw{prompt} is
+    set and \craw{timeout} isn't.
+  \item[\craw{serial=}\meta{parameters}] Enables control from a serial line.
+    The specified serial port is initialized and \LILO\ is accepting input from
+    it and from the PC's keyboard. Sending a break on the serial line
+    corresponds to pressing a shift key on the console in order to get
+    \LILO's attention. All boot images should be password-protected if the
+    serial access is less secure than access to the console, e.g. if the
+    line is connected to a modem. The parameter string has the following
+    syntax: \\
+    \raw{\meta{port},\meta{bps}\,\meta{parity}\,\meta{bits}} \\
+    The components \meta{bps}, \meta{parity} and \meta{bits} can be
+    omitted. If a component is omitted, all following components have to
+    be omitted too. Additionally, the comma has to be omitted if only the
+    port number is specified.
+    \begin{description}
+      \item[\meta{port}] the number of the serial port, zero-based. 0
+       corresponds to \path{COM1} alias \path{/dev/ttyS0}, etc. All four
+       ports can be used (if present).
+      \item[\meta{bps}] the baud rate of the serial port. The following
+       baud rates are supported: 110, 300, 1200, 2400, 4800, 9600, 19200, and
+        38400 bps. Default is 2400 bps.
+      \item[\meta{parity}] the parity used on the serial line. \LILO\ ignores
+       input parity and strips the 8th bit. The following (upper or lower
+       case) characters are used to describe the parity: \raw{n} for no
+       parity, \raw{e} for even parity and \raw{o} for odd parity.
+      \item[\meta{bits}] the number of bits in a character. Only 7 and 8
+       bits are supported. Default is 8 if parity is ``none'', 7 if parity
+       is ``even'' or ``odd''.
+    \end{description}
+    If \craw{serial} is set, the value of \craw{delay} is automatically raised
+    to 20.
+
+    Example: \verb"serial=0,2400n8" initializes \path{COM1} with the
+    default parameters.
+  \item[\craw{timeout=}\meta{tsecs}] Sets a timeout (in tenths of a second) for
+    keyboard input. If no key is pressed for the specified time, the first
+    image is automatically booted. Similarly, password input is aborted if
+    the user is idle for too long. The default timeout is infinite.
+  \item[\craw{verbose=}\meta{level}] Turns on lots of progress reporting.
+    Higher numbers give more verbose output. If \raw{-v} is additionally
+    specified on the command line, \meta{level} is increased accordingly.
+    The following verbosity levels exist:
+    \begin{description}
+      \item[$<$0] only warnings and errors are shown
+      \item[0] prints one line for each added or skipped image
+      \item[1] mentions names of important files and devices and why they
+       are accessed. Also displays informational messages for exceptional
+       but harmless conditions and prints the version number.
+      \item[2] displays statistics and processing of temporary files and
+        devices
+      \item[3] displays disk geometry information and partition table change
+       rules
+      \item[4] lists sector mappings as they are written into the map file
+       (i.e. after compaction, in a format suitable to pass it to the BIOS)
+      \item[5] lists the mapping of each sector (i.e. before compaction, raw)
+    \end{description}
+    When using the \raw{-q} option, the levels have a slightly different
+    meaning:
+    \begin{description}
+      \item[0] displays only image names
+      \item[1] also displays all global and per-image settings
+      \item[2] displays the address of the first map sector
+    \end{description}
+\end{description}
+
+Additionally, the kernel configuration parameters \craw{append}, \craw{initrd},
+\craw{ramdisk}, \craw{read-only}, \craw{read-write}, \craw{root} and
+\craw{vga}, and the general per-image options \craw{fallback}, \craw{lock},
+\craw{optional}, \craw{password}, \craw{restricted}, and
+\craw{single-key} can be set in
+the global options section. They are used as defaults if they aren't specified
+in the configuration sections of the respective images. See below for a
+description.
+
+The plethora of options may be intimidating at first, but in ``normal''
+configurations, hardly any options but \craw{boot}, \craw{compact},
+\craw{delay}, \craw{root}, and \craw{vga} are used.
+
+
+\subsubsection{General per-image options}
+\label{cfggen}
+
+The following options can be specified for all images, independent of their
+type:
+\begin{description}
+  \item[\craw{alias=}\meta{name}] Specifies a second name for the current
+    entry.
+  \item[\craw{fallback=}\meta{command\_line}] Specifies a string that is stored
+    as the default command line if the current image is booted. This is useful
+    when experimenting with kernels which may crash before allowing
+    interaction with the system. If using the \craw{fallback} option, the
+    next reboot (e.g. triggered by a manual reset or by a watchdog timer)
+    will load a different (supposedly stable) kernel. The command line by the
+    fallback mechanism is
+    cleared by removing or changing the default command line with the \raw{-R}
+    option, see \ref{invcmd}.
+  \item[\craw{label=}\meta{name}] By default, \LILO\ uses the main file name
+    (without its
+    path) of each image specification to identify that image. A different name
+    can be used by setting the variable \craw{label}.
+  \item[\craw{lock}] Enables automatic recording of boot command lines as the
+    defaults for the following boots. This way, \LILO\ ``locks'' on a
+    choice until it is manually overridden.
+  \item[\craw{optional}] Omit this image if its main file is not available at
+    map creation time. This is useful to specify test kernels that are not
+    always present.
+  \item[\craw{password=}\meta{password}] Ask the user for a password when
+    trying to load this image. Because the configuration file contains
+    unencrypted passwords when using this option, it should only be readable
+    for the super-user. Passwords are always case-sensitive.
+  \item[\craw{restricted}] Relaxes the password protection by requiring a
+    password only if parameters are specified on the command line
+    (e.g. \verb"single"). \craw{restricted} can only be used together with
+    \craw{password}.
+  \item[\craw{single-key}] Enables booting the image by hitting a
+    single key, without the need to press \key{Enter} afterwards.
+    \craw{single-key} requires that either the image's label or its
+    alias (or both) is a single character. Furthermore, no other image label
+    or alias may start with that character, e.g. an entry specifying a
+    label \raw{linux} and an alias \raw{l} is not allowed with
+    \craw{single-key}. Note that you can't specify command-line parameters for
+    an entry for which only \craw{single-key}ed names exist.
+\end{description}
+
+All general per-image options, with the exception of \craw{label} and
+\craw{alias}, can also be set in the global options section as defaults
+for all images.
+
+Example:
+\begin{verbatim}
+password = Geheim
+single-key
+image = /vmlinuz
+  label = linux
+  alias = 1
+  restricted
+other = /dev/hda1
+  label = dos
+  alias = 2
+\end{verbatim}
+
+
+\subsubsection{Per-image options for kernels}
+\label{cfgkern}
+
+Each (kernel or non-kernel)
+image description begins with a special variable (see section \ref{bootimg})
+which is followed by optional
+variables.
+The following variables can be used for all image descriptions
+that describe a Linux kernel:
+
+\begin{description}
+  \item[\craw{append=}\meta{string}] Appends the options specified in
+    {\meta{string}} to the parameter line passed to the kernel. This is
+    typically used to specify parameters of hardware that can't be entirely
+    auto-detected, e.g.\\
+    \verb'append = "aha152x=0x140,11"'
+  \item[\craw{initrd=}\meta{name}] Specifies the file that will be loaded at
+    boot time as the initial RAM disk. 
+  \item[\craw{literal=}\meta{string}] like \craw{append}, but removes all other
+    options (e.g. setting of the root device). Because vital options can be
+    removed unintentionally with \craw{literal}, this option cannot be set in
+    the global options section.
+  \item[\craw{ramdisk=}\meta{size}] Specifies the size of the optional RAM disk.
+    A value of zero indicates that no RAM disk should be created. If this
+    variable is omitted, the RAM disk size configured into the boot
+    image is used.
+  \item[\craw{read-only}] Specifies that the root file system should be
+    mounted read-only. Typically, the system startup procedure re-mounts
+    the root file system read-write later (e.g. after fsck'ing it).
+  \item[\craw{read-write}] specifies that the root file system should be
+    mounted read-write.
+  \item[\craw{root=}\meta{root\_device}] Specifies the device that should be
+    mounted as root. If the special name \craw{current} is used, the root
+    device is set to the device on which the root file system is currently
+    mounted. If the root has been changed with \raw{-r}, the respective
+    device is used. If the variable \craw{root} is omitted, the root device
+    setting contained in the kernel image is used. It can be changed
+    with the \name{rdev} program.
+  \item[\craw{vga=}\meta{mode}]\label{vga} Specifies the VGA text mode that
+    should be selected when booting. The following values are recognized
+    (case is ignored):
+    \begin{description}
+      \item[\craw{normal}] select normal 80x25 text mode.
+      \item[\craw{extended}] select 80x50 text mode. The word \craw{extended}
+       can be abbreviated to \craw{ext}.
+      \item[\craw{ask}] stop and ask for user input (at boot time).
+      \item[\meta{number}] use the corresponding text mode. A list of available
+       modes can be obtained by booting with \raw{vga=ask} and pressing
+       \key{Enter}.
+    \end{description}
+    If this variable is omitted, the VGA mode setting contained in the kernel
+    image is used. \name{rdev} supports manipulation of the VGA text mode
+    setting in the kernel image.
+\end{description}
+
+All kernel per-image options but \craw{literal} can also be set in the global
+options section as defaults for all kernels.
+
+If one of \craw{ramdisk}, \craw{read-only}, \craw{read-write}, \craw{root},
+or \craw{vga} is omitted in the configuration file and the
+corresponding value in the kernel image is changed, \LILO\ or the kernel
+will use the new value.
+
+It is perfectly valid to use different settings for the same
+image, because \LILO\ stores them in the image descriptors and not in the
+images themselves.
+
+Example:
+\begin{verbatim}
+image = /vmlinuz
+  label = lin-hd
+  root = /dev/hda2
+image = /vmlinuz
+  label = lin-fd
+  root = /dev/fd0
+\end{verbatim}
+
+
+\subsection{Boot image types}
+\label{bootimg}
+
+\LILO\ can boot the following types of images:
+\begin{itemize}
+  \item kernel images from a file.
+  \item kernel images from a block device. (E.g. a floppy disk.)
+  \item the boot sector of some other operating system.
+\end{itemize}
+
+The image type is determined by the name of the initial
+variable of the configuration section.
+
+The image files can reside on any media that is accessible at boot time.
+There's no need to put them on the root device, although this certainly
+doesn't hurt.
+
+
+\subsubsection{Booting kernel images from a file}
+
+The image is specified as follows: \craw{image=}\meta{name}
+
+Example:
+\begin{verbatim}
+image = /linux
+\end{verbatim}
+
+See sections \ref{cfggen} and \ref{cfgkern} for the options that can be
+added in a kernel image section.
+
+
+\subsubsection{Booting kernel images from a device}
+
+The range of sectors
+that should be mapped has to be specified. Either a range
+(\raw{\meta{start}-\meta{end}}) or a start and a distance
+(\raw{\meta{start}+\meta{number}}) have to be specified. \meta{start}
+and \meta{end} are zero-based. If only
+the start is specified, only that sector is mapped.
+
+The image is specified as follows: \craw{image=}\meta{device\_name}\quad
+Additionally, the \craw{range} variable must be set.
+
+Example:
+\begin{verbatim}
+image = /dev/fd0
+  range = 1+512
+\end{verbatim}
+
+All kernel options can also be used when booting the kernel from a device.
+
+
+\subsubsection{Booting a foreign operating system}
+\label{bootfor}
+
+\LILO\ can even boot other operating systems, i.e. MS-DOS.
+To boot an other operating
+system, the name of a loader program, the device or file that contains the boot
+sector and the device that contains the partition table have to be
+specified.
+
+The boot sector is merged with the partition table and stored in the map file.
+
+Currently, the loaders \path{chain.b} and \path{os2\_d.b} exist.
+\path{chain.b} simply starts the specified boot sector.\footnote{The boot
+sector is loaded by \LILO's secondary boot loader before control is passed
+to the code of \path{chain.b}.} \path{os2\_d.b} it a variant of \path{chain.b}
+that can boot OS/2 from the second hard disk.
+The \craw{map-drive} option has to be used with \path{os2\_d.b} to
+actually swap the drives.
+
+The image is specified as follows: \craw{other=}\meta{device\_name} or
+\craw{other=}\meta{file\_name}
+
+In addition to the options listen in section \ref{cfggen}, the following
+variables are recognized:
+\begin{description}
+  \item[\craw{change}] Change the partition table according to the rules
+    specified in this \craw{change} section. This option is intended for
+    booting systems which find their partitions by examining the
+    partition table. See section \ref{ptch} for details.
+  \item[\craw{loader=}\meta{chain\_loader}] Specifies the chain loader that
+    should be used. If it is omitted, \path{/boot/chain.b} is used.
+  \item[\craw{map-drive=}\meta{bios\_device\_code}] Instructs \path{chain.b}
+    to installs a resident driver that re-maps the floppy
+    or hard disk drives. This way, one can boot any operating system from a
+    hard disk different from the first one, as long as that operating system
+    uses \emphasize{only} the BIOS to access that hard disk.\footnote{So you
+should be very suspicious if the
+operating system requires any specific configuration or even drivers to use
+the disk it is booted from. Since there is a general trend to use optimized
+drivers to fully exploit the hardware capabilities (e.g. non-blocking disk
+access), booting systems from the second disk may become increasingly
+difficult.} This is known to work for PC/MS-DOS.
+
+    \craw{map-drive} is followed by the variable
+    \craw{to=}\meta{bios\_device\_code} which specifies the drive that should
+    effectively be accessed instead of the original one.
+    The list of mappings is only searched until the first match is found.
+    It is therefore possible to ``swap'' drives, see the second example below.
+  \item[\craw{table=}\meta{device}] Specifies the device that contains the
+    partition
+    table. \LILO\ does not pass partition information to the booted operating
+    system if this variable is omitted. (Some operating systems have other
+    means to determine from which partition they have been booted. E.g. MS-DOS
+    usually stores the geometry of the boot disk or partition in its boot
+    sector.) Note that \path{/sbin/lilo} must be re-run if a partition table
+    mapped referenced with \craw{table} is modified.
+  \item[\craw{unsafe}] Do not access the boot sector at map creation time. This
+    disables some sanity checks, including a partition table check. If the boot
+    sector is on a fixed-format floppy disk device, using \craw{unsafe} avoids
+    the need to put a readable disk into the drive when running the map
+    installer. \craw{unsafe} and \craw{table} are mutually incompatible.
+\end{description}
+
+None of these options can be set in the global options section.
+
+Examples:
+\begin{verbatim}
+other = /dev/hda2
+  label = dos
+  table = /dev/hda
+\end{verbatim}
+
+\begin{verbatim}
+other = /dev/hdb2
+  label = os2
+  loader = /boot/os2_d.b
+  map-drive = 0x80
+    to = 0x81
+  map-drive = 0x81
+    to = 0x80
+\end{verbatim}
+
+
+\subsection{Disk geometry}
+\label{diskgeo}
+
+For floppies and most hard disks, \LILO\ can obtain the
+disk geometry information from the kernel. Unfortunately, there are some
+exotic disks or adapters which may either not supply this information or
+which may even return incorrect information.
+
+If no geometry information is available, \LILO\ reports either the error \\
+\raw{geo\_query\_dev HDIO\_GETGEO (dev 0x\meta{number})} \\
+or \\
+\raw{Device 0x\meta{number}: Got bad geometry \meta{sec}/\meta{hd}/%
+\meta{cyl}}
+
+If incorrect information is returned, booting may fail in several ways,
+typically with a partial ``LILO'' banner message. In this document, that
+is called a ``geometry mismatch''.
+
+The next step should be to attempt setting the \craw{lba32} or \craw{linear} 
+configuration variable or the \raw{-L} or \raw{-l} command-line option. If
+this doesn't help, the entire disk geometry has to be specified explicitly.
+Note that \craw{linear} doesn't always work with floppy disks.
+
+Another common use of disk sections is if an (E)IDE and a SCSI drive are
+used in the same system and the BIOS is configured to use the SCSI drive
+as the first drive. (Normally, the (E)IDE drive would be the first drive
+and the SCSI drive would be the second one.) Since \LILO\ doesn't know
+how the BIOS is configured, it needs to be told explicitly about this
+arrangement. (See the second example below.)
+
+
+\subsubsection{Obtaining the geometry}
+
+The disk geometry parameters can be obtained by booting MS-DOS and
+running the program \path{DPARAM.COM} with the hexadecimal BIOS code of
+the drive as its argument, e.g. \verb"dparam 0x80" for the first hard
+disk. It displays the number of sectors per
+track, the number of heads per cylinder and the number of cylinders.
+All three numbers are one-based.
+
+Alternatively, the geometry may also be determined by reading the information
+presented by the ``setup'' section of the ROM-BIOS or by using certain disk
+utilities under operating systems accessing the disk through the BIOS.
+
+
+\subsubsection{Specifying the geometry}
+\label{diskspec}
+
+Disk geometry parameters are specified in the options section of the
+configuration file. Each disk parameter section begins with
+\craw{disk=}\meta{disk\_device}, similar to the way how boot images are
+specified.
+It is suggested to group disk parameter sections together, preferably
+at the beginning or the end of the options section.
+
+For each disk, the following variables can be specified:
+\begin{description}
+  \item[\craw{bios=}\meta{bios\_device\_code}] Is the number the BIOS uses
+    to refer to that device. Normally, it's \raw{0x80} for the first hard
+    disk and \raw{0x81} for the second hard disk. Note that hexadecimal
+    numbers have to begin with ``0x''. If \craw{bios} is omitted,
+    \LILO\ tries to ``guess'' that number.
+  \item[\craw{sectors=}\meta{sectors}] and
+  \item[\craw{heads=}\meta{heads}] specify the number of sectors per
+    track and the number of heads, i.e. the number of tracks per
+    cylinder. Both parameters have to be either specified together or
+    they have to be entirely omitted. If omitted, \LILO\ tries to obtain
+    that geometry information from the kernel.
+  \item[\craw{cylinders=}\meta{cylinders}] Specifies the number of cylinders.
+    This value is only used for sanity checks. If \craw{cylinders} is omitted,
+    \LILO\ uses the information obtained from the kernel if geometry
+    information had to be requested in order to determine some other
+    parameter. Otherwise,\footnote{I.e. if the BIOS device code, the number
+    of sectors, the number of heads and the partition start are specified.
+    Note that the number of cylinders may appear to vary if \craw{cylinders}
+    is absent and only some of the partition starts are specified.} it just
+    assumes the number of cylinders to be 1024, which is the cylinder limit
+    imposed by the BIOS.
+  \item[\craw{inaccessible}] Marks the device as inaccessible (for the BIOS).
+    This is useful if some disks on the system can't be read by the BIOS,
+    although \LILO\ ``thinks'' they can. If one accidentally tries to use
+    files located on such disks for booting, the map installer won't notice
+    and the system becomes unbootable. The most likely use of
+    \craw{inaccessible} is to prevent repetition after experiencing such a
+    situation once. No other variables may be specified if a device is
+    configured as \craw{inaccessible}.
+\end{description}
+
+Additionally, partition subsections can be added with
+\craw{partition=}\meta{partition\_device}. Each partition section can
+contain only one variable:
+\begin{description}
+  \item[\craw{start=}\meta{partition\_offset}] Specifies the zero-based
+    number of the start sector of that partition. The whole disk always
+    has a partition offset of zero. The partition offset is only necessary
+    when using devices for which the kernel does not provide that
+    information, e.g. CD-ROMs.
+\end{description}
+
+Examples:
+\begin{verbatim}
+disk = /dev/sda
+  bios = 0x80
+  sectors = 32
+  heads = 64
+  cylinders = 632
+  partition = /dev/sda1
+    start = 2048
+  partition = /dev/sda2
+    start = 204800
+  partition = /dev/sda3
+    start = 500000
+  partition = /dev/sda4
+    start = 900000
+\end{verbatim}
+
+\begin{verbatim}
+disk = /dev/sda
+  bios = 0x80
+disk = /dev/hda
+  bios = 0x81
+\end{verbatim}
+
+
+\subsection{Partition table manipulation}
+\label{ptman}
+
+Some non-Linux operating systems obtain information about their partitions
+(e.g. their equivalent of the root file system) from the partition table.
+If more than one such operating system is installed on a PC, they may have
+conflicting interpretations of the content of the partition table. Those
+problems can be avoided by changing the partition table, depending on which
+operating system is being booted.
+
+Partition table changes are specified in a \craw{change} section in the
+configuration file section describing the foreign operating system. Note
+that \craw{change} sections are only accepted if the build-time option
+\raw{REWRITE\_TABLE} is set.
+
+The \craw{change} section contains subsections for each partition whose
+table entry needs to be modified. Partitions are specified with
+\craw{partition=}\meta{device\_name}
+
+Changes are applied in the sequence in which they appear in the
+configuration file. Configurations containing changes that are redundant
+either by repeating a previous change or by changing its result further
+are invalid and refused by the map installer.
+
+Internally, all changes are expressed as rules which specify the location
+(disk and offset in the partition table), the value this location must
+contain before the change, and the value that has to be stored. As a
+safety measure, the rule is ignored if the previous value is found to be
+different.
+
+
+\subsubsection{Partition activation}
+
+This option is intended for booting systems which determine their boot
+partition by examining the active flag in the partition table. The flag
+is enabled with \craw{activate} and disabled with \craw{deactivate}.
+Note that only the current partition is affected. \LILO\ does not
+automatically change the active flags of other partitions and it also
+allows more than one partition to be active at the same time.
+
+Example:
+
+\begin{verbatim}
+other = /dev/sda4
+  label = sco
+  change
+    partition = /dev/sda4
+      activate
+    partition = /dev/sda3
+      deactivate
+\end{verbatim}
+
+
+\subsubsection{Partition type change rules}
+\label{ptcr}
+
+Partition type changes are normally a transition between two possible values,
+e.g. a typical convention is to set the lowest bit in the upper nibble of the
+partition type (i.e. 0x10) in order to
+``hide'', and to clear it to ``unhide'' a partition. \LILO\ performs these
+changes based on a set of rules. Each rule defines the name of a partition
+type, its normal value, and the value when hidden. Those rules are defined
+in the options section of the configuration file. The section defining
+them begins with \craw{change-rules}.
+
+The following options and variables can appear in the section:
+\begin{description}
+  \item[\craw{reset}] Removes all previously defined rules. This is needed
+    if a user doesn't wish to use the pre-defined rules (see below).
+  \item[\craw{type=}\meta{name}] Adds a rule for the type with the specified
+    name. Type names are case-insensitive.
+    The values are defined with \craw{normal=}\meta{byte} and
+    \craw{hidden=}\meta{byte}. Values can be specified as decimal or as
+    hexadecimal numbers with a leading \raw{0x}. If only one of the values
+    is present, the other value is assumed to be the same number,
+    but with the most significant bit inverted.
+\end{description}
+
+\LILO\ pre-defines rules for the three partition types of DOS partitions.
+The following example removes the pre-defined rules and creates them again:
+
+\begin{verbatim}
+change-rules
+  reset
+  type = DOS12
+    normal = 0x01
+    hidden = 0x11
+  type = DOS16_small
+    normal = 4 # hidden is 0x14
+  type = DOS16_big
+    hidden = 0x16
+\end{verbatim}
+
+
+\subsubsection{Partition type changes}
+\label{ptch}
+
+Partition type changes are specified in the partition section as
+\craw{set=}\meta{name}\craw{\_}\meta{state}, where \meta{name} is the
+name of the partition type, and \meta{state} is its state, i.e.
+\craw{normal} or \craw{hidden}.
+
+Example:
+
+\begin{verbatim}
+other = /dev/sda3
+  label = dos
+  change
+    partition = /dev/sda2
+      set = dos16_big_normal
+    partition = /dev/sda3
+      activate
+      set = DOS16_big_normal
+\end{verbatim}
+
+Only one \craw{set} variable is allowed per partition section. In the
+rare event that more than one \craw{set} variable is needed, further
+partition sections can be used.
+
+
+\subsection{Keyboard translation}
+\label{keytab}
+
+The PC keyboard emits so-called scan codes, which are basically key
+numbers. The BIOS then translates those scan codes to the character codes
+of the characters printed on the key-caps. By default, the BIOS normally
+assumes that the keyboard has a US layout. Once an operating system is
+loaded, this operating system can use a different mapping.
+
+At boot time, \LILO\ only has access to the basic services provided
+by the BIOS and therefore receives the character codes for an US keyboard.
+It provides a simple mechanism to re-map the character codes to what is
+appropriate for the actual layout.\footnote{The current mechanism isn't
+perfect, because it sits on top of the scan code to character code
+translation performed by the BIOS. This means that key combinations that
+don't produce any useful character on the US keyboard will be ignored by
+\LILO. The advantage of this approach is its simplicity.}
+
+
+\subsubsection{Compiling keyboard translation tables}
+
+\LILO\ obtains layout information from the keyboard translation tables
+Linux uses for the text console. They are usually stored in
+\path{/usr/lib/kbd/keytables}. \LILO\ comes with a program
+\name{keytab-lilo.pl} that reads those tables and generates a table
+suitable for use by the map installer. \name{keytab-lilo.pl} invokes
+the program \name{loadkeys} to print the tables in a format that is
+easy to parse.\footnote{On some systems, only root can execute
+\name{loadkeys}. It is then necessary to run \name{keytab-lilo.pl} as
+root too.}
+
+\name{keytab-lilo.pl} is used as follows:
+
+\begin{command}
+  keytab-lilo.pl
+    \unit{\[ -p \meta{old\_code}=\meta{new\_code} \] $\ldots$}
+    \unit{\[\meta{path}\]\meta{default\_layout}\[.\meta{extension}\] \]} \\
+    \unit{\[\meta{path}\]\meta{kbd\_layout}\[.\meta{extension}\] \]}
+\end{command}
+
+\begin{description}
+  \item[\raw{-p \meta{old\_code}=\meta{new\_code}}]~\\
+    Specifies corrections (``patches'') to the mapping obtained from the
+    translation table files. E.g. if pressing the upper case ``A'' should
+    yield an at sign, \verb"-p 65=64" would be used. The \raw{-p} option can
+    be repeated any number of times. The codes can also be given as
+    hexadecimal or as octal numbers if they are prefixed with \verb"0x" or
+    \verb"0", respectively.
+  \item[\meta{path}] The directory in which the file resides. The default
+    path is \path{/usr/lib/kbd/keytables}.
+  \item[\meta{extension}] Usually the trailing \path{.map}, which is
+    automatically added if the file name doesn't contain dots.
+  \item[\meta{default\_layout}] Is the layout which specifies the
+    translation by the BIOS. If none is specified, \path{us} is assumed.
+  \item[\meta{kbd\_layout}] Is the actual layout of the keyboard.
+\end{description}
+
+\name{keytab-lilo.pl} writes the resulting translation table as a binary
+string to standard output. Such tables can be stored anywhere with any name,
+but the suggested naming convention is \path{/boot/\meta{kbd}.ktl}
+(``\underline{K}eyboard \underline{T}able for \underline{L}ilo''), where
+\meta{kbd} is the name of the keyboard layout.
+
+Example:
+\begin{verbatim}
+keytab-lilo.pl de >/boot/de.ktl
+\end{verbatim}
+
+
+\subsubsection{Using keyboard translation tables}
+
+The keyboard translation table file is specified with the global configuration
+option \raw{keytable=\meta{table\_file}}. The complete name of the file has
+to be given.
+
+Example:
+\begin{verbatim}
+keytable = /boot/de.klt
+\end{verbatim}
+
+
+\newpage
+\section{Installation and updates}
+
+
+\subsection{Installation}
+
+This section describes the installation of \LILO. See section \ref{deinst}
+for how to uninstall \LILO.
+
+
+\subsubsection{Compatibility}
+
+The kernel header files have to be in
+\path{/usr/include/linux} and the kernel usually has to be configured by
+running \raw{make config} before \LILO\ can be compiled.
+
+\path{/bin/sh} has to be a real Bourne shell. \name{bash} is sufficiently
+compatible, but some \name{ksh} clones may cause problems.
+
+A file named \path{INCOMPAT} is included in the distribution. It describes
+incompatibilities to older versions of \LILO\ and may also contain further
+compatibility notes.
+
+
+\subsubsection{Quick installation}
+\label{quickinst}
+
+If you want to install \LILO\ on your hard disk and if you don't want
+to use all its features, you can use the quick installation script.
+Read \path{QuickInst} for details.
+
+\name{QuickInst} can only be used for first-time installations or to
+entirely replace an existing installation, \emphasize{not}
+to update or modify an existing installation of \LILO. Be sure you've
+extracted \LILO\ into a directory that doesn't contain any files of
+other \LILO\ installations.
+
+
+\subsubsection{Files}
+
+Some of the files contained in \path{lilo-21.tar.gz}:
+
+\begin{description}
+  \item[\path{lilo/README}]~\\
+    This documentation in plain ASCII format. Some sections containing
+    complex tables are only included in the \LaTeX\ version in
+    \path{doc/user.tex}
+  \item[\path{lilo/INCOMPAT}]~\\
+    List of incompatibilities to previous versions of \LILO.
+  \item[\path{lilo/CHANGES}]~\\
+    Change history.
+  \item[\path{lilo/VERSION}]~\\
+    The version number of the respective release.
+  \item[\path{lilo/QuickInst}]~\\
+    Quick installation script.
+  \item[\path{lilo/lilo-\meta{version}.lsm}]~\\
+    The LSM (``\underline{L}inux \underline{S}oftware \underline{M}ap'') entry
+    of the respective \LILO\ release.
+  \item[\path{lilo/Makefile}]~\\
+    Makefile to generate everything else.
+  \item[\path{lilo/*.c}, \path{lilo/*.h}]~\\
+    LILO map installer C source and common header files.
+  \item[\path{lilo/*.S}]~\\
+    LILO boot loader assembler source.
+  \item[\path{lilo/activate.c}]~\\
+    C source of a simple boot partition setter.
+  \item[\path{lilo/dparam.s}]~\\
+    Assembler source of a disk parameter dumper.
+  \item[\path{lilo/mkdist}]~\\
+    Shell script used to create the current \LILO\ distribution.
+  \item[\path{lilo/keytab-lilo.pl}]~\\
+    Perl script to generate keyboard translation tables.
+  \item[\path{lilo/doc/README}]~\\
+    Description of how to generate the documentation.
+  \item[\path{lilo/doc/Makefile}]~\\
+    Makefile used to convert the \LaTeX\ source into either DVI output or
+    the plain ASCII README file.
+  \item[\path{lilo/doc/user.tex}]~\\
+    \LaTeX\ source of \LILO's user's guide (this document).
+  \item[\path{lilo/doc/tech.tex}]~\\
+    \LaTeX\ source of \LILO's technical overview.
+  \item[\path{lilo/doc/*.fig}]~\\
+    Various \name{xfig} pictures used in the technical overview.
+  \item[\path{lilo/doc/fullpage.sty}]~\\
+    Style file to save a few square miles of forest.
+  \item[\path{lilo/doc/rlatex}]~\\
+    Shell script that invokes \LaTeX\ repeatedly until all references have
+    settled.
+  \item[\path{lilo/doc/t2a.pl}]~\\
+    \name{Perl} script to convert the \LaTeX\ source of the user's guide to
+    plain ASCII.
+\end{description}
+
+Files created after \raw{make} in \path{lilo/} (among others):
+
+\begin{description}
+  \item[\path{lilo/boot.b}]~\\
+    Combined boot sector. \raw{make install} puts this file into \path{/boot}
+  \item[\path{lilo/chain.b}]~\\
+    Generic chain loader. \raw{make install} puts this file into \path{/boot}
+  \item[\path{lilo/os2\_d.b}]~\\
+    Chain loader to load \name{OS/2} from the second hard disk.
+    \raw{make install} puts this file into \path{/boot}
+  \item[\path{lilo/lilo}]~\\
+    \LILO\ (map) installer. \raw{make install} puts this file into \path{/sbin}
+  \item[\path{lilo/activate}]~\\
+    Simple boot partition setter.
+  \item[\path{lilo/dparam.com}]~\\
+    MS-DOS executable of the disk parameter dumper.
+\end{description}
+
+
+\subsubsection{Normal first-time installation}
+\label{install}
+
+First, you have to install the \LILO\ files:
+
+\begin{itemize}
+  \item extract all files from \path{lilo-\meta{version}.tar.gz} in a new
+    directory.\footnote{E.g. \path{/usr/src/lilo}}
+  \item configure the \path{Makefile} (see section \ref{cfgmf})
+  \item run\quad\raw{make}\quad to compile and assemble all parts.
+  \item run\quad\raw{make install}\quad to copy all \LILO\ files to
+     the directories where they're installed. \path{/sbin} should now
+     contain the file \path{lilo},  \path{/usr/sbin} should contain
+     \path{keytab-lilo.pl}, and
+     \path{/boot} should contain \path{boot.b}, \path{chain.b}, and
+     \path{os2\_d.b}.
+\end{itemize}
+
+If you want to use \LILO\ on a non-standard disk, you might have to determine
+the parameters of your disk(s) and specify them in the configuration file.
+See section \ref{diskgeo} for details.
+If you're using such a non-standard system, the next step is to test
+\LILO\ with the boot sector on a floppy disk:
+
+\begin{itemize}
+  \item insert a blank (but low-level formatted) floppy disk into
+    \path{/dev/fd0}.
+  \item run \raw{echo image=\meta{kernel\_image}}\verb" |"\\
+    \raw{/sbin/lilo -C - -b /dev/fd0 -v -v -v} \\
+    If you've already installed \LILO\ on your system, you might not want
+    to overwrite your old map file.
+    Use the \raw{-m} option to specify an alternate map file name.
+  \item reboot. \LILO\ should now load its boot loaders from the floppy disk
+    and then continue loading the kernel from the hard disk.
+\end{itemize}
+
+Now, you have to decide, which boot concept you want to use. Let's assume
+you have a Linux partition on \path{/dev/hda2} and you want to install your
+\LILO\ boot sector there. The DOS-MBR loads the \LILO\ boot sector.
+
+\begin{itemize}
+  \item get a working boot disk, e.g. an install or recovery disk. Verify that
+    you can boot
+    with this setup and that you can mount your Linux partition(s) with it.
+  \item if the boot sector you want to overwrite with \LILO\ is of any value
+    (e.g. it's the MBR or if it contains a boot loader you might want to use
+    if you encounter problems with \LILO), you should mount your boot disk
+    and make a backup copy of your boot sector to a file on that floppy,
+    e.g. \verb"dd if=/dev/hda of=/fd/boot_sector bs=512 count=1"
+  \item create the configuration file \path{/etc/lilo.conf}, e.g. \\
+\meta{global settings} \\
+\meta{image specification} \\
+\verb"  "\meta{per-image options} \\
+$\ldots$ \\
+    Be sure to use absolute paths for all files. Relative paths may cause
+    unexpected behaviour when using the \raw{-r} option.
+  \item now, you can check what \LILO\ would do if you were about to install
+    it on your hard disk: \\
+\verb"/sbin/lilo -v -v -v -t"
+  \item if you need some additional boot utility (i.e. \name{BOOTACTV}), you
+    should install that now
+  \item run \path{/sbin/lilo} to install \LILO\ on your hard disk
+  \item if you have to change the active partition, use \name{fdisk} or
+    \name{activate} to do that
+  \item reboot
+\end{itemize}
+
+
+\subsubsection{Build-time configuration}
+\label{cfgmf}
+
+Certain build-time parameters can be configured.
+They can either be edited in the top-level \path{Makefile} or they can be
+stored in a file \path{/etc/lilo.defines}. Settings in the \path{Makefile}
+are ignored if that file exists.
+
+The following items can be configured:
+\begin{description}
+  \item[\raw{BEEP}] Enables beeping after displaying ``LILO''. This is
+    useful on machines which don't beep at the right time when booting
+    and when working over a serial
+    console. This option is disabled by default.
+  \item[\raw{IGNORECASE}] Makes image name matching case-insensitive, i.e.
+    ``linux'' and ``Linux'' are identical. This option is enabled by
+    default. Note that password matching is always case-sensitive.
+  \item[\raw{LARGE\_EDBA}] Loads \LILO\ at a lower address in order to
+    leave more space for the EBDA (Extended BIOS Data Area). This is
+    necessary on some recent MP systems. Note that enabling \raw{LARGE\_EDBA}
+    reduces the maximum size of ``small'' images (e.g. ``Image'' or
+    ``zImage'').
+  \item[\raw{NO1STDIAG}] Do not generate diagnostics on read errors in the
+    first stage boot loader. This avoids possibly irritating error codes
+    if the disk controller has transient read problems. This option is
+    disabled by default.
+  \item[\raw{NODRAIN}] The boot loader empties the keyboard buffer
+    when starting, because it may contain garbage on some systems. Draining
+    the keyboard buffer can be disabled by setting the \raw{NODRAIN} option.
+    \raw{NODRAIN} is disabled by default.
+  \item[\raw{NOINSTDEF}] If the option \craw{install} is omitted, don't install
+    a new boot sector, but try to modify the old boot sector instead. This
+    option is disabled by default.
+  \item[\raw{ONE\_SHOT}] Disables the command-line timeout (configuration
+    variable \craw{timeout}) if any key is pressed. This way, very short
+    timeouts can be used if \craw{prompt} is set. \raw{ONE\_SHOT} is disabled
+    by default.
+  \item[\raw{READONLY}] Disallows overwriting the default command line sector
+    of the map file. This way, command lines set with \raw{-R} stay in effect
+    until they are explicitly removed. \raw{READONLY} also disables
+    \craw{lock}, \craw{fallback}, and everything enabled by
+    \raw{REWRITE\_TABLE}. This option is disabled by default.
+  \item[\raw{REWRITE\_TABLE}] Enables rewriting the partition table at boot
+    time. This may be necessary to boot certain operating systems who
+    expect the active flag to be set on their partition or who need changes
+    in partition types. See also section
+    \ref{ptman}. This option is \emphasize{dangerous} and it is disabled by
+    default.
+  \item[\raw{USE\_TMPDIR}] Use the directory indicated in the \raw{TMPDIR}
+    environment variable when creating temporary device files. If \raw{TMPDIR}
+    is not set or if \LILO\ is compiled without \raw{USE\_TMPDIR}, temporary
+    device files are created in \path{/tmp}.\footnote{Note that, while honoring
+    \raw{TMPDIR} is the ``right'' thing to do, the fact that \LILO\ has to
+    create temporary device files at all may indicate that the operating
+    environment is not completely set up, so \raw{TMPDIR} may point to an
+    invalid location.} This option is disabled by default.
+  \item[\raw{VARSETUP}] Enables the use of variable-size setup segments.
+    This option is enabled by default and is only provided to fall back to
+    fixed-size setup segments in the unlikely case of problems when using
+    prehistoric kernels.
+  \item[\raw{XL\_SECS=\meta{sectors}}] Enable support for extra large
+    (non-standard) floppy disks. The number of sectors is set in the BIOS
+    disk parameter table to the specified value. Note that this hack may
+    yield incorrect behaviour on some systems. This option is disabled by
+    default.
+\end{description}
+
+\path{/etc/lilo.defines} should be used if one wishes to make
+permanent configuration changes. The usual installation procedures don't
+touch that file. Example:
+
+\begin{verbatim}
+-DIGNORECASE -DONE_SHOT
+\end{verbatim}
+
+After changing the build-time configuration, \LILO\ has to be recompiled
+with the following commands:
+
+\begin{verbatim}
+make distclean
+make
+\end{verbatim}
+
+
+\subsubsection{Floppy disk installation}
+
+In some cases\footnote{E.g. if no hard disk is accessible through the BIOS.},
+it may be desirable to install \LILO\ on a floppy disk in a way that it can
+boot a kernel without accessing the hard disk.
+
+The basic procedure is quite straightforward (see also section \ref{broken}):
+\begin{itemize}
+  \item a file system has to be created on the file system
+  \item the kernel and \path{boot.b} have to be copied to the floppy disk
+  \item \path{/sbin/lilo} has to be run to create the map file
+\end{itemize}
+
+This can be as easy as
+\begin{verbatim}
+/sbin/mke2fs /dev/fd0
+[ -d /fd ] || mkdir /fd
+mount /dev/fd0 /fd
+cp /boot/boot.b /fd
+cp /zImage /fd
+echo image=/fd/zImage label=linux |
+  /sbin/lilo -C - -b /dev/fd0 -i /fd/boot.b -c -m /fd/map
+umount /fd
+\end{verbatim}
+
+The command line of \path{/sbin/lilo} is a little tricky. \raw{-C -} takes
+the configuration from standard input (naturally, one could also write the
+configuration into a file), \raw{-b /dev/fd0} specifies that the boot sector
+is written to the floppy disk, \raw{-i /fd/boot.b} takes the first and second
+stage loaders from the floppy, \raw{-c} speeds up the load process, and
+\raw{-m /fd/map} puts the map file on the floppy too.
+
+
+\subsection{Updates}
+
+\LILO\ is affected by updates of kernels, the whole system and (trivially)
+of \LILO\ itself. Typically, only \path{/sbin/lilo} has to be run after
+any of those updates and everything will be well again (at least as far
+as \LILO\ is concerned).
+
+
+\subsubsection{\LILO\ update}
+\label{liloupd}
+
+Before updating to a new version of \LILO, you should read at least the 
+file \path{INCOMPAT} which describes incompatibilities with previous
+releases.
+
+After that, the initial steps are the same as
+for a first time installation: extract all files, configure the \path{Makefile},
+run \raw{make} to build
+the executables and run \raw{make install} to install the files.
+
+The old versions of \path{boot.b}, \path{chain.b}, etc. are automatically
+renamed to \path{boot.old}, \path{chain.old}, etc. This is done to ensure
+that you can boot even if the installation procedure does not finish.
+\path{boot.old}, \path{chain.old}, etc. can be deleted after the map file
+is rebuilt.
+
+Because the locations of \path{boot.b}, \path{chain.b}, etc. have changed
+and because the map file format may be different too, you have to update
+the boot sector and the map file. Run \path{/sbin/lilo} to do this.
+
+
+\subsubsection{Kernel update}
+\label{kernupd}
+
+Whenever any of the kernel files that are accessed by \LILO\ is moved or
+overwritten, the map has to be re-built.\footnote{It is advisable to
+keep a second, stable, kernel image that can be booted if you forget
+to update the map after a change to your usual kernel image.} Run
+\path{/sbin/lilo} to do this.
+
+The kernel has a make target ``zlilo'' that copies the kernel
+to \path{/vmlinuz} and runs \path{/sbin/lilo}.
+
+
+\subsubsection{System upgrade}
+
+Normally, system upgrades (i.e. installation or removal of packages, possibly
+replacement of a large part of the installed binaries) do not affect \LILO.
+Of course, if a new kernel is installed in the process, the normal kernel
+update procedure has to be followed (see section \ref{kernupd}). Also, if
+kernels are removed or added, it may be necessary to update the configuration
+file.
+
+If \LILO\ is updated by this system upgrade, \path{/sbin/lilo} should be
+run before booting the upgraded system. It is generally a good idea not to
+rely on the upgrade procedure to perform this essential step automatically.
+
+However, system upgrades which involve removal and re-creation of entire
+partitions (e.g. \path{/}, \path{/usr}, etc.) are different. First, they
+should be avoided, because they bear a high risk of losing other critical
+files, e.g. the \path{/etc/XF86Config} you've spent the last week fiddling
+with. If an upgrade really has to be performed in such a brute-force way,
+this is equal with total removal of \LILO, followed by a new installation.
+Therefore, the procedures described in the sections \ref{deinst} and
+\ref{liloupd} have to be performed. If you've forgotten to make a backup
+copy of \path{/etc/lilo.conf} before the destructive upgrade, you might
+also have to go through section \ref{install} again.
+
+
+\subsection{\LILO\ de-installation}
+\label{deinst}
+
+In order to stop \LILO\ from being invoked when the system boots, its
+boot sector has to be either removed or disabled. All other files belonging
+to \LILO\ can be deleted \emphasize{after} removing the boot sector,
+if desired.%
+\footnote{Backup copies of old boot sectors may be needed when removing
+the boot sector. They are stored in \path{/boot}.}
+
+Again, \emphasize{when removing Linux, \LILO\ must be de-installed before (!)
+its files (\path{/boot}, etc.) are deleted.} This is
+especially important if \LILO\ is operating as the MBR.
+
+LILO 14 (and newer) can be de-installed with \verb"lilo -u". If LILO 14
+or newer is currently installed, but the first version of LILO installed was
+older than 14, \verb"lilo -U" may work. When using \verb"-U", the warning
+at the end of this section applies.
+
+If \LILO's boot sector has been installed on a primary partition and is
+booted by the ``standard'' MBR or some partition switcher program, it can be
+disabled by making a different partition active. MS-DOS' FDISK, Linux
+\name{fdisk} or \LILO's \name{activate} can do that.
+
+If \LILO's boot sector is the master boot record (MBR) of a disk, it has
+to be replaced with a different MBR, typically MS-DOS' ``standard'' MBR.
+When using MS-DOS 5.0 or above, the MS-DOS MBR can be restored with
+\verb"FDISK /MBR". This only alters the boot loader code, not the
+partition table.
+
+\LILO\ automatically makes backup copies when it overwrites boot sectors.
+They are named \path{/boot/boot.\meta{nnnn}}, with \meta{nnnn}
+corresponding to the device number, e.g. \raw{0300} is \path{/dev/hda},
+\raw{0800} is \path{/dev/sda}, etc. Those backups can be used to restore
+the old MBR if no easier method is available. The commands are \\
+\raw{dd if=/boot/boot.0300 of=/dev/hda bs=446 count=1} or \\
+\raw{dd if=/boot/boot.0800 of=/dev/sda bs=446 count=1} \\
+respectively.
+
+\emphasize{WARNING:} Some Linux distributions install \path{boot.\meta{nnnn}}
+files
+from the system where the distribution was created. Using
+those files may yield unpredictable results. Therefore, the file creation
+date should be carefully checked.
+
+
+\subsection{Installation of other operating systems}
+\label{instoth}
+
+Some other operating systems (e.g. MS-DOS 6.0) appear to modify the MBR in
+their install procedures. It is therefore possible that \LILO\ will stop
+to work after such an installation and Linux has to be booted from floppy
+disk. The original state can be restored by either re-running
+\path{/sbin/lilo } (if \LILO\ is installed as the MBR) or by making
+\LILO's partition active (if it's installed on a primary partition).
+
+It is generally a good idea to install \LILO\ after the other operating
+systems have been installed. E.g. OS/2 is said to cause trouble when
+attempting to add it to an existing Linux system. (However, booting
+from floppy and running \path{/sbin/lilo} should get around most
+interferences.)
+
+Typically, the new operating system then has to be added to \LILO's
+configuration (and \path{/sbin/lilo} has to be re-run) in order to boot
+it.
+
+See also section \ref{othpro} for a list of known problems with some
+other operating systems.
+
+
+\newpage
+\section{Troubleshooting}
+
+All parts of \LILO\ display some messages that can be used to diagnose
+problems. 
+
+
+\subsection{Map installer warnings and errors}
+
+Most messages of the map installer (\path{/sbin/lilo}) should be
+self-explanatory. Some messages that indicate common errors are
+listed below. They are grouped
+into fatal errors and warnings (non-fatal errors).
+
+
+\subsubsection{Fatal errors}
+
+\begin{description}
+  \item[\raw{Boot sector of \meta{device\_name} doesn't have a boot %
+    signature}]
+  \item[\raw{Boot sector of \meta{device\_name} doesn't have a LILO %
+    signature}]~\\
+    The sector from which \LILO\ should be uninstalled doesn't appear to be a
+    \LILO\ boot sector.
+  \item[\raw{Can't put the boot sector on logical partition \meta{number}}]~\\
+    An attempt has been made to put \LILO's boot sector on the current
+    root file system partition which is on a logical partition. This usually
+    doesn't have the desired effect, because common MBRs can only boot
+    primary partitions. This check can be bypassed by explicitly
+    specifying the boot partition with the \raw{-b} option or by setting
+    the configuration variable \craw{boot}.
+  \item[\raw{Checksum error}]~\\
+    The descriptor table of the map file has an invalid checksum. Refresh
+    the map file \emphasize{immediately} !
+  \item[\raw{Device 0x\meta{number}: Configured as inaccessible.}]~\\
+     There is a \craw{disk} section entry indicating that the device is
+     inaccessible
+     from the BIOS. You should check carefully that all files \LILO\ tries to
+     access when booting are on the right device.
+  \item[\raw{Device 0x\meta{number}: Got bad geometry \meta{sec}/\meta{hd}/%
+\meta{cyl}}]~\\
+    The device driver for your SCSI controller does not support geometry
+    detection. You have to specify the geometry explicitly (see section
+    \ref{diskgeo}).
+  \item[\raw{Device 0x\meta{number}: Invalid partition table, entry %
+    \meta{number}}]~\\
+    The 3D and linear addresses of the first sector of the specified partition
+    don't correspond. This is typically caused by partitioning a disk with
+    a program that doesn't align partitions to tracks and later using
+    PC/MS-DOS or OS/2 on that disk. \LILO\ can attempt to correct the problem,
+    see page \pageref{fix-table}.
+  \item[\raw{Device 0x\meta{number}: Partition type 0x\meta{number} does not
+    seem suitable for a LILO boot sector}]~\\
+    The location where the \LILO\ boot sector should be placed does not seem
+    to be suitable for that. (See also also section \ref{diskorg}). You should
+    either adjust the partition type to reflect the actual use or put the
+    boot sector on a different partition. This consistency check only yields
+    a warning (i.e. \LILO\ continues) if the option \craw{ignore-table} is
+    set.
+  \item[\raw{\meta{device\_name} is not a valid partition device}]~\\
+    The specified device is either not a device at all, a whole disk, or
+    a partition on a different disk than the one in whose section its
+    entry appears.
+  \item[\raw{\meta{device\_name} is not a whole disk device}]~\\
+    Only the geometry of whole disks (e.g. \path{/dev/hda}, \path{/dev/sdb},
+    etc.) can be redefined when using \craw{disk} sections.
+  \item[\raw{DISKTAB and DISK are mutually exclusive}]~\\
+    You cannot use a \path{disktab} file and disk geometry definitions in the
+    configuration file at the same time. Maybe \path{/etc/disktab} was
+    accidentally used, because that's the default for backward-compatibility.
+    You should delete \path{/etc/disktab} after completing the transition to
+    \craw{disk} sections.
+  \item[\raw{Duplicate entry in partition table}]~\\
+    A partition table entry appears twice. The partition table has to be
+    fixed with \name{fdisk}.
+  \item[\raw{Duplicate geometry definition for \meta{device\_name}}]~\\
+    A disk or partition geometry definition entry for the same device appears
+    twice in the configuration file. Note that you mustn't write a partition
+    section for the whole disk --- its start sector is always the first
+    sector of the disk.
+  \item[\raw{First sector of \meta{device} doesn't have a valid boot %
+    signature}]~\\
+    The first sector of the specified device does not appear to be a valid
+    boot sector. You might have confused the device name.\footnote{Because
+    different partition programs may display the partitions in a different
+    order, it is possible that what you think is your first partition isn't
+    \path{/dev/hda1}, etc. A good method to verify the content of a partition
+    is to try to mount it.}
+  \item[\raw{geo\_comp\_addr: Cylinder \meta{number} beyond end of media %
+    (\meta{number})}]~\\
+    A file block appears to be located beyond the last cylinder of the disk.
+    This probably indicates an error in the disk geometry specification (see
+    section \ref{diskgeo}) or a file system corruption.
+  \item[\raw{geo\_comp\_addr: Cylinder number is too big (\meta{number} $>$
+   1023)}]~\\
+    Blocks of a file are located beyond the 1024th cylinder of a hard disk.
+    \LILO\ can't access such files, because the BIOS limits cylinder numbers to
+    the range 0$\ldots$1023. Try moving the file to a different place,
+    preferably a
+    partition that is entirely within the first 1024 cylinders of the disk.
+  \item[\raw{Hole found in map file (\meta{location})}]~\\
+    The map installer is
+    confused about the disk organization. Please report this error.
+  \item[\raw{\meta{item} doesn't have a valid LILO signature}]~\\
+    The specified item has been located, but is not part of \LILO.
+  \item[\raw{\meta{item} has an invalid stage code (\meta{number})}]~\\
+    The specified item has probably been corrupted. Try re-building
+    \LILO.
+  \item[\raw{\meta{item} is version \meta{number}. Expecting version%
+      \meta{number}.}]~\\
+    The specified entity is either too old or too new. Make sure all parts
+    of \LILO\ (map installer, boot loaders and chain loaders) are from the
+    same distribution. \footnote{The expected version number may be different
+    from the version number of the \LILO\ package, because file version
+    numbers are only increased when the file formats change.}
+  \item[\raw{Kernel \meta{name} is too big}]~\\
+    The kernel image (without the setup
+    code) is bigger than 512 kbytes (or 448 kbytes, if built with
+    \raw{LARGE\_EDBA}). \LILO\ would overwrite itself when trying
+    to load such a kernel. This limitation only applies to old kernels which
+    are loaded below 0x10000 (e.g. ``Image'' or ``zImage''). Try building the
+    kernel with ``bzImage''. If this is undesirable for some reason, try
+    removing some unused drivers and compiling the kernel again.
+    This error may also occur if the kernel image is damaged or if it
+    contains trailing ``junk'', e.g. as the result of copying an entire boot
+    floppy to the hard disk.
+  \item[\raw{LOCK and FALLBACK are mutually exclusive}]~\\
+    Since \craw{lock} and \craw{fallback} both change the default command line,
+    they can't be reasonably used together.
+  \item[\raw{Map \meta{path} is not a regular file.}]~\\
+    This is probably the result of an attempt to omit writing a map file, e.g.
+    with \raw{-m /dev/null}. The \raw{-t} option should be used to accomplish
+    this.
+  \item[\raw{Must specify SECTORS and HEADS together}]~\\
+    It is assumed that disks with a ``strange'' number of sectors will also
+    have a ``strange'' number of heads. Therefore, it's all or nothing.
+  \item[\raw{No geometry variables allowed if INACCESSIBLE}]~\\
+    If a device is configured as \craw{inaccessible} (see section
+    \ref{diskspec}),
+    its \craw{disk} section must not contain any geometry variables.
+  \item[\raw{No image \meta{image} is defined}]~\\
+    The command line specified either with the \raw{-R} option or with
+    \craw{fallback} does not contain the name of a valid image. Note that
+    optional images which have not been included in the map file are not
+    considered as valid.
+  \item[\raw{Partition entry not found}]~\\
+    The partition from which an other
+    operating system should be booted isn't listed in the specified
+    partition table. This either means that an incorrect partition
+    table has been specified or that you're trying to boot from a
+    logical partition. The latter usually doesn't work. You can bypass
+    this check by omitting the partition table specification (e.g.
+    omitting the variable \craw{table}).
+  \item[\raw{Single-key clash: "\meta{name}" vs. "\meta{name}"}]~\\
+    The specified image labels or aliases conflict because one
+    of them is a single character and has the \craw{single-key} option set,
+    and the other name begins with that character.
+  \item[\raw{Sorry, don't know how to handle device \meta{number}}]~\\
+    \LILO\ uses files that are located on a device for which
+    there is no easy way to determine the disk geometry. Such devices have
+    to be explicitly described, see section \ref{diskgeo}.
+  \item[\raw{This LILO is compiled READONLY and doesn't support $\ldots$}]~\\
+    If \LILO\ is not allowed to write to the disk at boot time (see section
+    \ref{cfgmf}), options like \craw{lock} and \craw{fallback} are unavailable.
+  \item[\raw{This LILO is compiled without REWRITE\_TABLE and doesn't support
+    $\ldots$}]~\\
+    If \LILO\ is not allowed to rewrite partition tables at boot time (see
+    section \ref{ptman}), options like \craw{activate} and \craw{set} (in a
+    \craw{change} section) are unavailable. You may also get this error if
+    \LILO\ is compiled with \raw{READONLY} enabled.
+  \item[\raw{Timestamp in boot sector of \meta{device} differs from date of %
+    \meta{file}}]~\\
+    The backup copy of the boot sector does not appear to be an ancestor of
+    the current boot sector. If you are absolutely sure that the boot sector
+    is indeed correct, you can bypass this check by using \raw{-U} instead
+    of \raw{-u}.
+  \item[\raw{Trying to map files from unnamed device 0x\meta{number}
+    (NFS ?)}]~\\
+    This is probably the same problem as described below, only with the
+    root file system residing on NFS.
+  \item[\raw{Trying to map files from your RAM disk.
+    Please check -r option or ROOT environment variable.}]~\\
+    Most likely, you or some installation script is trying to invoke
+    \LILO\ in a way that some of the files is has to access reside on the
+    RAM disk. Normally, the \raw{ROOT} environment variable should be set
+    to the mount point of the effective root device if installing
+    \LILO\ with a different root directory. See also sections \ref{creupd}
+    and \ref{install}.
+  \item[\raw{VGA mode presetting is not supported by your kernel.}]~\\
+    Your kernel sources appear to be very old ('93 ?). \LILO\ may work on
+    your system if you remove the \craw{vga} option.
+  \item[\raw{write \meta{item}: \meta{error\_reason}}]~\\
+    The disk is probably full or mounted read-only.
+\end{description}
+
+
+\subsubsection{Warnings}
+\label{warnings}
+
+Messages labeled with ``Warning'' can be turned off with the \craw{nowarn}
+option.
+
+\begin{description}
+  \item[\raw{FIGETBSZ \meta{file\_name}: \meta{ error\_reason}}]~\\
+    The map installer is unable to determine the block size of a file system.
+    It assumes a block size of two sectors (1kB).
+  \item[\raw{Ignoring entry '\meta{variable\_name}'}]~\\
+    The command-line option corresponding to the specified variable is set.
+    Therefore, the configuration file entry is ignored.
+  \item[\raw{Setting DELAY to 20 (2 seconds)}]~\\
+    Because accidentally booting the wrong kernel or operating system may
+    be very inconvenient on systems that are not run from a local display,
+    the minimum delay is two seconds if the \craw{serial} variable is set.
+  \item[\raw{(temp) \meta{item}: \meta{error\_reason}}]~\\
+    Deleting a temporary file has failed for the specified reason.
+  \item[\raw{Warning: BIOS drive 0x\meta{number} may not be accessible}]~\\
+    Because most BIOS versions only support two floppies and two hard disks,
+    files located on additional disks may be inaccessible. This warning
+    indicates that some kernels or even the whole system may be unbootable.
+  \item[\raw{Warning: COMPACT may conflict with LINEAR on some systems}]~\\
+    Please see section \ref{othpro} for a description of this problem.
+  \item[\raw{Warning: \meta{config\_file} should be owned by root}]~\\
+    In order to prevent users from compromising system integrity, the
+    configuration file should be owned by root and write access for all other
+    users should be disabled.
+  \item[\raw{Warning: \meta{config\_file} should be readable only for root if
+    using PASSWORD}]~\\
+    Users should not be allowed to read the configuration file when using the
+    \craw{password} option, because then, it contains unencrypted passwords.
+  \item[\raw{Warning: \meta{config\_file} should be writable only for root}]~\\
+    See ``\raw{Warning: \meta{config\_file} should be owned by root}''.
+  \item[\raw{Warning: device 0x\meta{number} exceeds 1024 cylinder limit}]~\\
+    A disk or partition exceeds the 1024 cylinder limit imposed by the BIOS.
+    This may result in a fatal error in the current installation run or in
+    later installation runs. See ``\raw{geo\_comp\_addr:
+    Cylinder number is too big (\meta{number} $>$ 1023)}'' for details.
+  \item[\raw{Warning: \meta{device} is not on the first disk}]~\\
+    The specified partition is probably not on the first disk. \LILO's boot
+    sector can only be booted from the first disk unless some special boot
+    manager is used.
+  \item[\raw{WARNING: The system is unbootable !}]~\\
+    One of the last installation steps has failed. This warning is typically
+    followed by a fatal error describing the problem.
+\end{description}
+
+
+\subsection{Boot loader messages}
+
+The boot loader generates three types of messages: progress and error messages
+while it is loading, messages indicating disk access errors, and error
+messages in response to invalid command-line input. Since messages of the
+latter type are usually self-explanatory, only the two other categories
+are explained.
+
+
+\subsubsection{\LILO\ start message}
+
+When \LILO\ loads itself, it displays the word ``LILO''. Each letter is
+printed before or after performing some specific action. If \LILO\ fails
+at some point, the letters printed so far can be used to identify the
+problem. This is described in more detail in the technical overview.
+
+Note that some hex digits may be inserted after the first ``L'' if a
+transient disk problem occurs. Unless LILO stops at that point, generating
+an endless stream of error codes, such hex digits do not indicate a
+severe problem.
+
+\begin{description}
+  \item[\rm (\meta{nothing})] No part of \LILO\ has been loaded.
+    \LILO\ either isn't installed or the partition on which its boot
+    sector is located isn't active.
+  \item[\raw{L \meta{error} $\ldots$}] The first stage boot loader has been
+    loaded and started, but it can't load the second stage boot loader.
+    The two-digit error codes indicate the type of problem. (See also section
+    \ref{bioserr}.) This condition usually indicates a media failure or a
+    geometry mismatch (e.g. bad disk parameters, see section \ref{diskgeo}).
+  \item[\raw{LI}] The first stage boot loader was able to load the second
+    stage boot loader, but has failed to execute it. This can either be
+    caused by a geometry mismatch or by moving \path{/boot/boot.b} without
+    running the map installer.
+  \item[\raw{LIL}] The second stage boot loader has been started, but it
+    can't load the descriptor table from the map file. This is typically
+    caused by a media failure or by a geometry mismatch.
+  \item[\raw{LIL?}] The second stage boot loader has been loaded at an
+    incorrect address. This is typically caused by a subtle geometry
+    mismatch or by moving \path{/boot/boot.b} without running the map
+    installer.
+  \item[\raw{LIL-}] The descriptor table is corrupt. This can either be caused
+    by a geometry mismatch or by moving \path{/boot/map} without running
+    the map installer.
+  \item[\raw{LILO}] All parts of \LILO\ have been successfully loaded.
+\end{description}
+
+
+\subsubsection{Disk error codes}
+\label{bioserr}
+
+If the BIOS signals an error when \LILO\ is trying to load a boot
+image, the respective error code is displayed. The following BIOS
+error codes are known:
+
+\begin{description}
+  \item[\raw{0x00}] ``Internal error''. This code is generated by
+    the sector read routine of the \LILO\ boot loader whenever an
+    internal inconsistency is detected. This might be caused by corrupt
+    files. Try re-building the map file. Another possible cause for this
+    error are attempts to access cylinders beyond 1024 while using the
+    \craw{linear} option. See section \ref{broken} for more details and
+    for how to solve the problem.
+  \item[\raw{0x01}] ``Illegal command''. This shouldn't happen, but if it
+    does, it may indicate an attempt to access a disk which is not supported
+    by the BIOS. See also ``Warning: BIOS drive 0x\meta{number} may not be
+    accessible'' in section \ref{warnings}.
+  \item[\raw{0x02}] ``Address mark not found''. This usually indicates
+    a media problem. Try again several times.
+  \item[\raw{0x03}] ``Write-protected disk''. This should only occur on
+    write operations.
+  \item[\raw{0x04}] ``Sector not found''. This typically indicates a
+    geometry mismatch. If you're booting a raw-written disk image, verify
+    whether it was created for disks with the same geometry as the one
+    you're using. If you're booting from a SCSI disk or a large IDE disk,
+    you should check,
+    whether \LILO\ has obtained correct geometry data from the kernel or
+    whether the geometry definition corresponds
+    to the real disk geometry. (See section \ref{diskgeo}.) Removing
+    \craw{compact} may help too. So may adding \craw{lba32} or \craw{linear}.
+  \item[\raw{0x06}] ``Change line active''. This should be a transient
+    error. Try booting a second time.
+  \item[\raw{0x07}] ``Invalid initialization''. The BIOS failed to properly
+    initialize the disk controller. You should control the BIOS setup
+    parameters. A warm boot might help too.
+  \item[\raw{0x08}] ``DMA overrun''. This shouldn't happen. Try booting
+    again.
+  \item[\raw{0x09}] ``DMA attempt across 64k boundary''. This shouldn't
+    happen, but may inicate a disk geometry mis-match. Try omitting 
+    the \craw{compact} option. You may need to specify the disk geometry 
+    yourself.
+  \item[\raw{0x0C}] ``Invalid media''. This shouldn't happen and might
+    be caused by a media error. Try booting again.
+  \item[\raw{0x10}] ``CRC error''. A media error has been detected. Try
+    booting several times,
+    running the map installer a second time (to put the map file at some
+    other physical location or to write ``good data'' over
+    the bad spot), mapping out the bad sectors/tracks and, if all else
+    fails, replacing the media.
+  \item[\raw{0x11}] ``ECC correction successful''. A read error occurred,
+    but was corrected. \LILO\ does not recognize this condition and
+    aborts the load process anyway. A second load attempt should
+    succeed.
+  \item[\raw{0x20}] ``Controller error''. This shouldn't happen.
+  \item[\raw{0x40}] ``Seek failure''. This might be a media problem. Try
+    booting again.
+  \item[\raw{0x80}] ``Disk timeout''. The disk or the drive isn't ready.
+    Either the media is bad or the disk isn't spinning. If you're booting
+    from a floppy, you might not have closed the drive door. Otherwise,
+    trying to boot again might help.
+  \item[\raw{0xBB}] ``BIOS error''. This shouldn't happen. Try booting
+    again. If the problem persists, removing the \craw{compact} option or
+    adding/removing \craw{linear} or \craw{lba32} might help.
+\end{description}
+
+If the error occurred during a write operation, the error code (two hex
+digits) is prefixed with a ``W''. Although write errors don't affect the
+boot process, they might indicate a severe problem, because they usually
+imply that \LILO\ has tried to write to an invalid location.
+If spurious write errors occur on a system, it might be a good idea
+to configure \LILO\ to run read-only (see section \ref{cfgmf}).
+
+Generally, invalid geometry and attempts to use more than two disks without a
+very modern BIOS may yield misleading error codes. Please check carefully
+if \path{/sbin/lilo} doesn't emit any warnings. Then try using the
+\craw{linear} or \craw{lba32} option (see section \ref{cfgglo}).
+
+
+\subsection{Other problems}
+\label{othpro}
+
+This section contains a collection of less common problems that have been
+observed. See also section \ref{instoth} for general remarks on using
+\LILO\ with other operating systems. Some of the problems are obscure and
+so are the work-arounds.
+
+\begin{itemize}
+  \item If \LILO\ doesn't go away even if you erase its files, format your
+    Linux partition, etc., you've probably installed \LILO\ as your MBR and
+    you've forgotten to deinstall it before deleting its files. See section
+    \ref{deinst} for what you can do now.
+  \item For yet unknown reasons, \LILO\ may fail on some systems with
+    AMI BIOS if the ``Hard Disk Type 47 RAM area'' is set to ``0:300''
+    instead of ``DOS 1K''.
+  \item Some disk controller BIOSes perform disk geometry/address translations
+    that
+    are incompatible with the way the device's geometry is seen from Linux,
+    i.e. without going through the BIOS. Particularly, large IDE disks and
+    some PCI SCSI
+    controllers appear to have this problem. In such cases, either the
+    translated geometry has to be specified in a \craw{disk} section or the
+    sector address translation can be deferred by using the \craw{linear}
+    option. In a setup where floppies are not normally used for booting,
+    the \craw{linear} approach should be preferred, because this avoids
+    the risk of specifying incorrect numbers.
+  \item OS/2 is said to be bootable from a logical partition with
+    \LILO\ acting as the primary boot selector if \LILO\ is installed on
+    the MBR, the OS/2 BootManager is on an active primary partition and
+    \LILO\ boots BootManager. Putting \LILO\ on an extended partition
+    instead is said to crash the OS/2 FDISK in this scenario.
+
+    Note that booting \LILO\ from BootManager (so BootManager is the
+    primary selector) or booting OS/2 directly from a primary partition
+    (without BootManager) should generally work. See also section
+    \ref{instoth}.
+  \item Windows NT is reported to be bootable with \LILO\ when \LILO\ acts as
+    the MBR and the Windows NT boot loader is on the DOS partition. However,
+    NT's disk manager complains about LILO's MBR when trying to edit the
+    partition table.
+  \item Some PC UNIX systems (SCO and Unixware have been reported to exhibit
+    this problem) depend on their partition being active. See section
+    \ref{ptman} for how this can be accomplished.
+  \item Future Domain TMC-1680 adapters with the BIOS versions 3.4 and 3.5
+    assign BIOS device numbers in the wrong order, e.g. on a two-disk system,
+    \path{/dev/sda} becomes \raw{0x81} and \path{/dev/sdb} becomes
+    \raw{0x80}. This can be fixed with the following \craw{disk} section:\\
+    \verb"disk=/dev/sda bios=0x81 disk=/dev/sdb bios=0x80"\\
+    Note that this is only valid for a two-disk system. In three-disk
+    systems, \path{/dev/sdc} would become \raw{0x80}, etc. Also, single-disk
+    systems don't have this problem (and the ``fix'' would break them).
+  \item Some BIOSes don't properly recognize disks with an unusual partition
+    table (e.g. without any partition marked active) and refuse to boot from
+    them. This can also affect the second hard disk and the problem may
+    only occur if the system is booted in a particular way (e.g. only after a
+    cold boot).
+  \item On some systems, using \craw{linear} and \craw{compact} or 
+    \craw{lba32} and \craw{compact} together
+    leads to a boot failure. The exact circumstances under which this
+    happens are still unknown.
+\end{itemize}
+
+%%beginskip
+\end{document}
+%%endskip
diff --git a/dos/Makefile b/dos/Makefile
new file mode 100644 (file)
index 0000000..1481da1
--- /dev/null
@@ -0,0 +1,81 @@
+# -*- makefile -*-
+# Makefile for BCC compilation of 'lilo.com'
+#
+# Known to work with BCC version 0.16.15
+# Known not to work with BCC version 0.16.10
+
+# adding variables
+include ../make.vars
+
+MODEL=d
+CC = bcc -M$(MODEL)
+CPP = gcc -E
+CINCL = /usr/lib/bcc/include
+AS = as86
+LINK = $(CC) -v
+COPT = -ansi -I.. -I$(CINCL) -c -O $(CFLAGS)
+LOPT = -m >$*.map -M -d
+AOPT = -0 -a -w
+CFLAGS = -DLCF_IGNORECASE -DLCF_DSECS=3 -DLCF_PASS160
+
+.SUFFIXES:     .com .S
+
+HFILES = ../src/lilo.h ../src/bitmap.h ../src/cfg.h ../src/config.h ../src/common.h ../src/map.h ../src/temp.h ../src/version.h
+
+.c.o:
+       $(CC) $(COPT) -o $@ ../$*.c
+
+.o.com:
+       $(LINK) $(LOPT) -o $@ $^
+
+.s.o:
+       $(AS) $(AOPT) -l $*.lis -o $@ $<
+
+
+
+
+all:   check lilo.com
+
+alles: all
+       cp -ufv lilo.com lilo.map /dosC/boot
+
+check:
+       @echo $(CFLAGS)
+       @if [ -x /usr/bin/bcc -o -x /usr/local/bin/bcc ]; then echo Okay; \
+       else echo; echo "You don't seem to have the 'bcc' compiler from the 'dev86' package."; \
+               echo; exit 1; fi
+
+lilo:
+       make -e CFLAGS="$(PCONFIG)" lilo.com
+
+lilo.com:      lilo.o common.o cfg.o map.o   # cprintf.o
+
+lilo.o:                ../src/lilo.c $(HFILES)
+       $(CC) $(COPT) -o $@  ../src/$*.c
+
+cfg.o:         ../src/cfg.c $(HFILES)
+       $(CC) $(COPT) -o $@  ../src/$*.c
+
+common.o:      ../src/common.c $(HFILES)
+       $(CC) $(COPT) -o $@  ../src/$*.c
+
+cprintf.o:     ../src/cprintf.c $(HFILES)
+       $(CC) $(COPT) -o $@  ../src/$*.c
+
+map.o:         ../src/map.c $(HFILES)
+       $(CC) $(COPT) -o $@  ../src/$*.c
+
+
+install:
+       if [ -d $$DESTDIR$(DOS_DIR) -a -f lilo.com ]; then \
+         cp lilo.com $$DESTDIR$(DOS_DIR); fi
+
+tidy:
+       rm -f *.map *.lis core
+
+clean: tidy
+       rm -f *.o *.s *.img *.b *.com *.gz
+
+distclean:  clean
+       rm -f *~ *.c *.h
+
diff --git a/dos/README b/dos/README
new file mode 100644 (file)
index 0000000..fe18123
--- /dev/null
@@ -0,0 +1,30 @@
+       DOS executable 'lilo.com'
+
+Configuration file:    C:\ETC\LILO.CNF
+Sector Map file:       C:\BOOT\MAP
+
+
+1.  The default configuration file may be overridden with the speci-
+fication '-C <filename>' on the command line.  '<filename>' may be 
+specified literally as "none", for no configuration file.  The only
+keyword allowed in the configuration file is "map=", to specify the
+name of the sector map file.
+
+2.  The sector map file is 'C:\BOOT\MAP' if no other name is explicitly
+specified by "map=" in the configuration file, or '-m <mapfile>' on the
+command line.  This file must be the same file as specified in the 
+'/etc/lilo.conf' file, except that under Linux, Linux file system naming
+applies; whereas under DOS/Windows, DOS file system naming applies.
+
+3.  The sector map file MUST be placed on a filesystem that can be read/
+written under both DOS and Linux.  FAT filesystems satisfy this require-
+ment.
+
+4.  The 'LILO.COM' executable must be placed somewhere on the executable
+path within the DOS/Windows system.  Or it may be referenced by a *.BAT
+file on the executable PATH, which provides the opportunity to override
+the default configuration and sector map files with command line switches
+that will always be seen by the 'LILO.COM' executable.
+
+--John Coffman
+23-Jan-2005
diff --git a/hooks/Makefile b/hooks/Makefile
new file mode 100644 (file)
index 0000000..d8a01ff
--- /dev/null
@@ -0,0 +1,27 @@
+# -*- makefile -*-
+
+# adding variables
+include ../make.vars
+
+POSTUP   = initramfs/post-update.d
+POSTINST = kernel/postinst.d
+POSTRM   = kernel/postrm.d
+
+all:
+
+install:
+       mkdir -p $$DESTDIR$(CFG_DIR)/$(POSTUP)
+       mkdir -p $$DESTDIR$(CFG_DIR)/$(POSTINST)
+       mkdir -p $$DESTDIR$(CFG_DIR)/$(POSTRM)
+       install -m 0755  $(POSTUP)/runlilo  $$DESTDIR$(CFG_DIR)/$(POSTUP)
+       install -m 0755  $(POSTINST)/zz-runlilo  $$DESTDIR$(CFG_DIR)/$(POSTINST)
+       install -m 0755  $(POSTRM)/zz-runlilo  $$DESTDIR$(CFG_DIR)/$(POSTRM)
+
+clean:
+
+distclean:
+
+uninstall:
+       rm -f $$DESTDIR$(CFG_DIR)/$(POSTUP)/runlilo
+       rm -f $$DESTDIR$(CFG_DIR)/$(POSTINST)/zz-runlilo
+       rm -f $$DESTDIR$(CFG_DIR)/$(POSTRM)/zz-runlilo
diff --git a/hooks/initramfs/post-update.d/runlilo b/hooks/initramfs/post-update.d/runlilo
new file mode 100644 (file)
index 0000000..100cfed
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+#  runlilo - postupdate script for modern initrd management
+#
+#  Copyright 2010 Joachim Wiedorn
+#  All rights reserved.
+#
+#  Licensed under the terms contained in the file 'COPYING'
+#  in the source directory.
+#
+
+set -e
+PAR=ever
+
+# check for maintainer param
+if [ ! -z "${DPKG_MAINTSCRIPT_PACKAGE}" ]
+then PAR="${DPKG_MAINTSCRIPT_PACKAGE}"; fi
+
+case "$PAR" in
+
+  linux-image-*)
+    # lilo will be updated later by the kernel postinst hook.
+    # no need to update it now.
+    true
+    ;;
+
+  *)
+    # Run the boot loader installer
+    if [ -f /sbin/lilo ];then
+      if [ -f /etc/lilo.conf ];then
+        lilo  </dev/null  >&2
+      else
+        echo "Warning: Not updating LILO; /etc/lilo.conf not found!" >&2
+      fi
+    fi
+    ;;
+
+esac
+
+# end of file
diff --git a/hooks/kernel/postinst.d/zz-runlilo b/hooks/kernel/postinst.d/zz-runlilo
new file mode 100644 (file)
index 0000000..f7c39b1
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+#  zz-runlilo - postinst script for modern kernel management
+#
+#  Copyright 2010 Joachim Wiedorn
+#  All rights reserved.
+#
+#  Licensed under the terms contained in the file 'COPYING'
+#  in the source directory.
+#
+
+set -e
+PAR=ever
+
+# check for maintainer param
+if [ -n "${DEB_MAINT_PARAMS}" ]; then
+       PAR=none
+       if [ `echo "${DEB_MAINT_PARAMS}" | grep -v abort | grep -c configure` -eq 1 ]
+       then PAR=configure; fi
+fi
+
+# check for configure|upgrade|remove|purge
+case "$PAR" in
+
+  ever|configure)
+    # Run the boot loader installer
+    if [ -f /sbin/lilo ]; then
+      if [ -f /etc/lilo.conf ]; then
+        lilo  </dev/null  >&2
+      else
+        echo "Warning: Not updating LILO; /etc/lilo.conf not found!"  >&2
+      fi
+    fi
+    ;;
+
+esac
+
+# end of file
diff --git a/hooks/kernel/postrm.d/zz-runlilo b/hooks/kernel/postrm.d/zz-runlilo
new file mode 100644 (file)
index 0000000..671c164
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+#  zz-runlilo - postrm script for modern kernel management
+#
+#  Copyright 2010 Joachim Wiedorn
+#  All rights reserved.
+#
+#  Licensed under the terms contained in the file 'COPYING'
+#  in the source directory.
+#
+
+set -e
+PAR=ever
+
+# check for maintainer param
+if [ -n "${DEB_MAINT_PARAMS}" ]; then
+       PAR=none
+       if [ `echo "${DEB_MAINT_PARAMS}" | grep -v abort | grep -c remove` -eq 1 ]
+       then PAR=remove; fi
+fi
+
+# check for configure|upgrade|remove|purge
+case "$PAR" in
+
+  ever|remove)
+    # Run the boot loader installer
+    if [ -f /sbin/lilo ]; then
+      if [ -f /etc/lilo.conf ]; then
+        # Do not abort kernel removal in case of error
+        lilo  </dev/null  >&2  || true
+      fi
+    fi
+    ;;
+
+esac
+
+# end of file
diff --git a/images/Makefile b/images/Makefile
new file mode 100644 (file)
index 0000000..93ce46d
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- makefile -*-
+
+# adding variables
+include ../make.vars
+
+BINLILO := ../src/lilo
+BMPS8 := coffee.bmp
+BMPS4 := debian.bmp debian-de.bmp debianlilo.bmp inside.bmp onlyblue.bmp tuxlogo.bmp
+
+
+all: $(BMPS4) $(BMPS8)
+
+$(BMPS4): %.bmp: %_16c.uu
+       uudecode $<
+       @echo Y | $(BINLILO) -E $(addsuffix .dat,$(basename $<)) 1>/dev/null
+
+$(BMPS8): %.bmp: %_256c.uu
+       uudecode $<
+       @echo Y | $(BINLILO) -E $(addsuffix .dat,$(basename $<)) 1>/dev/null
+
+install: all
+       mkdir -p $$DESTDIR$(BOOT_DIR)
+       install -m 0644  $(BMPS4) $(BMPS8)  $$DESTDIR$(BOOT_DIR)
+
+clean:
+       rm -f $(BMPS4) $(BMPS8)
+
+distclean: clean
+
+uninstall:
+       (cd $$DESTDIR$(BOOT_DIR); rm -f $(BMPS4) $(BMPS8))
+
diff --git a/images/README b/images/README
new file mode 100644 (file)
index 0000000..087d20d
--- /dev/null
@@ -0,0 +1,66 @@
+README for project LILO / images
+================================
+
+Picture files for boot menu must be rl-coded bmp files.
+
+Files as distributed have been edited through 'lilo -E XXXX.bmp' to specify
+useful boot table layouts, colors, and timer positions. The companion *.dat
+files contain photo credits, where applicable, as well as the  'lilo -E ...'
+parametric information contained in the LILO-bmp headers in the actual
+picture files.
+
+Naming convention:
+  "16c"  in the name indicates 640 x 480 x 4bit with 16 colors (mode 0x12)
+  "256c" in the name indicates 640 x 480 x 8bit with 256 colors (mode 0x101)
+
+*16c* files will display on any IBM-compatible VGA display adapter.
+*256c* files require a video adapter which supports VESA bios extensions;
+  specifically, mode 0x101 -- 640 x 480 x 256 colors.
+
+If you have booted with LILO, then you may easily inquire of your video
+adapter's capabilities with:
+
+  lilo -T video
+
+The video adapter type, and the video modes supported by its BIOS, will be
+displayed; i.e., those graphic modes of interest to the LILO bitmap
+interface.
+
+Creating image for background
+-----------------------------
+
+With ImageMagick you can use the convert command as follows:
+
+for images with 16 colors:
+
+       convert -verbose "$INFILE" \
+         -resize 640x480 -density 72x72 -depth 4 -colors 16 \
+         -colorspace RGB -compress RunlengthEncoded "$OUTFILE"
+
+for images with 256 colors:
+
+       convert -verbose "$INFILE" \
+         -resize 640x480 -density 72x72 -depth 8 -colors 256 \
+         -colorspace RGB -compress RunlengthEncoded "$OUTFILE"
+
+Note: the Runlength-Encoding (RLE) will be made better by Gimp.
+
+
+Example for syntax and colors
+-----------------------------
+
+  color palette: 0 black,         3 magenta,       7 pink,
+                 8 middle grey,  10 bright grey,  13 white
+  bmp-table  = <x>,<y>;<ncol>,<nrow>,<xsep>,<spill>
+  if <ncol> = 1 then there are only one menu column
+                and <spill> will not be defined
+  bmp-colors = <fg>,<bg>,<sh>;<high-fg>,<high-bg>,<high-sh>
+  if <bg> or <high-bg> not defined, than it is transparent
+  if <sh> or <high-sh> not defined, than it is no color
+  bmp-timer  = <x>,<y>;<fg>,<bg>,<sh>
+
+Details see lilo.conf(5).
+
diff --git a/images/coffee_256c.dat b/images/coffee_256c.dat
new file mode 100644 (file)
index 0000000..d166bc1
--- /dev/null
@@ -0,0 +1,14 @@
+# Lilo boot menu background configuration  (Lilo 23)
+#
+# color palette: 0 black,         3 magenta,       7 pink,
+#                8 middle grey,  10 bright grey,  13 white
+#
+# bmp-table  = <x>,<y>;<ncol>,<nrow>,<xsep>,<spill>
+# bmp-colors = <fg>,<bg>,<sh>;<high-fg>,<high-bg>,<high-sh>
+# bmp-timer  = <x>,<y>;<fg>,<bg>,<sh>
+
+bitmap = coffee.bmp
+
+bmp-table  = 385p,100p;1,10,,
+bmp-colors = 12,,11;15,,8
+bmp-timer  = 38,2;13,1
diff --git a/images/coffee_256c.uu b/images/coffee_256c.uu
new file mode 100644 (file)
index 0000000..9389f06
--- /dev/null
@@ -0,0 +1,2516 @@
+begin-base64 644 coffee.bmp
+Qk3auQEAAAAAADYEAAAoAAAAgAIAAOABAAABAAgAAQAAAKS1AQDrCgAA6woA
+AAABAAAAAQAAAAAAAP///wD+/v4A+/v7AP39/QD8/PwAiFzgABQPHgC+pe0A
+zb/pAFQK1gANBB0A5Nj5AAwEFAD07PwAcR+UAAwEDAC8bLwAjISMALSstAD8
+9PwAgGR8AJyMmADErLwAzMDAAPz09ADEoJwAlIR0ADQ0LAA8PDQAREQ8AFRU
+TAD8/PQAHCQcACQsJAAsNCwANDw0ADxEPABETEQATFRMAFRcVABkbGQAbHRs
+AHR8dAC0vLQA9Pz0AOv07ADj7OQAkpyUANrk3ACptKwAydTMAMHMxADR3NQA
+iJSMALjEvAAHFAwAf4yEAJ2spAAEDAwARExMAExUVABUXFwAkZycAGRsbACE
+jIwAwczMAPP8/ADs9fUAKywsAMPExAAI09kAGM3TACTN1AAr1NwAKcTMACzM
+1AAz3OQANtTcAD/c5AA5xMwASNTcAEnEzABX1NsAs+rtAKra3QCBmJkAcISF
+AOL29wAI1ucAEODwABTN3AAb1uMAGb3LABzM3AAg4fAAMd3tADrp9wBV5/MA
+bOjzAI3q8QCU190AxObpAFtnaABqdXYAcXx9AMfW1wCfq6wA0dzdAAjI3QAI
+uMwAEc/lABO/1AAcxNQAJMzcACTE1AAr1OYALMzcACzE1AA01OQANMjaADzU
+5AA/3e0AV9jnAGnY4wB5o6gA4uztABzD3AAi0uwAI8zkACTE3AAszOQAKbfK
+ADzH2QA5t8kAR9TmAETH2QBMx9kAR7jJAEeruQBwxtMAebK6ALDFyAATwt0A
+E7PQABy60wAmu9UALMPcADTT7AA52vQANsvkADzT7AAwlacAOKO1AFnI2gBm
+wM8Ad7vHAIrCzACNrbIAqre5AAmlxQASjqkAFpy4ABmqxgAkxOQALMzsACzE
+5AAoq8QAKKC3ADi81QA4q8EAMYaYAEe81QBXt8kASpqqAFeqvABossEAfMnY
+AJm8wwCJoaYA0ufrAL3Q1ACUo6YAMLLSACZugABNyeUAX29zAHiKjgCgsbUA
+GHqTACzE7AAGFBgAR6rFAFe71QAxt+EAGFpvAEey1QAeqdgAEjdGABpHWABB
+mLoATYKaALO8wAAKQFoANV9zABZ2sQAFL0wACCc9ABFXkAAIGSkABAwUALzE
+zAAXJTUADTd7AN7j7AAEDBwAkJScAAkURgAEBB0ABAQUAAQEDAAMDBwADAwU
+AHR0fQBkZGwAsrK+AIyMlAD09PwA9PT0AOzs7ADk5OQA3NzcANTU1ADMzMwA
+vLy8ALS0tACsrKwApKSkAJycnACUlJQAjIyMAISEhAB8fHwAdHR0AGxsbABk
+ZGQAXFxcAFRUVABMTEwAREREADw8PAA0NDQAJCQkABkZGQAMDAwABAQEAP8C
+/wKCAgAA/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/AoICAAD/Av8CggIA
+AP8C/wKCAgAA/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/AoICAAD/Av8C
+ggIAAP8C/wKCAgAA/wL/AoICAAD/Av8CggIAAP8EpQTcAgAA/wSlBNwCAAD/
+BKUE3AIAAP8EpQTcAgAA/wSlBNwCAAD/BKUE3AIAAP8EpQTcAgAA/wSlBNwC
+AAD/BKUE3AIAAP8EpQTcAgAA/wSlBNwCAAD/BKUE3AIAAP8EpQTcAgAA/wSl
+BNwCAAD/BKUE3AIAAP8EpQTcAgAA/wSlBNwCAAD/BKUE3AIAAP8EpQTcAgAA
+/wSlBNwCAAD/BKUE3AIAAP8EpQTcAgAA/wSlBNwCAAD/BKUE3AIAAP8EpQTc
+AgAA/wSlBNwCAAD/BKUE3AIAAP8EpQTcAgAA/wSlBNwCAAD/BKUE3AIAAP8E
+pQTcAgAA/wSlBNwCAAD/BKUE3AIAAP8EpQTcAgAA/wSlBNwCAAD/BKUE3AIA
+AP8EpQTcAgAA/wSlBNwCAAD/BKUE3AIAAP8EpQTcAgAA/wSlBNwCAAD/BKUE
+3AIAAP8EpQTcAgAA/wSlBNwCAAD/BKUE3AIAAP8A/wCCAAAA/wD/AIIAAAD/
+AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIA
+AAD/AP8AggAAAP8A/wCCAAAAHQAB/xAAA/8IAAH/Af8GAAH/Af8FAAH/RgAA
+BP8AAP9qAAH/QgAB/wMAAf8DAAH/Af8JAAH/HwAB//8ADQAAAAALRUX7RUX7
++0X7+0UACfsF+gH7CfoP+Qv4AfcBHwX3AfYB9wf2BPUB9AEpB/QF8wAEK/Lz
+8wbyAAXx8vLx8gAM8QAP8PAS8BLw8fAS8BLwEvASAATwARID8AAM7/Di8O/w
+7/Dv8O/wDe8B7g7vAe4D7wHuCO8AB+7v7u/v7u8AD+4B7QHuBe0F7gHtBO4A
+A+/u7gAD7wAG8PDx8vL0BPUBKQH1A/QE8wHyASsF8gXxAANBEvEAA/AG7wfu
+Ae0B7gTtAe4E7QAD7O3tAAjsAAMT7OwABOsAD+zs8/r27vX4+Pf5+vn17gAd
+6gAHRurq7O7sLAAq6gEs4OoAAAP6AAT5+vn6B/kABzz5+Pn5+PkAB/gN9wAE
+9vf29wj2AAP19eAABPUB9AHgBPQB8wH0A/MB8gHzA/IB8QHyBPEBEgESA/AG
+7wTuBu0AA+zs7QAG7AAEE+zr7AjrAAgs6+rr6uvq6wXqAesJ6gADRkbqAARG
+ARgLRgAD6UbpAANGA+kABkbpRunpRgTpAAVG6UbpRgAI6QEYC+kABujp6Ono
+6APpCOgB5wfoAekB6AbpAApG6uvr7e7vEvHxBPAB7wHvBO4E7QTsARME6wAE
+6uvq6gRGBekF6AAE5+jn6APnAAXm5+bn5wAF5gAF5ebl5uYABOUAFObl5Czf
+9+pG8/T09ff39O3lBAMFGQIACgUFA+Tn5+QD5OQGAwEFBAMBBQkDAQUBAwMF
+AQMDBQAHAwMgAyADIAAhAwFDCgMBFA8DARQxAwFDDAMBFAQDASAJAwEUAwMB
+QwYDAUMGAwEUFQMB4zEDAAAACvr5+vr5+vn6+foF+QALPPn4+fn4+Pn4+PcA
+BPgABff3+Pf4AAn3AAb29/f29vcH9gf1AAP04OAABfQE8wTyAfEB8gPxBPAB
+7wHwA+8F7gbtAewB7QvsCOsACSzrLOvq6uvq6wAD6gHrCuoAB0bqRupGRuoA
+C0YAB+lGRulGRhgABkYB6QRGAAvpRukY6UbpRulGRgAE6QADRulGAArpAAXo
+6Ono6AAD6QvoAekH6ATpAAcY6uvr7O7vAAXwBO8D7gPtAAPs7OsAA+wD6wHq
+AesD6gRGBOkB6AHpBegE5wAI5ufn5ufm5ucF5gHlAeYG5QAS5OTn8fjt5/D2
+9fTg9fbx5wQFGwIADgQDA+fo5APkAwPkAxnjGgMASeQD4wPjA+MDQxQDAxkD
+IAMDLQPkA+QD5APkA+QD5APkA+QD5APkAxkDGQPkAy0ULQPkAy0DLQPjAy0U
+LQMD4wMg4wMtAxkDAxQADgMAKOQDGQMZA+QDGQPkA+QD5APkA+QD5APkA+QD
+5APkAwMZA+QD5AMtFC0DAwAGLQMD4wPjAwMB4wMDACfjAy0DAxkDGQMZAxkD
+GQMZAxQtAy0DLQMtAy0D5APkA+QD5APkA+QABAMAMSADA+QDGQPkA+QD5APk
+A+QD5APkA+QD5APkA+QD5APkA+QD5APkA+QD5APkA+QD5AMAAAAD+gH5A/oL
++QADPPn5AAP4AfkF+AH3A/gD9wH4A/cB+Av3B/YABfX29fX2AAP1AeAB9QT0
+A/MF8gPxARIB8QPwBe8ABu7v7u7t7gPtAATs7eztB+wAB+vs6+zs6+wACusA
+Berr6+rrAA/qAAhG6upGRuoY6gNGAeoFRgEYBkYABRhG6hjqAANGAeoDRgAL
+6UbpRulG6elG6UYABOkBRgjpAAbo6ejp6egF6QXoAAPn6OcABegB6QToBekA
+Bkbq6+zt7wTwAe8B7wXuAe0B7QTsARMG6wPqBEYB6QFGA+kB6AHpBugF5wAE
+5ufm5wXmAAbl5ebm5eYG5QAS7fb25ur29/T09vbz6wMFAgIFGQIACwED5enm
+A+QD5ANDABoDAQWBAwEUBAMBFAgDAS1dAwAAAfoB+QT6AfkB+gT5AAP6+foA
+BfkD+AE8CPgB9wT4A/cB+AT3AAP49/gACPcABPb29/cF9gAI9fb29fbg9OAD
+9ATzBPID8QESBPAE7wXuBu0M7AAF6+zr6+wAB+sACizr6+rrLOrr6usI6gAG
+GOpG6upGA+oABUbqRuoYABNGAATqRkYYBUYAD+lGRulGRulG6UbpRunpRgAK
+6QAE6Ono6ATpEugE6QAHGEbq6uzt7gAG7wAD7u3uAATtBOwD6wXqA0YAAxjp
+RgAD6QHoAekE6AfnAATm5+bnBOYABOXm5eYI5QAQ5Or09+vo9fjg9fX39ezl
+BBgCACQEAQQBBOTl6ecD5OQD5AMZAy0DAxkDLQMDGQMtAwMZAy0DA+QHAwEF
+NwMBGUgDAAwtA+MDAy0DAy0DA0MDAwEUXAMAAAEeA/oB+QT6AAf5+fr5+vn6
+AAb5AAP4+fkAA/gB+QT4AAT39/j3BPgB9wH4BfcBHwP4AfcB+Az3AfYB9wT2
+AAb19eDg9PQE8wPyBPEBEgTwBO8F7gftCuwBEwHsBOsB7AbrAAks6+rr6+rr
+6usAC+oAHkbq6kbq6kbqRkbqRuoYRupG6kbqRkbqRupGRupGGA1GAAvpRukY
+6UbpGOnpRgAH6QAI6Onp6Ojp6OgD6QXoAAPn6OcAC+gB6QHoA+kABUbqE+zu
+AATvBO4D7QPsBOsBLAHrBOoFRgAF6eno6ekABegB5wHoA+cABebn5+bnAAXm
+AeUB5gnlABDk5vD58ObxH/f19vb08egDGgIABwEFBAPk6OkAA+QBAwHkGQMB
+5AQDAeMqAwAGLRQDAwUFCQMBLQcDAS0HAwAEBQUDBQQDBQU5AwADLQMZAFoD
+AAAAA/r6+QAF+gAH+fr6+fr5+gAD+QAF+Pn5+PkAE/gAA/f49wAM+AAI9/j3
++Pf49/gG9wP2A/UD9ATzA/IE8QTwBO8H7gbtAAXs7O3s7QAD7AADMuvsAA7r
+AArq6+rr6uvr6urrBeoAEEbqRurqRkbqRupGRupGRuoFRgEYAeoERgAF6kbq
+RuoABUYBGAVGAAkYRulGRulG6UYAA+kBRgjpAAXo6eno6QAE6AHpAekE6AAE
+5+jn5wXoAecE6AHpAegD6QAFRurr7O0AA+8D7gTtAATsMuzsBOsE6gRGBekB
+6AHpBOgB5wHoBecAA+bn5wAF5gHlAeYG5QAU5OTl5OTt9vboRvb39fb19PIs
+AwQZAgAOAQIFAwPn6eUD5APkA+QZAwEFMgMABwQDAwUDAxQAFgMBBQUDAQUO
+AwEtHAMBFG4DAAAE+gAL+fr5+vr5+fr5+voAA/kADDz5+Pn5+Pn4+Pn4+Qf4
+AfkL+AAD+fj5ABH4BfcABfb29fXgAAP0A/MABPLz8vID8QESBPAD7wEwAe8D
+7gAD7e3uAAbtAewB7QTsAAUT7OsT7AAD6wHsB+sBLAPrAAbq6+vq6usJ6gEY
+A+oBRgPqAAZG6kbqRkYD6gANRupGRurqRkbqRupG6gAGRgAD6kYYAAVGAAbp
+RulG6UYG6QHoA+kABOjp6OkI6AHpA+gB5wPoAecP6AAF6err7O0ABO4E7QPs
+ARME6wTqBEYAB+lG6eno6ekAA+gABOfo5+gD5wAD5ufnAAbmAeUB5grlABHk
+6fT47enz9uD1KeAq7eUDBAAaAgAMBAQD5UboA+QD5APkGgMB4zADAAMFA+QA
+BAUiAwEUBAMB5AEFBgMBFBoDAS0SAwEFBAMBBQECDwMBGQUDASAkAwEtARQZ
+AwAACPoAA/n6+gAI+QADPPk8AAP5AfgB+Qf4AfcE+AAE+fj4+QP4BfkB+AT5
+AfgH+Qj4A/cD9gAD9fXgAAP0AAbz8/Lz8vIF8QPwBO8F7gjtAewB7QXsAAXr
+7Ovr7AAL6wAGLOss6+rrDuoADxjqRupG6hjq6kbq6kbqRgAD6gAORkbq6kbq
+RkbqRkbqRuoDRgHqBEYACelG6UbpRunpRgAG6QHoA+kABejp6OjpAAfoAAjp
+6Ojn6Ofo5wXoAecD6AAD5+jpAAToAARG6hPtA+4E7QPsA+sB6gHrBOoERgXp
+BugF5wHmAecF5gAE5ebl5gnlABPk5S/i+fTnEvf19PX19PHoBQUEABkCAAYE
+BQXl5+kD5AEDAeQYAwAHFAUFA+Tm5gAD5AAEAwUDIAQDARkIAwAFBQUDAy0A
+DQMBQwQDAAcEAwPk5OXqAAPrAAnq6yzpMeQZ4wQAAwUIAwARBQPkFOTk5ehG
+6+ss6+ss6OUABAMBBQUDAS0SAwEFCQMB4xADAAbkGePk5BkTAwEgDgMAAwUF
+AwAFFAMDASAUAwAGFAMUAwMUDgMAAAAF+vn6+vkABfoAB/n6+fn6+foABPkA
+CPr5+fj5+Pj5BfgB+QH4IPkH+AH3AfcE9gP1A/QACvPy8/Ly8fLx8RID8ATv
+Be4B7QHuBe0J7AAF6+zs6+wADesACOrr6+rr6urrDOoADEbq6kbq6kbqRurq
+RgTqARgE6gAVRurqGEZG6hjqRupGRhhGRukYRulGAAfpAAjo6ejp6Ono6QTo
+AATn6OjnA+gACOnp5+jn6OfnBOgB5wPoAecG6AAGRurr7O3uA+0D7AXrA+oD
+RgEYBOkB6AHpBegE5wAE5ufm5wXmAeUB5gjlAA3k5eTl5eQT9/bp6vb2AAP0
+AAXz9OrkBAAaAgAQAQQF5ebq5OQDA+QD5AMD5A8DABQULQMFBeVG7/Ye/v4c
++fXvRuQDFAMDAA9E7PHu7u3u7Ovt7u7xRuQACAMB5AMDAAsULQMD5Ubt8vf6
+/gAE/wAtAAD//xD79yvv6+flFAMDGQMFBeXn6u4r9vr9AP8A/wD/AP///Pfy
+7OjlAwMUAA8DABIE5ANG7+3r6kbn6Ofn6ers7kYJAwAQBQMD5u3z9/ohRfn4
+9O7o5AYDAA/k5BPx7+3t7uzs7e3w7+UABgMABeTp7+0TAAbqAATs7uLpDQMA
+Befu7OvpAAPnAAfoRurs7u/mAAwDAAAH+gAG+fr6+fn6BPkB+gT5AA36+fn4
++fj4+fj5+Pn4AAr5AfoE+QAF+vn5+voABvkABPr5+foF+QP4AAP5+PgAA/cA
+A/b39gAD9QHgA/QD8wPyA/EBEgPwA+8F7gHtAe4I7QbsAAXr6+zr7AAE6wHs
+COsAA+rq6wAR6gAWRurqRupG6upG6upG6hjq6kbqRurqGAXqAARG6kbqBkYA
+BelG6elGAAjpAAPo6ekAEugE5wXoAecD6AHnBOgAC+fo6Ubq7O3u7eztAAPs
+A+sF6gAEGOlGRgXpBugF5wjmAeUB5gXlABXk5eXk5eXk6PT57+nz9in29fT0
+7uYAAwUBBBUCAwQABgEEA+ZG5gPkAAUD5AMD5AATAwAIFC5GH/z+AP8DAAAY
+/wAQ/PXo5AMFA+Yf///+///e/f4Q//0TCgMAEAIDAyDk6O/3Iv7/AP8AAP8H
+AAP/AAX+/fvzLQADAwAG5UbiJ/v9BP8LAAAJ///++/Xr5i0ZABADAAcU6/z+
+/SH8AAT7AAX8/f38RgAFAwHjAwMACQTm7vr9/wAA/wADAAAG//5F9OnkAwMA
+BOQD5PQE/wAJ/t7+EP/+8+TkAAYDAARG/P79BiEABP7+/esMAwAGBOj7/f38
+BPsACCH9/f8d5QTkCgMAAAX6AfkG+gAD+fn6ABL5AfgH+QAF+vn5+vkABfoA
+A/n6+QAH+gH5AfoL+QT4AfcB+AP3AfYD9QHgA/QAA/Pz3wAD8gAG8fESEvDw
+BO8F7gHtAe4E7QAE7O3s7QbsAAXr7Ovr7AAM6wAHLOvq6+vq6wAO6gAIRuoY
+6kYY6kYK6gAKRupG6kbqRupG6ghGAekBRgbpAAXo6ejp6QAK6AHnBOgB5wPo
+AATp6OfoA+cB6AHnA+gADufn6Ojn6Ojn5+jp6ursA+0E7APrBOoDRgXpBegI
+5wTmAAXl5ubl5gAI5QAL5OXl5OXw+PXp8PYAA/UACPTz8ekFBAUEFQIAEAEE
+BQUEA+Xo6QPl5APkA+QDAwHkEQMABOfz/f8DAAH/BgAACf//Re/kAwPm9wAF
+AAH/BAAAAyXm5AAJAwAH5AXk6PNF/wAKAAH/BwAB/wMAAAr6FAMD5vb9/gD/
+BAAB/wwAAf8DAAAI/fjt5CADAwUKAwAN5AUt5fcAAP8AAP8A/wADAAADKOTk
+AAcDAAcZ6fb+AAD/AAQAAf8FAAAK/PLlAwMEA+X3/wcAAAT//OjkBAMAB0MD
+A+b4//8ABwAAA//76AAMAwAHGeX1AP8A/wADAAAH/wD///ED5AALAwAAA/oB
+HgT6AfkB+gP5AAT6+fn6FPkABvr5+vn6+Rr6AfkB+gb5BfgD9wT2AfUB9QP0
+AATz8/LyBPEAAxLw8AAE7wTuBu0ABuzt7O3s7QPsAATr7OvsA+sB7AjrAAQs
+6+ssFeoBRgzqARgG6gAHRupG6kbqGAADRgAG6UbpRulGBukB6AHpB+gABOfo
+6OcE6AAF5+jn6OcABOgF5wHoAegD5wHoBecADujn5ufoRurr7e3s7OvsA+sA
+A+rqGAAERgPpAegB6QToAecB6ATnAeYB5wbmAAPl5eYAB+UADuTk5eXk5Or3
++O7t9vb0A/MACPTr5AIFAgQEFgIACQQFA+XnRuXkAwAD5AQDAeQQAwAK5Ok8
+EP8AAP8A/wgAAAf//e7lFOb3AAgAAAb///PkBOQJAwAM5/BFEAD/AAD/AAD/
+EAABHQMDAeYB+BIAAA//AP8AAP8AAP/e9OnkA+MADQMAA+Ty/wAIAAAD/xDw
+AAcDAAYtFDT5//8EAAH/Af8EAAAM/wD/ABAp5wUZA+f5AwAACv//AAD/APbk
+A+QGAwAD5PT/AAcAAAT/APjmAwMADBQtFAMDFC0D5APk8QoAAAP+6wUADAMA
+AAX6AfkG+gX5AfoJ+QH6BfkABfr5+vr5AAv6AfsU+gH5BPoF+QH4AfkD+AP3
+A/YB9QH1A/QB8wHzA/ID8QTwA+8F7gTtAewB7QfsAATr7OvsCOsB7AbrAAUs
+6+vq6wAG6gHrGuoBRgTqAUYB6gVGAAQYRulGBukABOjp6OkN6APnAAPo5+gA
+BOcADujp6Ojn5+bn5+jo5+foB+cADebn6Bjq6+zt7OsT6+sAA+oABUbqRulG
+AATpBugE5wHmAecF5gHlAeYG5QAG5OXl5OXlA+QAD+fz+SsT9vby8/P19fDm
+BQADAgEEFQIACAQCBAMD6OrnA+QABgPkA+QD5BIDAATo+f//CAAB/wYAAAb/
+Ie0D5voFAAH/Af8DAAHtCwMABuj2/gAA/wQAAf8FAAH/DAAACfoDBEMD8/8A
+/wARAAH/BwAABRAkE+QZAAwDAAcZA+0QAAD/AAYAAf0B6wUDAAUgAwPm9wAD
+/wYAAf8FAAP/AAn+9uUDA+f5AP8ABgAAA//xQwAJAwHwAf8JAAAD9OQUAAwD
+AAMt7v8ABgAABf8A//zpAA0DAAAH+gAL+fr6+fr5+vr5+foABfkABvr5+vn5
++gf5D/oABPv6+vsL+gAE+/r6+wf6AAT5+vn6BfkB+AH4A/cABvb29fXg9ATz
+AfIE8QPwA+8F7gftABDs7ezs6+zr7Ovs6+zr7OvsCesABurr6uvq6wrqASwL
+6gHrCuoAA0bqRgAD6gdGAAXpRunp6AAE6QnoAATn6OfnBOgB5wHoCOcD6ATn
+AAPo5+gACucACOXl6Onq6+ztA+sF6gADRulGAATpAegB6QPoB+cF5gAE5ebl
+5gnlABTk5OXk5e/49u3x9vX09vb18+kDBBkCAAoFBQMD5eno5OQDBOQABgPk
+A+QD5AsDAAYUAwXn+/8MAAAE/wAA/wMAAARF6Ob6CQAABv7pA+MDIAQDAAUF
+5OpF/wAaAAAI/0XlAxkD7f4IAAH/BQAB/woAAf8DAAAE/e7kBQMDAeQJAwHp
+Af4JAAH8AUYDAwHkAwMAAxQpEAATAAAG/irlBeb5CAAADt7sAxkDLQMZAwMF
+5PD+CAAAA//zLgANAwEFAesKAAH6AeYNAwAACfoABPn6+foD+QH6BfkACfr5
++vn5+vn6+QAI+gH7A/oB+wT6AAb7+vv6+vsR+gAD+/r7AAr6BfkAA/j49wAD
+9gAE9fX09APzAfIB8gPxAAMS8PAABO8E7gXtAewB7QbsAArr7Ovs6+vs6+vs
+CesADSzr6izq6+vq6+rr6usABuoB6wXqAAjr6+rr6uvq6wfqAAQY6kbqBEYJ
+6QHoAekH6AAH5+jn6Ofo6AAP5wPoA+cB5g3nAA3l5ugYRuvsE+ss6+rqAAVG
+A+kF6AHnAegE5wXmAeUD5gblAATk5eXkA+UAEuTl6PYf8u739vf29fX27uUF
+BRkCAA8EAwPk6Orl5OQD5OQD5OQAEAMACS0D5vX//wAA/wAHAAH/Af8EAAAH
+/wAAEEHo+wAJAAAG/eUZAy3jBAMAAxTqJQAD/wcAAf8B/wQAAAf///4QO///
+AAYAASIB5gMDAAQT/gD/BwAADN759BLu7O3v8/chEAMAAAv/AAD//wAh7uQD
+5AALAwHpAd4JAAEdAecGAwAD5Eb9AAsAAAT/AAD/BQAACf/e6yDo+gAA/wAF
+AAH9AUYJAwAD5O7+AAkAAfABGQoDAAYtBQMU6v8JAAH4AeYNAwAAA/oADPn6
++vn6+fr5+fr5+gT5AfoD+QAJ+vn6+vn6+fr5AAX6AfsI+gH7BfoB+wn6AAr7
++vv6+/r7+vv7BPoABvv6+vv6HQb6A/kAD/j49/f29vXg9PTz89/y8gAD8QAD
+EvDwAAPvBO4G7QAE7O3s7QbsAAUT7Ovr7AAP6wAULOrr6uvq6+rq6+rq6+rq
+6+rr6usD6gAD6+rrAAjqAAtG6kbqGEZG6UbpRgAG6QAE6Ono6QXoAAbn6Ofo
+5+gK5wHmA+cABebn5ufnAAPoC+cADubn5ufm5ebn6Ubq7OzrA+oAA0ZGGAAF
+6QToAecB6ATnAeYB5wbmBuUB5APlAAPk5eUAA+QAEOfy+fTu+Pr5+Pb29/Ho
+AgQZAgAHBAMC5Ofq5gAI5AAIAwPkA+QDAy0LAwAD7/7/AAMAAf8MAAH/AwAA
+BP8d6vkJAAFFAeMFAwAG5AUD5vr/CAAAHP8A/wAA/vz69fPx8PDx8/b6IRAA
+AP1GBQMD6v0HAAAQ//8o5uUDLQUD5OTl6fFF/wYAAAX/AP3rFAALAwAD5Och
+AAkAAfoB5gQDAAQFA+T1BAAB/wUAAf8IAAAI/wD/APro6SEIAAADIUYUAAcD
+AATkA+v9CAAAA//w5AAMAwAEQwPp/wkAAfYB5A0DAAAE+gH5BfoAEfn6+fn6
++fr5+vn6+vn5+vr5AA76AAj7+vv6+/r7+gP7AAP6+/oAB/sBHQ37AfoB+wT6
+AfsD+gH7A/oAD/n5+Pn4+Pf39vb14PT08wAD8gPxA/AB7wHvBe4F7QvsARMB
+7BfrABcs6+rr6izrLOss6+ss6yzr6uvq6+vq6wAF6gFGAeoDRgAD6UZGAAfp
+AegB6QboAAXn6Ojn6AAK5wHmA+cADObn5ufm5+fm5+fo6AXnABbm5+fm5ufm
+5+bn5uXl6OlG6uzr6+rqBEYABOnp6OkD6AHnAegE5wHmAecE5gAE5ebl5gfl
+AeQD5QTkABHtH/Xz4Pr5+h/39/VG5AUCBQAYAgARBALk5kZG5OQD5APkA+QD
+A+QABQMAEBQDAxQtFAMDFAPj5xwAAP8IAAAP/wD//SH8/N7//wAA//ghAAkA
+AR8IAwAF5in/AP8ACQAABv9F9O3o5wfkAAjm50bw9v3e7QMDAAPp/P8ABwAA
+BxD15S0DFC0AAwMABuQD5Oj4/gQAAAb/AP//RUYMAwAD5kX/AAgAAAv45gMD
+BQMFBUb8/wAJAAAT///+/Bz4+/07AAD/AP7y6fz//wAGAAH9AUYKAwHrAf0I
+AAAF/0EDA0MABAMABEMDAxQEAwHqATsJAAAEKOUD5AsDAAAF+gAQ+fr6+fr5
++vn6+fr5+fr6+Qv6AAX7+vv6+gAD+wAL+vr7+vv7+vv6+/oAH/sAA/r7+wAD
++gH7BPoD+QP4A/YAB/X09PPz8vIAA/EB8AHwBO8ABO7u7e4I7QrsAAbr7Ovs
+6+wF6wHsCOsBLAXrASwO6wHqAesF6gAERupG6gRGB+kB6AHpBegABufo5+jn
+6A7nAArm5+bm5+bn5ufmB+cABObn5+YF5wAO5ufm5+bl5efoRuoT6+oERgAE
+6eno6QPoAecB6ATnAeYB5wTmAeUB5gjlAAPk5eUAA+QACOXk5Oj29+DzA/oA
+Cvn39/bv5AUCBAQXAgAGBALk5+nqC+QABQPkAwPkAAsDAAbk8f7/AP8IAAAM
+/yH27urqRu32/QAAA/8IAAAG//MZAwPkBAMB7QH9CgAABv/+9kbl5AQDAQQH
+AwAK5Obt+PHkAwPoIQgAAAP/9uQACgMADi3n9P7/AAD/AAD///blCwMB5QH8
+CQAACvfmBAMFAwUE7/8DAAH/BgAAEv/74kbp5uhG8/sAAP8A/OlF/wcAAf0B
+RgoDAewB/QgAAAP/8OQACQMABy0DAxkDLBAACQAB9gHkDQMAAAT6AAn5+vr5
++vn6+foAA/kABfr5+vr5AAr6AAz7+vv6+vv6+/r7+/oM+wFFBvsBRQ77ARwG
++wH6A/sABPr7+vsE+gAF+fn4+PcAA/YACvXg9PPz8vLx8RID8AHvATAD7gHt
+Ae4F7QAE7O3s7QPsAe0E7AHrAewE6wAD7OvsAArrAewS6wAFLOrr6usAA+oA
+BEbqRuoDRgAE6UbpRgPpAAPo6ekACugG5wAP5ufn5ufm5+bn5ufm5+bnAAXm
+AecB5gfnAATm5+bnA+YB5wXmAAjk5ufo6ers6gNGBOkF6AbnA+YAA+Xm5gAI
+5QAG5OXl5OXlA+QADubxPfX0+fv6+fn49/HoFAIAEAQEAgEBBAQDFOTm6evm
+5AMD5AAGA+QD5APkAwMB5AwDAAPnRf8ACgAAA//2RgAGAwAE5On5/gsAAf8B
+8AcDAecB+wgAAAf//wBF7uQtABEDAAfl6eQDA+ZFAAgAAAP/9eUADAMAA+X2
+/wAHAAAH/u/kAxQtFAADAwAF5AMD5fsAAwAB/wUAAfYB5gUDAAPk9/8ABgAA
+Bv8AAP7y5gUDAA0tFOfz/v8AAPr9/wD/AAUAAfwBRggDAATkA+r9BwAADP8A
+8OQDAxkDLQMDGQYDAAXp/QAA/wAGAAH1AeQNAwAABvoACfn6+vn6+vn5+gAD
++QH6AfkG+gAG+/r7+/r7A/oQ+wFFCvsABfr7+h36AAj7AR0M+wAD+vr7AAf6
+AA75+fj49/b29fX09PPy8gPxA/AB7wHvBe4H7QAD7OztAAjsAArr7BPs6+vs
+6+vsFOsABOzr6+wF6wAJ6uvq6kbqRuoYAARGBekABejp6OjpAAToAecB6Afn
+AeYD5wAF5ufn5ucAEOYABOfm5+cQ5gAJ5OXn6Onq6+pGAATpAegB6QPoAATn
+6OfnB+YJ5QAD5OXlAAXkABDl5Oz49/b3+/v6+vj39OvkFAIADQECBAIBBAUD
+5eXp6ugAA+QBAwXkAAQD5APkDgMABOTv3P8HAAAQ/wD+4OYD5AUFAwPkAwPp
++QsAATsB7gYDAAPk8P4ABgAAB/8A//9FRuQAEwMBBQQDAeYB+wgAAAP/9eUA
+AwMADxQtFAMDFC0UA+Tp+/8A/wAFAAH7AecKAwHlAfoJAAAK9eUD5AMDBeZF
+/wYAAAX/ANz25QADAwEUAwMACUMD5fEQ/wD//wAIAAEdAegKAwHoAfwIAAEQ
+Ae4PAwHnAfwJAAHgAeQNAwAAAfkD+gAJ+fr6+fn6+fn6AAP5CPoB+wX6CfsB
++gr7BvoABh76+vn5+gb5A/gB+QH4BfkBHgT6AAT7HfscB/sB+gH7BPoB+QP4
+AAr39vb14PTz8/LyA/EB8AHwA+8D7gHtAe4G7QnsAAkT7Osy6+zs6+wAA+sB
+MgXrAAPs6+wABusABhMy7OzrEwXrAeoB6wbqBEYB6QFGBOkABOjp6OkG6AHn
+AegK5wAG5ubn5+bnHuYB5QbmAA3l5Obn6Onq6xhG6UbpAAToB+cD5gHlAeYI
+5QAF5OXl5OUABOQAEOPn9Pj24Pr7Hfr5+PXv5gUVAgALBAQCAQMD5efp6esA
+BeQADQPkA+QD5APkA+QDA+QACgMB5QEfCgAAA//25gADAwECAeQFAwAD5Ov9
+AAoAAAX+7QMDQwADAwHnAfoJAAAI//zrA+QDAxkVAwHmAfsIAAAD//XlAA0D
+AAMt7t4ABQAABf8A/vHkAAUDAAYtFAMD5fkJAAH0AeUEAwADGej9AAkAABAc
+6QMDBAMtAwMFIAMF5SvcCwAB+gHnCQMAA+To/AAIAAE7Ae0MAwAHBQQD6PwA
+/wAHAAEpAeQNAwAAAAP6+vkACPoD+QAF+vr5+vkAA/oB+wP6AAT7+vv6CvsB
++gH7B/oE+QAKHvj5+Pn4+fn4+Qb4AAYf9x/4H/gH9wH4AR8D+AALHvn6+/v6
++/v6+vsABfoACPn4+Pf29vX0A/MABPLx8RID8AHvAe8D7gHtAe4E7QAE7O3s
+7QnsAAYT7Ovs7OsD7AAF6+zr7OwABesE7AAI6+sT6+vsMuwH6wXqBkYG6QXo
+AecD6AbnAAPm5+YABOcJ5gAG5ebl5ublG+YD5QAK5ujp6utG6eno6QXoA+cF
+5gHlAeYD5QHkBeUB5AHlA+QACeXkLS4S9/j29wAD+wAH+vr18ekDBAAUAgAO
+BAIEAgUD5Ofp6Szl5AMG5AAIA+TkA+QDA+QMAwADRvz/AAgAAAT/I+kZAwMB
+5AcDAAMu9f8ACQAB/gHrBgMB7AH+CAAABP/+7+QTAwAJFC0DFC0DFOb7AAgA
+AAP/8uQADgMB5gH3BQAABf8AACPoAAgDAAQF5fr/CAAACfTlAwPjAwMs3gAJ
+AAAF80QDA+QABAMACeQDFAMD5vkA/wAJAAH6AecKAwHoAfwIAAH/Ae0LAwAG
+BeQD5OdFCQAAA/XkGQAMAwAAAAP6+vkABvoABvn6+fr6+Qj6AAb7+vv6+/oH
++wAE+vv6+wX6AfkB+gb5BfgABR/3H/cfAAT3AAv29vf39vb39/b39gAF9wAO
+9vf29/b29x/4Hvr6+/sH+gAN+fj49/f29fX09PPy8gAD8QHwBO8D7gftAAPs
+7O0ACuwAAxPr7AAD6wAKE+vs6+vs6+zr7ATrAA7s7DLs7Ovs6+vs6+vq6wXq
+BUYG6QjoB+cB5gTnEeYB5QHmBeUE5gHlCOYB5QPmABHl5uXm5ebk5OXn5+nq
+6kbp6QAF6APnAeYB5wPmAeUB5gblAeQE5QbkAAYU6vYf+PYF+gAF9/PtAwMA
+FQIACwEBAgUD5Ofp6eroAATkAQMD5AAHA+TkA+QD5AADAwHkCgMABe/eAAD/
+AAYAABPc8eTjAwPkAxQtFAMD5AMU7P7/AAgAAf0B6wUDAeUB9QP/BwAB+AHm
+AwMBGRcDAeYB+wgAAAP/8eQADwMB7QgAAf4B7wkDAAXlHgAA/wAGAAAD9OUF
+AAMDAAPk7/4ACAAAEv/qFAPkAwMU5AMDFC0DA+Tt/QoAAfoB5woDAegB/AgA
+ARAB7QsDAeQDAwAF5/wAAP8ABgAB4AHkDQMAAAEeAfkD+gH5BfoAA/n6+QAG
++gAG+/r7+vv6BfsI+gb5B/gI9wn2AfUB9gT1AfYB9gb1A/YE9QAK9vX19vYf
++Pke+gP7A/oD+QH4A/YAA+D08wAD8gAG8RLw8O/vBO4B7QHuBu0ABOzt7O0O
+7AAH6+zr7BPsEwAI7AAH6xPr7Ovr7AAE6wXqBEYE6QAE6Ono6QPoAAbn6Ofo
+5+gD5wAF5ufm5+cAC+YACuXm5ebm5ebl5uUH5gAM5ebl5uXm5ebl5uXlA+YA
+EeXm5ebl5uXm5Rnl5+jpRurpAAXoA+cG5gHlAeYD5QAE5OXk5QnkABID5/T3
++Pf2Hfv7+vgq7uYDBQQWAgAMBAPk5uhGRuoDA+QDA+QBAwPkAAQD5APkAwMB
+5AcDAAgZAy3kHwAA/wcAARwB5w0DAAPk5/wACQAACUXoAwMZAwPpRQAJAAAE
+/esDIBoDAeUBHAgAAAP/8eQADwMAA35F/wAEAAAF/wD/++QAAwMBBQEFAwMB
+5QH5CQAACfTlAwUDA+Tw/gAIAAFFAegOAwHlAR8KAAAF+ucDAwUABwMB6AH8
+CAAB/wHsDwMB6AH8CQABKQHkDQMAAAAK+vr5+fr6+fn6+Qj6AAX7+vr7+gAG
++wf6BfkB+AH5BfgAA/f4HwAG9wj2BfUAA/T19AAE9QAE9PX09QP0AfUD9Ar1
+ABr29/j5Hvr6+/r5+fj49/b29fX08/Ly8fHw8APvBO4G7QAH7O3s7O3s7QAN
+7AAD6+zrAAvsAAUy6+vs7AAF6wPqBUYB6QFGBOkB6AHpB+gE5wAG5ufn5ubn
+D+YAB+Xm5uXm5eYACeUABubm5ebm5QXmABXl5ebl5uXm5ebl5uXk5efo6UZG
+6ekABOgD5wAE5ubl5gjlAATk5eTlCOQAA+73+AAD9wP6AAj59PDoAwQEBRUC
+AAgEAwPm6Ono6gPkAQMF5AAJA+QD5OQD5APkAAsDAAMU5kUACgAB8w8DAeUB
++AcAAAT/AEXoBQMB7AH9CQAB+AHlHAMB5gH7CAAAA//x5AAMAwAHBQMDGff/
+/wAGAAH+AUYEAwAH5AMgA+T2/wAIAAAJ9OUDBQMDGeL+AAgAAfoB5w0DAATk
+5O7/CQAB+gHnCgMB6AH8CAAB/wHtDwMB6AH8CQAB9QHkDQMAAAH5A/oB+QP6
+AAP5+vkABvoABPv6+/oE+wj6BvkK+AX3AfYB9wT2AAT19vX2BPUB9AT1CvQB
+8wr0ABX19PX19PT19fb3H/ke+/r6+fn49/YAA/UAA/Py8gAD8QHwAfAD7wTu
+B+0ABezt7OztAAPsAe0G7AAEE+zs6w/sAAbr7BPr6usE6gFGARgERgAF6eno
+6ekABugF5wAH5ufn5ufm5wAL5gAK5eXm5ebl5ebl5hDlAeYG5QAF5uXm5eYA
+B+UABxnl5udG6ukABOgD5wfmBOUABeTl5eTlAAjkABBG9vj49/f2+B759fIT
+5AIFFgIADwEF5Ofo6EZG5+QD5OQDAwAH5AAIA+QD5APkA+QJAwAD6f3/AAgA
+AAP96wUADgMB5AHzCQAAA0XoBAAEAwH0Af8IAAAE/vAD4xsDAeUB+wgAAAP/
+8eQACwMBBQQDAe0B3ggAAfEB5AUDAAbjAwP1//8HAAH0AeUEAwADLfD+AAgA
+AfcB5QsDAeQDAwAD6P3/AAgAAAT66AMFBwMAAwXo/AAIAAEQAe0PAwHnAfwJ
+AAHgAeQNAwAAAAf6+fn6+fr5AAj6AAP7+voABPsI+gb5BvgABff4+PcfAAT3
+AfYB9wb2AAT19vX2B/UG9AAE8/Tz9BLzBvQAB/X19vf4+voAA/kABx/39vX0
+9PMAA/IACxLw8O/v7u/u7u3uAAbtAAbs7e3s7e0E7AHtCuwAA+3s7QAK7AXr
+A+oABEbqRkYH6QToAATn6OfoA+cB5gHnDuYD5QAG5ubl5uXmFuUB5gblAAfm
+5eXm5eXmAAPlAArk5eXn5+lG6ejoA+cB5gHnA+YE5QHkA+UABOTl5OUF5AAS
+LRnl8vj4H/f29ff59vLv5wMFFgIACQQD5OTm6OnqRgAE5AEDBOQACAPkA+QD
+5APkDgMB7AH/CQAABfrn5APkAAoDAAUtBQPy/wAIAAADRefkAAMDAeQB+gkA
+AAX86QMDBQAaAwHmAfsIAAAD//HkAAwDAeQDAwFGAfwDAAH/BAAB+AHmCAMB
+9gH/CAAACfTlAwUDA+Tw/gAIAAEoAeQPAwHlAfoJAAH6AecJAwAD5Oj8AAgA
+Af8B7Q8DAegB/AkAASkB5A0DAAAB+QP6AAP5+vkAB/oF+wb6AAT5+vn6BfkF
++AH3A/gF9wj2AAT19vX2B/UB9AH1BfQAA/P09AAI8wHyCfMBKwXzAB308yrz
+9PTz9PUf+fn6+fj39/b19PTz8vIS8PDv7wAE7gAD7e7uAAntAAXs7e3s7QAW
+7AXrBOoABRhGRulGAAXpBegAA+fn6AAF5wPmAecK5gAD5eblAAPmD+UABOTl
+5eQR5QAD5uXmAAblAAjk5Obm6EZG6QbnAAXm5uXm5gAE5QAD5OXlAArkABPs
+9/j39/b29Pf18/Dq5QIDAgMEABQCAAkD5ObpRkbq5eQAAwMB5AEDCeQABwPk
+A+QDA+QACAMABeTxAAD/AAcAAAT05AMtDQMAA+Tx/wAIAAH6AeUEAwHnAfwJ
+AAH4AeYdAwHlAUUIAAAD//HkAAsDAeQBBQMDAecBJQQAAf8DAAH8AekHAwAD
+5PX/AAgAAAn05QMFAwPk7/4ACAAAA/bk5AALAwHjAwMB9QkAAAX65wMDBQAH
+AwHoAfwIAAH/AewPAwHoAfwJAAH1AeQNAwAAAAP5+foAA/kACfr6+/r6+/r7
++wAH+gAF+fr6+foABfkG+AH3AfgH9wAD9vf3AAX2AAT19vX2BvUB9AH1BfQB
+8wH0B/MACvLz8vPz8vPz8vMJ8gErA/IF8wAX9PP09fb4+fn49/f29fTz8/Lx
+EvDw7+8ABO4B7QHuCu0ACOzt7Ozt7eztBOwABO3s7e0I7AETAewE6wAE6upG
+6gRGBekE6AAL5+jo5+fm5+bn5ucACeYE5QAD5uXmAAvlAeQI5QHkA+UAB+Tl
+5eTl5eQAEuUAC+RE5eboRuno6OfnAAXmB+UAA+Tk5QAH5AAIFEbg9/j49vYD
+9QAK8/Ls5gUDBAECBBECABQEBAPk5eno6Orm5OQD5OQD5APkAwPkAAgD5APk
+A+QD5AcDAAXkAwPl8wAIAAAE/wDv5BADAfIB/wgAAfoB5QMDAAMF6f4ACQAA
+BPPkBCAbAwHmAfsIAAAD//HkABADAATl9QD/BgAAA97tGQADAwEUAwMB9gH/
+CAAABPTlAwUDAwAD6v3/AAcAAfgB5QkDAAoULQMgAwMg8f7/BwAB+gHnCgMB
+5wH7CAAB/wHtDwMB5wH8CQAB4AHkDQMAAAAE+vn6+QX6AAb7+vr7+vsI+gH5
+AfoG+Qj4AfcB+Af3AAz29/b39vb19vb19fYG9QH0AfUF9AHzAfQD8wHyBfMA
+BfLz8/LzAAXyAfEL8gATK/LzK/Ly8/P09vf4+fgf9/b19AAD8gAD8fDwAAPv
+Be4N7QAI7O3t7O3s7ewF7QHsAe0E7AAD6+zsAAPrBOoERgXpBugF5wAE5ufm
+5wjmAeUF5gblAATk5eXkBuUACeTk5eXk5eTl5AAD5QAJ5OXl5OXl5OXkAAvl
+AAPk5eUABOQABeXm6OnpAATnBeYD5QHkA+UH5AAIGQNE8vf4H/cD9gAJ9fPz
+4ujlAwUEABMCAAoBAgUD5ebp6UbpBOQABAPk5AME5AAIA+TkA+TkA+QDAwHk
+CAMB5QH2BQAABv8AAP8Q6wMDAeMNAwHxAf4IAAH7AeYDAwADAuz/AAgAAAb/
+7y3jAxQaAwHlAfsIAAAD//HkABADAeQB8ggAAAf/8gMDQwMtAAMDAfYB/wgA
+AfQB5QMDAAQFA+j9CAAB+wHmEAMB7gH+CAAB+gHoCQMAAwXn+wAIAAE7Ae0P
+AwHoAfwJAAEpAeQNAwAAAfkG+gH7AfoD+wH6AfsE+gAG+fr6+fr6BfkI+AAD
+9/j4AAn3B/YB9QH2BfUABPT19PUE9AHzAfQI8wAE8vPy8wbyAATx8vHyA/EB
+8gHxDvID8wEpAfYD+AAL9/b19PPy8fES8PAAA+8F7gAG7e7t7u3uE+0B7AHt
+BewE6wPqA0YF6QboCecI5gAD5ebmABHlAATk5eXkA+UAA+Tl5AAD5QAN5OTl
+5eTl5eTl5eTl5AAM5QAN5OXlGeTk5ufoRujn5wAF5gblAATk5eTlB+QABuv4
+9/j29gP1AAf09PHr5gMEABQCABQBAQIF5ObpRkbq5OQD5APkA+TkAwXkAAcD
+5OQD5APkAAsDAeYB+AkAAf0B6BEDAe0B/QgAAAf65QMFAwPvAAkAAAP/7BkA
+HQMB5gH7CAAAA//x5AAQAwAEGfD//wcAAAT35AMZBQMAA/UA/wAHAAAJ9OUD
+BQMFA+b7AAcAAAT//ekFDwMB7AHeCAAB+gHnCAMABOQD6EUIAAAD/+0FAA4D
+AecB/AkAAfUBGQ0DAAAE+gH7D/oAA/n6+gAF+QAD+Pj5AAX4AAb3+Pj3H/gG
+9wAD9vb3AAX2A/UB9gb1BfQABPP08/QE8wAF8vPz8vMACfIAA/Hy8QAG8grx
+AAPy8SsAA/IAE/Pz9fcf9/f19fTz8/LxEvDv8O8AB+4Y7QAL7O3sE+vs6+vq
+6hgAA0YABulG6eno6QXoAecB6AXnCOYAB+Xm5ebl5eYACeUB5AXlAAbk5eTk
+5eUD5AHlAeUD5AAS5eXk5OXk5OXl5OXk5eTl5OXkB+UADuTl5OUZ5OTm5ujp
+6OfnBOYF5QAD5OXlAAfkABQF6PX3+Pf28/T19PTy7OjkBAUBARQCACAEGeXo
+Rujq5eQDA+TkA+TkA+TkA+TkA+QD5OQD5AMD5AkDAegB+gkAAAj85wMDBQMD
+FAQDARQGAwHsAf0IAAAH+uYDA+Pk8QAGAAAF/wAA3uoAHgMB5QFFCAAAA//x
+5AAQAwAD5O3+AAgAAfoB5gcDAfYB/wgAAAn05QMFAwMZRPUACAAABP/v5AUO
+AwHqAf0IAAAF+ucDAwUABwMB6AFFCAAAA//tBAAOAwHoAfwJAAAD4OQgAAwD
+AAAQ+gAF+fr6+foABvkB+AH5CfgABff49/f4AAf3BPYB9QP2A/UB9gP1AfQB
+9Qb0B/MABPLz8vMG8gPxAAPy8fIAFPEF8gATK/X3+Pf29fTz8vLx8fDv7zDv
+7wAI7gAG7e3u7e3uCO0B7gPtAewB7QPsAAQy7OvrA+oDRgHpAUYE6QboBOcB
+5gHnCOYB5QHmDeUAC+Tl5eTl5OTl5OTlAATkAeUD5AAD5eTlAAPkAATl5OTl
+BOQABOXk5eQF5QHkA+UABOTl5OUF5AAF5ufp6ecABOYF5QHkAeUI5AAHA+Xx
++B/49QAF9AAM8/BG5gUCAgEBAgIBEAIACAQD5ObpRurpBeQAEgPk5APk5APk
+5APkA+QD5AMD5AgDAAUFAwNGRQAIAAAD//vmAAUDAAktAwPjAy0DA+MAAwMB
+7AH9CAABJAHlAwMB5AHzCQAB/QHoHgMB5gEcCAAAA//x5AARAwHrAd4IAAH8
+AekHAwH2CQAABPTlAwUEAwHuARAIAAH4AeYPAwFGASEIAAAE+ucDBQgDAegB
+RQgAAf8B7Q8DAegB/AkAAAMp5OMADAMAAAAK+vr7+vr5+vn6+QT6AAn5+vr5
++vn6+foABfkD+AH5BfgABPf49/gF9wAF9vf39vcABPYABPX29fYH9QH0AfUD
+9AAD8/P0AAjzAAXy8vPy8wAF8gAF8fLx8fIACfEB8AnxABPwEvHyK/LyK/T2
+H/f19fQq8vHxAAPwA+8ABO7v7u8F7gAM7e7u7e7t7e7t7u3uBu0D7AETA+sB
+6gHqA0YB6QFGA+kG6AfnB+YB5QHmB+UB5ATlAAvk5eTl5OXk5eXk5QAD5AHl
+BOQB5QPkAA3l5OTl5OTl5OTl5OTlAAPkAAXl5OTl5AAG5QAE5OXk5QTkAAbl
+5ebp6OcE5gjlBeQACQMD6/f2+PX08wAD9AAI3/FG5QMCAQUQAgAoBAIBAgQC
+5ejpRunq5OQD5OQD5OQD5OQD5OQD5OQD5OQD5OQD5AMD5AYDAAME6/wACQAA
+BfnkAwTkAA0DAAMg7P0ACAAAB/vlBQMF5fQABgAABf8AAP3nABgDAAMFBSAA
+AwMB5QH7CAAAA//x5AARAwHqAf4IAAAD/UbkAAYDAfUB/wgAAfQB5QYDAegB
+RQgAAAf+8uQtGQMFAAYDAAfkA+MD6fz/AAcAAfoB6AoDAegBRQgAAf8B7Q8D
+AecB/AkAAfUB5A0DAAAE+gH5AfoD+Qf6AAT5+vn6B/kB+AH5BvgAB/f49/f4
+9/gAA/cAB/b39/b39vcABPYJ9QH0AfUH9AfzAfIB8wjyAAXx8vHx8gAM8QXw
+AAPx8fAABvEADvLx8Sv09vf29fTz8/LxBPAD7wTuAe8K7gAG7e3u7e3uA+0E
+7APrBOoAB0ZGGOnp6OkABegF5wjmAeUB5gjlAeQB5QTkAAfl5OXk5eTlAAPk
+AAfl5OXk5eTlAATkACPl5OTl5Bnk5Bnk5Bnk5eTk5eTk5eTl5eTk5eTl5OXk
+5eTk5QAD5AAF5ebo6ecABOYD5QHkAeUI5AAUGef19vj28/P09PP0K+3n5AEE
+AQQPAgAkBAICBAQD5OXm6Ojq5eQD5OQD5OQD5OQD5OQD5OQD5APk5APkAwMB
+5AYDAAQFA+tFBgAABP8A//USAwHsAd4IAAAH+uXkBQPmHwAGAAAH/wAA/egD
+LgAY5AAGAwUDA+b7CAAAA//x5AARAwAD6t7/AAcAAd4B7AcDAfYB/wgAAfQB
+5QQDAAQCA+XzBAAAD///AP///e7kAwMtAwMtFAAGAwAF6fwAAP8ABQAAA/rn
+GQAIAwADGehFAAgAAf8B7A8DAegB/AkAASkB5A0DAAAABPr6+foE+QAI+vn6
++vn6+vkE+gH5AfoG+QAD+Pn5AAb4AAT3+Pf4BvcB9gH3BvYB9QH2B/UB9AH1
+BPQB8wH0B/MABfLz8/LzAAXyAAbx8vHy8fIG8QAF8PDx8PEAA/AB8QnwABMS
+8fDx8fLx8vIq9ij29fTz8vISAATwA+8BMAHvDu4B7QHuBO0ACezsE+zr6uvq
+6gAERgXpA+gF5wHmAecE5gAF5ebm5eYABuUABuTl5OTl5AXlAATk5eTlA+QA
+EOXk5OXk5OXk5OXk5eTk5eQJ5QAI5OTl5OUZ5OUD5AAF5eTl5OUAA+QB5QTk
+AAgZ5OXm6Onn5gXlAATk5eTlB+QABPH3H/cD9APzAAny7+nlBAEEAQQADwIA
+HQQBBAUEA+Tm6Onq6OQD5OQD5OQD5OQD5OQD5OQDAAPkAAYD5OQDA+QIAwAE
+5APq/AgAAAP/9QQAEQMB7AH9CAAB+gHmAwMB5gH4CQAB/gH2GvIABu3kBAPl
+RQgAAAMQ8i0AEQMB6QH9CAAB/gHvBwMB9gH/CAAAC/TlAwUDA+QFA+j9AAUA
+Af8DAAAF/RLmAxkAAwMBIAMDAAUgAwNG/AAIAAH6AecKAwHoAUUIAAAD/+0E
+AA4DAegB/AkAAeABGQ0DAAAK+Qf6AAb5+vn6+foE+QAF+Pn4+PkABPgABPf4
+9/gE9wAG9vf29/b3A/YB9QH2BPUABvT19PX09Qj0A/MABvLz8vPy8wXyAfEE
+8gPxAfID8QHwA/EABPDx8PEN8AESA/AF8QAL8vT29vX09PLy8RIAA/AB7wHw
+Bu8B7gHvB+4AB+3u7e7t7O0AA+wD6wPqA0YF6QAE6Ojn6ATnAeYB5wfmAeUB
+5gPlAArk5eXk5eTl5eTlBuQAFOXk5OXk5eTl5OXk5eTk5eTl5OTlDOQB5QPk
+ABDl5OTlGeXk5OXl5Bnl5OTlBuQABuXm6Ojm5gflBOQABxnkA+v39vgAA/QE
+8wAJ8OrmAwQCBAIEABECACIEBQPk5unn6UbkA+QD5OQD5OQD5OQD5OQD5OQD
+5APkA+TkBAMB5AYDAAMF6yEABgAAB/8AO/IDAwUADwMB7QH9CAAB+wHlAwMB
+5gH4CgAABP/+//4X/wAG9uUDA+b7CAAAA//15QARAwHpASEIAAAD/yvlAAUD
+AAMt9f8ACAAB9AHlCAMABfD9AAD/AAUAAAv//ibu6OXkAwMEIAADAwADIOn8
+AAgAAfoB5woDAegBRQgAARAB7Q8DAecB/AkAAfUB5A0DAAAD+QAI+Pn5+vn5
++vkJ+gr5AAP4+PkABfgB9wH4BfcB9gH3BPYB9QP2CPUF9AHzAfQH8wHyA/MI
+8gHxA/IH8QAI8PHw8fDx8PEL8AHvAe8G8ATxAAjz9Pb19fTz8gPxBPAJ7wju
+A+0E7AHrAesD6gAERhhGRgTpBOgF5wbmCuUAB+Tk5eTk5eQABeUD5AHlC+QB
+5QPkAA7l5OTl5OXk5eTl5OXk5QPkAAnl5OXk5OXk5OUAA+QACOXl5OXk5Bnl
+BeQABOXn6ecD5gAG5eXk5eTlBOQABgPn9vX49QXzAAry8ezoAwIEAgIEEAIA
+HwEEBQMD5ejq6OvkA+QD5APk5APk5APk5APk5APk5AMAA+QABQPkAwPkAAkD
+AesB/QgAAAUQ9AMDLQAPAwHsAf0IAAH6AeYDAwHmAfgJAAH/AwAB/xYAAAf/
+9uUDA+X7AAgAAAT/9uTkDwMAAyDp/AAIAAADEPTkAAYDAfYB/wgAAfQB5QUD
+AAbkAwPm9f8HAAAK/wAA3vv18evq6gNGAAcYRuwj/wD/AAUAAfoB6AoDAegB
+RQgAAf8B7Q8DAegB/AkAAAMp5OQADAMAAAH6CfkF+gAF+fr5+vkAA/oF+QH4
+A/kD+AAE9/j3+AT3AfYD9wH2AfcE9gf1B/QABfP08/T0AAPzAAPy8/MACfIA
+A/Hx8gAH8QHwBPEABPDx8PED8AHxB/AB7wTwAe8F8AESBPEB8wP1AAb08/Py
+8fEG8AjvAAPu7u8AA+4D7QHsAewE6wHqAeoERgPpBOgF5wXmAATl5uXmBOUA
+DOTl5OXk5eXk5eXk5QXkAA3l5OXk5eTl5OXk5eTlABXkAeUF5AAF5eTl5eQA
+A+UAEuTk5eTl5OXk5OUZ5OPl5ufp5wflBOQAAwPl8AAD9wAK8/Tz8vPz8u7q
+5RECAwEADwICBAMFA+Xp6+fq6APkAwAD5AEDA+QAEQPkA+TkA+TkA+TkA+QD
+5APkAAMDAeQHAwHqAfwIAAAW/+AgAxQD4wMZAwMULRQDAxQtFAPs/QgAAfsB
+5QMDAeYB+AoAAf8PAAH/CQAAB//75QPj5vsACAAAA//25QARAwAE6f3//wYA
+AAP/9OQABgMB9QkAAfQB5QkDAAnm9f4AAP8AAP8ACAAACf/e/f793t79/wAI
+AAH6AecKAwHoAUUIAAH/Ae0PAwHnAfwJAAHgAeQNAwAABPkAB/j5+fr5+vkA
+CvoD+QAJ+vn5+Pn5+Pj5AAX4AfcB+AP3AfYB9wX2AAX19vX19gAE9Qb0AAXz
+8/Tz9AAG8wTyAfMD8gAF8fLx8fIACfEABvDx8fDw8QPwAfEI8AAG7/Dw7/Dv
+CPAAERLw8fHy9Pb29fTz8vLxEvESAATwAATv8O/wBO8D7gPtBOwB6wHrA+oD
+RgPpAegB6QPoBOcABebn5ublAAPmBeUABeTl5OXlAATkAAjl5OXk5OXk5RXk
+AeUE5AAR5eTl5OXk5eTl5OTl5eTl5OUAA+QB5QPkAAfl5OTl5OTlAATkAAcZ
+5OXn6enmAAPlABnk5eTk5eTkA+r39Pj09PPz8ivx7+tGAwQEAA8CAQEBAQQC
+ACcEA+TnRkbpRuQDA+QD5APkA+QD5APk5APk5APk5APk5APkAwPkA+QABQMA
+BQUDA+tFAAgAAf4B9BIDAewB/QgAAfoB5QMDAeYB+A8AAf8DAAH/EQAABkXm
+BAPl+wgAAAP/+OYAEQMAA+r+/wAIAAH2AeQGAwH2Af8IAAAE9OUDBQYDAAXk
+A+f0/QAGAAH/Af8WAAH6AecKAwAD6EX/AAcAAAP+7QUADgMB6AH8CQAB9QEZ
+DQMAAAr5BPoB+QX6AAP5+voACfkE+AH3AfgH9wP2AAX19vb19gAF9QH0AfUH
+9AAM8/Tz8/Tz8/Lz8vPzBfIABPHy8fIH8QAF8PHw8fAAA/EAA/Dx8QAM8AAE
+7/Dv8APvAfAD7wAO8PDx8PDx8Sr29fX08/MD8gAH8fHw8PHw8AAF7wTuBO0B
+7AETA+sB6gHqA0YE6QAE6Ofo6APnAeYB5wbmBuUABOTl5OUD5AAH5eTl5OXk
+5QAs5AHlA+QB5QTkAAjl5OXk5OXk5QTkAAct5ETl5+noAATlABXk5OVE5OTm
+9PT49fLz3yvz8vHs6uYAAwQPAgEBAwIAJQQCA+Tn6UYz7OXkA+QD5APkAwPk
+A+QD5APk5APk5APk5APkA+QACwMAAwXr/AAIAAH/ASkSAwHsAf0IAAH7AeUD
+AwHmAfYbAAH/CQAABkXmBQPm+wkAAfoB5hADAAMF6t4ACAAAA//35QAGAwH2
+Af8IAAH0AeULAwAE5RP7/gP/BAAB/w0AAf8GAAH6AegKAwHoAUUIAAH/Ae4E
+AwFDBAMBQwUDAegB/AkAASkB5A0DAAAK+QH6AfkF+gH5A/oAA/n5+gAD+QAE
++Pn4+QP4AAX3+Pf4+AAF9wb2AfUB9gT1AAT09fT1BfQABfP08/P0AAfzAfIB
+8wbyAfEB8gvxAAXw8fDw8QAE8AHxB/AABe/w7/DwAAPvAAbw7+/w7/AD7wAH
+8PDx8BLy9AAD9QAE8/Py8gTxAfABEgPwBO8B7gHuBO0D7AHrAesD6gFGAUYD
+6QXoA+cB5gHnBuYB5QHmBOUACOTl5OXk5eTlB+QB5SfkAA3l5OXk5OXk5eTl
+5OXlAAPkAAfl5OTl5OTlAATkAAcZ5ebpRubmAATlBOQABPD19/YF8wAI8vHt
+E+cDAgQTAgArBAQFA+foLEYT5gMD5APkA+QD5OQD5APkA+QD5OQD5OQD5OQD
+5APkA+QD5AAHAwHqAfwIAAEQAfIRAwADBez9AAgAAAck5RkDA+UqAAgAABb/
+AP3e/d793v3e/d793v3e/d79/v//BwAABkXmAwPl+wkAAfsB5xADAAMF7P4A
+CQAB9gHlBgMB9QH/CAAB9AHlCQMACeQDA+To7/n9/wAZAAH6AecKAwHoAUUJ
+AAHwAeQOAwHnAfwJAAHgAeQNAwAAAR4D+QH4A/kACPr5+fr5+vr5A/oB+QP6
+B/kF+AH3AfgF9wAD9vb3AAf2AfUB9gX1AfQB9Qj0B/MABPLz8vMG8gAD8fHy
+AAXxAA0S8fDw8fDw8fDw8fDxAArwAAPv8O8AA/AB7wHwBe8ABvDv8O/w8APx
+AA3z9PX19PPy8/Ly8fLxAATwA+8D7gHtAe0D7APrAAXq6kZGGAAD6QPoBecG
+5gflAeQB5TnkAeUK5AAE5eTk5QPkAeUH5AAE5udG6QTlAAnk5eQZ6fXz+PIA
+A/MD8gAH7+zqAwMFBAASAgASBAQFA+Xo6UbrRgPkAwPkA+TkAwMABOQD5AMD
+5AAKA+TkA+TkA+QD5A0DAekB+ggAAAP/KRQAEQMB7AH9CAAAB/vlQwMD5PMA
+CQAAA97v7AAO7QAE7PL+/wcAAAZF5gMD5vsJAAFFAegQAwAD5O4QAAgAAAP/
+KOQABgMB9gH/CAAB9AHlDAMACOQD5Oft4PohBP8TAAH6AecKAwHoAUUIAAAT
+/xLkAxkDAxkDLQMDGQMtAwPo/AAJAAH1AeQNAwAAA/kB+AX5BfoABvn6+fr5
++gb5AfgB+Qb4AfcB+AT3AfYE9wX2B/UK9AvzAATy8/LzBvIB8QHyBvEABPDx
+8BID8AHxCvAAA+/w7wAD8AHvAfAL7wAD8PDvAAPwAAjx8ir29fT08wPyA/ED
+8APvAe4B7gPtAewB7APrAATq6kZGBOkE6ATnBOYB5QHmBOUABeTl5eTlADXk
+AATl5OTlA+QAB+Xk5eTl5OUABOQB5QPkABjl5OTl5Rnk5APk5unq6OXl5OXk
+5Ofy8fgD8wAJ8ivy8fDs6uQFAA4CADMEAQIEAQEEAQQF5ejo6Ubr5OQD5APk
+A+QD5APkA+QD5APkA+QD5OQD5OQD5APkA+QDA+QABwMB5wH5CAAB/wH1EgMB
+RgFFCAAAA/rlGQADAwHwCQAABEXkAxkOAwHpAfwHAAAH/0XmAwPlHAAJAAH9
+AeoQAwAD5PH/AAgAAAP/8+QABgMB9gH/CAAABPTlAwUQAwAR5enr7vIq+Pgm
++Pn4+ODyHxAACAAABEXp5AQDAwEUBAMB6AFFCAAB/wHwDwMB6AH8CQABKQHk
+DQMAAAv5AfoB+Qn6BfkI+Ab3AfYB9wb2AAP19vYACPUK9AAD8/P0AAfzAAPy
+8/MAB/II8QAD8PDxAAvwAe8G8AAF7/Dv8PAADO8E8AAL8fHz9vb09PPz8vIA
+A/EABPDw7+8D7gPtAewB7APrAeoDRgPpBOgE5wTmAeUB5gPlAAbk5eUu5OU5
+5AAEGeXk5QfkAAPl5OUABOQAB+Xk5OXk5OUABOQADubn6urm5eTk5eTu8vX3
+A/IACPPz8vDt7OcDDwIAEwQBAgQBAwIEAwPn6Onp7OUDA+QABAMAGuQD5OQD
+5OQD5APkA+TkA+TkA+TkA+QD5APkCAMAAwXl9gAHAAAI/wD45AUDBOQMAwAD
+IOn8AAgAAAj75QMFAwPs/wgAAUUB5RADAUYB/AgAAAZF5gMD5vsJAAAU/u0D
+Ay0UAwMULRQDAxQtFAMD5fQJAAAD//PkAAYDAfUB/wgAAfQB5RQDAAYF5OTl
+5ucD5gAI5+bl5Ov9AP8GAAH9AUYDAwAD4wMtAAMDAAPj50UACAAAA//x5AAO
+AwHnAfwJAAHgAeQNAwAACvkABvr5+vn6+QX6BPkAA/j4+QAG+AH3AfgJ9wX2
+AAT19vX2BPUAB/T19PT19PUAA/QAA/P09AAD8wH0BvMABPLz8vMF8gHxAfIF
+8QAGEvHx8PDxBPAABO/w8O8D8AAL7/Dw7+/w7/Dv7/AABu8B7gfvA/AABvHz
+9PX09APzAAPy8fEAA/AABu/v7u7t7QPsAAbr6+rqRkYF6QHoAegE5wbmBeUA
+A+Tl5QAY5AAFFOQD5AMABOQABS3k5BktAAvkAeUJ5AHlA+QABeXk5eTlAAPk
+AA7l5OXk5eXk5eXk5eTk5QPkAAUu50bsRgAD5QAG5Ony8fnzBvIABe7s6uQE
+AA8CAAQEAQIEAwEACAMD5Ubn5uroBQMAKOQD5APkAwPkAwPkA+QD5APk5APk
+5APkA+QD5AMD5AMD5AMDBQTk5PMJAAAFRebkBeQADQMAA+PpRQAIAAAI+uYD
+QwMDRv4IAAEiAeYPAwADFOkhAAcAAAf/+eYDA+b7AAoAAfIB5A8DAeUB9wgA
+AAT///LkBgMB9gH/CAAB9AHlFAMABwQDAwUDA+MABAMABC0D6v0IAAAD/UYF
+AAkDAecBHAkAAfQB5A4DAegB/AkAAAX15AMDFAAEAwEUBQMAAAn5AAT6+fr5
+BPoAA/n6+gAH+Qb4AAT3+Pf4B/cAA/b29wAE9gAE9fb19gX1AfQB9QT0AfUD
+9AAE8/Tz9AbzAfIE8wjyAAnx8fLx8vHxEhIAA/ABQQfwAArv8PDv8PDv8O/w
+Eu8ACvDwEvL09fX08/MD8gAL8fDw7+/u7u3t7OwAA+sABOrqRkYD6QPoA+cG
+5gjlEeQAAy3kAwAE5AEtCuQABRTkLeTjAAPkAQMO5AAR5eTlGeXk5eTl5OXk
+5eTl5OUACeQB5QPkABDl5RnmRuvs5+Xk5/Dv9/QrBfIABu/s7OYFBQ8CABIE
+AQIEAQQEBeXp50bq6uQUA+QHAwAb5AMD5APkAwPkA+TkA+TkA+TkA+QD5APk
+AwPkAAYDAeQB8AkAAf0B5w8DAAQFA0ZFCAAACvvl5AMEA+f9AP8GAAH9AecP
+AwADLev9AAgAAAb25AMD5fsJAAAD//XlAA8DAUYBRQkAAAb+7uQDA+MDAwH1
+CQAB9AHlDQMAC0MDAy0DBQPkAwPkAAkDAAXq/QAA/wAFAAADIUYUAAkDAekB
+/AkAAfUB5Q4DAecB/AkAAAwp5AMDLQPjAwMtA+MDAwAAA/kB+Af5AAf6+vn6
++vn6AAb5DPgAA/f3+AAE9wAD9vf3AAb2AfUB9gb1AAb09fT19PUF9AAG8/Tz
+9PP0CvMAA/Ly8wAE8gHxAfIH8QESAfEK8AAF7/Dv7/AABO8B8AHwBe8AA+7v
+7gAH7wTwABnyKvX19PPz8vHxEvDv7+7u7e3s7Ovr6upGAATpA+gF5wPmAeUB
+5gXlAeQB5QvkARQD5AADLeQUAAfkARQE5AADA+QtAAXkAAXj5BnkLQAU5AAN
+5eTk5eTl5OXk5eTl5AAK5QHkBuUACunr7uvlGe3u9fYG8gAH7+3t6QMDBAAP
+AgAPBAECBAECAQPo6elGE+UtAAkDAAbkAwPkAwMD5AARA+QD5OQD5OQD5APk
+A+QDA+QACQMB6wH+CAAB/gHrEQMB6QEiCAAB+gHlBAMAA+T7/wADAAH/AwAA
+A95GLQAPAwHtAd4HAAAH//XlBQPm+wAIAAAE/wBF6A8DAewB/QkAAATeEwMZ
+BQMB9gH/CAAABPTlAwUQAwAF5AUDA+QAAwMAAy0DGQADAwADIOr9AAgAAAT9
+RgMFCAMB6AH8CQAB+AHlDAMABOMD6CIJAAHgARkNAwAACPkACfr5+vn5+vn6
++gAF+QH4BPkI+AAF9/j39/gABPcAA/b29wAE9gAG9fb19vX2BPUD9AH1CfQD
+8wH0CPMABfLz8vLzAAfyAAPx8fIABPEABBLxEkEJ8AAF7+/w7/AADu8B7gXv
+A/AAFPHz9PX08/Py8fHw7+/u7u3t7OzrA+oABBhG6ekE6APnBOYB5QHmBOUA
+A+Tk5QAH5AAX4+QZ4y3k5C0U5OQt5APkLeQD5OQD5AMAA+QBFAPkAAQDLRlD
+A+QBAxHkAAzl5eTl5eTl5OXk5eQS5QAe5ubp7O7vRkbv8B/z8vLx8vHw7e3q
+5AQCAgMCAQEEDQIACgQFAuTn6ehG7OcDAwAN5APkA+QD5AMD5AMD5AAEAwAU
+5APkA+TkA+TkA+QD5AMD5APkA+QGAwHnAf0JAAAH8OQFAwMULQAGAwAH5AMD
+BRnp/AAIAAH7AeUFAwAD9v//AAUAAAX//+0DBQANAwAD4+z+AAYAAAj///Lk
+AwPl+woAAf0B7A4DAAMZKf4ACQAB/QHpBQMABBQD9v8IAAH0AeUIAwHkAwMB
+GRQDAAPq/f8ABwAABP1GA+QIAwHoAfwJAAAF++gDFC0ACgMAAy1G3gAJAAH1
+AeQNAwAABvkB+gP5A/oABfn6+fr6AAX5AfgB+Qn4AAT3+Pf4CPcB9gH3BfYA
+A/X29gAH9QAG9PT19PT1B/QD8wH0B/MABPLz8vMI8gHxAfIH8QESAfEG8AAF
+7/Dw7/AAA+8B8AjvAe4L7wAZ8PDxK/T19PPy8vHw7+/u7u3s7BPr6upGRgAD
+6QHoAegD5wAG5ufm5uXmBOUAA+Tl5QAE5AAE4+TkGQPkAAlD5APkA+Qt5BQA
+A+QADhTkA+QD5OQD5APkA+QDA+QACOPkGS3k4+QZBuQB5QfkAATl5OTlA+QA
+COXk5eTl5OXkD+UAHObm5+dG7O/x7/Dv9/Ty8vHy8fDu7e7mBQUCBAUEBAoC
+AQQDAgALBAXmRkbo7erkA+QACQMAF+QD5AMD5APkAwPkA+QD5OQD5OQD5APk
+AAcDAeQEAwHlAfoJAAAD9uYFAAYDAeMFAwAFBQMD6UUACAAB+gHmBQMB7gHe
+BwAABP8S5AUNAwADGe7+AAcAAf8B8AMDAeYB+wkAAAP///UADAMABAQD5fsK
+AAFFAegDAwEUAwMB9QH/CAAB9AHlHQMABgQFAwTt3ggAAf0BRgoDAegB/AkA
+Af0B6wMDARkKAwHqARAJAAEpAeQNAwAACPkB+gP5AAP6+foABvkABfj5+fj5
+AAP4AfkH+AAM9/f49/j39/b39/b3BfYAA/X19gAE9QH0A/UB9AH1CPQABPP0
+8/QK8wAE8vPy8wfyAfEB8gjxARIB8QbwAAbv8O/w7/AL7wAi7u/u7+7v7u/v
+7vDv8PDx9PX08/Lx8fDv7+7t7ezr6+pGRgPpA+gD5wXmB+UB5AHlBOQAEy3j
+5ORDGeQZ5APk5BTkLeQD5AMABOQAFQPkA+QD5APk5APkA+QD5OMZ5C3k4wAI
+5AAJ5eTk5eTk5eTkAAPlA+QABOXk5eQF5QHmB+UE5gAN5+fp6u3v8fLt8/by
+8gAE8QAK7+zvRgEBBAQCBAMFCwIADQEBBQEE5OfqRurt5AUAAwMAB+QD5APk
+A+QABQMB5AEFAwMAE+QD5APkA+TkA+QD5AMD5APkA+QACAMAA/L//wAHAAEh
+AUYDAwFDBgMACOMtA+QDA0ZFCAAB+wHlAwMABRQD6fz/AAcAAAP25eQACAMA
+CeMDAy0D5PP//wAGAAHeAesDAwHlARwIAAAF/wAA/OYACgMAB+QD5Oz+AP8A
+CAAB+QHlAwMABi0DA+T4/wgAAfQB5QkDAAcFAwMUAwMZABADAAQE4v7/BwAB
+IQFGCgMB6AH8CQAABP7wA+QJAwAFBQMD6f8ACQAB4AHkDQMAAAv5AAP6+foA
+CPkAB/j4+fj5+PkAB/gABff3+Pf4AAX3AfYB9wX2AAP19vYABvUAB/T19PX0
+9PUAB/QAB/P08/P08/QAB/MABvLz8vPy8wnyB/EH8AAE7/Dv8AvvAAXu7+7v
+7gAE7wAe7u/v7vDv8PHzKfTz8vHw7+/t7ezs6+rqRkbp6ejoBOcD5gHlAeYD
+5QAs5OXk5eRE5OQZLRnk5C0UGS3jLRTkA+QtFOQD5APkA+QDA+QD5APkLRQt
+FC0E5AADA+QtAAPkAS0N5AHlAeQD5QPkAAPl5eQACuUB5gHlB+YAIOfn6Ubr
+7vHy7u/28fLx8fIS7+3v7OQFBAIFAgEEBQUECwIDBAALGefqE+ru5gXkA+QA
+CgMAEuQD5APkAwPkA+QDA+QD5AMD5AMDAAPkA+QABAMB5AYDAesB/QgAAAP/
+8+QADgMAA+Tp/AAIAAAJ+uXkAwMtA+b2AAgAAAUd5wMDQwADAwFDBwMB5gH4
+CAAB/QHpAwMB5gH7DAAABPLlA0MJAwAE5vgA/wgAAAT/9OQFBAMABi3l+v8A
+/wYAAfQB5QkDAeQBBRYDAfMB/wgAAUUB6QgDAAQZA0b8CQAAA//55AADAwEF
+BQMABRQDA+TsAAQAAf8FAAH1ARkNAwAAA/kB+AX5AAb6+fr5+foK+Qr4AAP3
++PgABvcABfb39/b3AAb2AfUB9gb1AAT09fT1C/QB8wH0DfMABPLz8vMH8gAE
+8fLx8gbxCfAB7wHwB+8B7gTvAAzu7+/u7+7v7u/v7u8D8AAQ8/Tz8vLx8O/u
+7e3s6+rqRgPpAegB6APnBeYD5QAD5OXlAAfkAC7j5AMD4y1DGUMZLeTkFOQt
+5OQD5APkA+TkA+QDLRQD5APkFC3kFC3kGeTj5OQZC+QABC7k5OUD5APlAeQB
+5AflAeYB5QrmAAzn6Ojp6uzv8PDt9vME8QAR8O/s7fDmAwQFAgIEAQECBAQA
+CgIAGAQCBAPmLOws60YD5ATkA+QD5APkA+QD5AwDAArkA+QD5OQD5APkBAMB
+5AkDAecB+ggAAAT//OgFCwMABeQD5On8AAgAAfsB5QYDAATw/wD/BQAABt7s
+AwMZQwoDAegBRQgAAAf75QUDA+X7AAwAAfwBRgkDAAQE5O/eCgAABf7uAwMt
+AAQDAAPl+v8ACAAB9AHlCQMABOTu6SAPAwAHBQMFA+Qe/wAIAAH6AecKAwEs
+Ad4IAAAI/wD96QMDBeMFAwAFLQMD5PEACgABKQHkDQMAAAAD+fkmAAn5AfoH
++QAI+Pj5+Pj5+PkJ+AH3A/gF9wH2AfcI9gH1AfYG9QAG9PX09fT1BvQAA/P0
+8wAD9AAJ8/Tz9PP08/P0AAXzCvIAA/Hx8gAH8QHwAfEH8AAD7+/wAAfvAAju
+7u/u7u/u7wTuABzv7u7v8BIr9PPz8fDw7u3s7OvqRkbp6Ono6OfnBeYF5QHk
+AeUE5AAvGS0DIOPkLRkDGUMZ4xktA+QD5APkFC0D5AMD5AMtFOQD5APkA+Tk
+FC3kA+Mt5BkADeQABhnl5OTl5QTkCuUB5gHlB+YD5wAW6Onq6+zv8Ovy9fLx
+8PHw7+7t8eoDAgMEDAIAEgECAgECBAUD5+oT7Ovr5AME5AsDABnkA+QD5APk
+A+QDA+QDA+QDA+QDA+QD5APkAAMDAAPkA+QABQMABOTw//8GAAAG///25gMZ
+DAMB6QFFCAAB+gHmBgMB5wH7CAAB9gHkCAMACiADAxkD7v//AP8EAAAI//UD
+QwMD5vsIAAAI//0QAAAe6BkHAwAE5Or8/woAAf0BRgcDAeUB+QkAAfQB5QkD
+AAbm+vzw5BQEAwHkBQMACeQDA+QDAyDq3gAFAAH/AwAB9wHmCQMAA+Tr/QAL
+AAAD9uUtAAgDAAQZBOceCQAAA/8SLQANAwAAB/kB+gT5AAP6+foAC/kABPj5
++PkG+AAD9/j4AAb3AfYE9wb2AAT19vX2BPUB9AT1CPQB8wH0A/MB9APzAAP0
+8/QACfMABPLz8vMG8gAF8fLx8fIABPEAA/Dw8QAE8AAG7/Dw7+/wB+8B7gHv
+Cu4E7wAO8PIq8/Hx8O7u7Ows6kYD6QHoBOcE5gTlAATk5eTlA+QAMBQt4wPk
+IOMZQ+MD5APkLRTjA+QULRQtFOQD5OQD5BQtA+QD5APkLRQt5BTk5BnkLQvk
+AA3l5OXk5OXk5OXk5eTkAAflAeYB5QXmBecAGOjo6Ubq7O7v7O728fHw8O/u
+7ezx7uYEAw8CAwEADQIFAgMx6uzs6uvmA+QAAwMAB+QD5APkA+QADwMADOQD
+A+QDA+QDA+QD5AMDAeQJAwAD6Pz/AAcAAAf//u/kAwMgAAMDAAkZ5AXkA+QD
+RkUACAAB+wHlBQMABCDk8xAHAAAH/eoDIAMD5AADAwAI4wPkA+X3AP8GAAH+
+AewEAwF+AfsIAAAT/fD6/wD/+UbkA+QCBAPl7EX//wAJAAAD//jmAAQDAAcF
+AwPm+wD/AAcAAfQB5QkDAAnoIf/eKkbkFC0ABQMBFAcDAAXm9QAA/wAEAAAG
+/wAAKuQZCQMAA+3+/wAIAAAK/wD97xTkBQMD5AQDAAPk7t4ACQAABv/uFAMD
+BQoDAAAE+QH4B/kB+gn5AAb4+fn4+PkK+AAD9/j4AAb3C/YB9QH2B/UAA/T0
+9QAJ9AAF8/T08/MAA/QB8wH0A/MB9APzAATy8vPzB/IABfHy8vHyAAfxB/AH
+7wAIMO7v7u/u7u8L7gPvABLy8/PxEu/u7ezr6kbp6ejo5+cE5gHlAeYD5QHk
+AeUG5AAvLRQDGUMULQMZAy0ZQxnjLRktLQPkA+TkLQPkAwPkA+TkA+QD5BTk
+LRTkLeQD5OMAD+QABeXl5OTlAAPkBuUD5gHlBeYE5wPoAA7pGEbs7O3t6vT0
+8PDv7wPtAAXu8+kCBQAQAgEBAwIACgQF5xPt7Ubr6QUNAwAN5APkA+QD5APk
+A+QD5AADAwAL5AMD5APkA+QDA+QABQMB5AYDAATk8///BgAAB/8A/fDkAxQA
+CAMABOQDRvwIAAAD+uXjAAQDAATjA+n8BwAABP/45uMIAwAFFAPv3v8ABwAB
++wHnBAMB5gH7CAAAEv1G8P//AAD8Kuro5kYTKf0A/wkAAAb/AO/kA+QFAwHm
+AfwJAAAD9OUUAAgDAAnuEAAA/yH16+QABAMBFAUDAAbkA+Xy3v8JAAHiCgMA
+A+Ti/gAGAAAJ/wD//v8AIe7lAAgDAUYB+wkAAAP//iwADgMAAAv5AAP6+foA
+CfkB+AX5AfgB+Qj4AAP39/gABPcABPb39vcH9gH1AfYH9QAG9PX19PT1CfQB
+8wH0A/MD9AHzAfQH8wAD8vLzAAjyAA3x8vHx8vHx8vHx8PHxAAfwC+8B7gHv
+A+4B7QjuAA7v7/Hy8vHv7u3s6+pG6QPoAAbn5ufm5eYE5QAE5OXk5QPkADID
+5BQtA0MZLQPkA+QD4+QD5CDjGRTkA+QULRTkA+TkA+QDA+QD5APkA+TkA+QD
+5OQtGQjkAeUD5AAF5eXk5OUAA+QAA+Xl5AAE5QAM5ubl5ubn5ubn5ufnA+gD
+6QAd6urr7e3r8PXw7+7u7ezt7/Ls5QMEAgECBAUFBAQACQIADQQFBATmLOvs
+E+zr5OQABQMAB+QD5APkA+QADgMABeQD5APkAAYDAeQDAwAD5APkAAkDAAPo
++/8ACQAAB9706eQDAwUAAwMABgUD5Ub4/wgAAfsB5QcDAAPk8RAABQAABf8A
+3PTmAAQDARkDAwAHLUb8AP8A/wAEAAAD//HkAAQDAeUB+wgAAATe60b8BAAA
+BhD9Rfv8/QP/CwABIQHoCAMB5wEhCQAB9AHkCAMB5QH3BAAAEv///fjy6+fl
+5OQDBOTk5ur23gQAAAP/AP8AAwAB/QFGCgMAA+Tw/gAHAAAK//0S+///3vXr
+5wPkAAXl6O9F/wAKAAHeAecOAwAADPkAB/r6+fr5+foABfkD+AAF+fn4+PkA
+BfgAAx/4+AAJ9wAL9vf29vf29fb29fYACPUABfT19fT1AAz0AArz9PPz9PP0
+8/P0BvMAA/Lz8wAG8gAI8fLy8fLx8fIE8QHwAfEE8AAD7+/wAATvAAXu7+7v
+7wAH7gAE7e7u7QbuABPw8fE27u3s6+pG6eno5+fm5uXmAAPlAAPk5eUABuQA
+By0ULRQtAxQABAMAH+QDGQPkLRQt4y0ULRQtFC0ULRQtFC3kFOQD5APk5AMA
+BOQBAwzkAAQZ5eTkA+UABeTl5eTkAAjlBeYE5wToAAzp6erqLOzs6+z18u4D
+7QAP7O3t8fLoAwUFBAQFBQMDAA0CAA0EA+kT6+zr7eYDAwLkAAsDAAvkA+QD
+5APkA+QD5AAIAwAD5APkAAkDAeQJAwHuAd4GAAAS/wD/AP9FK+vm5QPk5ejv
+9fz/CQAB+gHmBAMABhQDAyDo+QcAAAX//vbnIAAEAwAEIOTt+wMAAf8B/wQA
+AAne6AMD5AMD5vsACAAABP3s5fUEAAH/BQAB/wkAAAX/AAD/8wAIAwAEBOn+
+/wgAASgB5ggDAAfpIgAA/wD/AAMAAA3//fv39Cvx8PHz+f3/AAoAAAb/++UD
+A+QHAwAD5PP/AAcAAAT/IUbyAwAACf/9+fXz8/Uc3gAIAAAJ/wD///vlAwPk
+AAsDAAAM+QAF+vn6+foACvkB+AP5AAP4+PkABfgAA/f4+AAI9wH2AfcF9gAE
+9fb19gn1AAb09fT19PUH9AAD8/TzAAP0AATz9PP0B/MADPLz8/Lz8vLx8vHy
+8QPyAfEB8gbxAAPw8fEABfAB7wHwA+8ABe7v7u/vAAfuABXt7e7t7u3u7e7u
+7/ES8O7sE+rp6egAA+cD5gXlB+QACQPkA+QDAxktFAADAwAnFC3j5AMZ4xkD
+5APkA+QD5C0ULQPkAwMtFC0D5APk5AMD5APkA+QDAAnkAATl5OTlBuQG5Qbm
+BecABOjn6OgD6QAKRkbq6xPs6vPz7wPtAArs7e7v9exEBQMFAwME5AADAwUF
+AAgCAAkB5OXq6uvrQegAAwMB5BgDAAXkA+QD5AAGAwAH5APkA+QD5AADAwHk
+BQMABOQD5fINAAAH/vxF+0VF/QANAAEdAeUEAwAJLQMD4wNGIQD/AAcAAAn9
+9e3r6uru+BAACAAAA//+8gAGAwAD5UX/AAcAAAj96wPnIQD//wsAAf8GAAAD
+//roAAgDAAPk7RAACQAB+AHmCAMB9AEQHwAB3gHvCwMB5gH3CQAABN4s5/0D
+AAH/EAAD/wHyDwMAAAv5AAf6+fr5+vn6AAT5AfgD+QH4AfkE+AH5BfgB9wH4
+CfcABPb39vcD9gAJ9fb19vX29fX2AAT1AAv09fT19PX09PX09QAI9AAD8/P0
+AAXzAfQF8wHyAfMG8gPxAAXy8fLx8gAH8QXwCO8B7gHvB+4J7QAP7u3t7vDw
+7u3rRkbp6OjnAAPmA+UB5AHlBuQAAwPk5AAHAwAmLQPjIC3jIAMt4y0D5OQD
+5APkA+QULeMZLeMg4y0U5Bkt5APk5AMP5AHlA+QB5QHkCOUI5gAG5+fo6Ofo
+A+kBRgFGA+oAE+zr6u/08O3t7Ozt7+z08OgZBAUABQMF5AEDAQUFAgAFBQXk
+5+kAA+sABO4TLeQQAwAL5APkA+QD5APkA+QABgMABeQD5APkAAkDAeQJAwAG
+5vf+/wD/CQAB/wQAAf8NAAAD+uXkAAcDAAbkA+78AP8GAAAI//7e/SH93v8H
+AAP/AfgB5wUDAAMU5hwACAAACd7r5APw3v8A/wALAAAI/wAA//8A/u0HAwAE
+5APk8woAAfcB5QcDAAPoIf8AHAAD/wEfAecLAwHnAUUJAAAF/esD8v4AEgAA
+Bf//APzqAA8DAAAM+QAE+vn5+g75AfgB+QX4AAT3+Pf4B/cABfb39/b3AAT2
+ABP19vX29fb19fb19PT19PX09fT1AAr0AfMD9AAI8/Tz8/Tz8/QF8wHyAfMD
+8gHxA/IE8QAD8vHyAAXxAAPw8fEAB/AF7wTuAAPt7u4ABu0ACOzt7ezt7O3s
+A+4ACe3r6unp6Ofm5gAG5QfkBAMABOQDAwUHAwAgGQPjIAMZ5AMD5APkA+QD
+LRTkA+QD5BkD5C3j5APk5AMD5AEDC+QACuXk5eXk5OXk5eQE5QPmAAbn5ufn
+5ucE6AHpAegD6QAkRkbq6uvrLOvz8e7s6yzt8Ozv8+zlBQMD5AMFBAUDLRQD
+5QMDBQIACgMF5ehG7e3w7+UeAwAD5APkAAgDAAfkA+QD5APkAAkDAAYF5AXn
+9v8OAAH/DwAB+wHlBQMB5AQDAAXk7f3//wAHAAH/DgAAA0VG5AAGAwHlAfsI
+AAAJ/u0DBeb1AP//ABAAAAT+8OTkBwMABxTo+gD/AP8ABgAB+QHmBgMABOTv
+AP8cAAAE/wBFRgwDAAPt/v8ACAAAB/3sA+b3AP8AEwAB9AHlDwMAAAv5AAj6
++fr6+fr5+gn5AAX4+fn4+QAG+AAD9/f4AAX3AAT29/b3B/YB9QH2A/UB9gX1
+AAz09fT19PX09fT19PUI9AAE8/Tz9AXzAfQG8wAF8vPy8vEABfIAA/Hx8gAK
+8QHwAfEE8AfvBO4B7QHuBu0B7ATtAAzs7ezt7u3s6uno6OcD5gAF5eXk5OUA
+BuQBLQYDAwUDAwEgAeMEAwHjAwMAG+QDA+QD5APkFC0D5APkA+MtFBktFOTk
+A+TkAwAN5AHlA+QABeXk5eTkAAblA+YAA+fn5gAD5wHoAegE6QAcRhhGRurq
+6xPq8PPv7Ebr7e/t7CruRgMFA+TkAwMCAAcEBAXk5AMEAAUCAAUE5Ubs7gAD
+8QHnEgMAC+QD5APkA+QD5APkAAYDAAXkA+QD5AAJAwAD5APkAAYDAQUDAwAD
+5/L8AAcAAf8VAAAR+uXkA+QDFAMgA+QDA+TtHP8ABQAB/wYAAf8HAAAN//vr
+5AMDFC0UAwPm+wAIAAAI/u3kAwPnKP8OAAAG/wD98eTkBwMABATm9P8KAAH6
+AecFAwAHAuTl7fj9/wAaAAAF//vq5OQACgMABej6/wD/AAcAAAje6wPk6B7/
+/xAAAAP/+egAEAMAAAz5AAT6+fn6DvkABPj5+PkH+An3AAP29/cABPYABfX2
+9fb2AAz1AAP09PUAC/QAB/P09PP08/QABfMACfTz89/z8/Lf8gAG8QAF8vLx
+8fIACvEF8AHvAfAE7wHuAe8D7gXtAAPs7O0ABOwABO3s7e0D7AAGLEbp6Ofm
+BOUB5AHlBuQBAwEZBQMBBQMEAQUFAwAe5AMZAwMtFAMD5APkA+QtA+MZLeMg
+LRnjLePkLeQDEOQACOXk5eTl5OXkBuUF5gAH5+fo6Ofo6AAD6QVGAB/q6uvq
+6uz08Ozt7e/w7kby80bmAwTk5eQCAQIEAgECAAMDAQQDAgALBAXm5+3z9fHz
+6+QAHgMABeQD5APkAAYDAAfkA+QD5APkAAgDAArkAwPkAwUD5e36HAAB+wHm
+BAMACy0D4wPkA+MD5On1AAcAAf8MAAADH0bkAAgDAeUB+wgAAAn+7uQD5APn
+JxAACwAABv8AAP3t5QkDAAjk7PhF/QAA/wYAAUUB6QMDAArkA+QD5OTm7Pb9
+GQAAA/ZG5AALAwAD5PP9AAoAAf0B6wMDAekB+BEAAfoBRhEDAAAL+QT6AAX5
++vr5+gAL+Qn4B/cABPb39vcD9gH3BfYD9QAD9vX2AAf1AAj09fX09PX09Qn0
+AAXz9PTz9AAE8wAF9PP08/QABPMB8gHyB/EABfLy8fHyAAjxBvAG7wTuAe0B
+7gPtAewB7QfsAA/t7e7u7e3sLEbo5+bl5OUABuQAMwPjIOMDBQUDBAQFBQMD
+BQMDLQMDQwMtFAPkLeMg5AMtFBnkA+QDA+Tk4yDk5APkA+QDAwAK5AAL5eTk
+5eTk5eXk5eQABOUH5gAD5+jnAAToA+kABEZG6kYG6gAWRvPx7u/v8O/v6+31
+6+jlA+Tl5QMEAgMEAAYCAgQFBAIDBAALA+Xo7PLz8/Lv5AQAHQMB5AcDAAPk
+A+QACgMB5AoDAeQDAwAF5uwf/f8ADQAAA//+/wAIAAFFAegNAwAFBeTr9iEA
+A/8KAAAF//757eQACgMB5gH7CAAB/gHuAwMACC0U5e37/gD/AwAACP//AAD/
+/PXoCwMAEC3k5ubo6Czv8/lF/v8A/eoKAwAIBeTn7fb73v8FAAH/CgAABRD8
+KBPkAA0DAeQD6AALRuzx9voh/wAA/esABAMABOXu+/4LAAAH//3y5wMDBQAP
+AwAAAAP5+TwABPkB+gX5AAP6+foAEPkB+AH5A/gB9wP4DfcE9gH1A/YAA/X1
+9gAK9QH0AfUD9AH1AfUJ9AAD8/P0AA7zAAby8/Lx8fAF8QAE8vHx8gbxAAMS
+8fEABfAABe/v8O/vAATuBe0E7AHrA+wAA+3u7wAE8AAI7u3s6ujn5eUG5AED
+AeQGAwEFAQIDBAMFAB0DAxkDAxkDFC0DA+Mg4wPkFC3jLeQD5OQULRnkAwAT
+5AAI5eTl5OXk5eQI5QPmA+cAB+jo6eno6OkABEYF6gAH60bu8+/v8AAD7wAj
+7Ov08Ojn5+Xl5uQEBQQCAQICBAQCBAQCAgXl5+n09vbz8ucAIQMABeQD5APk
+AAYDAAfkA+QD5APkAA8DABYEBeTm6/D3+vz93v3+/f79/Pr28e9FCAABRQHo
+DwMACOTl6vH3Rf39Bf4ACf38+iru5+QDBQAJAwHmAfsIAAAE/u7kFAQDAA/k
+6e/3Rf39/t7eIfkr6uUADQMBFAMDAA4EA+Tl5kbu9kX97SAD5AgDABDkA+Tl
+6O3w9flF/P3e/f3eBP0ACUX69fBG5uQDBQAQAwAW5APl5ebr7x/9/esDA+QD
+A+To7/dF/QX+AAbe/Prz6+UDAwHkDwMAAAP5AfgH+QAI+vn6+vn6+foJ+QAE
++Pn4+QT4AAf3+Pj3+Pf4AAb3AfYB9wj2AAj19vX29fb19gb1AAX09fX09QAE
+9AAE9fT08wf0AAXz9PP09AAL8wAH3/Pz8hLw8AAP8QAD8PDxAAXwBO8BMATu
+A+0F7AHrA+wB7wHwA/EADRLw7+7u7Orp5+Xk5AMAA+QBLQEZAwMAAwUFBAAD
+AgAGBAQFAwPjBAMBQwQDABkUAyADA0MDGQMDGS0ULRQtFEMZLeQU5OQtAAjk
+AAvl5OXk5eTk5eTl5AAH5QXmAATn5+joB+kBRgXqAAfr60YT8+/wAATvAA7t
+6vDx6ufl5ehG6AMDBQYCAwQADQIEA+Tl6e/g9vT06QUAHgMB5AcDAAXkA+QD
+5AAJAwHkDAMAFwLkA+QD5APl5unq6+zt6+tG6Ofl5Of7AAgAAUUB6AsDABUF
+AwMEAwPkA+XnRuvt7u/v7uvo5+UADgMB5wFFCAAAA/7u5AAIAwAN5udG6+3s
+6ujn5AMD5AAMAwAHLQMDBAMULQAEAwAF5ejx7OMAEQMABeTm5uhGAAfrAATp
+6OblEgMBBQHkBQMB5AMDAATm6vTrAwMAEwIDAwTk5ejq7u/i7+7r6ebkA+QA
+EwMAAAH6C/kAB/r6+fr5+foADPkB+AH5BfgB9wH4B/cB9gX3AfYB9wb2BPUB
+9gb1AAr09fX09fT09fT1CfQABfP09PP0AAPzAfQD8wH0B/MABPLy8fED8APx
+AfIB8gjxAfAB8QXwAe8B8AXvAe4B7gTtAAzs7Ovs6+zr7Ozv8PIF8QAMEu/v
+7u7s6unn5uQZAwMACAQEBQQEAgQEBAUFAwAKFAMZA+QDAy0D4wMDAeQEAwAL
+QwPkLRQt5APjGS0AA+QBGQHjCOQB5QPkAATl5OXkB+UF5gPnAegB6APpAAZG
+6ekYRkYD6gAH6yzqRvDx8AAE7wAo7evs8u3o5+bm6e3qIAMDBAUFBAICBAME
+AgXk5ebt7vX3Ku4DBQMEBR0DAAXkA+QD5AAIAwAF5APkA+QADQMABAUDAwUF
+AwEFAwMABeQD5APkAAUDAekB+wgAAAP86AUACgMABQUDAwQFAAYDAAbkA+Tk
+A+QDAwAEBQMDBQsDAAPp/f8ABwAABf7uLQPkAAMDAeQGAwAE5APkBR4DAAPk
+5eQACQMB5AoDAAnkA+QD5APkA+QAAwMABQUD5AMEABMDAeQEAwAF5AMD5eUA
+AwMACeQDAwUDBQPkAwAE5AEDAeQEAwEFEgMAAAz5AfoB+QT6AfkB+gP5AfoE
++QH4AfkK+AAD9/f4AAb3AfYB9wf2AAf19vX19vX2AAn1AAX09fT09QAL9AAJ
+8/Tz9PP08/P0AA7zAAPy8hIABPABEgrxAAQS8RLxBfAF7wPuAe0B7QTsARMD
+6wAE7O3v8QPyAfEB8gPxBPAAEe/v7ezrRufn5eQgBAMgAwEEAAMDAAcFAwMZ
+AwMFAAQDAAYgAwMZAwUEAwAE5OQDGQQDAeQEAwAD4y0UAAPkAS0G5AAI5S7k
+5eXk5eQG5QXmBOcB6AHoA+kABkbpRunpRgPqABrr6uvp7PLv8O/v7u4T6vDx
+6+Xk5ert7UbmBQMDAAMEAgEABAQACwLk5efq7fP28+/mAAMFAQQSAwMFEAMA
+BeQD5APkAAcDAeQLAwAE5AMD5AQDAATkAwPkBQMACOQDA+QD5Oj7CAABRQHo
+AwMHBQUDAeQBBQMDAwUHAwEEDAMABRQDA+j8AAgAAAP+7uQAAwMB5AUDAAvk
+AwPkBQMD5AMD5AALAwHkBQMBQwMDARQFAwHjASAHAwHkBAMB5AMDAeQKAwHk
+BAMB5AMDAeQSAwHkAwMB5AwDAAnkA+QDA+QDA+QABwMABOQDA+QPAwAABfkB
+PAb5AAr6+vn5+vn6+fn6B/kB+AH5CPgAA/f3+AAE9wH2A/cAA/b39wAH9gAE
+9fb19gn1AfQD9QT0AfUF9AHzBfQADfP08/P08/P08/Tz8/QABPMD8gAE8/Py
+8QXwARII8QHyA/EG8AAE7/Dv7wPuA+0ADezs6+vq6+vs7xLx8vMABPIB8QPy
+BPEAExLw8O/w7+7t7CxGRunp6Ofn5uYAB+UJ5AEZAeQGAwPkAAgDAxQtGeTk
+GQfkAS0F5AAD5eTkAAblAeYB5QXmA+cE6APpAANGRuoABEYACerq6+tG6vHv
+7wAE7gAU7Ebu9Ozm5OXn6Ubt6hPq6OjlBAQFAgAM5OXn7fH19/Ly5wMEAwUB
+AwEFBAMBBRYDAAfkA+QD5APkAAYDAAXkA+QD5AAlAwHoAfsFAAAH/wAARegD
+AwADBQUDAQUBBRgDAAzjAy0DA+MDLQMD6CEIAAH+AewmAwAEGQMDQwMDASAB
+Q24DAAAN+QT6AAP5+foAB/kABfj5+fj5AAb4AAT3+PcfBvcABvb29/b29wX2
+AAb19vb19vYK9QAI9PT19PX09PUD9AAN8/Tz9PP08/Tz9PPz9AAH8wH0BvMA
+B/Lz8vLx8O8ABfAE8QAI8vHx8vES8fEF8ATvA+4B7QHtA+wD6wAE6uzv8APy
+AfMF8gHxBPIB8QPyBPEABRLwEvESAAPwBe8D7gHvBe4B7QHuBO0D7AETA+sB
+6gHqA+kAA+jo5wAD5gHlA+QABxnk5Bnk5BkABeQB5QHkA+UD5gHlBOYF5wAG
+6Ojp6RjpBkYB6QPqAAXr6e8S7wAE7gAL7OrrKe/p5efnRukAA0YACOpG6erm
+5BQFAwQAEOTk6O3z9fT08evkAwICBAQDBQMDAQUBBR0DAAPkA+QACAMB5CMD
+AekB+wcAAAX//OgDAwADBQUDAQUBBSEDAAMg6PwACAAABP7uFC0mAwMgAwMB
+GW4DAAAD+QE8B/kAA/r5+gAD+QAE+vr5+gj5BPgB+QP4AAP3+PgAB/cABfb3
+9/b3AAn2AfUB9gb1AfQD9QAE9PT19QT0AfUJ9AAP8/T08/T08/P09PP08/P0
+AAbzAAjf8/Lz8/Lx8ATvAAXwEvHx8gAH8QfwBO8ABO7u7e0D7AAJ6+vqLOzu
+8PHyAAPzGPIAA/Hy8gAD8QHyAfIE8QAF8vHy8fIADPEBEgXxBPAADu/v7u3r
+6unp6Ofn5uUZA+QH5QXmA+cD6ATpBkYAGhhGRurr6evx7+/u7e3sRuni8hPm
+5+fo6OnpA+cAFujo6unpLgMDBAXk5e4S8/bz8e7kBAQDAgEEAQQDBQEDAQMD
+BRcDAAPkA+QABgMAB+QD5APkA+QAJAMB6AH7CAAABP1GAwMJBSMDAUYB/QgA
+AAP/8eQAJQMABi0FBCAFIHEDAAAM+QP6AfkB+gT5AfoG+QAF+Pj5+PkABvgK
+9wAE9vf29wj2AAb19vX29fYE9QAH9PX09fX09AAD9Qf0AfMD9AAF8/Tz9PMA
+A/QABfP08/P0AAvzA/IAA/Hw7wAD8AAH7+/w8fHy8gAE8QESAfEE8ATvA+4D
+7QAL7Ozr6+rq7O/w8fIABvMF8gAH8/Ly8/Ir8wAD8gADK/PzAAPyAfMD8gAI
+8/Py8/LzK/Md8gAD8fHyAAPxAAwS8RLv7u3s60bo5uYD5QTmBecD6APpABFG
+6RhGRurqRkYYRkbp8e/u7gAD7QAnRhjr9evm5+hG5+np6Ofm5efoRuflFC0D
+5OXo7PDx9PTw7ucDBQUBAAMCAwQABwUFAwQEBQUAGgMABeQD5APkACsDAegB
+HAgAAf4B6wMDCAUjAwHrAf4HAAAG/zvx5BQtIgMACQUDAxQODhRDBQBvAwAA
+AAP6+TwACvkABfr5+vn6AAX5AfoF+Qj4AAX3+Pf3PQAG9wAH9vf29/b29wAG
+9g31AAT09PX1A/QB9Qj0AAvz9PTz9PTz9PP09AAD8wAD9PP0AAjzABLf8/Py
+8/Hw7+/w7/AS8vLx8fIE8QESAfEE8ATvAATu7u3tBOwADOvr6uzu7/Hy8/Tz
+9ATzAAXy8/Ir8wAL8gErDvIB8QfyAfME8gHzASsD8g3zDPIACfES8O7s6+ro
+5wAD5gAD5+jnAAPoBekAD0ZG6kZG6upGRupG7vDv7gAD7QAS6uks8Pbs5+Tm
+6Ebq6Ofl5uXlA+YAEeQD5OTl5Ubw9PL09e/q5AMEAAMCBQQDBQEEAQQDBQ8D
+AwUNAwAH5APkA+QD5AAjAwHoAfsFAAAF/wD//usACAMBBQEFIAMBQwMDAesB
+3ggAAAP/8eQAJQMACSDkDglVQyAF4wBuAwAAAAX5+SX5JQAD+QE8A/kACPr5
++vn6+fr6BfkAB/r5+fj5+PkACPgH9wAG9vf29/b3CvYAA/X19gAG9QH0A/UB
+9AP1DvQAC/P09PP08/P09PP0AAPzAAP08/QACPMACPLy8fDv7/DxBfIAA/Hy
+8gAD8QHwAfEE8AAE7+/u7gTtAA3s7Ovr6urt7+/w8fIqAAP0AAXz8/Ly8wAK
+8gAK8fHy8fLx8fLx8hDxAAPy8fIABPEE8gADK/IrAAfzAfQF8wAD9PPyAATz
+AAby8vPy898E8gAHEu7r6ujn5wAD6ATpBUYADepG6kbq6Szx7+7t7ewAA0YA
+Bu7x6evp5wPpAAPo5+gAA+YAFuXl5OXl5APk5ent8/X29O/tAwQBAQIFBAYF
+TQMB6AH7BwAAA//e7AAJAwEFHQMBQwUDAAMF7f4ACAAABP/x5C0eAwAF4wMg
+BQUAA0MADLEKCggOAyADBSAD5GkDAAAABCX5+TwJ+QP6AfkB+gX5AfoF+QH4
+AfkH+AAD9/f4AAn3AAT29/b3BPYB9QH2A/UB9gP1AfYD9QAG9PX09fT1A/QA
+BPX09PUI9AAQ8/T08/Tz8/T08/T08/Tz9ArzAAjy8/Py8RLw8QfyBvEBEgHx
+A/AD7wPuAe0B7QPsAAnr6+rs7+/w8fIABfQD8wHyAfMD8gAD8fHyAAvxDfAB
+7wvwAAgSEvES8fHy8QTyASsD8wAKK/Pz9PTz9PP08wT0BvME8gAEEu/s6wPp
+AAPo6UYAA+kERgTqABbp7xLu7ezs6ulG6vPv6ejq6unp5+fmA+gB5wHmA+UA
+EuTk5eXo7/D09h/z7+cFBQQCAQUEBwUkAwAH5APkA+QD5AAbAwHkBQMB5wH7
+CAAB/gHsAwMBFAEtBAMB5CQDAfAB/wgAAAMQ8eQAIQMABuMgIENDCAQKAAhl
+4+MgLQMDIGkDAAAK+QAMPPn6+fr5+vr5+vn6B/kM+AAE9/j3+AT3AAT29/b3
+BvYAA/X29gAE9QH2B/UAA/T19AAE9Q30AAPz9PMAA/QADvP08/P08/Tz9PP0
+8/P0A/MACPLz8vPy8vHxCPIB8QHyBfEE8APvAe4B7gPtAAfs7ezrLOrsAAPv
+AAPw8fMABfQB8wTyBPEB8AHxB/AN7wjuC+8B8AHvBPABEgXxA/IB8wHzB/QA
+BPX09fQH8wTyAAXx8O4TRgAE6QA2RulG6RhG6urp7PHv7ezrRufqRvAS6+nn
+6uzt7Ebp6Ofo5+Xm5uXk5OXm6Ozy9Pj5KfDpAwUEAwIFBAgFRwMB5AMDAekB
+RQgAAAX/7gMDLQAEAwHkHgMAChkDLQMDGQPk8v8IAAAD//PkACQDAUQBCAYK
+AAYIQy0DBC1qAwAAAAcl+fk8+fklAAX5AAUe+vn6+gAH+QH6BfkH+AAF9/j4
+9/gABvcAB/b39vf29vcAA/YAB/X29vX29fYAB/UABPT19PUH9AAE9fT09Qr0
+AA3z8/T08/T08/Tz9PP0AAfzAAff8/Py8vPxAAryAAPx8fIAA/EAB/Dx8O/w
+7+8AA+4D7QAM7Ozr6+rs7+7v8PDyBPQABfPzK/LyAAPxA/AE7wAE7u/uMAbu
+AAXt7u7t7gAQ7QHuAe0J7gTvAAPw8BIABPED8gADK/PzAAj0BfME8gAJ8/Lx
+8O7rRunpAAVGAB7q6erw7+3r60boRurr8+3m6Onr7ezu8hPp6ejo5+YF5QAM
+5u7z9fb49vTr5AMEAwINBAEFAQUiAwAH5APkA+QD5AAbAwHkBAMAA+RG/AAH
+AAAM///tAxQD5APkAwPkJAMB5QH2CQAAA//15QAgAwAFLQMDDggACAoAAwhD
+QwBsAwAADfkAA/r6+QAE+gj5AAP4+fkABPgB9wP4AAT3+Pf4BvcD9gH3B/YB
+9QH2A/UB9gj1AfQH9QAD9PT1AAj0AAPz9PMABPQADPP08/Tz9PPz9PTz9APz
+AfQD8wAF8vPy8vMABPIB8wfyBfEE8APvAe4B7gPtA+wABOvq6+4D7wAO8PHy
+9PTz9PPz8vHx8PAF7wPuAe0B7gjtAewB7QjsARMD7AADE+wTAAnsBu0D7gXv
+AAnw8EHw8fHy8isAA/MI9AbzAEDy8vPz8u/t6ukY6UZG6ujt8O7s60bo6erp
+8fHq6Ovq7OzrRu7y7uno6Ofm5uTk5ujr8vb19vHy4uUDBAEEBQQCDAQIBSUD
+AAPkA+QAFwMAB+QD5AMD7P0ACAAABP/uAy0rAwAE5voA/wgAAfUB5CADAAQg
+A+NVCgoABQlDIC0UAGkDAAAM+QH6AfkD+gX5AfoE+QH4AfkF+AAG9/j3+Pf4
+C/cD9gEoBPYABfX29fb2AAr1CPQABPX09PUL9AAO8/Qq9PP08/Tz9PTz8/QK
+8wAEK/Py8wbyAfMD8gAD8fHyAATxAAUS8PDv7wAE7gHtA+wBEwPrAe4E7wAD
+8PErAATzAAby8fDw7+8D7gPtAewB7QPsAAQT7OsTA+sABxPr6+rr6usAB+oA
+Buvq6+rr6gbrARMBEwXsA+0ABu7t7u7v7gTvAA/w8PHy8vMr8/P08/T19PQA
+A/MB8gbzADb08xLtLOpG6unr7+7t6upG6evp7vTt6+np7xPs8O3s7vLv7Ofl
+5ubl5ufq8PX29PD18ugEBQUFBAECAQIIBAUFBQQBBSEDAeQgAwHkAfIDAAH/
+AwAD/wAIQRkDA+QDA+QlAwAG4yz9/wD/BgAABP/15QUgAwEtAQgMCgAECC0D
+42kDAAAB+QElA/kBPAf5AfoB+gP5AAr6+fn6+fn6+fj5DPgB9wH4BfcAA/b3
+9wAI9gH1A/YL9QH0CPUABvT09fT09Qr0AAzz9PP08/Tz9PPz9PQL8wAI3/Lz
+8vLz8vMJ8gAE8fHy8QPwAAXv7+4w7gAD7QPsA+sB7gTvAAPw8PIAA/MAB/Lx
+QfDv7+4AA+0E7AHrARME6wjqAUYB6gxGAeoBRgfqAUYE6gPrA+wD7QXuAAfv
+7/DwEvHxAAPyAAUr8vPzKgAF9APzAfID8wAy9PPy8e7sGOnv7+3s6kZG60bp
+9O3qRulG7u729/Dv7/L08enm5eXk5erw8vb59/Pg6hkIBAECAQIIBAUFBQQB
+BQEFQAMAA+Tl9wAJAAEQAfEpAwEFAwMB9AP/BQAD/wH3AeUgAwHjAQgOCgEJ
+AQVqAwAAA/kBJQf5AAP6+fkABPoABfn6+fn6AAT5AAP4+PkAB/gABPf4PR8H
+9wAD9ij3AAj2AAb19vX29fYG9QH0A/UH9AAE9fT09QP0AfUG9AHzBvQABfP0
+8/T0AAPzAAP08/QACfMAA/Lz8wAE8gHzBfIAA/Hy8gAE8QPwAe8B7wPuAe0B
+7QPsAAXr6+ru7gAE7wAK4vDy8ivy8fDv7gPtAAbs7BPr6usE6gdGAATpRulG
+A+kABOjp6egH6QAHRunpRulG6QAFRgTqA+sE7ATtAe4B7gPvAATw8PHxBfIK
+8wPyA/MAMfLy8O3s8O7t6+np6uvn7/HsRkbq7PX39/jv9vHw8evo6ebm5+fs
+9Pb1+ff08OQDBAMABgQBAgECCAQFBQUEAwU+AwAE5APr/QMAAf8B/wQAAf8B
+8ykDAAXkAxTp/QADAAH/BwAB+QHmHwMBFAEJEAoBCQEZaQMAAAAEPPn5PAj5
+AfoE+QH6B/kABPj5+PkH+AAEPfgf+AX3AfYD9wH2ASgF9gH1A/YB9QH2C/UB
+9Af1AAb09PX09PUN9AHzBPQABmjz8/Tz9APzAfQI8wAD8vPyAATzAAPy8vMA
+BfIB8QHyA/ED8APvAe4D7QPsAAXrLOru7gAG7wAM8PHx8vDu7e3s7BPrBOoA
+BEZG6UYG6QAE6Ono6RHoAAbp6Ono6egE6QFGAekDRgHqAUYD6gAGLBPrE+zs
+A+0B7gHuA+8D8APxAAXy8ivyKwAF8wA38vPy8/P08/Py8u7x7uvr6uvr6Cz0
+8hPp7/P2+Pf49vHzKvHt6Ubp5ubn6e3z8/Q8H9/mAwUEAgAGBAECAQIUBAEF
+AQU9AwAEBOn7/woAAAX25AMD5AAnAwAERh/9/gkAAAP/+eYAHwMAAy0MBgAO
+CgADBtYgAGkDAAAAA/n5PAAK+QX6B/kABfj5+Pj5AAj4CfcAA/b29wAF9gAJ
+9fb29fb19vX2AAb1ABb09fT19fT19PX09fT19PT19PX09fTgBfQB8wb0AfME
+9AAEaPTz9AvzAAfy8/Lz8vLzAAbyAfEB8gbxAAPw7+8AA+4B7QHtA+wABOvr
+GO4J7wAH8fDv7u0T6wAD6gNGAATp6OjpA+gACeno6Ofo5+jn6AAR5wAE6Ofo
+5wfoBOkAA0bpRgAD6gTrAAMT7OwAA+0ABO7u7+8D8AAE8fHy8QTyAAQr8vLz
+A/IB8wHzA/QAL/Py8PPt6+wTRuby8fLr7PH2+vj7+vXy7O7s6ebp5+jo7O7x
+9PX3+PZGLQUCBQQFAAUEAQIBAhQECAUUAwQFHwMACOTp8fP1+vwQBgAB+AYD
+BAUgAwAJ5Ofq7PDy9/z+AAYAAfoB5h8DAAQg4wwGDAoAAwYM4wBqAwAAAAX5
++Tz5PAAF+QAE+Pn5+gf5AAX4+fj4+QAI+AAD9/f4AAf3AAX29/b39wAI9gAE
+9fb19gj1AAz09fT19PX09fT19PUD9AH1FfQADPPz9PPzaPPz9PPz9AXzAAff
+8/Lz8vLzAAryA/ED8APvAAbu7u3t7OwD6wFGAe0G7wAO7u7v7u/u7evq6kZG
+6ekF6AAD5+foAAXnAeYB5w/mAecB5gPnAeYJ5wToAekB6ATpA0YE6gHrARMD
+7APtAAbu7u/v8PAF8QPyASsF8gPzACr09BIq9evq6ufv8vDv7PL4+vr4+PX0
+8/Lr6urt6UbqRtj09/j5+vgTGQMFBAcCEgQLBTgDAA0EA+Tm5uju8/v9///8
+AC8DAAzk5eXp7/ZFEAAARegiAwEMAQYKCgAEBgwFBWoDAAAN+QAD+vn6AAr5
+AfgB+QX4AAP3+PgABvcABfb39/b3AAb2AAX19vX29gAE9QH2BPUAEvT19fT1
+9PX09fT19PX09PX04Av0AfMI9AAO8/T08/T08/Tz8/Tz8/QG8wHyA/MB8gHz
+CPIB8QHyA/ED8AAE7+/u7gPtAAns7Ovq6e7v7u8ABO4ACu3u7u3t7OpG6ekE
+6APnAAnm5+fm5ufm5ucAHOYB5wHmBOcAA+jo5wAD6AbpAUYBRgTqAesB6wPs
+AAXt7e7u7wAD8AfxBfIBKwT0ACjzEvnr5udG9vLw6/L5+vn6+vn59/Pu8RPq
+7Ebn6+zy9Pj6+/jx5QMFBQQHAhIEDAU3AwAOBQMFBQMF5OXo7ClF/eQyAwAI
+5OVG7/n9ReghAwAEIAMMBggKAAQGDC0gawMAAAH5ASUM+QH6B/kABPj5+PkE
++AH3A/gL9wH2AfcI9gAF9fb19fYABfUB9AP1AAz09fT19PX09fT19PUQ9AHz
+BvQAA/P08wAF9AAF8/Tz8/QACfMABPLz8vMD8gHzBvIE8QHwAfAD7wAE7u7t
+7QPsAATr6kbtA+8E7gHtA+wABhPr6uno6APnAeYB5wrmAeUE5gAE5ebl5Qbm
+AATl5ublBOYB5QzmBucD6AHpAegD6QADRulGAAPqAAjr6+zs7e3u7gPvA/AF
+8QTyAfMD9AAo9fL29eXk7/Tw7e74+fn6+EX69/Xy8e/w7Ovo6u3z+vn6Hvr2
+6AMDBQUEBwISBA0FNAMBBQQDAQUBBQUDAAbl6e/mAwUwAwAIBQMD5Obq9ekg
+AwAGBeMgLQwGBgoABwYMLQME4yAAaQMAAAT5ATwI+QH6BvkAB/j5+fj5+PkA
+BfgABPf49/gE9wAF9vf39vcAB/YAA/X29gAD9QH2CfUAC/T19PX19PX09fT1
+ABj0AfMK9AAF8/Tf8/QABvMAB/Lz8/Lz8vMAA/IB8wbyAAfx8RLw8O/vAAPu
+AAjt7ewT6ulG7QPvA+4ACe3t7OwT6upG6QAD5wPmAAPl5eYAF+UABObl5eYE
+5QAJ5uXm5eXm5eblAAbmBucB6AHnA+gAC+no6elG6UZG6usTAAPsAAbt7e7u
+7+8D8AESBfEAA/Ly8wAE9AAl8/nv5Onw7+7z9/j3+vr5Pfr49fHw7u7rRhPy
+H/n7+vr36y0DBQAGBAcCHgQBBQEFNAMBBQQDAQUBBQYDAAXk5AQDBQApAwHk
+AQUEAwHkBAMD5B8DAAgtFBQDFOMMBgQKAAcG1hQDFOMUAGoDAAAABPk8+TwP
++QAF+Pn4+PkABfgABPf49/gM9wAD9vYoAAb2AAP19vYACvUABPT19PUD9AH1
+BvQAA/X09QAM9AADKvTzAAb0AAjz9PP09PPz9APzAfQD8wH0A/MAA/Lz8gAD
+8wPyAfMG8gXxAfAB8APvAe4D7QAH7Ozq6ent7wAE7gAN7e3s7Ovr6kbp6Ofm
+5gAM5QHkBuUB5ATlAeQY5QHmAeUF5gAD5+bmAAfnAATo6OnpA0YABerq6xPs
+AATtAAPu7+8ABPAF8QAQKvT09fb09/jq4+rsEjny9QP5ABf6+/v6+eDy8Ubp
+7O72+fv6+fri5AMFBQAGBAcCHgQNBSsDAwUAAwMFBQAFAwMFAAMDAwUAKgMB
+5AoDAQQfAwAUFC0gAwMt4wwGCgoGDOMtAyAgLRRpAwAACvkBPAf5AAT4+fj5
+CPgABPf49/gH9wH2AfcI9gAH9fb19vX19gAH9QAO9PX19PX0KfT19PT19PUY
+9AHzBfQAB/P09PP08/QADPMABPLz8vMH8gAD8fLyAAPxAfAB8APvAe4B7gPt
+AAXs6unp7QAD7wHuA+0ACuzs6+pG6ejn5uYI5QAK5OTl5OTl5OXl5AXlAAfk
+LuXl5OXkAAPlAAjk5eTl5eTl5A/lAeYB5QXmAAbn5ufn6OcD6AAM6elGRuos
+6xPs7O3tA+4B7wHvA/AD8QAn8vT09fX09vj46Bns8hL1+vn6+/v5+ff5KfLt
+5izt8fb4+Pn68+YDAAMEAQUFBAUCCgQBAgECEgQKBQAGAwMFBQQFlgMABgUD
+DAYGDHEDAAAF+QEmD/kB+AH5BPgABff4+Pf4AAb3AfYF9wH2AfcI9gAD9fb2
+AAn1AAn09fT19OD19PUABPQB9RL0AfMI9AAE8/Tz8wP0AAXz8/Tz9AAH8wAH
+8vPz8vPy8wAH8gAE8fLx8QTwAA7v7+7u7e3s60bp6e7v7wPuAAvt7Ozr60ZG
+6ejm5gAE5QFEEeQB5QXkAA7l5ETk5eTl5OXk5eTk5QPkAAbl5OXk5eQJ5QAD
+5uXlAAfmA+cACejo6elGRurr6wAE7AHtA+4B7wHvA/AALPHx8+D19vb3+fnx
+5Onv9fj5+vn7+0X6+/nz7+wT7/Ly+Pf6+vhG5AMFBAQFFgISBAoFAQMDBQAD
+BAUFAJQDAAogAyADCQzkIAMgbgMAAAAD+fklAA/5AfgB+Qn4B/cB9gP3AAX2
+9/f29wAF9gAF9fb19vYACPUBKQX1AAn09fT09fT19PUAEvQB8wP0AAPz9PMA
+BfQB8wT0AAjz9PPz9PPz9ATzAfIE8wAF8vPy8/MABfIB8QHyA/ED8AAQ7+/u
+7u3t7OpG6enu7+/u7gPtAArs6+pG6eno5+blI+QBRAXkAAfl5C7kLuQuAAXk
+BOUB5AjlBeYD5wPoAA/p6Ubq6+sT7Ozt7O3u7u8AA/AAB/Hy9PX29vcAA/kA
+Hunk7B/3Hvb5+fv6+ffy7+zs7u/2+Pf2+/nu5BkDAwMEFgISBAwFAwQDBZMD
+AAYgAwUgAyADAwEgbgMAAAAD+SU8AAb5ATwF+QAH+Pn4+fn4+QAF+AAF9/f4
+9/gABvcAA/b39wAM9gAF9fb19ikABfUADOD19PX09fT19PX09RT0AfMD9AAF
+8/Tz9PMAA/QACfP08/Tz9PPz9AAD8wAD9PP0AAXzAAfy8/Lz8/LzAATyAATx
+8fLyA/EB8AHwBO8ACu7t7ezrRulG7u8D7gAN7e3s7OvqRuno5+fl5QAD5AAE
+GeQtFAXkAQMF5AAFA+QD5AMAB+QBGRrkAATl5OXkCOUE5gHnAeYD5wAI6OlG
+Rurq6+sE7AAD7e7vAAPwABDy8/X29vf5+vn05ubz9vf3A/sACvr3KfHy6+zx
+9/gD+QAK+/TlBAPkAwMEBBYCHAQBBQMEAAUCBAQFBQCSAwAILRTj4wMUAxRw
+AwAAEvkM+Af3AAM+9/YAA/cB9gH3BvYAB/X29vX29fYABvUB9AP1AAb09fT1
+9PUc9AAE8/T08wX0A/MABPTz9PQH8wHyBfMABfLz8/LzAATyAATx8vHxBfAA
+HO/v7u7t7Ovq6eru7+/u7u3t7Ovr6kbp6Ofm5eUE5AAJQxnkA+QDA+QDAAPk
+AQMG5AARA+TkGeTj5C0D5OQZ5C3k5C0AFOQABuXk5eTl5AflA+YD5wAJ6Ojp
+Runq6+sTAAPrABTt7u/w8PL09fb3+Pn6Hvju5RP4PAX6AA/38PHx7u/y9fr6
++fj4RgQABAMAAwUEBAAFAQUCCgEBAgECHAQABwUEBAICBAQAAwWSAwMgAAYD
+Ay0gA+NuAwAABPkABTz5+fr6AAb5A/gAA/n4+QAE+AAG9/j49/f4CvcAA/b2
+9wAJ9gH1AfYG9QARKfX1KfX09fT19PT19PX19PUADPQBKgf0AAPz9PMAA/QA
+D/P09PP08/P082jz9PPz9AAJ8wHyBPMB8gHzBvIABPHx8PED8AHvAe8D7gAG
+7ezqRkbqA+8AA+7u7QAD7AAJ6urp6ejn5uXlAAPkAAUD5AMtAwAF5AAIA+QD
+5APk5AMD5AARA+TjLeQZ5AMD5C3jGeTj5BkAFuQAA+Xk5QAE5AXlA+YACufn
+6Ojp6OlG6usD6gAr6+3u8PDx9PX2+Pj6+vnx7hPm8h35+h36+/Xw7+zu8xP5
++Dz7HOoDAwQD5AADBRUCBQQBAgECHAQFBTwDAQUBBQgDAwURAwEFAwMB5AkD
+AQWgAwAAAAf5PPk8+fn6AAb5AfgB+AP5AfgB+Qf4AfcD+AH3AfgF9wAJ9vf2
+9/f29/YoAAT2AAX19vb19gAJ9QAO4PX09fX09fX09fT19PUQ9AAD8/TzAAP0
+AAfz9PP09PPzAAP0AAPz8/QADfMABvLz8/Lz8gPzAAvy8/Ly8fLx8fDx8AAE
+7wAE7u7t7ANGAeoD7wAN7u7t7Ozr6upG6Ojn5gAG5AADIOMZAAkDAB7kA+QD
+5APkA+QDLRQt4wPkAwPkAy0DGS3j5OMZLRkR5AEuA+QD5QAD5OXkAAPlA+YA
+Nefn6Ojn5+hG6upGRuoT7u/w8vP19vf4+fr38+/s6en19/n6+fnw7+3v7/Dz
++/r7++AuBAMEAAMDAQUBBRwCHAQKBRwDGwUBBAEEAwUFAwMFEQMBBQ0DAQWg
+AwAABvkBPAT5AfgE+QH4AfkH+AAE9/j3+Az3C/YABfX19vX2AAj1AAgp9Sng
+KfT19AX1AAP09fUAA/QB9Q/0AfMD9AHzAfME9AAD8/P0AAPzAfQO8wAE8vPy
+8wbyBPED8AAj7+/u7+7t7OpG6evv8O/u7u3t7Ovq6unp6Ofn5uXl5OTjA+QA
+AwMFBRYDAAzkAy0U5APkLRTjLRQI5AEZDOQABETk5eQF5QPmBecB6ATpACpG
+6uzv8PH09ff4+fr69+Dx7evm7/r6+fXu7u/t8vT1+Pr7+/boAwMFAwQDAwEF
+FQIFAQECAQIcBAUFBQQDBRcDAQUBBRsEAAQCAgQECQURAwEFCQMB5AMDAQWg
+AwAAB/kBPAT5ABb4+fn4+fj5+Pn4+D34+Pf4Pff49/c9BPcABPb39vcD9gE+
+BPYB9QP2DfUADOD14PUp9fX09fX09Qb0ASkH9AHzA/QAEvP0KvTz9PP09PPz
+9PP09PP09ArzAfID8wHyB/MB8gHzA/ID8QPwA+8AGu7t7RNGRunr8O/v7u3t
+7BPr6urp6ejn5uXlBeQAAwMDBQAFAgEEAQQQBQAQAwNDGQMD4xktFC0UA+Qt
+GQbkARkJ5AAFFC3jAy0AB+QG5QAu5ubn5ubn6Ojn6OhG7O7w8vT19/j5+vof
+9PLv6+nn9/sd9hLt7vHw9fb0+foe7AQDAQQBBQMDAQUVAgUBAQIBAiYEAAMC
+BAUAFwMBBQEFGwQABAICBAQJBREDAAkFAwMF5APkA+QABQMBBaADAAAJ+QE8
+BPkABvj5+Pn4+QX4AAT3+Pf4C/cAA/b2PgAI9gAG9fX29fX2DPUBKQP1AAfg
+9fT19fT1ABj0AAzz9PQq8/T08/Tz8/QL8wAF8vPz8vMACfIB8QHyA/ED8AAk
+7+/u7u3r6urp7PDw7+7u7ezs6+oYRujo5+fm5uTkLeMZAwMFCAIOBAMDAAwZ
+4y0ZA+TjLRQt5BQI5AHlCuQBGQPkAAMZAxkAA+QACS7k5eTk5eTl5QAF5gAx
+5+fm5+nr7vDy9Pb3+Pn6+ff18/DsRuXw+fn3K+7y8fXz8fb7+vLlA+QDAwUC
+A+QDBAAcAiYEAAMCAgUAGAMDBRwECgURAwEFDQMBBaADAAAG+QAD+Pn4AAP5
+AAk8+Tz5+fj5+DwABfgACff49/j39/j3PQAE9wAD9j73AAb2AT4B9QP2AAMp
+9mcABPUBZwb1ASkE9QHgASkD9QAF9PX09PUAB/QB9Qr0AAfz9PP09PPzAAP0
+AATz9PP0BPMB9AbzAd8F8wHyBfMB8gHzA/ID8QTwACjv7+7u7OvqGEbt8PDv
+7+7t7Ovr6urp6ejn5ubo5eQZ5C3jLQMEAgEBCAIGBAQFBwMACOQD5APkA+Qt
+B+QACeXk5eTl5OXk5AAF5QAE5OXk5QTkARkD5AAH5eTk5S7k5QAD5gAo5+bn
+5+jr7vDz4Pb4+Pr6+ff18/HtLOfp9fHx4vLv9vng9vb69ucD5AQDAQIBBQMD
+AQQZAg8EAQIBAhkEAwUVAwADBQQCABwEDQUKAwMFsQMAAAX5AzwD+QAHPPn5
++Pn4PAAD+AE8A/gABz34Pfj3PT0ABfcAFj4+9/f29/Y+9vY+9vX29Wf29vX2
+9WcE9QFnA/UADuD19Wf1KfX09fT19PT1A/QB4A30AfMF9AHzBPQABPP08/QD
+8wH0DfMABfLz8/LzAAfyBPED8AAO7+/u7uzq6kZG7/Dw7+8D7QAQ7CzqRunp
+6Ofn5ebl5eQDGQMDAAQEAgEBCAIFBAYFAAsDA+QDA+QD5APkAwAN5AAF5eTl
+5eQABeUABObm5eYN5QAF5OXk5uUABOcACujn6u4S8/X3+PkD+gAX9/bz8e7s
+Rubt9e/u7/T2+ff7+vrr5OQAAwMABOQDBQQDAwEFKgIZBAMFFAMABOQFBAIc
+BA0FCgMDBbEDAAAD+QAGPPn5+Pk8A/kACDw8+Tz5PDz5A/gADD34+D34Pfgf
+9z33PQT3AAP29z4ACPYADGf29mf19mf19fb1ZwT1ASkF9QAH4PX19PX09QAK
+9AEpAeAF9AHzA/QAD/Pz9PP08/Tz9PTz9PP09AAF8wH0CPMAA/Lz8gAE8wHy
+AfMD8gAE8fLx8QTwABrv7+7u7OpGRurw8fDv7+7t7BPr6kZG6ejn5wPlAAvk
+A+QD5AMDBAIBAQAIAgUEBQUEAwAK5AMD5OQD5APkAwnkAAbl5OXk5eQF5QAD
+5uXlAAjmAeUB5gTlA+YABi/k5ubn6APnAAfq7vHz9ff4AAP6ABr59/Xz8e/t
+6+jm8vArEvj4/Pz9+vHkAwPk5AMDAQUBBQMDKwIZBAMFFgMBBAECHAQaBbED
+AAAB+QE8A/kABTz5+Pk8AAP5AAc8+Tz5+Pg8AAj4AAYf9z099z0F9wAHPij3
+KD72PgAD9gADPvb1AAP2AfUB9gf1ABPg9eD19Wf19SngKfX19PT19PT1AAb0
+AeAQ9AAG8/Tz9PP0A/MABPTz8/QJ8wAK8vPz8vLz8vPy8wTyACDx8UHx8fDw
+7+/u7uvqRkbq8PHw8O7u7ezr6+rq6eno5wPmAAPl5OQABAMABQUEAgEBAAgC
+BQQFBQYDAAnkA+QDGUMZ5BkAB+QB5QPkAeUB5AflAAPm5eUAA+YABOXm5eYD
+5QAu5uXm6Ofq6+nn5ubn6Ofn7O/y9Pb3+Pr6+fn3KfPx7+3s6eXq8+D2+0X8
+/Pv25QPkAAYDA+QDAwQEAysCGQQDBRUDAAMFBAIAHAQaBbEDAAAACSb5+Dz4
++fg8+AAD+QAKPPn4+fn4+Tz4PAP4AAU9Pfc9PQAH9wAIPvb39j729j4D9gAR
+PvX29vX29Wf1Z/Vn9Wf19SkABvUAC+D19eD09fT19PTgAAz0AATz9CrzBPQA
+C/P08/T08/Tz9PP0ABDzAAny8ivz8vPy8vMAA/IB8QHyA/ED8AAb7+/u7hPq
+Rkbr8fDw7+/u7ezs6+pGRuno5+fmAAPlBOQABgMEBAIBAQgCBQQGBQQDAAot
+FC0ULeMZLeMtBeQB5QPkAAXl5OTl5AAH5QAF5ubl5uUAA+YB5QHmBOUACubn
+6Ozt7Ovp6OgD5wAh7eLy9Pb4+fr5+fj29PLx7+3rRufn8/b5+vwhRfnq5OQD
+AAPkAAUD5AMDBAADAxoCDwEBAgECGQQDBRUDAAMFBAIAHAQaBQcDBQWlAwAA
+AAg8+Dz4PPg8+AT5ABD4+Tz5+Dw8+Pg9+Pg9+Pc9BPcBPQT3AAc+9/c+9vY+
+AAP2AAg+9fb2Z/Yp9gn1AAvg9Sn19Sn1KfVAKQADQAAH9EAp9ED0KQAF9AAE
+QPT0QAX0AWgD9AAJ8/T08/Tz9PP0AAPzAAb08/P08/QL8wAF8vPy8/MABfIE
+8QTwABDu7+7s6kZG7fHx8O/v7u3tA+sAEurp6ejn5+bm5eXk5C0UA+QFBAoC
+CAQAEQIEBQMD5AMULRQt4xkt4xnjAAjkABPl5OTl5OXk5eXm5ebm5ebl5uXm
+AAflACvm6Ofq7evr6kbq6Ofo6e7w8/X3+fr5+fj39fTy8O/t60bo5fD4+/oh
+/PruAAXkBwMABAUD5AQoAg8EAQIBAgoEBAUDAwHkDwMABOQFBAIfBA8FAQQB
+BAgFFAMDBZgDAAAB+QE8BvgADDz5+Tz4+Dz4PPj4PAP4AAc9+D099z09AAP3
+AAko9z739z739j4ABfYACfX29vX29fb19gAE9QHgA/UAAyn14AAD9QAW4PVA
+9UD1QPVAKUAp9PTg9Cn04PT0KQX0AWgD9AAK8/Tz9PP09PP08wP0AAPz8/QA
+CvMACPLz8vPy8/LzBvIF8QPwAB3v7+7u7CzqRu7x8fDw7u7t7Ozr6upG6eno
+5+bm5QAD5AEUAS0DAwAEBAIBAQcCCAQBAgEEBwMAB+TkA+QD5C0ABOQACeXk
+5eTl5OTl5AAG5QAL5uXl5uXm5ebl5eYABeUALOfn6e0T6+rqRunmA+fp7/H0
+9vj5+vn4H/b08/Hw7u3r6unl6vv39ftF9OUDBeQBAwHkAwMABQQFAwMFADIC
+BQQBAgECCgQFBRQDAQQBAh8EDwUBBAEECAUUAwMFFQMB5AcDAeR6AwAAA/kD
++AAOPPj4+Tz5PPj4PPgnPD0D+AAE9/j3PQP3AT0D9wAGPfc+9z73BfYAHGc+
+9mf2Z/X1Z/X1Z/Vn9Sn19UD1QCngKeApQCkDQAEpAfQFQAAK4Cn09ED0QPTg
+QAv0AAvz9PPz9PTz8/Tz9AAF8wH0CfMB8gPzAATy8/LzBfID8QTwACDvMO7t
+6+pG7vLx8O/v7u3s7Ovr6kbp6Ofn5ubl5eQD5AQDAQQDAQcCCQQBBQQDAAvk
+A+QD5APkA+TjGQAG5AAH5eTl5OTl5AAD5QAM5uXl5ubl5uXm5eXmBeUAK+fn
+6Ozs6+rqRunn5eXqLPDy9ff4+h75+Pb18/IS7+7t7OpG5+b4RfxF+OkABOQA
+BAPkA+QEAwAFBQQDAwUAMgIFBAECAQIKBAUFEwMAAwUEAgAfBA8FAQQBBB8F
+GwMB5HwDAAAAA/n5PAAF+QAGPPn5+Pj5A/gBPAP4AAM9PfgABj0AEPc99z33
+9z0oPSg+PvZnZ/YE9QAa9vVn9fVn9fXgKeApQPVA4PQp9EBA9ED0QPQDQAH0
+BEAADfRA9PRA9ED09ED09EAABfQB8wb0AAnz9PTz9PMq8/QACfMB3wTzAAXy
+8/Py8wAE8gAD8fLyAAPxAfAB8APvAA7t7Ovr6u/y8fHv7+7t7QPrAA/qRuno
+6Ofm5uXl5OQZA+QAAwMKAgkEBAMB5AMDAAbkA+QD5AMG5AAI5Rnk5OXk5eQF
+5QHmA+UABebl5uXmAAflACrn6Czt6+vqRkbo5OTsE+3x9Pb4+fr5+Pb1KvLx
+7+/t7BPqRujk7kVF+u4H5AALA+QD5AMDBQQFAwUAOQIKBAMFAAQEBAUFEQMA
+AwUEAgAMBC8DFAUVAwAF5APkA+QAAwMB5HoDAAAB+QEmA/kACjz5PPj5+Dz5
++PgDPAAEJzw9+AQ9AAb4Pfg9PScFPQAG9yg+PvZnA/YAFWf2Z2f1Z2f1Z/Up
+QClA9UD1QClAKQADQAH0BEAAB/RA9CpA9EAAA/QAEWj0QPRA9PRA4PRA9PRA
+9PQqAAn0AAVo9PTz9AAD8wAEaPPz9ATzAAgr8/Lz8vPy8gPzBPIE8QTwAAjv
+7u7s7Ovr8APxABLw7+7t7Owy6+rqRuno5+fm5eUD5AYDAQUBBAcCCAQABAUD
+AxkEAwAG5APkIOMgCOQABuXk5eTl5AjlAAjm5ebl5ebl5gXlABPn5+nt7Ovr
+Runo5uTn8Orw8vX3AAT5ABT39vTz8fHv7u3s6+pG6OXpHPvy5QXkAA0D5OQD
+5AMD5AMEBQMDACgCBQEFBAcCCgQDBQEEAQQDBQ8DAATkBQQCCwQxAxMFHAMB
+5HsDAAAAF/n5PDz5+Dz4+Tz5+Dz4PD08+Dz4PPj4AAo9ABb3Pfc9Pfc+PvY+
+4Gf19Wf19Sn19eApDUAADvQqQPRA9PRo9Gj0aPRoDPQACCr0QED0KkD0A0AB
+aAFABvQAA/P08wAD9A3zAAPy8/MAA/IB8wPyAfEB8gPxA/AABO/v7e0D7AAW
+8PLx8fDv7u7t7BPr6kZG6enn5+bm5QPkAAkDGUMgAwMFBAIAAwEDAgUEAwUF
+AwAK5AMtA+Tk4xnjLQbkAAjl5OXk5eTl5AblAeYD5QHmCOUAK+bo6OwT6upG
+Runm5OXv7e3x9fb4+vr59/b08/Hw7+7u7Ovr6kbo5uT1+OcACuQBAwHkAwMD
+BAEFAwQ0AgUEAQIBAggEAQUDAwHkEQMBBAECCgQzAwUFAQQBBA0FCgMBBQEF
+CAMABeQD5APkAH0DAAAADPn5Jjw8+fj5+Dz4PAT4AT0B+BE9ABUoPfc99z72
+Zz72Z/bgZ/Vn4OBA4EAABSkABUApQEApAAlAAAQqKvRoA/QAC2gq9PMq9PP0
+8/RoAAT0AAtoQPRA9Cr0KkD0aAAE9AAK8/Ro9PNo8/Tz9AjzAATfK/PyA/MF
+8gXxA/AAA+/u7gAE7AAW8fLx8fDv7+3s7Ovr6kZG6ejo5+fl5QTkAAPjGeMA
+AwMBBAECAwEDAgUEAwUEAwFDAwMABxQtFOQt5AMAA+QAB+Xk5OXk5OUAA+QD
+5QAD5uXmAAPlAeYI5QAt5Obn5ywT6kZG6unn5eQT8+vw8/b4+fn49/b08vHw
+7+7t7ezr6upG6Ofk7u0DAAPkAQMG5AAFA+QDAwUAAwQBBQMEOwIIBAEFAQUT
+AwADBQQCAAkENAMFBQEEAQQNBQoDAQUBBYoDAAABJgY8AAP4PTwAA/gBPQH4
+DD0ABD49Pj0EPgE9Bz4ADfZnPmf29mf2Z/b2Z/YABGcADPX2Z/X1KfVnKfUp
+QAQpAA5AKkAqKmgq9Gho9PP0aAX0ABVo9ED09Gj0QPRA9CpA9Gj09Gj09PMA
+A/QN8wAG3/Pz8vPzBvIAA/HxEgAD8AAd7+/t7Ozr7PHy8fDw7+/t7ezr6+pG
+Runp6Ofn5eUAA+QACS0tAwMtFAMEAgADAQMCBQQEBQMDAAwZA+QDLRQt4xkD
+5BkG5AAF5eTk5eQACOUB5gvlACvn50bsLOpGRunn5eTl9ezu8eD2+Pn5+Pb0
+8vHw7+7u7OwT6+pGRunm5OjlAAnkAAcD5OQD5AMDAAMEAQUDBDsCCAQDBRID
+AAMFBAIACQQ1AwQFAQQBBBAFkwMAAAAHPDz4+D34JwAD+AQ9AfcJPQAEPj0+
+PQo+AA72Z/b24Gf24PZnZ/Zn9gNnAT4BZwM+AARnKWcpBGcACiln9Sln9Wf1
+ZykDQAAZ9CpoKvNo9Gj082gqaGj0KvQqQPRAaPQqQAAI9AAHaPQq9PNo9AAN
+8wAN8vMr8vPy8vHy8fLwQQAD8AAD7+/uAATsAAjx8vHx8O/u7gPsAATr6uoY
+A+kABOjn5uUD5AAFGeMZ4xkAAwMBAgMBAwIFBAQFBwMABxQtGeQt5OMABOQD
+5QAE5OXk5AblAeYE5QHmBuUALOTl5ufo7OrqRkbp6Obk5e7y7PHz9fj5+ff2
+9PPy8O/u7e3s7Ovr6kbp6OblBeQBAwfkAQMB5AMDAwQBBQMEOwIKBAEFAQUQ
+AwAE5AUEAgkENQMGBBEFkgMAAAAFPPj4J/gACz0AAz49PQAPPgNnAAM+Zz4A
+B2cD4AZnAT4ZZwRAABgqQCpoKmjzKvRo9Gj08yr0KvT0aEBo9EAE9AAI8/T0
+aPT08/QL8wAFK/Pz3ysABfID8QXwAAPv7e0AA+wD8gAK8UHv7+3t7Ovr6gNG
+AAfp6ejn5uXlAAPkAwMABS3kAwMCAAMBAwIFBAQFAwMAC+QD5AMt4y0U5AMZ
+AAfkAATl5OXkCeUB5gflACHk5eXm5+oT6kZGGOjm5OXq9uvv8vT3+Pj39vXz
+8e/v7e0AA+wB6wPqAAVGRufn5QAL5AAHA+TkA+QDBQADBAEFAwQ0AgUBAQIB
+AgoEAQUBBRIDAQQEAwYENQMGBBAFEQMBBYEDAAAAAzz4JwAJPQQ+AT0GPgFn
+AT4DZwE+D2cAA7pnugAFZwG6BmcBugNnAAq6Z2e6Z7q6Z2e6BGcABSlnKSln
+AANAAWcDQAAPaCrzaGj0aPTzaPRo8/RoAAX0ABDzKvP0aPRo9PTz9Gjz9PMq
+BfMAByvz3/Pf8vMABPIB8QHyA/EE8APvAATt7eztA/IABRLw7+7uAAPsAesB
+6gNGAAfp6Onn5ublAAbkAAUU5AMFBAAEAQcEAwUJAwADGeMtAAjkAAXl5OXk
+5AAH5QHmC+UAIeTm50bsRkYY6ejm5eXm9O7u8Sr2+Pj39vTy8fDv7ezsEwAD
+6wAK6kZG6eno5ubkAw3kAwMBBQQEAAMCAQEAOgIKBAEFAQUZAwUEMwMKBAUF
+AQQBBAUFEgMB5IEDAAAHPQQ+AT0FPgFnAz4FZwE+BGcBuhFnA7oAA2dnugAG
+ZwG6A2cBugVnAAS6Z2e6A2cABilnQEC6KQZAABO6QED0aPTz9N/zaPRo9Ggq
+aPTzAAT0AArz9PTz9PRo9PNoCfMADCvzK/Mr8/Lf8vLx8gPxAfAB8ATvABPu
+7ezt3/Lx8fDv7u3t7BPr6kZGAAPpAAPo6OYAA+UE5AAJA+QDAwUEAgEBAAYC
+AQQBBAMFBwMABuMZLeTkFAXkAeUD5AAE5eTl5AXlAAPm5eYAB+UADeTl5Obn
+6Ovq6kbp6OcAA+UAEu7wE/Hz9vf3KPb08/Hv7u3s7APrA+oAB0ZG6enn5+UA
+DuQEAwEFBAQAAwIBAQA6AgoEAQUBBRoDBAQzAwoEBQUBBAEEBgWTAwAAAAQ9
+PT49Bz4BZwE+BGcBPgZnAAa6Z7pnuroDZwG6AWcGugFnDLoBZwe6AWcDugFn
+C7oAC2cpQEAqukBAZ0C6AARAAAP0aPQABmgAFypo9Gj0KvP082jz9PRo9PPz
+9PP08/NoAAXzAAkr3/Pz3/Lf8isABPID8QAE8BLw8APvACnu7u3uK/Lx8fDw
+7+7t7Ows6upGRunp6Ofm5+bk5eTkAwMtFC0DBQIBAQAGAgAEBAQFBQUDAAnk
+AyAD5BTk5C0ABuQABuXk5eTl5A3lACXk5OXl5OXn6OrrRunp6Ofl5eTq8uzw
+8vX29/f29PLw7+7t7OvrAAPqBEYAC+np6Ofm5eXkA+QDAAjkAQMB5AMDAQUE
+BAADAgEBADoCCgQDBRoDBAQxAwsEBQUBBAEEBgURAwHkgQMAAAc+AcwNZwW6
+AANnumcACLoAA2i6aAADugAJaLpoumi6aLpoAA26AWcUugFoA7oBaAO6D2gA
+FfMq9Cpo8/RoKmgqKmgq8ypo82jzaAAD8wAHK/MrK9/fKwAD8gTxA/AAKu/v
+7u7t7e/z8vHx8O/u7u3s7Ovq6kbp6Ubp5+bl5ubl5OXk5BQtFAMFBAgCAAQE
+BAUFBwMABuMD5C0Z4wPkAAoZ5OXkGeXk5OXkDuUD5AAg5ebn6evqRuno6OXl
+5Ofw7e/z4Pb39/b08vHv7ezs6+oGRgPpAAXo6Ofm5gAG5AADA+QDAAXkBAMB
+BQQEAAMCAQEAOgIKBAEFAQUbAwUELwMTBAYFkwMAAAM+AWcBPgZnAboBQAW6
+AUAEugFoAWgDaQRXAbsBVwS7AVYBuw9WA7sFVwAKaFdXaFdoumm6aAm6AANo
+umgABLoACGi6umi6umi6EGgAEfRoKmj0aPNo82gqaPNo82grAAPzABPf89/z
+K/Jp8vLx8vHxQfHw8O/vAAPuABft7/Py8kHw7+/u7ezs6+tGGOlG6kbp5gAF
+5QAM5OQD5OQD5AUFBAIEBQEAAwQEBQAEAwAL4wMDLQPkA+TkLRkABeQABOXk
+5OUD5ArlACTk5eTl5OXk5efo6+rp6ejn5uXl5u7t7vL09vf29fTz8O7t7OsD
+6gNGBukACejn5ubl5APkAwAL5AMDAQUEBAADAgEBADoCCgQBBRwDBgQrAxYE
+BgUEAwAD5APkAAoDAeSBAwAACGcABLq6Z2cEugFoA1cDuwRWAB6zs7aeOp5r
+vLyfvJ+yn5+yyp+yyrKfsp+fsp+8vJ8DvAAFa562nrMABVYBuwG7BFcABmho
+ule6aAa6AANoumgAA7oABGi6aLoKaAFpBWgADPRo9Gj0aCpoKvMq3wTzAAlo
+K/PzK/Mr3/MABPIE8QPwAe8B7wTuAA/v8/LxEvDv7+7t7ezr6+oAA0YABOoT
+6ugD5APlA+QABwPkA+QDBQQABgIAAwQCBAAFAwAIGeMg4yDjGUMJ5AHlAeQN
+5QAl5OXk5OXk5ufo6upG6Ojn5i/l5Ubt7fHz9fb29fTy8O7tEyzq6gAG6QHo
+AekD6AAF5+fm5uUABeQAAwPkAwAG5AAFA+QDAwUABAQAAwIBAQA4AgAEBAIB
+AgkEHQMFBCgDGQQGBZMDAAAABGdnumcDugAIZ7q6aVdXu7sDVgAIs562nry8
+n7IFjgAKtY61QkK1tWpqtQ9qBbUBQgHTBI4ADZ+yn7y8nrazs1ZWu7sABFcA
+BWhXumhoAAO6AWgBaAO6AAtoumi6aGi6aGloaQAHaAAO82j082jzaPNoaPMr
+aCsH8wHfASsE8gAK8fLx8UHwQfDv7wPuACDt8PLy8fHw7+7u7ezs6+tGRunq
+6+3t7Ebp6Ofm5BnkRAPkAwMHAgAQBAIEBQMZLQMDLRTkFC3jGQbkAAfl5OXk
+5OXkAArlACXk5eTk5eTk5udG60bp6Ofm5uTl6O3t8PP19vb08/Hw7uzr6upG
+AAPpCegABefn5ublAAPkAQMJ5AAGA+QD5AMFBAQAAwIBAQA4AgAEBAIBAgkE
+AQUcAwQCJgMcBAYFkwMAAAO6AA5oaGlXu7tWVrO2nryfsgOOAbUBQgRqAAds
+amy0bLQxAAO0AAMx1rQACn4B1gHWA34G1gAFMbS0bLQAA2wADmq1tUK1Qo6O
+n7K8Op6zA1YBuwG7BFcGaAG6BGgBugFXBWgBaQNoABFpaGjfaGjzaPNoaPPz
+aPPzaQAD8wAGaPMr3ytpBPIAB/HxOfFB8OIAA+8AEu7t7vDy8vHw8O/v7u3t
+7Ovr6gNGAewB7gPwAAjv7+xG5+XkGQPkAAUZAwMEBAAFAgADBAIEAAUDAAfk
+FAPkLRQtAArkAATl5OXkCOUAKOTk5eXk5eTk5ufp6urp6Ojm5uXl5+rt8PP0
+9fX0K/Hw7uzr6kZG6ekF6AAE5+jn6APnAAbm5uXl5AME5AEDB+QBAwHkAwME
+BAADAgEBADgCAAQEAgECCQQdAwECAQIoAxwEBgWTAwAAAApXu7tWs7aea5+f
+A44DtQAKamxqbDG0Mda0tAZ+AAZYfn5YRFgHRAAD40TkAA1EAAXlRC4uWAAE
+fgAEL9bWtANsAAxqarW1jo6yn7y8a7MDVgG7BFcEaAG6AboGaAADumm6AARo
+ACTfaN9oaWjz82gr8yto8/NpK/Np8yvyK/JX8fJX8fESQfDw7+8D7gAV7fDy
+8vFB8O/u7u3s7Ovq6kbpRuzwAAXxAAXv7Ebo5QAF5AAEQwMFBQUCABAEAgQF
+5AMD4wMtAxTkIOMZA+QACxnl5OXk5eTl5OXkAAnlACbk5eTl5OXn6OrrRuno
+5+bl5eZG7fDy9OAp8/Lw7+3s60ZG6eno5wPoCOcD5gHlA+QAAwPkAwAK5AAE
+A+QDBQQEAAMCAQEAOAIABAQCAQIJBB0DAQIpAxwEBgWTAwAAAAeztryfyo6O
+AAO1AAhqamxstDHWtAN+AAhYWER+WFhEWANEABNYQy1DQy1ERC1D4y1D5C3j
+LeNEAAUtAAZDREQtQy0DRAAILVhELURYLlgFfgEvAdYDbAAEamq10wOOABa8
+nmuzs1a7u1dXaWhpaLpoaGloabpXA2gAFWloaWjfaN9oaSto32jzaCvzaGnz
+8wADaQPyBPEAHkHx8OLv7+7u7e7iK/LxEvDv7u7t7ezr6+pG6Ubs8ATyAAfx
+Eu7r6eblAATkAAQZAy0EBQIADwQCBAUDA+QDGUMZLQPjLQAE5AHlBeQAA+Xk
+5AAK5QAk5OXk5OXk5ufp60bp6Ofm5eTm6e3w8ir09PPy8O7t6+pG6enoCOcA
+CObn5+bn5+bmA+UB5AEDBOQBAwfkAQMB5AMDBAQAAwIBAQA4AgAEBAIBAgkE
+RwMcBAYFkwMAAAHTA7UAJGpstNa0tNZ+flh+RERYLlhYLkNYRENEQ0RDLS1D
+LkQuLkQuQwMtBEMACi0tIEMtQ0RYLUQDLQEuBC0BRAEtBEQAJC1EQ+RE40Qu
+RC5Yfn60fi+0MWxsakKOyrK8vLNWVru7V1dpaQNoAA26aLpoV2ho399oaWhp
+AAVoAAtpaGjfK/PzaSvyKwAD8gAPOfLxOfFB8DY27z/u7e42AAPyABDw8O/u
+7u3t7BMs6kbpRuvwBfIABvHw7uvo5gPkAAUZLRQDBQAFAgMEAQUEAwAHQyDj
+A+TkGQAH5AAH5eTl5OTl5AAG5QPkACPl5eTl5Obn6OpG6efm5uXl5unt8PLz
+9PTy8O/t7OvqRuno6AAF5wzmAeUG5AEDCeQBAwHkAwMEBAMCAQE3AgAEBAIB
+AgkEAQVGAxwEBgWTAwAAAAhsbLS0frR+tARYAAREWENYA0QAAy1EWAAGLQNE
+AS4BLgZYAAovtGa0ZrRmZrRmBLQAA35YWAADLgADWFi0AANYAAYtLi0tICAE
+LQAMRC0tRC3jROMORERYA34AB9bWtGxsarUAA44AB546s1ZWu7sABFcACWhX
+aLpoaWhp3wAEaAA3aWhpaGhpaWhoK98raWnyafI58rvx8UFB8OLY7z/u7e3i
+afHxQe/vMO7t7ezr6+pG6ejq8fLy8wAD8gAN8e/tRuflLuXk4y0DBQAFAgME
+AQUEAwAFGeMD5AMABeQAA+Xk5QAF5AHlAeQF5QHkBOUADOTl5OXl5ujqRunm
+5gTlABHo7e/y9PTz8vDu7OvqRuno6AAE5wjmAeUE5gTlAATkA+QDCeQAAwPk
+5AADAwEFBAQDAgEBNwIABAQCAQIJBEcDBgQDAxMEBgWTAwAABH4AA1hEWAAD
+RAAEQ0QtRAUtABBELS5YWLRUVWVlnYycm42vBIsDmQAEqJmZiwaZAAeLmYuu
+i62LAAOwAZwDnQARZVVmZlhYLi4tLVguLS1ELUMABC0ABkNEQ+VERAN+AA7W
+bGxqtbWOn7y2s1a7uwVXAARpaWhoB2kAB2hp32hpad8AA2kANPJpK1fy8vHy
+OfHxQTY27zDuP+3tQfLy8fDw7+7u7e3s6+vqRunq7PDz8vPz8vLx8O8s6eUE
+5AADGQMDAAUCAwQACwUD5APkAwPkAxktAAfkACTl5OXk5eTl5OXl5OTl5OXk
+5OXk5OXm6Onq6ebl5eTl5enu8fID8wAN8e/t7OtGRuno5+fm5wAP5gPlBuQB
+AwjkAAYD5OQDAwUEBAMCAQE3AgAEBAIBAgkERwMEBAcDEQQGBZMDAAAAGETk
+5C0uQ0RDLUMtLVguLmZmVFVlnIyLiwOZAZgBmASoAAmhqJmomZmomIsAA5gA
+FqiZmZiYmZiYoZioqJiYqqiZmKiYmZkDiwAKr5ydZVVmMVhYLgYtAAouIC0t
+40PkRETkA0QADX7WtGxqao6OvLy2s1YAA7sBVwFXBGkABd9paGloAANpAVcD
+aQAE32nyaQTyABVX8vHxOUFB8OIw2D/t7u1B8vLx8PAAA+4B7QPsAAfr6urp
+6/DuAATzABDy8/Hx8O3q5+Xl5OXkAwMEBAIDBAEFAwMACBQD5AMt4+QZBOQA
+COXk5eTl5OXkA+UB5APlAA3k5eTl5eTl5ubp6unnAAXlABJG7xLy8/Py8O7t
+7OpG6ejo5+cG5g/lA+QAAwPkAwAL5AMDAQUEBAMCAQE3AgAEBAIBAgkERgME
+BAkDEAQGBZMDAAAAGOQtLi0gLS1YWLRUVZ2wr4uLmZmoqJmomAOoAAWnqJmZ
+pwADqAAFqqiZp6oAA6gAEaqZiqqqqKiqqKiqqqinqqeZAAWoAASqi5moA5kA
+DouLrotSsJ2dsmZmWFguBi0EQwAV5EMtRORE5X7WtGxqtdOOvJ6zVla7AAVX
+AAXfV99X3wAJaQAQ8mlp8mnyOVc58UFB8DbvMATuAAzx8jnxQfDv7u7t7ewD
+6wPqAAPy7/IABfMACPLx8fDs6eblBOQBAwEEBAIDBAEFAwMACC0tFAPkA+Tj
+A+QAC+UZ5eTl5OXk5eXkAAPlABbk5OXl5OXk5OXm6EZG5+bk5eXm6+/xA/IA
+CvHv7uzrRkbp6OcE5gHlAeYI5QHkCOUD5AEDDeQBAwHkAwMEBAMCAQE3AgAE
+BAIBAgkEAQVEAwQECwMPBAYFkwMAAANYABC0VFWMnIuLmJihmKGop6inA6oA
+CKinqKeohqinA6gACaeqp4anqqqGqgAEqAADp6qGAAOqACqooaiqqKeoqqeo
+qpmqmYSomaqqqJmqqouLmKGYmZiurrBlVVQvWC4tLkMDLQAJQ0RDQy3j5ERE
+AAN+ABUxbGpCjsprnlZWu7tXV2lX31ff31cAA2kACt/f8mny8mk5V/IE8QAJ
+QeLv2O4/7u0/AAPyAAvx8O/vP+7t7OwyEwAE6gAG8vHy8/P0A/MACPLxEu7r
+6OblA+QAEgMFBAICAQQEBQMD5AMDFOTkAwfkAAjl5OXk5eTl5APlAeQD5QAg
+5OTl5OXk5ufpRujm5eTk5+7w8vIr8vDv7ezqRuno5+cD5g7lAeQE5QHkAeUE
+5AADA+QDAAjkAAsD5OQD5AMDBAIEBAADAgEBIwIHAw0CAAQEAgECCQRDAwYE
+CwMPBAYFkwMAAAAEVbGciwSZAAyqqKqoqJmoqJmoqqgDpwBPhKeop4Snp4Sn
+qKeGUIaqhoanp6iohKiqhqqohIaqhIaGqIaGp6eqp6iGp6qnqqqYqKqoiouG
+mZmYmZiZmL2YmK6Lr41lVDFYLS1ELS1ELQADQwATRENYRER+L9ZsarWOjp6z
+fVa7uwAGVwNpAVcDaQALV2ny8lfxV/FX8UEAAzYBMATuAA/y8vFB8OLv7u3t
+7OwT6ywAA+oD8QHzAfMD9AAU8/Ly8fDtRufl5OXk5AMEAQICBAQFAwAI5AMD
+5C0ULRkE5AAJ5eTl5OXk5eTkAAPlAAXk5eTl5QAD5AAM5ebo6unn5eTlRu5B
+A/IACvHv7uzrRuno6OcD5gjlAA7k5eXk5eTl5OXk5eXk5QPkAAQD5OQDC+QA
+CQPkAwMFBAIEBAADAgEBIgIJAwwCAAQEAgECCQQ+AwsEDAMOBAYFkwMAAAGr
+AZgDqAAPmKiomaqoqKeoqKKnp6iqAAOGACiop6Knp7ejhLejp4Snp6OEhKeE
+p6OnoqOEhqejhpKphKeEp4anp4SEA6cABoSnqKqrpwOqABiZi4qZmJmoqpio
+i5mZi4uZmK6vsJ1VtFgGLQAUQ0NEQ0NEQ0R+frRsarVVn7yzs1YDuwRXA2kA
+G1fyaWlXV2lX8fI58UFB4u/YMO7tPyvy8fHi7wAD7gAF7ezs6+sABOoAF/Dy
+8fP09PP09Cvy8fDv6+nm5eTl5AMDAAMEAQUFAwAF5APk5AMACOQABuXk5eTl
+5ATlACHk5eXk5eTk5eTl5+hGRufl5Ofs8PHx8vHw7u3s6kbp6OcAA+YE5QAU
+5OXk5eTk5eXk5eTl5OXk5OXk5eUE5AAFA+QD5AMACeQACQPkAwMFBAIEBAAD
+AgEBIgIKAwsCAAQEAgECCAQ/AwoEDgMNBAYFkwMAAAATqKqop5mEp6inhKei
+qKK3o6enqAADpwAEhKeEpwOEADCnt4S3p4SRXYSSp4SEkoSEkaOEkqOio6en
+eISEdpKEhHanhIZQhoanqqiGp4a9vaoEhgGLA6oDmQGoA5kADZiYma6YrrCc
+VbQuWC4AAy0AFENDLQND5ENERH7WbGy1jrK8s1ZWA7sEVwAM8ldp8lfyOfI5
+V/E5A0EAHFY2Pz/u7vJX8UHwMD/u7e3s7Ovr6upG6u/z8vMF9AAR8/Ly8fDt
+LOfl5OTl5BQFBAUABQMABUMDA+QDAAPkAQMD5AAf5eXk5OXk5eXk5eTk5eTk
+5eTk5eTl5ufp6ujm5kbtEgAD8gAMEvDu7OpG6ejn5+bmBeUACuTl5OXk5eXk
+5OUD5AAE5eTk5QfkAQMM5AALA+TkA+QDAwQCBAQAAwIBASECCwMLAgAEBAIB
+AggEPwMKBA8DDAQGBZMDAAAABL2hqKIDqAAkp6ejqKGop7eno6ehp6eGt4S3
+p7eTqXaSqXiSo5KSo5JzkqOEBJIALZCSo6ephHa3hJKEhHOpqainhIaErKGY
+qqKEqKqKrIaGUKqnhqiGp6iomYuZhgAEmQAKq5mYma6vjY5mLgMtABVYLS0D
+QwNDRORE5H60tGq1jrKzs1YABbsABVc5aWnyAANXABNp8bs5u0E2QdgwP+62
+OfI5Qe/vAAPuAAXt7BPr6wAD6gAFRu7z8vIABfQACvPz8vHx7+xG5uUD5AAD
+LQUFAAQDARQDAwAF5APk5AMAB+QAG+Xl5OXk5eXk5eXk5eXk5eTl5OXn6Orp
+6Ojs8AAE8QAL8O7t6+rp6ejn5+YAA+UABeTl5OTlAAbkAeUP5AAFA+QD5AMA
+C+QACQPkAwMFBAIEBAADAgEBIQIMAwoCAAQEAgECBAQjAwECHwMFBBQDDAQG
+BZMDAAAAGqGop6eop6Ono4Sgp6Kho13FhKmIhLephJGRBJIAUXOTkpOTkYKT
+gqN2k5KTknORXZCSkaOpt5KFdnaEqXaEk3Z2t6mphqqooamphIWEqYS3p6eG
+qKqoqoaKhpmZqqiZqJiZi5iZmJmumK+cVbQuIAAELQRDAA9EQ0REfn5sakKy
+vLazP1YAA7sACjlXV/JX8VdX8vEDQQAaNjbi7z/uQfLxQeLv7rbta+wy68rq
+Rurq7/ID8wAV9PT19fTz8/LyEu8T6ebk5OXk5AMFAAMDAAotA+QDA+QD5OQZ
+BOQAKuXk5OXk5eTk5eXk5OXk5eTk5eTl5ujp6Onr8PHy8fHw7u3r6kbp6Ofn
+5gblAeQB5QPkAAPl5OUAEeQAAwPkAwAO5AAGA+QD5AMEDQIFBRUCDQMKAgAF
+BAIBAgQAJgMBAiADAwQWAwEEAwUKBAUFBQMBBQEFigMAAABXqoaqhKKnp5KE
+kqeEp6eSkoSSk7eSeHZ2kYSSkoKRkaOjk5KRkpKTo7eFo6eSkpGSkJGSp6mF
+hXh2hJJzdpN2k3N2doSEhoiphHajhJKEhoaEhoWnhoaqAAWGA6oACZmoiqqq
+qJiLmAADiwAKrrCcVbRYLkRDQwMtAUMBQwNEAAp+tGxqtY6ynrOzBLsAJzm7
+8ldp8bu7Obs5QTZWMD/uNvI5Qe8wP+7t7ewT6+vqN0ZG8PLz8wAD9AAM9fX0
+8/Py8vHx7uvnA+QB5QHkCAMABeQD5OQDAAXkAAfl5OTl5OXkAAPlAAPk5eUA
+BOQACuXl5OXn6Onq7vAD8QAL8O/t7CxG6ejn5+YABOUE5AHlGOQABAPk5AMO
+5AAFA+QDAwQADAIGBQEDAQMTAg0DCgIABAQCAQInAwECAQIfAwEEAQQXAwEE
+AwUKBAUFBQMBBYsDAAAAGKiEhLeEp6OhhJKjp7ejkpKRdoKCp5KWkwOSADWC
+f5CSo6OEkpKno5KjkZKTkoKmkZCRkbejloV4kniEk5KTk5Fzk5N1eIaop6mp
+drenqaOpdgADqQANqFCGhYSGqIaGp6iZhgADqgARmaqYqIuYmZmYmZiLi41l
+Zi4AAy0AFSAtQ0MtRENEWH7WbLW1n7yzfVa7VgAFuwA3V/G7OTlBVjbYPz/i
+afJBNtjuOjrs7DLryurqRjfi8fPz9PT14PX19PPz8vLx8O7q5+Tl5OQD4wAF
+AwAF5APk5AMABeQACuXk5OXk5OXk5eQD5QAb5OXk5eXk5eTm6evu8PHy8fHv
+7uzrRuno5+fmAAPlH+QABwPk5APk5AMAC+QBAwHkAwMDBAkCAQQGBQAHAwMC
+AuQD5AAEAwoCDQMKAgADBAIBACgDAQIBAh8DAQQBBBgDAwUDBAEFBgQLBYsD
+AAAAH4SikreSt3ajp6eSkpOQkZKSpnORoqeTkpOSpJGCcJEAA6MAMJKQkYSS
+o4KCpIJ/ppGRkn+EqYiTc3aWk6aTcZGCgpKDg5aqvaqnoqmpkoWTqXh2lgSE
+ADWGhYi3hqeqrJqGp6qGmYaZqoaqmYtSi5iZmJiurp1VZlgtWEREQy3jQ+NE
+RFh+bGq1n7w6tgADVgADu7tXAAO7AB45u0FBNjbYMD/xVzniMD/u7Wvs6+vq
+RurqRu/y8ioD9AAGKfX1QPPzA/IACfHx7urn5Bnl5AADAwAG5APkA+QDCOQA
+Bhnl5OXl5APlA+QAC+Xk5OXkA+XoLO7wAAPxAAzw8O7s6kZG6Ofn5uYE5Q7k
+AQMF5AADA+QDAAbkAAUD5APkAwAQ5AMDAQUDBAgCAQQBBAYFDAMJAg4DCQIA
+AwQCAQAoAwMCOQMHBQUECgWMAwAAABujo6eSkpHFkrenqZKRgpKmgpOSkKOS
+kX+DkJEAA4IAB4OSkJKkcpQAA5IAN5OTkpGTgpCCppOTkpZ1dZOTg3Wmf4GC
+k4KWcnGWrJaFk8K3woWTkpF2hISFhXlQeIhRhqdRhqgAA4YACb2KmayGqqiY
+mQADqgALmYaLmJiZi6+cVS4ABC0ABUMFLePjAANEAAl+MWwzjryes7MAA1YG
+uwAdQUFWMDA/QfK7QTDutu3sMuvqyurryuru8fLz9PQAA/UAB/b19PTz8/IA
+A/EAA+7r5wAE5AUDAATkA+QDB+QB5QTkAAPl5eQABOUBRAPkABjl6Ovv8PDx
+8fDv7uzrRkbo5+fm5ebl5OUR5AAEA+TkAwTkAAMD5AMABOQABQPkA+QDABDk
+AQMBAwMEAQUIAgEEAQQGBQ0DCAIOAwkCAAMEAgEAKAMDAjkDBwUFBAkFjQMA
+AAAHo6Oio5JwfwADkgBggoOSc5Fdo3GEvamTc3+SkYSEf5GCpIKkkZKCkIOC
+kZCRf391g5GQeKZzg4OmoqeWeINKdXJyg5SCg3KDgpOTeJaWkpF4kniSeHZ4
+qXanS3aFeKmqvYaFiLmIolCGhqmKA6oBigOZAA6YmYuLq4uZr51mWFhDLQRD
+AEsD4+REftZstY6fvJ5Ws1a7u0G7QUFWNuI/P1Y58UHvP+7taxPrLOpGLBPq
+a/Ly80D19eD19vX19PTz8/Ly8RLv7Onm5RkDA+QD5AMAC+QB5QHkA+UAA+Tl
+5QAD5AAYGeXoRu4SOfHxEvDu7ezrRkbo5+fm5uXlCOQAAwPkAwAD5AEDA+QB
+AwPkAQMD5AEDBuQABgPkA+QDAwPkAQMM5AEDAeQDAwADBAIEAAgCAQQBBAYF
+DQMIAg8DCAIBBAECKQMEAjgDAQQBBAUFAQQBBAYFEQMB5IEDAAAAJYKRkpGR
+kH+CkZGmgoKmgnWCf5GqkpJ/g5CTo6ORk4Kkg5Gkpn8AA4IAA5ORkAAEggAQ
+k5KDpoJygoKWpnWmdYOCgQODACZxg3JzgnKDk5KXdZaFeJZ4hYWpUIWEeISF
+hamprE54dkt4hoSErAOGAAiop4aoqqqZqgSZABqLmZmujWW0WFgtAwUDIAMt
+5ER+tGxq05+8swNWAB82Vru7NlY2VjA/QTlB4u/uOuwy68rq6uvsLO3x8Wn0
+AAP1AfYD9QAX9PQq8/Py8vHx4u1G5+Xk5APkA+TkAwMACuQADOXk5eXk5eTl
+5+rt7gPwAA0S8O/u7ezqRunp5+fmAATlBeQBAwjkABgD5APkA+QD5APkA+QD
+5APkA+QDA+QD5AMD5AEDDeQACQPkA+QDAwQCBAAIAgEEAQQGBQ4DBwIQAwcC
+AQQBAiwDAQI4AwEEAQQFBQEEAQQGBZMDAAAAWoKSknCQpHKCf4N1kXOCkX+D
+XpGTkIJ/f4KToqmRkpCQcJGCgn9/g6STkpB0kZCCg4KDdaaBgqSBgYKUeHWC
+f3+DpIKDgnJ0lIN3k4OCqad4qaN4iKGohalLTAN4ACmWhXh4dpKEqaiGhqqG
+p5momaqoqoaKhoaZhqqGmZiYrrCdZi4tIAMCBQADQwALRER+tGy1jp+2s7MA
+A1YACEG7QTbYPz/iA0EAFDA/7uzrnyxG6p/s6+1B8fLzQPX1A/YABPX19PQD
+8wPyAAjx8O/r6S/kAwPkAQMD5AHlBOQABC7l5OUD5AAG5efn6u3vBfAACu/u
+7ezs6kbp6OcD5gPlBuQAHAPkA+QDA+QD5APkA+QD5APkA+QD5APk5APkAwMD
+5AQDAAbkA+QD5AML5AEDAeQDAwADBAIEAAgCAQQBBAYFEgMDAhADBwIBBAEC
+ZQMBBAEEBAUDBAYFEQMB5IEDAAAAgpCRo5Bwk4KCcYJ/f4F/cX+DgY+CkpGS
+g3+So5OCk6SCgn9/gaR/gaSCg3eCcIOCg4GRf3OSf39egYJ3k5RycKaCg4Jy
+dXR1dYJzk5aSo6dzdZZ4hYV5lniSk3WWlnaThZZ4S6KFqbeEqYSqqKinqoao
+hIaZqpiLqJmZmJmrmK6vjWUDWAASREMgBENDREQu1my1yp+es1Y/BVYAGNi2
+P7vxQdg/Omvs68rKRusyE+3w8PHzQAP1AAP29vUABPQE8wAU8vLx8fDvE+nm
+5eQU5OQZ5BkDLRkE5AAb5efp6u3u8O/w7+Lv7u7t7OvqRuno6Ofn5ublAAXk
+AQMK5AAOA+QD5APkA+QD5APkA+QGAwHkBwMB5AEDEeQABwPkAwUEAgQACAIB
+BAEEBgUUAwECEAMHAgEEAQJlAwkEBgWTAwAAAXADkQANkpGgkF2CcHKkg39/
+pAADfwBxt6KWeIOSeJJwkX9/c3+Rg4GApKSCk5SBg5FwdH9wgpGRgnSkdJSW
+g5SBkYGRgnKCdHKWknZ4eYOmhXhxgXV2dXF3dXd3dXWThLd5eHh1loSploh4
+hISGioaop6inhlCqoaqohpmZmIuhmJmuma6NVS8AAy0BIAEDBEMACkR+MWq1
+jryes7MFVgAYtj/YObs2Pz86Mp/qN+rrEzLs4vDx8fP1A/YAB/X19PTz8/QA
+BPME8gPxABLw7Ubo6Obk5eXm5+fo6ers7e8D8AHiA+8ADu7u7e0TLEZG6ejo
+5+bmA+UD5AEZBOQAHAPkA+QD5APkA+QD5APkA+QD5APkA+QD5APkA+QDAwAF
+5AMD5AMAA+QABgPk5APkAwrkAQMB5AMDAAMEAgQACAIBBAEEBgUmAwYCAQQB
+AmUDCQQGBREDAeSBAwAAAIB/j3+CgpOSkoKlgn9wf4KSkHCkpKGno6CSdIOm
+kpGSeKRxf4N/gl5epH+Dg3KDpYNwXoGRpIKUdIOCg5Z0goKWdYODc4JzlnmE
+p5ZzdXaWkneDk3mWdHiSdpaDeKl4p5d5dZNziIV4k3iWhYmpp6eGhlCphqyG
+qr2YmJmZmKqLqAOLAAevjbJmWC4EAANDAA4FA0NEWLRstY68nra2swM/AB2z
+trtBNtg/tjrsn+o3658TMu/wQfHyKvX19vbg9AAD8wAI8vPzK/LzK/ME8gXx
+BPAAB/Hw8EHwEvAABu8ADu7t7Ovq6kZG6ejn5+bmA+UJ5AMDAAfkA+QD5APk
+ABYDAAvkAwPkA+TkAwPkAwAL5AAEA+QD5AMDAAQFBAIBCAIBBAEEBgUmAwYC
+AQQBAmUDAQUBBQoEBQUFAwMFiQMAAAA0kX+kf4KmkXKRXZCRkIKRf6SkkKOp
+p6eSkX+mt5KTkH9/gpF/f15/pICkvoF/gaSBf3GkcgSDAEt0g5SDkpOUlpCU
+g3KCdZOWqYWSg3WWdYJzlnd3eHJ3dnWWdXaiqYh4k3V4k3hLc3iTc5aWhqNQ
+iaeGhIWGhlKGipmKmZmKwJmLipkAA4sABI1VZi4DLQAOAwMFQ0REfrRsNI68
+nrYFswALP0FWNj+2OjLrysoAAzIADezY7/BB8d8p4Pb19fQABfIB8QXyAATz
+8vIrBPIAB/HxQfFBEhIAA/AE7wAP7u7t7BPq6kZG6ejn5+bmAATlBOQMAwAD
+5APkAB0DAAvkA+TkA+TkA+TkAwAJ5AMDAAUFBQQCAQAIAgEEAQQGBSYDBgIB
+BAECZQMBBQEFCgQFBQUDAQUBBYoDAAAAfpKkg3Bwc5GDgn+Rf3+RkZKmkZLC
+hKOTkpOClqineJBxppOng4GDgZGPj3+kj3+Ccn+DdIGDgoNxgqaDlIKDkoOT
+g4OUcnV4eKJ4hHJ1g4Jyk3eXd5aWd3WCd4NzlnhzdZZ3loVzd5OTdpZ4hYWn
+iIiGiKlQhFCEqqqoUpmGqAOKAYsBqgOLAEGZi7BVLy1DAwNDQwMtQ+V+tGq1
+n7y2nra2nj9WNj8wtrZrMizKMp/r7O8w4jbw8vP09fX0KvLxQfAS8RJBEhLx
+8QAG8gTxAAMS8PAAA+8B7gPtAAns6+vqRkbp6egAA+cD5gPlA+QDAwEFAQUF
+BAADAgQFABEDAQUBAwQFAQMEBQQDAAzkA+TkA+QD5APk5AMH5AALA+QD5OQD
+BQUEAgEACAIBBAEEBgUnAwUCAQQBAmUDAQUBBQMEAQUGBAwFigMAAAAHf3+C
+gnGRoAADkQAnf4Kkf4ORf5O3p5LFkcVzbnGTgnFwgYF1lKaWgoNwpI+Pf6R/
+cKRxAAODA4IAA6aTcgADgwADkn+TAAODADt3dZR1lpd4lpSWeHd2d3V2eJZO
+g3J3d16TdZF2knV1lpd1dU6Sc4eXiKq9hIiHeHVzeISGp4ashqqqpwAEhgGL
+AYoFiwAFr41lLy4AA0MALi0DLQNDLn4xakKyvJ6etms/P1YwPzo6vJ83nzLr
+azDY7+I28PIqQEAq8vHx7+8D7gAD7+7uAAPvAAXwEvHw8QAD8AAD7+7uAAPt
+AAbs6+rqRkYD6QHoAegE5wHmA+UD5AUDAAQFBQQECAIABAQFAwMNBQoEAwUD
+AwAJ5APkA+QD5OQDAAPkAQMI5AMDAAUFBQQCAQAIAgEEAQQGBScDBQIBBAEC
+ZQMHBQUEDAWKAwAAAEN/goKgkIJ/goKQf4Fwf4KkpIKRo5GSxYKWgqSCpI+C
+gqRypYKCoJOCj6SPgW+Bg4J/dYGDgoKDlHWkg4F3pn90gYNyAAOUABqCd5Z3
+g3l4eJeWd3V1TnmXd3SBcpZ5lqlzdgN1AAt3eKmWk5F4dZOHhgADeAAOTHJz
+dnaphomGqqiGUoYDigADqoaGAAOLAZkDiwAIjVUvLSAgQwMDQwAIRH60bLWO
+n7wDngAVs1aztj86MjI3yjJra+4w7zDv8PDyAAPzAAXy8e/v7QAF7AftBO4A
+Ce3t7OvrLOpG6QAD6APnA+YB5wHmBOUE5AAFA+QDAwUAAwIBAQEBCAIBAQEB
+AwUBBAEECgUFAgUEABIFBAUDA+QD5OQDA+QD5OQD5AMH5AAKA+QD5AMDBQQC
+AQgCAQQBBAYFJwMFAmcDBwUFBA0FiQMAAACEj3+RkYNecpKpcYF/goOBcYOX
+kpGQvqeTj3+RkYKApnJ/kqKWk3+Cj3+PgYFyg3SDdZZ1d4N1c5aWdXWCk5OD
+g4GCgoOCc5F4lpZ1lJSWo5JMeXd3enmDd3KClHV5qsPDq3Z1uUx5d5aWdXNL
+g3N1hHZ2TKl4hVCIrKmGiIasqoaqiqGZA6oBiwGZBYsABZxVtAUtAAVDAAkD
+5FjWbGrTnzoAA7MAIFY/s7a8vJ83nzLtMO8/7j/YMPDx8vLx7z/t7Ovr6urr
+BOoF6wHqAesD6gAFRkbp6ecABeYD5QHmBOUG5AAHA+QDAwQBAQAEBAoCBQQF
+AgMEAAMCAgEAAwIAAwQCAgADBAAOAgQD5OQD5AMD5OQD5AMM5AAHA+QDAwUE
+BAALAgEEBgUoAwMCaAMYBYoDAAAAJ39wgZKTcH+ihIKWkZODg6Cmg5F/kJGW
+g4GkkpGmgn+BgnKSgpOkfwADpAAIj4GCd3R3lpYDdQAgg3V1d4OTdYKWk4KD
+lneXlIODlJOSg5aFloWWeHd6d3cDSgAOcnKXl4WKvcfGzKeWeJYDdwBKeJZ4
+l4NOo3h4lnh4hYeFhYaGqaqGhqpSrKioqoaqiouKmYuKi6+wnFVYLS0gAwUD
+Qy1EfrRstY68nrazP7a2OjKfN5/sa+7uMD8D7gAMP+9B8fDv7uzq6kZGCukB
+RgFGA+kE6AHnAeYD5QHkA+UB5AHlB+QBAwPkAAkDAwUEAQECBAQAFQIBBAEE
+AwIBAQMCAAMEAgIABAQEAwAN5APkAwPkA+TkA+TkAwAG5AAGA+TkA+QDAwQL
+AgEEBgUoAwMCaAMYBYoDAAAAeaSkkIKggoOUg4JdonWDgqZ/goGApH+SgVuS
+kZaTg3KBgaSSgY9ygoJ/f4F/f3WWlnWWc5KDg5Z1lHeDd4JydZd1g6aSknWU
+d5Z6lIejp5d3d3V3Tnl3dYOUdJN5loeFmavDiIiYqHh1ek1OdnlNlIeWdnh4
+kqmHhYUAA4YAEoeEqYiphayGhoqGhqqZi4qLrQOLAAiunWZEQwMgFARDABNE
+ftZqtbK8njqeOmu8n8qfMmu2AAM/AA7uOrbu7j/v4j/t6+pG6Q/oBOcB5gHm
+A+UAA+Tl5QAI5AAQA+Qt5OQD5OQDAwQBAQIEBBUCAQQDAgEBAQEDAgADBAIC
+AAMEAwMADuQD5OQD5OQD5OQD5OQDCeQABwPkAwMFBAQACwIBBAYFKAMBAgEC
+aQMWBYwDAAAAjJOBf5Gikn+Bg3+SpIGBgqSSxaSkcoKmgn+DcXSDl5SBkYKS
+g5SDg4J/f16CpoKTc5OWdYKCcoNxdYOWd3WUlnd4lniik5Zxg5aUlHmphXqX
+c3OUd4d3dZZ4eHWWeHmUTIeshqzLuIuphVBOUHeXdZaThKZ2k6mWloWGUIh4
+hYWEhoWsiKxQrKiqqKqYBIsAMYqLr6+yZlgtLQQDAyBDLUTWbLWOyp5rOp46
+n583nzLt7j/utu3t7Gvt7u3t7MpG6egABOcACubn5+bn5ubn5ucF5gXlAeQB
+5QvkAAQU5APkBAMBBAMBGgIDAQMCAAMEAgIAAwQBBQMDAAzk5AMD5AMD5APk
+5AMJ5AEDAeQEAwEEAQQLAgQEBQUFAwEFAQUgAwECaQMWBYwDAAAAD5GDgZKW
+qXCPcKCRpIGkkgADfwCKgpGmk6Bxf3SBgXKTlIOUlpNzk6Z1lnKDgYKDcXKR
+dXWDdZSDlF6UcnWWdHZ3lJSXlql4ln+Dg5SUeHmWeHdyc3WXdnh5eXh4dXWU
+k5all3qRToRQi5uruItLSUx1c5K3krd4eXl4hbmpiXipUIiGhlCphayJhqmK
+hqpQioqLiq+KrouNalgtIAMEAwMACC1EWLRqtcqyA7wDnwAMyp86tu62Omvs
+n+vrA+wABuvq6ejnMQ/mBeUABOTl5OUF5AAQLeTkA+QD5C0D5AMD5AMFBAMB
+AAMCAgEACgIFAQcCBAEDAgAUBAICBAQC5APkAwPkA+QD5OQD5AMD5AEDBuQB
+AwHkBAMDBAsCBAQFBQUDAQUhAwECaQMVBY0DAAAAeKSkj4/Fo6B/wpd0paSk
+j3+Pj3+gf4KDgoJwgXSjo4NxgYKEppJzgnKCcnSBg6SWdYGTk5SDg4J/kpaT
+kqmQc5N1lpZdg3ODg3V1eZZ1lnd1lpdNdoR4eZeEhE6HTnl5lpOWgnN5cl1Q
+mMfGz8ermKqEp4V2iJZOdQN2AEh1hIapeUt4had4hVCFhqeGUoqKwIuqra2K
+i5munFVYREMDLQQCQ+REfjFqjp+fvLyfn8rKa7Y/Omvs7DLrLMosyjdG6ejn
+5uYS5QnkAAwD5BQt5APkAxQtA+QDAwADBQQEAAUBFAIIAQQCAQUGAwAL5APk
+A+QD5APk5AMADOQAAwMDBQAPAgMECwWLAwEEAQQFBQEEAQQGBREDAeSBAwAA
+ABV/pIF/kpKipJGgpKSCgpKkf3+BkX8ABIIAe3+CgoOWgn+SppKCg4OWg4N0
+g4Nyg5OCf5ODg5Z0daR4k3eEhXWDeZZzlnd6g3V6coOWl3WWcndciHhLTU10
+dHeHd4hLUEp1cl6CpnWWqYWnp5i4x8/Gx657qaeWTnl3hIV2ck6HiId4iIWH
+hoWFiISGhlCqUoqZmYuKigADiwAHrrBVZkNDAwAFQwAfRES0bLWOn5+8n8rK
+vO0/Ou3sMuEs6kbTRunpaufn5gAE5QAD5OXkAAPlAeQH5QAD5OQtAAbkAAsD
+5AMtFOQDAxQtFAAFAwADBQQEAB4CAQEBAQQCAQQBBQMDABPkA+QDA+QD5APk
+A+QD5APkA+QDAAXkAQMB5AMDDwIDBAoFeQMBBBIDAQQBBAUFAQQBBAYFkwMA
+AAAQf3+QkH+QoIKCpJGkgqOjkQN/ABRwg3KCg4Jyg4OWlIODgpKjpoODcgOD
+AGiUg3Vwk4J/g5OWg4OUd5OTdbeEdZKFeZN3l3V1eINyd4OWloWEhYrMx8OY
+Sk9Rk3LAuMvDuIRLSUp1g3V1loeHl3eGmczHuKqTlnaWTnl5UYd3d4dQUHin
+UYiFUIV4qVCphqyKiomtUgSLAAqKmK6wsGpYLS1DAwUACENERH4xakKOBMoA
+IZ9rtu1rn+vrN0ZC6TPp6Ohs5n7l5OXk5eTl5OXk5eXk5QAI5AAQ4+TkLeQU
+LRTkAwPkAy0D5AUDAAMFBQQAHgIBAQMCAwQHAwAJ5OQD5APkA+QDAAnkAQMD
+5AQDDwIDBAkFeAMDBBIDAQQBBAQFAwQGBREDAeSBAwAAAISRf5CQpJGSoKSC
+cJCkpYOCg5F/gnKBkYKmloKDcoGDgYKWl4KDgpGCd4OUg5STlpOmlpKWloOU
+dINNdYV6g3OSk4OCkpKWdZOTpoV1dE2WUbjR3tLUuKp2d4Sr0Qfdv8/Dq6qE
+hXhMTk96endJToSnhoiplpZOeHmFhHh3S4iihHa5qIQDhQAkdnapqYiGqYqK
+qqqKiq2ZmYuLmJmwnbQtLQQDQwMDQ0QutGy1BI4AFjefa2sy6ywsykbpauhs
+5+fm5uXl5OUR5AAMFC3kLQMZ4y0ULQMtAwMBFAUDBQUFBBwCAAMEBAUAAwMB
+5AMDABDkAwPkA+QD5APk5APkA+QDBeQAAwPk5AADAxACBQURAwHkbAMDBBID
+CQQGBZMDAAAAho9epJFwo6KEpIOkkXB/go+BcoN/kX+QcoKUpoOBdHJ/gXKm
+coOCcnKTdYOTdZOTlpOTepN1dXeUdF5ehIJyg3hzd3d6ek5zdoWIhoqZmcPH
+1P44ONLRxqtSU8PXvzu/0tfRz8bHx8O4q5mKhoaEeYSphUt6TZNLdnqHTk6W
+UYiHeFCIiIeFA3gAGYVQt4WsrFCKwZpSwYqtiouLmZmLjVVYLS0AA0MAGAVD
+Q0R+bLVCRo6OyjJr7DKfyjfTM+jn5wTmAeUB5RDkAQME5AALFOTkA+QgAxnj
+GeMABwMEBQEDAQMZAgUEAAUCAgQEBQAGAwAN5AMD5APkA+QD5APkAwAF5AAL
+A+QD5APkA+QDAwUAEAIFBX4DAwQSAwkEBgURAwHkgQMAAABLgaSgkJCRxaOC
+kZGQkaOBj3+Ro3ORkXGBgaZ0lH9/ppKTlnXFgnSDgpN1loOUeISTkqendqaD
+lHaTgnd4d5OWdXeBllFShri4x8fRAAPXAAm/0t3dv9e/0tcAA9IAOb/e0r/S
+0r/S3t7S0r/S0tfX0df7vYajipmoqEuFhXl5h3ZPp3l1eYeIh6mFhXV5halL
+hoWpiqyGUgAEigADi4uKAAOZAAaLsJ1mLS0EQwAbBS0t5dZstULT08q8n5/K
+6jRG6TVsMX7m5eVEAA3kAS0F5AARA+QDLRQD5APj5AMtAwMUAwUABQMFBBkC
+AQEDAgAFBAICBAQABQMB5AMDAA/kAwPkA+QD5APk5APk5AMACOQABAPkAwMR
+AgQFEQMB5G0DAQQBBBIDAQUBBQoEBQUFAwEFAQWKAwAAAFGRpYJ/kKSkk6Zy
+kZN4k4GCgpKRkoGDgYJ3goKDgYGWgpKDkpKWg5GSc4N3goOTkXV4kql5d3d1
+k3mphZaXlpd1XqeGmcPPB93Sv9c70ji/OL8ABNIAOL/S0r/S3d6/0tK/0r/S
+v9LSv9LSv7/S0r/Rw4q41M/Dq05NXUuWeYhzeEt4eYVReHmFloWEhampBIYA
+BYqsUqyaAAOKACmLi6+vi6+LjWYuRC0FAwQFQ+MufjFqQkKOn5/Kyo5GQmro
+5+bm5eXk5QAL5AEDBOQADwPkA+QDLRQt5AMZLQMDFAAFAwUFBQQcAgADBAQC
+AAMEAAQFAwPkBAMADuQD5AMD5APkA+QD5OQDBOQABwPkA+QD5OQAAwMRAgQF
+fwMBBAEEEgMBBQEFCgQFBQUDAwWJAwAAAB+joqSkkJGSpqR/cJKno4J/gpaD
+cJFykqaRkXKDgpGSAAOWAC6DeJaWeHWDg4GBXpaTlJaTl3V0g4J/g5R3lnVK
+eKq4x8/X0r/S0r/Svzi/0tI7A78ADdLS17/S19Lev9K/0r8ABdIBvwPSAEm/
+0r/S0r+/x8a/0r/Gq4RRT05JdUt2dod4eXmEeE6Fh4WIUISFrIaKhopSiYpS
+moqZmYuLq62Li41VWCAtICBDQy1DRH60bGpCAATKAAdGQukzbDHWAAPlBuQB
+AwfkAA8D5BQt5BTkA+QUAwMUA0MABwMBBQEDBAUGBBsCBQQBBQEFBAMAA+QD
+5AAEAwAJ5AMD5APkA+QDAATkAQMH5AMDAQURAgQFEQMB5G4DAQQSAwEFAQUK
+BAwFigMAAABNhJGSj6SRppKCgYGTk5KBlKORo5F1kJGWg4OkgoODopGSgn9/
+gpZ3k3WDgqSkk4KDlJJ1dZN3hKeSdkxOhqvH0Qfd0tK/0r/Sv9LS178AA9cE
+0gBr3tLXv9K/0r/S0r/Sv7/Sv9LSv9LSv9K/v9K/0r/X3r/e0tHGuKuLhlKo
+UIZRiHmHUXZ1p7eIhYSphamIiFKsiqyKrIqKwIqKUpmti5mvi5xmLUMDBQND
+LUMtLtZsakLK0zeOQkLpbOfmfuUABOQAFAPkA+QD5APkA+QD5APkA+QD5AMt
+AwMABS0DGQPkAAQDAAQFBQQFBAQfAgAFBAQFBQQAAwUJAwAb5AMD5APkA+QD
+5OQD5APk5APk5APk5APkAwMEABECAQQFBQUDAwV2AwEEEgMHBQUECQWNAwAA
+AEGCf3B/j6SCkYJ/j3CDoJGDk4WEwpKTk4ODdIN0d5Z4t5GCgl6Bd3Vyg5Sm
+goOTkYOBf5eRdXmihEuGq8fU0dI4OAAE0gARv9LXv9K/OL/S0r/Svzi//r8A
+A9IB1wPSAb8F0gALv9K/0r/S0r/S0r8AA9IB1wPSAB7e19K/0cbHuJhSe3mE
+S4i5UXiEqbmIeIWFh1GsiIkDUgAUilKKxIuZrYuKi62Ki4uwZkRDQwMDQwAG
+A0NEfmxqBUIABTNqbOcxAAPlA+QAJRnk5APjIOMg5APkA+QD5APkAxTkA+QD
+FANDFAMDFAMFAwQFAgQAIQIDBAAFBQUEBQUABgMABuQD5AMD5AMDAAbkA+QD
+5AMD5AEDA+QACQPkA+TkAwMFBAASAgUFBQMBBQEFdwMBBBIDBwUFBAcFjwMA
+AAAEf3/FfwORADZ/kX+Qf5KTc5KBf4JdcpGRcqaCgoOgc6KElpOShHeDSnKC
+dZSUk7eBlpOWlqSDloWux9G/0r8D0gS/AdIBvwPSABW/3tK/ON7eB7/P0dEH
+3d3ev9K/v9IABL8AYtfS3dfS0r/S19fS19LX0tK/0r+/0tLdv9K/3r/DeXmH
+eYWiqXl5uXapUIeWiIaIiKxSiYmaUMBSUoaKhpmLUouLiouwZX5DLUMFQ0MD
+Q0RE1mxqQkIzajPoMeZ+5eXk5EPjEQMBLQYDARQFAwAFBQUDBQQAJAIFBAMF
+CAMAG+QD5APkA+QD5APk5AMD5APkA+TkA+QD5AMDBAASAgwFigMBBAEEBQUB
+BAEEBgUDAwEFDQMB5IEDAAAAO6SRf3+Rk5GSkZB/pIKmpaRwbXCPgpCDgoKD
+dH+CgpOCdZaRhHaDlnV1loOUhISCeKSDc3V5UqvP197eAAPSAAi/v9LS3d6/
+0gO/AdIDvwAQ0c/HuL2YmL3G0dfS0t7+vwM4ADu/OL+/3tK/0tK/0tK/0r+/
+0r/X0te/0r/S17/S0v3DUUx4Tod7hUyFhXh5eod4hYaIqYaKiVGKrFJSwQAD
+UgARi4uti4uYmIuvnS8tLQQFQwQAA0MADkR+MWpqM2robNbmL+VEA+QFAwEF
+AwMBBQgDARQEAwADBQMDAAMFAwQAAwUEBQAlAgUEAwUDAwAR5APkA+QDA+QD
+5APkAwPk5AMAA+QADAPk5APk5APkAwMFBBICDAWKAwEEAQQFBQEEAQQGBZMD
+AAAAHY9/f6R/o6OSkZKkg3+Rf3CkgYGCg3KCg4GBgF5/AAOCABeBg5N5k3d3
+k3KDdaa3dpOWk5ZJhYvGvwAD0gAhv9LX0tK/0r/e3g3SODjRxse4uKh2dXp1
+gXJ0ir3G1NfGAAPHAA3Dx8vG0dLe3b+/0tK/AAPSAAnX0tK/0tK/0tcABNIA
+ML/Sv8OESnSWS3lRqalLhXl7S4eFqYWpioZTiYmKqqqJhqqqisCKiq3ArYqL
+r51URAMDABMFBEMD4+R+MWxqM2wxbOZ+5eREAAPkAQMFBQEDAwUBAwQFBgMA
+BAUDBQMIBAECAQQkAgUEBAUIAwAZ5APkA+QD5OQD5OQD5APkA+TkA+QD5AMD
+BQATAg0FiQMBBAEEBQUBBAEEBQUSAwHkgQMAAAAFkaSkgaQAA5MAOJKRkZKQ
+cJDFpH+kgn9/gnGCg4GBkIJzg3R3g5aDdZaTcXaTeKi3lsKRp6i40b/dvzu/
+0r/Sv9LSA78AJcbDuL2hqIR2d3WDdXJ3lHV3pXV4hqiZhod2dnh1dlCYvca/
+0t4ABNIAML/Sv9K/0te/0te/0r/Sv787v8+rhXJLeFGEh3h4UYmIhYiFhVGp
+UFJTiIpQrKxSigOGACeqi5mLrYqtiq2LsFUuLUMFQ0MEQ0NE5ebnbDVsMTEv
+5UTkROQDIAMAAwQDBQYEAwUDAwAGBQUEBQQFCAQBAgEEIwIFBAQFBQMADuQD
+5APkA+QD5AMD5OQDBuQACAPkA+QD5AQEEwIMBYoDCQQFBZQDAAAAOH+Rf6B/
+gqaCgqCjcHCkcJJ/f3CCgn+Cf3Klg6SDppOUdIFegnWDk5FOlnWReZOkkYS9
+1NfS3dLSA78AP97Sv7/SO97Hhk6TpKSDdHSUlJV3dEpydnl1dGB3d4N6l5R0
+g6amgZaHmbjU0r+/OL87v9K/0tfSv9LSv9K/1wAD0gAjB93Gi1BOTEuEUU97
+ubmaiImJeamIrKFSiImsioqsmomsUokABIoAKa3BrYqLrY1VLi4tAwMFQwMD
+ROV+MWxsMdbWfkRE5EPjAwUEAgIEBQQCAAcEBwUBBAEFBwQAAwUEBAAkAgUE
+BAUJAwAJ5APkA+QD5OQDAAPkAAgD5OQD5OQD5AMDAQQTAgwFUwMBBDYDCQQG
+BQAHAwPkA+QD5AAKAwHkgQMAAAAfkoKCo4Kkf5GSpoOSwpJxg3GRk5GCgZGC
+g4KSkYOSdQADlgA4k16TkpKpiXWkXoKBk5nH197Sv9IH3b/Sv7/S0tsHC9S4
+dniSdXWDg5R0dHWDTXR1d3dzd02Wd3kDhwBHlkp3ekx3d01Omcbdv96/v9fS
+0r/Sv9LXv9LX0r/Xv9fS17/GzLiup0xOTnqHeYqriXiEUIhSiVCIiqqsrIZS
+mlKGiqqKiqwAA4oADYuKi62vZX4tAwUDBQQAA0MAGkTl1ucxMS/lLuRELeQD
+AwUFBAIEBQICBQQCBAQABgUFAgIEAgkEAAMCBAQAAwIBAQEBAwIBBAQCAAYE
+AgQBBAQEAgEEDAIIBAQDAB/kA+QD5APkA+QD5APkA+TkA+TkA+TkA+TkA+QD
+BQIBABICCgVVAwEENgMJBAUFlAMAAAAykpGCgn+kkpGRkn+EoYSggoKRg5SC
+g6SDcYKRlJJzeJSDdHKmg4JOhMOZcZaTeJjG190E0gA5v9K/v90H0cbHuKuL
+UXiEeId3dXd3Snd1dHR5eXqHhXl1d010l4eWTnp6d3N3d19yTqq4z7+/0tK/
+AAPSAAXX0r/XvwAF0gBIv7/e3de/0dG4iFFOeYd4U8fDUlG5hYWIU1OshnuG
+qomIiaqKiYqKUopSqouKilKLr2VmQ0MtQ0MDQwNDROV+5tbmfuVEROTkBAMA
+CAUCBAUFAgQEAwIABAQEBQUDBAEFCgQBAgEFAwIBAQEBAwIDBAMCAAUFBAUC
+BQARAggECQMAGuQD5APkA+QD5APk5APk5APk5AMD5AMDBQIBEgIKBVUDAQQB
+BDUDCQQFBZQDAAAAFqR/gn+BkIKlg6Zxf5J4l3+jk5ORopEDggAblnWTo5aD
+dIGRg4GDlpjGx4aReHaYxtu/17+/AAPSABY4v9HHq6qJlnl3d3mpqId3enN1
+d3qUBHcAS5R5l3p3eYNKdIN3eJZNl3d1dE1NdE1glkurz7+/0te/0tK/v9K/
+17/Sv7/S19e/0tfe0sdRTk9NSUt2wDzGmFGHh1CGUImsiFOGiAADigAmmq2K
+ilLBiotSrYuZioqvnLRYLS0DQwNDAy3kLn7m5i9+ROREA+QEAwAFBAQCAgEA
+AwUDAgcEAQUBAgsEAAQCAgEBAwIEBAQCAQMBAwQEDgIIBAQDAAPkA+QAAwMA
+DeQD5APkAwPk5APk5AMAA+QAAwPk5AADAwEFFAIJBVYDAQQBBDUDCQQFBZQD
+AAABfwGmA38AV5CRkJKCcIKRkXe3t3jChcWTkoGkg4Kmg5N/gpOCdZFdvdHG
+rHJ4UL3Rv97e0tfSv7/Xz8Oqt4WDg3R0cYKUToeTc5OEk3eUdHRNlGBglGCU
+lpd1d5R1lQAEdwAXSnR3YHd3YHd0SnKEuNTX17/Sv7/Xv9cAA9IAKNfS17/S
+v9e/0r/PrlKrmFBPUHau1MeYhVCFrFNRiVKJiVCsUsGKqoYDigAQhqqsrIqt
+i4uvr51mRCADBQRDAAxERC5+L37lLkRE5OQDAwAGBQMFBAPkAwMEAgAGBAQF
+BAUFBwQBAgMEAQUDAgATAQECAgQEAQQDAwUFBAMD5AUFBAAOAggEAQUHAwAZ
+5APkA+QD5APk5APkA+TkA+QD5AMD5AUFBAAUAgMFEQMB5EoDAwQ0AwkEBgWT
+AwAAAICCcYKRf5KRkXKklpJ2oJF/coJzg7eSgpKBlKWkkaSCkqmDj3C41M+u
+f3Gjq9Te0ji/0tK/3dIhmJOBg3aXlIOBcZFbgYOmg5eWk4JydFyBdXJddXVz
+lHmWl3lyd5RNSk10TWB0dHp3d3p6l3WimDy/0jjS0r+/0r/Sv9K/v9K/0gO/
+AFjd3ca40dGYU6enTq7UxrlRhVCJiVKqiIaaUomJUoaKrKyJrIpSwKqKiq2t
+Uq2NtEMCLUMDBUMDQ+RE5X5+5UTk5AMZAwMFAwXk5eZE5AMCAQECAgQCBAQC
+BgQBAgMEAQIBBQMCAQEBAQMCAAMEAgIAAwMACAUDA+fnAwMEDgIIBAQDAA7k
+A+QDA+QD5APk5APkAwPkAQMD5AAIA+QD5AMFBAQVAgEFAQVcAwMENAMJBAUF
+lAMAAAAPgqCRkMKCgo+RkrejhMWSAAN/ACWCf3+RcIKSlpKTg5STt5OTTKvR
+B712b0vD3d3ev9LSv97dv8OZAAOCABKRl3dgf4KSf4Jwf3R0lpN3f4IDgwAi
+dINwg5eWeXeUeXqHeZZ5lpZ3TXd0TWB1TU16dU9ieEuZxgO/AdIBvwfSAAO/
+0r8AA9IAEr/S0b8Hv9SrUVBRiMPRx4uGiQRRAA5TiVKIUIiJiIhQhlBQqQOK
+ACSJrYqKi4qKsFVELQMFBUNDA0PjLeUu5S5E5ORDA+MDAwXl5jED5QALROTk
+AwQCLRQCBAIAAwQACQICBAUCAgQEAQAEAgAOBAQDFAQUBRTm6xL48+YRAggE
+CAMAEuQD5APkAwPkA+QD5APkA+QD5AQDAwQVAgEFAQURAwHkSgMDBDQDCQQF
+BZQDAAAAC4KCkpCQk5BwkJGTAAORAFGQk5KSkIKBpJGmxamilIGBg5OBp73U
+0aunh1C40b+/19K/ON4H0bh2cXBelIOUk4J/gX+UlHR0f2CTlpR0cpN1lHWD
+d3R1lnqUYHlzdnpPdXMAA3oAXHRKYGB0YJR6eamHek1Mp7jUON6/0r/Sv9K/
+v9K/0r+/19K/17/S17/GmFB5ha/PB7hSiYVQUolTiYaGUFKKUImsrIiGrFCs
+mlJSiq2KrYuLnFREBQMFA0MDQ0PjBEQAH+Tk4yDjAy3jGX7n5+bm5eXm5ufp
+6OXkLQUDBAQFBBQAAwQAFhQEBBQCAgUCFBnl5eYY7vP3RUX56QMRAggEAQUI
+AwAS5APkA+TkA+QD5APkA+QD5APkAwMDBBUCAQUBBVwDBAQzAwkEBQWUAwAA
+AHiCgn+RkKaCkH9zppGRcIF1kpOmkpCRf7eihZaDgnRzf6SY1N24SkqGw7/e
+3tLXv97e18urhJOkgnV3kXWHlpZ/goF1k5Z1lnd1dXSXd5d3T3eDdXqThIN6
+g3eXenl3TXl6d3R0TXdNd0qHhYR5d3l5hFGKw884/b8D0gG/A9IBvwTSACi/
+0tLX0r/XzpiIqYm4DcavUVFShoaIUbmJiImJhohQUImsiIqGUIqsBYoACIuL
+rTVEAyAtA0MAHi0t5ERE5ETkLeMt5eXkROXo6Od+5eXn6Ebs6+ssRgPpAAXr
+6kbp6AAE5wAL6Ojp6xPt7/P2+PoABUUABPvqAwURAggEAQUDAwEFBgMAFuQD
+5APkA+QD5APkA+QD5AMD5AMFBAQVAgEFAQURAwHkSgMEBDMDCQQGBZMDAAAA
+CHGRoJGRf6SkA4IAA5GRkAADfwF0AV4DggBQksKIhJeDg3GSgobG3riGc6rL
+vzu/0tLe0tfGuF2EqJKmk5aSoaehqZeWlICUdnl5dXeDg3eXd3d5d3l3d5R3
+eXdygnVNlE2UdEp1gnd3dE0EegA+T4d6d3SHoXuHUa7D0Qe/0r/S0r/S0r+/
+0r/S17/Xv9Ldv8aYUYiKx7/GrpqtUlCIrFCsUImsiVKorFJShogDrAARhlKK
+UsBSi4uKsGZDICBDAwMAA0MBLQHkA0QAHeRD5C/W5eXmbEbo5uXn6Onr7ezr
+ExPs7Pb6+/f3AAP6AfsD+gH5AfoE+wP6AAhF+/xFRfLkAxICCAQDAwEFAQQD
+AwATBeQDA+QD5APkA+QD5APkA+QD5AADAwMEFQIEBQUDAQUBBVMDBQQyAwkE
+BQWUAwAAAAaQf4N/oJEDggBxpH+kgV6Cc5CjgoKWgpGTl6B1c3Ojk3jDv9Gm
+kpK4vwe/0r/XOL/GmZZ4pnWDdHF1g3aRc5eWlHR0k6GneZd3cneUTU13TU2E
+c01PeXZ2cXJ0d010TU10TU11d3pgend3SmBNSkx5eYh7enpKUJjHv78ABNIA
+BL/S0r8D0gBRv9LXv9K/1wfHUEtSrtEHx6u4mJp7UqpThlCZU1KGU4msiqxS
+iaxSrIqsUlKKqouZjdZDLS1DQwVDA+Mt40TkREMu1jHmfubnRkLn5mzp6u3t
+AAXsAAry+/r79fZF+vj6A/sABPpF+/sD+gALHRxFRfz8H+gDBAQAEQIIBAMD
+AQUBBAUDABDkA+QD5OQD5APkA+QD5APkBAMDBBUCBAUFAwMFUgMFBDIDCQQF
+BZQDAAABkQGmA6QAMIKQpHGCcZGRf4+RoKN/kXOSkZGWlndyc4LCuL/Rq3SD
+hsbX3tfX0r+/z5hOdXV3gwN1AEJKdHJ0gYOSpYNyg5d6eXd1eIZ5ek5MXXd3
+eXZ5qKd5YEqWendKg3dNd051ek1Kc3Z5eU9NemBPlk51ck+HYoVMuM8EvwAv
+O7/S0r/Sv9K/v9K/0r/e0ZhTeYnMO9K/3r+4rYlQhohTiFJQUqqGhYiGhYhQ
+rIgAA4oAJYuKrYuKi69m40MDBQVDQy0tQy3kRORD5ecxfufnRuro5+jq7GsA
+A+wAA+3s8QAD+gAR+/f5Rfj3+fr7+0X7+kX7HfsAA0UACPz8+0YFBAQBDwIK
+BAAGAwUFBAIFAwMAEeQD5APkA+QD5APkA+QD5APkAAMDAQUZAgoFUwMFBDID
+CQQFBZQDAAAABZKRf3CPAASQA5EABHGBgZADkQAkf3+WlJaWqMV1XnGEx9LD
+hLeow93XONLX1zjRq0uWlnh3dZOEA3QAOXVeXnSCk5R/cnN3YHV5h6dRdUlN
+TId3eaGpwFCHdHV5enV5T3eXT3hOek13dUxzlHd3dXdgYJZdhAADhwAfeU65
+q8a/0tK/0r/Sv9K/0r/Sv9e/0tLRq4lOua7U/QAD0gAcz66JiayJUoaIqqiq
+iaiGrFC5rIlSqYaKUsGtUgOLADCNZgNDAwMFQ0MDQ+RERC3kRDHn5i9sQurq
+bOnsa+3s7e3s2Pf6+fv59/r6+fr7+vkD+wEdA/oAC/tFRfz8RfEDAwIEABAC
+CgQDBQADBAQFAAMDABXk5APkA+QD5APkA+QD5APkA+QDBQQAGQIHBVYDBgQx
+AwkEBgWTAwAAAH7CkKSPj3+RgpGCg4J/cH9/koKSgm6Sg5KTqKdygU240cao
+pHir0d7ev9LSONG4THB4dnJygXd6dZRgcnJxkHKCg3F0g4N3dXiXeHWTeXd3
+p6x7hHl1l3V0dHV5THd6Tk+EooV5TEp1eXdOg5eTd3V3l5aWeU+Hh093qq7G
+B94D0gAIv9K/0r/S19IEvwAOw4ZOh3tSw92/v97ew4oDiQAlmlOohomJmlCJ
+U4WIUKmsUoaJrFKKra2LwK6wLy0DBQMFQwRDQwAD5AAMROR+bOfW5+lGLOnq
+BewADO7t9vs99/r59/r6HQT7AAb6+/r7+voDRQP8AAf15gMCAgEFAA8CCgQD
+BQAVBAQDA+QDA+QD5APkA+QD5APk5APkAAQDAQQaAgUFWAMGBDEDCQQFBZQD
+AAABowGgA48AmaOQgpGDg3OCgn9/g8KRkpGSk4KSlpZ/SZnR17hxgqjP0tK/
+0t440cOFgpGSlIN0cnJ3g3J1SnSDg150SpaTc3eDdXddeKerhlCHdnZxdXqH
+d3R0YHR3eXd5d3J5eU95dU51d3WWTnp6eaeHeU51TnhLh3pOeYeLx9fdv9I4
+0r/Sv9LSv9LX3b/MUXmHiIbMv9K/0gfRq4qIuQAEUgAjqqqsUoSFqVCsUKys
+hlKKilKKisCKi4udtEMFQ0MFQwRDLeMAA+QACuUxbGwx6UbryjIE7QAD7u1o
+AAT7AAr5+vn7+/r7RUX7BPoAD/v7Rfv8RUX6NAMEBQICBAAPAgwEAQUBBQQD
+ABXkAwPkA+QD5APkA+QDA+QD5OQDBQQAGgIBBQMDAQUNAwHkSgMHBDADCQQB
+BQEFlwMAAABhgqR/pKR/koKjkZKggn9/pKWlkJGjo5aBg3+lkam9/caGbYjH
+3d7Sv9fe3sOGcJaSk3d4eJN5eHV3g150dXSAdJB1k7dOcnp5S4q4xtTHuFKF
+THmEcl2SlnWRTkp3TXd3SgADdwBFTnlOd3VKeHqHelCFenlMeXiHT3pPd2B3
+hczd3t7Sv9K/0tK/19K/v93UmFBOrsPUv9Le0t7dxoaJUoaGqoqJUomJqlKs
+AAOGAA+FhoaIiVKKra2KwJmZrp0AA0MAHQNDBUMEAy0ULeMtfujoMWxC6+xr
+7Wvt7j/x+fv7AANFABz8+vr7+0X7+/r7+/r7RUX8RfxF/PAZAwIEAgQFDwIK
+BAAEAgQFBQYDAA7kA+QD5APkA+QD5OQD5AQDAQUBBBkCAQVcAwcEMAMBBQgE
+AQUBBZcDAAAANJKRkI9/pH+QpqOCgXJ/f4+RkJCCkoKCkZFzpJNdx9KrgXWh
+3r/S0r/X3cahTJSllIF/gXIElwBSgXKTlHR0YHRydZFzlHV0d3aZ0d7eB93R
+iYWHh6mpl3qmdU9NYU13l3dgd3V3YHdNd6d5h4dReU5OenpNeaeHeXp6T3pP
+eavUvzu/0r/Sv9LSvwTSAEzRzK7H0g3e0r/Xv9K/rqpLiqhSholSoVLBoYpS
+rImKrIiqioqJiVKKiqqLqq+yWEMtAyAEAgRDQ+Qt5ER+amroM8pr7Trt7j8S
+JUX7A0UACPtF+/tF+0UcBfsERQP8AATg5QMEEQIIBAUCBQQGAwAJ5APkA+QD
+5APkAAMDAAbkA+QDBQQaAhIDAeQUAwECNQMHBNIDAAAAC5CRpIGkgX+BgoOB
+AAN/AD1epKaScIGCkYOjkpOCdajR1KqDqcPSv97Sv93RvUtzg3KDg3KDgpKE
+k4WDg3deW0pgdHR3c3mDSnd3ea7RAAS/ADM4iU6FTnd5h4R4lHh0YHRcdXWX
+h0+XTWB1c06Hek6iiHZ4eHd6TYR5c09Penl6TVG40Q0AA9IABr/S0r/S0gO/
+AArd0dHX193ev9K/A9IACseLUYlQiFJSiIoDUwALiqxQiVCJiYasUqwAA4oA
+NlLAqouur1VEBQUEAkMEAwNDA0TkRDEz6ek3Mu627u/wPUX7+kX7/PxFRfxF
+Rfv6+/j39/tFRQT8AAUdRgMFBQARAggEDAIAFgUF5AMD5APk5APkA+TkA+QD
+5AMDBQQbAiYDAQI1AwgEKQMBBKcDAAAACpF/f5CRkX9ygXQDfwALj4GTopKB
+pJGRg4MAA5YAa3HDv9SEgYvRv9K/0r/Xw6ODcnWSknWDlJd5T4SXdpZ0cZR3
+d4Fwc3Jyl5R6g3SFw9HRv9HGUXddlHKShLeHd2FKTk5Nh0x5S0xzSpRNTXp5
+eHiFh4h5eklyl0x6endNek16dHdTq9HXv9K/AAPSAb8E0gAd3tLS17/S197S
+0r+/0te4UFCJhoaJiaxQUImniIQAA4gAKqqGrIqGiq1SilLAqoausFVDLQME
+BQUEQwMD5EPk5WwzQkbr7u4w4j1F+wRFAfwERQAL+0X5+fby9vQd/EUAA/wA
+BCHi5AUTAggEBQIHAQAWAgMD5AMD5AMD5APkAwPkA+QDAwUEBBsCAAcDA+QD
+5APkAAoDAeQTAwECAQI1AwgEKQMBBQEEpgMAAAAUf15/kIOTkYJ/dHKCf15/
+dbeTf38FkQBvhH+pxr/HhnfDv7/S3r/S0ZiRlnGEeamSdZZ2dqNMd3Z1dHZM
+eKmFhJR6dV11dYNgdXaqmKuYp4d0d0qBSXd6endxqZi4q09KTqd5TndKYHpK
+YE5Mh3qHTnh1Snd1ek93endPd02FTlHJ2784v9K/AAPSAAa/0tK/0r8D0gAD
+v9K/AAPSAAa/3tSuhlADiAA0iYlSiFKGhqmIqayGqoapiVJSwVKtxIrAi6+N
+ZkMDIAMFQwQFQwMtQ+Mv6elCyj8/4kAcIgNFAfsGRQAK/PxFRfT0+/pFRQT8
+AAT45gUDEwIIBAoCAAQBAQIFAwMADuQD5OQD5APk5APkAwMFAwQbAiUDAwI0
+AwgEKQMDBaUDAAAAJJCRkF6BkqKCg3STcXWDcJN2gqSUf5GmgoJdcJjRv8td
+qM/e0gO/ACPSxoS5k6OjhXl2dpJdqXh5dGB0TqjDuL2ZUHp3dU2UcXGUdAAD
+cgBJgYFcTlx3lHd0ekpzdXRSxwfRuIROe4d2dXRKSmBKg3d3eHp6XUx3T3VP
+e3d5eXp6eU55T6nH3jjev9LSv9LS3dfd0t7S0r/SvwAD0gAPv9Lev6tSrIiG
+uYaIiIaGAAOJACuGiImprIiKrFKJmouKiq3AmYuLsi8tLUMDBAVDBQUD4y3k
+bEJGN+42afvUAANFAfwDRQAM/PxFRfz8Rfv4+0VFBfwABvvsBQMCBBICCAQF
+AgUEAwIADgQFA+QDA+QDA+QD5APkAwMFBBoCJQMDAjQDCAQpAwYFogMAAABD
+lIORkpOWkoOBj1yPf5GQgYODgYFbf39ypqVMw9c7w0jHv9LX19L+17iGTqO3
+lpZ3kpaXk4KCpnV3UavR3r/PmXl1dQADdwA4g3Rgenp0g01gd3eXd5R1d3V1
+lEqAhMvR/dG4hEp4d0xNek1cTUp6YE93T3p6dU16hHZ1eXlMdHUDeQBTeovU
+19LSv9LSv9LS19LS19K/0tfS0r/S0r/ev8ZShayGiYiqrKm5iayGhqqJhYao
+hayswYmqUobAisCZi7BlWC1DBQMFAgJDA0MDQ+UzRkbs3yMAA0UAB/xF/CL8
+RUUABPwABUX8+0X7AANFAAj8Ifz98eQDBQMEEQIIBAcCAAYEBAUCAgUEAwAJ
+5OQD5OQD5APkAAMDAQUfAiUDAwI0AwgEKQMFBaMDAAAAIYKCg4OmgF6PXm+B
+gX+Cf6WBg39ef15/pZBuosa/v8eqzwAE0gBiv97RqHd1kZORkpaWd5Z3lIN3
+ckyY1L/dxph4k3p3lHeUd3KDTXp0cnR6lHV3XUpyendNd3pgdqu4x8aLT2BN
+eXVOYHpgTXd5dXVKl3l6TXlPek9OTod5Tk95enpPTqu/vzgE0gAU19K/19K/
+0tfSv9fS0r+/0r841K4DiAAmhoiIhoashqiGiapQqYiKhoqGrKyaionEioaL
+i7CNtVhDBAMDBQQDAwARLQPj5kI3ymlFIkX8+yTU/EUABPwERQAD+0VFAAb8
+AAf25wMFBQQEABICAwQLAgAFBAQFAwUABAMB5AMDAAvkA+QD5APk5AMDBQAf
+AiUDAwI0AwgEKQMFBaMDAAAAFoJ/goOBXHCRf15/gXJ0gn9/gnJ/cX8DgwAt
+garU3dLGuL/S17/X17/LdXdecHeRf5N3epeUgnWTgqPHv7+4UE54f3qXdXF1
+AAN0AB6Ud3R3dHeBTXR3dXd6TZR3TUp1TIVRTnlNSndKd3cDegAfTXd3eXdg
+TU9Nek16T3t4hUtOd3p5e05PTYnHv93SvwAI0gHXBNIBvwPSACq/0tLRq1CG
+iqmIhoaIiYiGuVOshlCaiayshpqJiaysiqqGqoqvr51mRAUDAwAXBUMFA+MD
+LUTo0yw6+0VF/Pn5RUX8/CEAA/wIRQP8AANF6wMABAQTAgMECgIAAwQEBQAG
+AwAK5APkA+QD5OQD5AQDAQUBBB8CJQMEAjMDCAQpAwEFpwMAAABCkoKDcXB/
+XoKBdH+BgYKgf4GDg3+UlH+DgYGh0d7ev9HXO7/S17+/q0p0cYGRkXOTeaOW
+g3WDoHir0dLLXU53d3N2A3cADHRxg3d1TXR1dpeDegN1AAVPd2BNTQADdwBL
+cXVdeExOdGBNTXd6ek9Nd056T016eXpNTXl4eVGHhYVPek+HeYd3eavR3tLS
+v9K/0te/19K/0tLXv9LSv9LSv9LSw5mEUIiIrImsAAaIAAmFhbmGqoWGiYYA
+A4kAIoaniqrAi62vslhDQwVDBANDAy0DLeMx6crr+SLUI/tF/EUG/AVFARwD
+RQAF+/zy5AMAAwQUAgMECgIBBAMFBAMB5AMDAAzkAwPkA+QD5AMDBQQgAiUD
+BAIzAwkEKAMBBacDAAAADJKmdZCQf3KDf4FyggSBAGiRkJGDdIJ/gYJcvb/S
+OL/X0r/Sv9K/0ah1eJaBpKaik4Snl5eDlJaEx93GmUp1eHV1g06Dd3qBYHlK
+lHR4p4d3TnVOhIdgepRNd3d5eE5MlXlOTZdgekp5Tnp6dXWHek5Ph093ek95
+TgOHAA16eXlPhYVieU2Jx9e/AAjSAAPX0r8ABNIBvwTSACK/0seLhoiIqVCJ
+iYiphVCFiVGFhYSGrImJhqyJqaqGhoqGA68AB7COLi1DA0MABAMACkMUQ+Rq
+N58++/oDRQAE/PxFRQP8AAch/PxF/EVFAAP8AANF+OgABAQDAgEBEQIDBAUB
+BQIAAwQFBQAEAwAM5APkA+QD5OQD5APkAwMBBSECJQMFAjIDCQTQAwAAAAiF
+opFxk4JwgAOBABZxf39ecnF0gn+DcpaCcG+9v7/RuKveA9IAT9fSxl2Ug3V3
+c5d4hXanhJeXeIWoxsaZlHGWendydHSWTZd2eHd4THmXek93dHd5l3pgYE13
+enl3Tnp6eXl6TXd0cnd5eXp3TpZPelGoiIcAA3kBTwF4A3kAFIdiek53eniU
+dkyZz97S3dK/19K/A9IATdfSv9K/0tK/0t6/0saZhalQrKlSrKmGUKmKhoiF
+iIiJiKmIiamFqayGp4aqhsCLr5y0ROQDA0MDQwMDBQNDfkLqViT7RSLU/CFF
+/EVFAAP8AAVFRfz8RQAE/AAF6wUDBQQAFAIFBAcCBAQBBQEFCwMD5AAIA+QD
+BQQCAgQfAiUDBQIyAwkE0AMAAAAOqZKQf5CCgn9egYKkcn8FgQCGf3+Cf4OD
+grjXv9GEmb+/0r/S0sZdcnR3gpCXkaN4hHZ5eoSFlqiLTmCTdnmUl0qCcneS
+dXV4d3N5eU95ek13eXl3eUp0dXdOd3dNYId1TndNTUpyeU56eXlOh4d7qolR
+T3lOc4dOeU95T3l3Tk91eod5UsO/v9fS19LS19LXv9LS19LS178F0gAQ0ZiI
+hYiIiamGiamphrmsiAOFAD6piayIiKmsiKyphoanqpmYsI2ytBQZQy1DAwMF
+AwMtRDU37fojRUUjIkX81PtFRdT8/EX8RUX8/fz25AMEBCECAwQABAUDAwUI
+AwAN5APkA+TkAwMFBAICBAAfAiUDBQIyAwoEzwMAAABfknCCg4OCgl6Cf39y
+g39/XIFbXm+Bg3+DgZGr0tfUXaq/0r/S19LHSYGBXHSBg3VNd3d2eE5MeIJ2
+hHeSeJeXeXdgdXWXd3l3d3l3c3d5l3dNd3p1lkt2d0pyTnp3ekwAA3kACHp1
+TXdOeneFA3kAI4d2h4dOTod2d3h5TpZ6TEp1Tnd3T0yWTIVS0d47v9K/19K/
+AAPSAAS/0tK/A9IAGb/Xv9LRrlCJiFBQiaxRiKlSiKmFhYapiIkAA4gBUAOp
+ACysqbeoqorAra+Njg4Z5EMDQwUFAwNDQ+XKMj37IyNF1CP8+iVF+0X8Rfz8
+RQP8AAZF6wQDAgUQAgUEDAIDBAMDAeQDAwHkBwMB5AQDAAUFBAICBAAfAiUD
+BgIxAwoEJwMBBacDAAAAR3GCgYGlcoJ/cIGCgn+BdF6BgaRef49/caCTmdI7
+1F2Z0tLX0tK/y3GlgXKBYHCDlHSUdXWDeIWHqXaFhnlPd5R3cneDdU5zAAR1
+AE9Olk9NdHV1d6OEh3l3d3V3d094eFFOdU53eXV1T056eU96hXN6TXV3eV1P
+dXhOTnl4eE93T3d1knl3THnMB7/S19LS19LXv9LX0r/Sv9K/AATSACm/zFFQ
+qYh2uYiJiKmJh1GFqYWphreJhqypqYWpqbeGhKqqwMCvsJ1mRAADAwEFAwQA
+EEMF5ENs7PIi1Psj+/tF+/sDRQAN+/v8Rfz8/fz05QMCBQARAgUEDAIDBAQD
+AeQEAwHkBQMACuQD5AMFBQQCAgQgAiQDBgIxAwsEzgMAAAAof39xXlx/f5OB
+W4KCkXCQcX+BcoF0j150koGK19LUXagHv9LS19LHcQN0ABxxkX+lf4CBdHSD
+dqJ3l4d5h4eWTXR3dHRyd5dMA3UARHd1dXqXd3dMd055eU93eU5OenpPdnp4
+lk93d096l3V4d3d1TlB4d3V5eXN1TpZ5T3lOT3l3enpPd3V6Tnqu0dI419K/
+A9IABNfS0tcF0gAav9fSv97HhqlQhoZRqYRQqYaGhXiIhYWshokDqQAYiLmF
+qYSphIqqxIqtrY2dfhkDAwUEBAUFAwMAC+WfOfz8ISJF+vr7AARFAA77RfxF
+Rfz8ReoDBAIEBBACBQQFAQcCAwQBBQUDAeQMAwAGBQUEAgIEIAIkAwYCMQML
+BM4DAAAAF5OipoJ0gX9yg5GRcJBegoGBcqSBdIGlAAN/AHKLv7/Uc6jR0t2/
+3dLHW4N3g3RecX+BXn+AcneUeXlOl3lOcnJ1SkqWdXp3lJV6knh6TXpzS3NP
+d3Vzk3d3dU55p0t5eHh3d3l6ek93l0xPT3VKeoinTnd6TXeTeXhOToVPeHl4
+eXl1d3lOeXpOiMe/v94D0gG/A9IAB7/S0te/0tcAA9IAFb/S0VKJqYSGqYZQ
+rImFiIWGhYiIqQAEiAAWhYWTqYWpt6epp6qqmYuLsLVY4wMtBQMCABYFQy0D
+6O37If0H/SH8Rfr7+/r8/NRFA/wAAx/lBQADBA4CBgQAAwICAQADAgEEBQIH
+BAAEBQMD5A0DJgIkAwcCMAMLBCkDAAPkA+QAogMAAABpk6N1g4+Bj4F/kIKD
+dIKSj15/gXJ0gF5ecIGov9LRoKjUO7/S0r/Hd3SUk5aWpHKAYF6BlJR3d3iW
+Tndyd3l3dZN5dXd0dE2Xdnd6YHd3dXl6enV2d3dKd06WeXlKTXl3doVPd4dP
+h3dOAAN1AB5KTod5eoN3kV2WeXmHT4WFh0uWeXd3T3p5eXp6uP4E0gAGv9Ld
+0tLXBNIAFL/S0r/Sv9LUhomFhYmGhoisiIiJA4gAPoWpqayshYiFhamFqYSj
+o6enqpnAi5mwsrTk4yADAwRDBAUDQ0TqPCH8IUX7/P0k+Tz5/CH8/fz8RfHk
+AwQEDwIGBAADAgIBAAMCAQQFAgcEAQUQAwEEJQIkAwcCMAMMBM0DAAAAjIOD
+goGBXoFecHCCdZKRdY9/gXR0j16AgIF0vb+/0aKExr/Sv9fSxoWUdJKTll6A
+gIF/gYFxgnajdoNydHWDgnVOYHpNT3R3d3p5ek93Tkp1eU16d3F4THV3eXlO
+c3lPhXZOeHh5d3dLmXVNT0pNlnN0d5aRpnWRlE54enlOTnd5Tkx6dZZ5dUqr
+vzjdBNIAA7/XvwAD0gA3v9fS19LX0tLe0VCIhYaFiomoiIiFiLmIrLmsiIip
+qZaIhal2woSRkrenqqqKiouvfWXl5CBDQwADBAAVQwNDLedAIfzR/PoiB/36
+Pfr8/fz9AAP8AATsAwIEAwIBAQwCBgQAAwICAQADAg0EAAkFA+QDAwUFAwUA
+AwMABuQDAwUEBCYCIwMIAi8DDAQoAwHkpAMAAAAHgXCQXo+BXgADgQAjg5CR
+kIJ/cXCBgXSBgV5/Sr2/0tenkcfSv9K/0saGgaWSgpQAA3QADHKVlKWCck15
+l3NycgN3AFeUdHdPo6N5TnpPd3mXTXd1dEp3TXpKdnVNT3h2d3hMeXlKeXdP
+g01NmMZRTnp5dXl3d5aSeHmWeU54Tk93eXl3d3p4eU5OT3V0mdG/3tK/0r/S
+v93Sv9cAA9IBvwPSABk4v9GqiKl4iKqGiIiFhYiFrIa3t6y3qYWIAASpAB+T
+kqejxaOnp6qLra+wnLREGQNDBAQFBAUDQ0Tu1Pz8AAP9A/wABCT6/PwD/QAF
+/EVGBAQAAwIBAQEBDAIGBAADAgIBAAMCDQQFAwAFBQUDBAUABAMBBQMEJgIj
+AwgCLwMMBCoDAeSiAwAAABuBgoF/XoF/gYGRXn+Dgn9ej3B/gXSDf4NypKEA
+A78AdoZwuN2/0tLev5hwg6WUgIOUlKaXcnJ1g3SUYHdgd5R0dHKBd4eFqXl5
+emB1eU93dXJNTk1NeneHeU5Pd3V6TqJ4Tnd0dUx5SlyZ0bhRS02UTnd3hUuF
+eXhMek5Md051TU55enh6eHl3eU2LzzjXv9K/v9K/0tcD0gBWv9LS197Sv97R
+qFGFUIm5U1FOUYWFUIiGhqyIqYWshYV4kre3p6OjxaCnt6qZr62vjY5YLRQD
+BQIEBQVDA0Po+iEh/CEHIQch1PtF/P0h/fz76QIEAgIDAQwCBgQAAwICAQAD
+Ag0EAAUFAwPkBAADBQADBAQFAAMDAAQFAgIEJgIjAwkCLgMMBCUDAAXkA+QD
+5ACjAwAAADB/XoGBXoGDg3CBXoFef4F/cn+Bf393c4KklKfU0tKrd73dv9K/
+0r+rg16WXpKUf38DgwBQk5aXTXR/XnR0XHF0dEqBSk15eU10dXd1k3dgdXRK
+d3pKSk14p3hPdE12hXl3d011g5aXSpnU0ah3dHR1T093endyeXmHSpdNek96
+d3OWT04DeQAHenpRw9fevwAD0gA1v9fSv9K/0tfS0r/Sv9Ld1IpRh6yHmom5
+iKm5hqmprKm3iLmIuYinqbeTkpLFkpCgo7eqra0AA68ACY20Li1DBUMCQwAD
+BQAMAy7zIfwh/fwh/P38A0UADfz9/PxF6QQEAgEBAgEABQIBAQMCCwQQAgEE
+AQUEAwEEBwUABAMFBAQnAiMDAAYCAgQCAQIDBC4DDATNAwAAAYIBcQOBAIpw
+cJJzgoGBf5Fxf3+RgX9/g39/gXJLy93SuJSo0Ti/0t7Xx0pcdIGAgn9edIF/
+lpd6d3RxXoCAdHRydGBydHlMdpF6eXd3lHd3YGByd5RKdHd6hk53cnZ4h3hK
+d3dzlneWSqHRx3hNSoN5eXdPl3dKTXeFTk93TXd6ek5OdXl5d016Tk6rv97S
+v78D0gAUv9e/19LSv9fSv9LSv9RQh4iJiVEDiAAzhYqhhISFeKmpeYiIqaep
+hXbCkpDFosWit6qKwK2Lr7COfkQUQwNDA0MEAwND7CHUIgchAAT9AAT8RftF
+A/wACEXpAwQBAgIBCQIMBBACAAcEBQPkAwMEAAcFAAMDBQQAKAIWAwECDAMA
+BgICBAIBAgMELgMNBA8DAQW8AwAAAIyCf3+BXn+DlpKTf4GBf6SBcoGCf4GB
+goFwW13Dv8e5g4TG3r/X3t7XiFyAYHR0j1yAdH+Bc3WUYHRgdGCVYIF0gYN0
+YHdOqaN1lHR1c2B6dHddSndKenl5o3h3dYWEdnd1c3VykpNOqNHDdXRylnp6
+dnlOTnV3TnpNeXVPenV5dXp5TXJKenl6eK/RvwTSAb8B1wPSAAO/0tcABNIA
+ML+/3saFeYhRiIWFhqyIiYiHwqmphYWphbmIhYS3qZKRksWgoKe3hpmur62u
+sLJqRAMDBAUABgID5GpFIgP8ABP9/CH8/fxFRfz9/PtGBAMBBAQBAAgCEgQM
+AgQDAQUBBAkFAAMEAgEAJgIWAwECDAMABgICBAIBAgMELgMNBCcDAwWiAwAA
+AJCTg39ef3+DkKKDgYFej3KCf4JygpBxj3J/qpKY0cdQW4HD3d7X0r/Xq0lc
+pVuBgGCAYIF/f3JydIGBlHSUlHSAdIFgdJRKl3l3d0p1kWB3dGBylHR3lGB1
+dXdzdXl3eXVKTpd1eEpPq7/DTZdKdXmHdnp5ek16dHdOeU5PdUx3eE55h3d1
+T1GFS4rU0tK/0r8D0gASv9LS19LSv9e/0tK/x1CFiKxQBKkBrAOpADGFiKmF
+iIWpiKmpkniTkpF/kMWgxaKqyMiurq+vjVUv5EMDBQQFBAIDAy48Rfwh/Qch
+AAP9AAr8/UVF/PxFEwUDAwQIAgAEBAQFBQ8ECgIABAECBAUDAwEECAUABAQC
+AgEnAhUDAQIMAwAGAgIEAgECAwQuAw0EEgMB5BQDAAMFAwUAogMAAAARloKC
+j1uBg5STg15egYJ/f6QAA4IAhnWlf3KTuL2Ey92iSnS9v97dv7/SxoR/pVx0
+YFyBdIOCYIBcf4GDYIKRlGBggHR0YHR/dYNgYHRzXXd0dHJyTXR3YHSBdIN3
+dXd1dU13d3WDTmBRxt7DTXl3lE96eHl3eXVySnZOdUxddnlPd3l4eXlOeYdO
+TonGONK/0r/Sv9LX0te/0tLXBdIAMcdQiFOGhbeFhaeIeIWpqbm5qYiphoiW
+uZaTt5ORkJDFoqCnhsjJyK6vsI2yZi4gBQMABAQDQwAL8yLU/fwh/Af8/P0A
+A/wAC0X8++7kAwMEAgQEAAUCAwQBBQEFDwQKAgAEAQICBQMDCAUABQQEAgEB
+ACcCFAMBAgECCwMDAgAEBAIBAgMELgMNBCQDAwWlAwAAAERuf15/gYJ/gnBw
+XoFegHCCdZCCgqZ1gYOWx9G9vf3LXYOnxr/S19Ld0sOWlHSAgYFglHRegV5/
+gXKlkZRyf4CAgVx0YANzAEp1dGCVenp0YEp0dGB0YHRgSnd1g3pgd4NylnaS
+epRNq9E7mE9glYN5T3lPeXp3Tnd6lk54dkx5eYeHhXZ5doeFp4VQx9LSv9fS
+1wPSAb8D0gAJv9K/0tK/3sNSAAOGABiIiKyIp4aGhYhQiKqGrIi5hYWphXh2
+ppMDkQARxae3o6eYvZitsI2eVdbj4wMABAQACgUDA5/8ISH9/SEE/QH8Af0D
+/AADRfLkAAMDAQIBAQYCEgQMAgAGAQIEBQMDBAUFBCwCFAMDAgoDAwIBAQMC
+AwQuAw4EIwMAAwUDBQClAwAAAC9/Xo+BcpFygX+Pf4Fef4GDkZGCc5GkkpOE
+wyHHqMbPp290w7/dv9K/0tSYll90gQADdABPYGB0YHSDcnd3lYN0YGCAdHRg
+dIN1dXSUTXV3SmB0dHdgd3RKdHR1kmB3TZV6d0x4d3eUTsMHv4hNdXd3eXd5
+TXdMd5dOlk5Od053h3mEeQADhQAIeXmHhVFSzL8D0gAIv9LX0tfS178F0gAE
+v9LexwOGAA+FiIWFqYaqiFGGqYapiKwAA4gALrmFqbeSwpKRkJGQo8WSt6qZ
+ma2vsI2ytERDAwIEBAIEQwMxPCH9If39/P38/P0D/AAHRUX15gUDAwAIAhIE
+DAIABQQFBQMDAAUFBQQtAhMDBAIIAwQCAQEDAgMELgMOBCMDAAPkA+QApQMA
+AABYcn+AgYFwcH9ygVuBf4GBcZBygoGCg5OEopnPv5iozqeDhazU3r/Sv9LX
+w0t0YHR0XF5ydIF0dIN0g2CDk4OAdGCAdHRglHWUdEqUenJxdHR3lnd6d2BN
+dAd3AA9NdXZ3d02Z3d3Rh012d4cABHcAEnJ5T3l5S3h5d3l3eXl2hYSFeQWF
+AApRzNK/3r/S19K/BdIAA7/SvwAE0gHDAZkDhgAsqqmGrIanqYmop1KqhqeG
+t4WIiLeSlpORhJGQxcWjp4jEisCtsI2NsrUO40MDBAAJQwIDA0NAIf0hAAP9
+AAUh/f38/QAD/AADRfjoAAMDAAMEBAIAFwQBAgECCQQBBQEFBQMDBQYELQIT
+AwUCBgMFAgEBAwIDBC4DDgTLAwAAAAWBgV5egQADfwBBgYOBf15/gYFegX+C
+f5GTwpaEvdfHUMSWeLi9zDi/3tK/19GrTkp0dGBgdHSDd4FgdIF0kE50YHR0
+YHR0d4NMd2AAA3QAQZRyd3R0YHV1lE13YHdOenp1dXp5eXd0TXbHv9LHUXR5
+eU51eHVKdZd5eXZ4eYh4hXl4kqmphYiHTnl5UalQzN47AAPSAC6/0tLX0r/S
+v9K/0tfSv9G4i4aKUqqqrKmJhoashqqsqYiphoa5iKm3qZOpo5HFA5AAD6On
+qqqKiq+wsJyNjtZEQwAFBAAGQwMD4v3UBf0ABPz8/SEE/AAI+uzkA+MEBAIX
+BAECAQIKBAYDCQQvAhADEQIBAQMCAwQuAw4EIAMAC+QD5APkA+QD5APkAKAD
+AAAAloFegYGkgX9/kYKBXqRxcX9/goGCkqKEk5KCqsbUqKWldsfRxge/0r/X
+0t3Pp3RedGB1g3dgYHF0YIN3dJd3YGB0dGB0dHV3lHR0d3R3dJV0d3pgdHp6
+TXdNTXl3ek56eHVKdH+rBzgHq7l3eUx3eHl3eHZOTIdPeFCEqXZ5koR4hXas
+hYeFh4VQqMbXv7/Sv9fSv9LS1wfSAAO/IpgAA4YABqqnhqyGtwOsAC+KrMGp
+rIiIhYWpube3eMKSwpKQkZCSt4bAisCvsLCNjbLWDkNDBAIEAgMFQ0L8IQAE
+/QAF/P39/P0ABPwACPsS5RktBQICFwQBAgECCQQBBQUDAQUJBDUCCgMRAgEB
+AwIDBC4DDgQBBcoDAAAAQoF/Xo9eW3+Bgl5/gYKkf4F0XIFygYKSgqZ/cb3Z
+0Yh/pJnRIcbX0tK/0jjSzHWWYIBNXpR6lHd3dE2UlHN1g3R6cgN0AECUd3d0
+YFx3dHR3d0p0YHVgTXRMeZd4endNTU53lGJR0dLdv5l5eXpzTJZ5eHmHh3iH
+hal2qaiGhoSEeIWFdoV5A4cAJU+L0TjS0tfS0tfS17/Sv9K/v9K/0jjHi5mq
+qKqLipmLioZSiKwAA6kALIisqam5hamIlreFkpGSkqORhLeGwK3ArbCwnI2y
+tX7kA0NDBEMFQwPmPCHUB/0B/AH9A/wAB0X16QMUBAIADAQABgMFBQQFBQME
+AAUFBAQCAgAFBAECAQIFBAMDAAUFBAIBAQA7AggDFAIFBC4DDgQBBSADAAXk
+A+QD5AClAwAAADZef4F/cFtedH+BXoJ/goFegICBgo+BgoKBgoKsxwe4f5OT
+uMOZ1NHS17/Sv9fDS1xycnRgd4MDdABDlEqUepRKd2B0TZV3dHdgd3R0lU13
+dGB0d3dKYHp1d3dPendzlod3lE1MuNK/3cNLTk6WdYN1k3N1eXd1dXipt1CG
+rAADqQAUhLephISWTodLTpnRONK/0r/S0r8H0gA5v7/Sv7iqipmoi8CGqopS
+iomsrFCpiYiIqaysubl4qbd4k8K3kpGRt7enhqyLr62wnJ6d09ZEAwMFAAQE
+AAdDRCskISHRAAb9BPwAB0X57BQtBAIADAQACQMDBQQFBAQCAgADBAECAQIF
+BAUCAAMEBAUAAwMABAUCAgQ8AgYDFQIGBCwDDwQBBcoDAAAACH9/gV6BXn+C
+A38ABIFxf38DgQAVdIF/XqVegoJzeJnHx5KCk5PElr0HAAO/AA3S17/dx71L
+TXR0gnRxAAN0AC6Dd3RNdINNdHdNTWB6endgTXp0dHJNd3RKcXdKd3d5epd5
+d4eHpU5LuL/9ONFQA3cAK010TXdgenqUl3eDTnhOh3h2doWphISnt4R4eHmF
+dZi/v9K/0tLd19LX0tcABNIABb/S0tTJAAOZAAyKwKqoqqqKiqynqqkDiAAh
+rKy5qamGqbmnt8KTo5GQhLept4aKwMCwm5yNsrJsWOTjAAMEAAhDAgND7T09
+/AP9AAYh/fz8/f0D/AAH+/PlGQUFAgAKBAEFBAMDBAECAQIEBAECBwMADQUE
+AgQEBQMD5AMDBAQAVwIGBCwDAQUBBQMEAQUBBQMEAAMFBQQAAwXKAwAAAYIB
+ggOBAHh/pHJ/Xl5/knKBf4FygV5egYCRo6ajbpKGqpOmlpOWc4W40Tje19fS
+3t3Rq0yAdHeBYHSBYHJ0dIFNdHJ3YGB3YGByck93YE1NcnV3dXp6d3V1lk54
+eXd3dYVMqMu/B/4Hq3d5epRNdGBKd013Snd3TXqWd3V0dZYDeQAPlnaHeHhO
+eXZKmL+/0tK/AAfSACi/0r/S0jjRw5mLmZnAmZm3hoasrMSsrIishoq5hoaI
+rKmshbmFk5KRA5IAIbeGxMDAra2vsJ2cnbK1fkQtQwUEBAJDAkIjPD5FIf39
+/AAD/QAK/P38/EX56AMEBQsEBQMACAUDBQUEBAUFCgMBBQMEAQUEAwMEVwIH
+BCEDAQQBBAcDEAXLAwAAADtygXGkgX+BgXCBgZGCgoFbgX+Bj4FegYKTk5KS
+k5OQqZKjf3KRXkvD3t7Xv97SONLRq0p0gUpgYHRgYAAEdABNYJR6TWBNek1M
+d0p5d3V3dUpPd5d3dXd5eoR2T3lgS0pQx/2/v97Dh3VOdXl3dU10SmBPenN1
+dXeHdXd0TnN3lHd3dXd3dXd5h0qrvzgABNIB1wrSAEve0cmYmaqZmZioqsSJ
+qqeGqayJiIqsqqyJhre3iKmIeJORkJKSp6zEwMTAwK2wsJyNnrKOMUTjAwVD
+BAICQ34kISTgJP38/fz9/P0AA/wABxxF7eTjBAMABwQACAUEBQMDFAMFCQMB
+5AMDAeQFAwAEBQUEBQMDAQUDBFcCCAQgAwUEAQUFAwQFAAUDAwUFAwAEBcwD
+AAAASIKBgW+BXoGBf4KSkIJegXByg3SBXn90f5OCk4KTk5KSlnimeJR1g3PH
+v96/178H3te/w1CXlHRcYE10YINNlHR0TWBNd0p3lAN3ABZ6d3l5enR3TXJ6
+ckp5lpZ1dXROqNG/A9IAJ8+ZeIh2XXd3lXRNlEp0TXN1d054eUqXl3eWdUp5
+eXh4dpaTeUu40QAG0gE7A9IBOwXSAAXe0auZiwADmAAHmYaqqqysqAAEhgAm
+UoqsrIqsqcSnt6yTwpKRknC3hITEycmurq+tm5yNnbLKZuVDA0MDBAAZQwRD
+9fz9ReAn/fz9/P0h/Pz7RUXg5xkDBQAEBAADBQQFAAUDAAMtA+QABgMB5AMD
+AArkA+QD5APkAwPkBQMFBQEEAwIBAQEBAwIBBE0CBgQBBSEDAwUABAIEBAUP
+AwEEzQMAAAAHgn+BW39vfwADgQAtcX+CgX9wf5GkgoBecnCBj39egpJ2c6Z/
+f6Z1gnWDqsO/3t7Sv9LS3b/HiIN6AAR0AA56TWBKTXRKTXdNd016TQN1AApN
+dXJ3end1TndyA3cAHXR3eUyZz7+/3r/Ri4V3hXh1TYNycnRNd3dKenl3AAN5
+ABN0dXhzdYJ1dU52eXl4lpd5uNI4AAPSAAY70ts70twG0gAG3s+rmZmYA5kA
+P4qGilCKqoaGiqyGiqysqreprMKFwpaSkqmTt7ept8ies8nIra+wsI2NnrJq
+fuMDAwUEBEMFQ+Ih/P1F89/8RQAF/AP7AAUe6gMDBQAFBAUDAS0BFAsDAeQE
+AwAG5APkAwPkBQMBBQUEAwIDAQMCAQRNAgYEAQUhAwMFAAMEBQUAEAMB5M0D
+AAAAG4KBXn9/XoFegYJ0goGkf3+Dg4JwgYGAgV51gQADkQArp6KTknNyf4KT
+k3KGx9G/3tfSv7/+3st2XHSDUXiETXd3TXR3TXpKo3V1eQADdwBvlEp1d5N3
+d5Z3lHeUTXRNUMzRv97ev9SZlHR0eU53d4ODd4J1dXd2eXeTeXh4dpKpknVO
+d3h2eVCWeJaDhsPS2zvSO9vSO9vc0tzcO9s70t7Rq5iZmK6ui6qKhqyGqqmq
+rIaqp6rAp6ysqYW5uZapAAOSAA7CqcKSp8mvyYvAsLCcfQOyAAW11kQDQwAE
+BAALAwPrRfz8/fzx8RwABPwADkX7Rfj47+QEBQQDBQUEBAMADBQDA+QD5APk
+A+QD5AYDAeQEAwAI5AMD5OQDAwQHAgQBAwIBBE0CBgQBBSEDBQXfAwAAAKx/
+cH9egl5bf3+BgXBwXqRyg4OCcXKBpXJwg4OCkaOphKmSwqZzk5aTdHWGw8/S
+3dK/O7/dv8aYdUxNTUp3d3SDd2BKdXd3T3l4lnlKeHd1dYKUd5RgYHRKeU6Y
+x96/0r+/1ItKg3d3TXlydXd3lnN1dXlzdnlOUYR4ToSEeJaWdniFhal4eJas
+qtTS0jvbO9Lc0jvSO9LS3Dvb0jjUq5iYmZjIi5mqxKqsqobEB6oAMMS3qcKI
+lqmWhZKSt5OSkZGomM3IwJuwnI2cnrKOtERDBQQEAgQCBOj6Rfz8/fzwEgf8
+AAn39/Xm5OMDAwUABgMBLQwDAAPkA+QABAMAC+QD5APkAwPkAwMEAAYCBQED
+AgEETQIGBAEFIQMEBRADAeTPAwAAAHqCf3+Bg4GBcIJ/gV5/gl6RgpaCkYGC
+goOTf4GBgpGTkqOEk4XFp5GReHKRqJjH1we/0r/S3t0HuIpcXHRKc0x1Snd1
+TXdPd3hOT3l4THZLeHRydGBKSXRKmccH0ji/3gfUmU1gXXZOcpd3d3h4k3V6
+lnV2hHaWlrepSwOpACGFqXZQhVCEt6ent6vX0tLbO9s70tLbO9vcO9vS0jvS
+1K4AA5gAK5mYmYrEhqiqxIaGqJmqwIqKqoapuYWXwoWWwnaTkpKRt8LCt6i3
+xLCwnY0AA7IAN45sROMDBQUEBAIC5vf7/CH8/fzx8fz8Rfz8Rfn2+eoDGQMD
+BQMD4yDjAxQD5APkA+QD5APkA+QABAMACOQD5APkA+QDA+QDAwUEBgEDAgEE
+TQIGBAEFIQMGBQQDAeQDAwAD5APkAAUDAAXkA+QD5ADJAwAAACR/gXKBf3+B
+g39egYKBcqRzo6ORgoFwgXSCpIKDcoN/gn9/gpMDkgCvt3V2qXmCdqvG3Qe/
+v9Ldv9LPq5iEcXSUpZN1d02Eh054T4SFTISEeHVJk05LS6i41NLe3b/Sv7/G
+mU13l096eXmFhUp2dnN1lnOWlnlLt4WphIS3p1CEqU63hKeqp6OGqMa/ONI7
+2zvS3NI72zs72zvbO9w7xq6YmK6ZmZiqqIaGiqiqxMjAwKrEqqqGwoW5qamI
+loWFqbfCqcTAwcTAsK2vm5yNnrKyymp+LQNDAQADBAAFBeX1RUUAA/wADiFF
+7u9F/PxF+vX1+RLlCgMBLQ4DAeQDAwAH5APkA+QD5AAEAwEFBQIFAVACBwQD
+BSADAwQGBQMDAeTXAwAAABaCf3Skbl6BgoKBdH9ef4GmkZKTg3+BA4IAG3Jw
+f39ygXKCg4KTkpOTkpKEt5KTdXiKuM8H1wAGvwBm0cbLq4ZLcnp1SkhISk6F
+hEtOXYRQqIRLqsPH1NHSv97dvw3RzIZ5Xnd1h3l1S6mpk3Z4eHWWeJN2kqeE
+qYWnhIS3t6mSqYaoqqeoo6q40dLSO9s70tzS29I7O9vS3DvSOzjRrpmuA5kA
+KqqqmcSqqsS3wJnAipnAqMSsiKmWloiWiJaWwqesxIzBwcTBwZuwm5yNnQOy
+ADdq1kRDAwIFBAIB5PJFRfz8/fz9+uvx/EVFHvj3+PToAwMFLQMg4wPkAwPk
+A+QDLQPkA+QD5APkAAMDAArkAwPkA+QD5APkAwMBBFoCBwQDBR8DBAQFBdwD
+AAAABIGCgV4DfwAJcoF/f4F/gXBeAAN/AHWBgoKRgn+kXn+BdH+Bg3+RhKOi
+kpGSkre3hKmidZLEx9Hd3TjS0r/S3b/Xv8e4uJiqmZmoqJioqpmZuMzR1NG/
+19fSONI4v97Sx6uJgnVKT3N4lniTkpOEeKmpgpGjp6mShJKTkreEt6eneKmS
+p6eqqKeomMYABNIABNzS3NIDOwAh29LcO9s7O9K/1MmYmIuZmYaZhqqop8Sq
+wMCsqpmqhqysAAS5AAeFuZZ4k5bCAAPEAAqMwcGwrZzBnJyNA7IAB45C1uQt
+AwIAAwQABQIF7kVFAAX8AAT99ufxBEUAD/j2H+vkAwMZ4wMDIAMDFAAFAwEU
+CQMACuQD5APkAwPkA+QDAwEFWwIHBAMFHgMFBAUFBAMB5NcDAAABcgN/ABqB
+gX+Df3Fyf4KCgX9egYGCk4KDgYJypoOCpASCABx/oHaSk5GCg4KSkZKjlpOS
+havL0drd3dLSO7/SA94ACNLR0c/R1NHUA9EAM8+/v93e3Qe/v96/B93Rx6uF
+hXJyepOCcnaDg4KDeIKEt5NxgoKSk3Fzf3WBkpGRk5OSkgADkwAHkqOnmcPS
+vwAE0gBKO9vS29LbOzvbO9Lb0tK/v8yumJmYqJmqmZmqyKrIp6qqxKiZxIis
+rIWpiJaFwpbCwsTEwYzBnJybrcGwnJ2NnbLhsrVm5eMDBAQDAgAHA+n7+vv7
+RQAE/AADEufzAANFAAb54Prv5OQFAwAS4wPjIC0ULRQtAwPkA+QD5APkAwMA
+BeQD5APkAAQDAAPkAwUAWwIHBAMFHgMBBQMEAQXhAwAAAIuBgoJ/XqRygoKP
+gqZygnWBgXRyo5OCk4OBg3WUkl2QdH9ypJGSkoJegYF/kZCCloNwdaZ1dqvD
+B9rS3NLb19e/ONe/0tK/0t2/0r/Sv97S197S0r/Sv97dxr1LcX+CgV53dXFx
+k3R0cKSWgpOikn9/Xn9/cqSBgIGPcH9egX9/cIKmf4+EmM87v9K/AAPSAzsA
+INI70ts72zvcO9K/0ceumJirmJiKmKiZmMCoqLeowMCqA6wAE4msqXiFwpKW
+iLmvnK/JfZyur68AA5wAErF9nY6ystNqLkMDAwQFBAIF5AP6ABj49vv7RfxF
+6ufzRfr58h3z5gMDFC0D4yADAwAFFC0ULRQACgMB5AMDAAbkAwPkA+QDAwEF
+BgIFBFACBwQDBSwDAeTXAwAAAAaSg15cgYEFfwAbXoKPcHCBgaSCgnN/g5G3
+o5KRpXelco9/gYGCAAOBACBegX+DgX+PcH9wgYKDdJKouMPPv7840r/S19e/
+17/XvwTSAAS/0r/eA78AMtTGw4RyXoJ/f4Nzk5SCf3+BkYOmc4F0goGDf15/
+gXKCg4J/f3KUf4NekoKCg4JxgXbHBdIB1wXSABfbO9s72zvb0r+/0f3GyauY
+mK6ZmK6ZmAADqgAsqKrExIbErKm3t6m5hYWSeKmsxMSc4hK6sZirwcGcnI2N
+sryyn59qfuMDAgUDAQAWAgL3+kX79fb6+vtF+Ojo9Pv47vng6AgDAAjkAy0U
+LQMD5AoDAAXkA+QD5AAGAwEEWQIIBAECAQQDBf8DBQMAAABugpF/f16CgV5/
+XnKBgV5/XoGBXoGCg5OWk5K3kaKWlIOCXl6BpYKDc5F/f4F/coF/f4ODf5GC
+XnReW3Knw8fGz9e/Ib/Rv92/z9HP1M/UxtTGy6uYqKG3g6SBgqRegZGSo5CR
+goF/dIKCgYOBgl4DgQAXdIKClpGRgXKBkH+CgYGDgX9wXqvR0r8ABNIBvwTS
+AAk70tzS3Ds70t0AA78ACtHDq5iYq5iYma4DmQAaqoqqhsCqhqysiLmIhYW3
+qZOWwojEwH3YV6sDrwGwA5wADI2dsryyn2p+5AMCBAMBAAoCAvX5+vsl9x4d
+A/sAIPHnRu7y7Pg9RgMD5AMDLRQtA+QD5OQD5AMDBQUDBAUFCAMB5AQDAQUB
+BFkCCAQBAgMDAQX/AwUDAAAAB5OCf4GBf38AA4EABJF/f4EDfwAPgX9xgYKR
+kqeSlpOTkaaTAAOBAB1vdJGTkpOCgYBwkX+Bg4OWg4KCg4GWknKCk6i9qwAF
+vQAQuL29mKeEgoOCgpFzkXKBggOTADempYFegX+DkJGWdYORgYKBgXF/gl6U
+gV5egJGRhJKWg3+Bcn+BkpKmdZKPhM+/ONK/0tLX0tK/AAPSAAM70twABdIA
+Cr+/B9fPq6uhmJkDmAASmZnAqorEqsC3xKypiKmFt7eFBMIACoXCwK4TntCY
+wK8DnAANjY2yvLKfn7XW4xkEBAADAQAQBAX1+/r6+/scRUUcHPvs6QPqABH3
++esDA+QDAxQtA+QDFC0ULQADAwMEAAMCAgUABQMAA+QD5AAEAwEFAQVaAgkE
+AAQFAwMF/wMFAwAAAGeSgn9/kXF/W4F/g4FegYJ/gX9egY+BkaOSg6Zzk5KT
+lJSCgV5/XZKjlpR/Xn+Bf3KRhJORkYJ/XoF/k4FcXnJecn9/gZGTg3+RXoGB
+f4F/f4ODgn+CgnN/g4OlXl6BgnWCkYKDf3GRAAR/AB+BgoOAXn+BcqajkZaD
+gXKkcoKCkqOnkYTD29fSv9K/AAPSAAO/0r8AA9IASzvbO9LS3r+/B9H90cfJ
+q6uYq6uYmYuZwKrAqIaqxKmpwoi5wreFvsKpucTAws3Myauura+MnLGNnuGy
+yo6ftdbkFAMFAgECBAXzRQAD+gdFABb56elG6ff67gMZAy0ULRQD5AMtFC0U
+AwMDBAMCAQQDBQADAwPkAAUDAQVbAgkE/wMJAwAAAHODgn9ygoJ/W15zpoF/
+XoKCcl6PXn+BgoJzf4KRf5GCc6WBpF6Dk3OjgoOCcnGlgYKSoISTknKCk1yB
+g3+kf3V1gV5elF2TcXFyg4F/cH+BgYODpnVxgqSSk5OBgV6Bf4+kgYF/k4Ol
+coKDg4GBcn+BXoGRAAOTABaCg4OBf4GBgpOReHC40b+/19LS19LXBtIABDvS
+Ow0F0gAHv92/B97DrgADqwAEmJmZwAOZAB+qqqiGqcKFhcKWuYipwsK5msS5
+xMjL2dDIwa+wnJyNAASyAAifjkJsRBQFBQMCAAgEBfBF+/r6HARFABf8RUXx
+5uno9/rvA0PkA+QD5OQD5BQt5AADAwEFAwQGAgEEBwMABAUEAgFZAggEAQX/
+AwkDAAAABINygpADggB8kYF/kZFygoGBgn+BpIKCcIGBgoOCc4OXknJ/XoGC
+gpOWc5OUlKRegnKBf5KCgYF/gpGRcnBef4GUg15ecpFzopKWcnKCgXGBkZGS
+kpF/poKlg6Ref4OCgYFedJGSk5aTg6SBpHKQkaSCf4KBgpKCkaSXg16Bf15/
+cV29vwPSAb8B1wbSAb8E0gAQ29I70jvS0t6/0t2/v8bJqwOYACGZmJmYmZmq
+qKysuazCubmXqcK5lsKawZycm8jIuKvAsMEAA5wADI2djo68so5C1kQtAwQE
+AAQCAez7A0UABPv7RfsFRQAX8eXp+B3uBBkD5OQDA+TkA+QDFOQDBQUAAwQG
+AgADBAUFAAMDAAMFBAQAXAIIBAMF/wMHAwAAAXIDfwAsgYJ/cYGBgn+Cf4KC
+gXKBXoKBf4GDkpGCkYOTo5GCf15ygX9/koKDloFepIEEfwGDA4IBgwN/ABeB
+g4FygYFegX94hJOCcoJ/gYF/gpCjkwADggAzkoOCgl5/g39/Xn90f5KCkYKT
+k7eTkoKDg3R/f3GCgn+CgpKDgYKBgnFIq887v9K/0tK/AATSAATX0te/A9IA
+FTvb3tLS3tK/3r/e3dHMq5irmZiYiwADmQADqqqKAAOpAC65uYXClpOWhcHB
+CLO6V8ivwK2bsJuxnJyNsrLKn7KftWzl4wMFAgQCBeRG9R/6BPsAGUVF/PxF
+RfvtE/n77QID4+QD5OQDA+QD5C0AAwMBBQMEBQEABAICBAUDAwADBQQEAFwC
+CAQDBf8DBwMAAAN/AIRegXKCgn9ygnKCpF6CgX9yf4KCXoF0f5BycX+So5KC
+kX9wf39epJORcoGBcoJ/XoGBcIKTg3WBf4GCgn9/gqR/pIKCpoJzg5SBXlyB
+goGCgqaBcZJxkX+Bf3KCf4JegYJ1f3Kmg5OiqaKTlHSDf16Bf3KRg3KTg16B
+g4Fep8Y40tK/0tcF0gAE19LXvwPSABc70t7S0t7S0t7S3tfdv8euq669mJmZ
+mAADmQAExKyprAOFADLCuaapksSasZ4VEvbMyY2vwJubnJ2cjbKOsrLhytNs
+5eMDAgIEAQID6fPg9fX2HkUcIwVFABL7+Pr67AIDGS0ULRQD5C0ULRQDAwAE
+BQUEBAYBAAgCBAUFAwUFBF0CCAQDBf8DBwMAAAAUf4JygYF/f4OBf4J/gV6k
+coKkXl4DgQB0XpGBgYJ/g5KRkXF/gYOkgl2Dg5OkXl6BgoFegYFdgpKSppOl
+f5aCknGDf39epH+CkoKCg4F/f4GCf39ygYKTcoODgoGDg3ekcoFef4NykH+S
+koWTkpOmf6SBf4GCgnKBg3J/cH9xTKjG17/Sv9K/0r/X0tcF0gAGv9I729I7
+BdIAC97d0t7e3caroaurAAOYAEHAyKqqisSGhoiIkoW5lqnEucGawLq7u8fH
+yZ2wsIycnY2esrLKn7LKRmx+5AMCAgQCAQXp+Pr6Hvc8+/scRfxFRQAE+wAQ
++uoF5OTjLRQt5C0ULRQtAwQFAQQBBAUCAAQBAgIEAwUBBF4CCAQDBf8DBwMA
+AAAKgoJ/pH+kkX9/cAOCAASPXn9wA38AIIJej4GBcX+BgX+jkoJ/pHSBcpOT
+kZKCf4F/cn9/gXKBBIIAI6aThKKSo5allHWBcF5wgoGkgoKDgYFypF5/gHCC
+cnKDcl6BAAOCAC9/goJ/gaSCgqOjk4KRg5KCdGCBXoF/f4KQcX9/cFteocbd
+v9LSv9LS19LSv9K/1wAE0gAKO9I729s72zvS0gPeAATSDb/RA6sByAOYACOq
+mcSKhoaoxKeIuampubmawJu5yMgW4sO9ybKcm7CxnI2csgADjgAIn7zTbOVE
+AwIDBAAFBQPn8iYAA/oABfsd+vv8AANFA/sAEfr6RhQD5APkLRQtFC0ULRQD
+AAMFCAQACAEBAgQEBQUEXgIIBAMF/wMHAwAAABV/f3FxXoFyf3+Cgn+CgnSC
+f4F/gXQAA4IBcgGCA38ANnV/goJwcXBef3+CgYKRgoJ/gYKCcqSCf4GBc4Km
+kniSo4KDdZNygYGCgpKWgoJbgoN/gV6BdAOSACuCgoOWk3WTkZGDg39xXoF/
+k5J1dYJxf5KTg4GBgoKkgpaUj3KjhKvU0r87AAPSAAe/0r/S19LXAAbSAAYN
+0t473DsD0gANENLS3t0N3dHMmJi4qwADmAAaqpmZqoqqrIjCt6y3yMDIq8HE
+yJivfdC9yJ0FnAAbsJ6O4Y6OvLzTbNbkFAQEBQICAwXk7Pb2H/tFAAP7AARF
+RftFA/sAA/jn5AADAwAKLRQtFC0ULRQtAwgFAA0DBQUCAgQEBQQEAgEBAFwC
+BgQBBf8DCwMAAAAig4N/gXKTpHKCgYGCgn9/gYKCXn+Af5B/f4Jxf4F/kYF/
+kQeBAEBxkYJwgYJypIKBgnGDf5GRp5KTk6Zxg6WDpH9eXpKCgn+CgYGCcn9e
+gYOCk4KCg5OSoZKjgneDg4KPcY9yk4OmA38AFYN1goKBgX+Rk3Vyk3+pw8PR
+v9LS3QAR0gAT3NLc0tzSO9vS0jvd/QfS0syrqwADmAAIqMiZmarErKwDiAAG
+uZbExMDIA8EBxAPIAATNmK6dBZwAD42yssrKvJ+8jmx+5AMFAgADBAANA+Tn
+4vr49R4c+vr7+wADRQAQ+vv69eXk5BTk5APkA+QD5AQDBgQABgUDBQQCAgQE
+AwIBAVwCBgQBBf8DCwMAAAADXl6PAAOCAA6SkX9eXn9ygVuCf16BXgN/AA2D
+f3Skgn+DXoF/XqRyAAOCA38AV3F/cX9/gnKCgn+Bf16ko5KWgpFykYKWlHKB
+f3+CgXNxgoJ/XoF/f4KDf4OkcZOWk5aTo5Kmg4KkXoF/f5GUk4F/j4F/pF5e
+dH+Sk5CCd3Gnxwe/3tLSOwAN0gAVO9LS3Nvc0jvb3Ns7EA3b292/3t7MAAOr
+AEGhmJiZqJiZrIqJiLmIhbnB2D3VzMjBxLfIzb3NwJ2cnbGdjY2yysqy4bLh
+juh+RAMFBAQFAwQD5uz3+UX7Rfn4RQAH+wAEK+MDLQMDAAbkA+TkA+QEAwUC
+AQQDBQYEYQIGBAEF/wMLAwAAAARJXoGPA4IAE3Kkf4GCf4GkXoGPgX9bgYKB
+f4EAA5EAEF5/gX+Cf5GCf39egYKDf3EDgQAcpHF/kYGCf3+CkoJygoKkgpKT
+pF6Bg16Bf5CCcAN/AFSCdYGCf4FekZCjo5OTpoKTg4OBXoF/pHCCkn9eXoGC
+gn+BgX+Df4FydajH0jsN3NLc0tw70jvbO9vSO9vSO9LcOzvSO9zc29w73Nzb
+3NI70jsNB7gDmAAVq5jImJmZqqyJuaysqYjEnBUP+tnMAAOwAA6Nr8ivsJyx
+sZyxsI2OsgSOABafjmx+REMDBQIFBAHk5+vs8PpF+/sdA/sAB0X7+/r77gMA
+A+QADAPkA+QDA+QD5AMDBQYCAAQEBQQCAwQAAwICAQADAgEEXAIGBAEF/wML
+AwAAACeihYF/gnB/cXGRg4KScV6CXn+Bf15/kV5/XpGCdYF/f4KCkpGmkXIA
+A4EAmnR/f4GBf3J/pF6Cf3Jbf4GCk4J/g4OTgnF/Xn+PXqSRgnGPXqSCkYKC
+gV5/pJKSlqaSkpF/g5SBpF5/f16Ckn+Cf3+DgnJ/g5KBW3CShMvdv/7S2zvb
+O9LbO9s72zs72zs729zSDdLe0t470tLc2zvS0tvS0g0H0auYmKurmMiZqpmq
+iqxTiLm5iLmxZ8zZy8mznZyxsJucsJsEnAAEfZ2y4QOOACHKyo5s1kQDQwQF
+AgEC5+zu6O77HPocRfv7RftF+x766RkAAwMACOQD5APk5APkBAMFBAECAwQA
+CwIFBAQCAgEBAgQEAFwCBgQBBf8DCwMAAABEB8uip15wgXKCg4KCf6SBcIF/
+XnKkcn+BgoGCgpF/cZF/kXCSgoJwf3CBgn+CgnF/f4FegYFypH+Cf4KBgnCC
+kqOQf4EDfwAzgV5/goJygV6Df4KRf3Vef4GRf4J/goOCkoKCXoGBcoGCkX9/
+cIKBf6R1cnCBXpKoyzu/AAPSAFk72zvbOzvbO9I729I70ts72zvSv9Le0js7
+EDs72/7c0tzb3tfGq6uYq6vImcjAisSJrKyIiIWpt5rAob29ybGuu8nIfZyd
+nJydsbKwstOO0+HKn5/TbH4u4wAEBAAKQwLl7u/q9fv7RQP7AUUD+wAXRfrg
+LgPkA+TkA+QD5AMD5AMD5AMDBQQAawIHBAMF/wMKAwAAADPS18eopIGkXoKA
+cIKCcoB/XoKRf4KCf4KBXnKRf4GBgoJyf3KCgX+BXoKkcn+CkH+Cf14AA38A
+DYN/gX+RgXF/cpOEc4IAA38ADYGkXoGDf4GBf39yf4EAA38ADoFyf4KBgnGC
+lKmTf4KCA38ANoGRgnN/pF6kcZOmpl6Rmce/0tLe0tzSO9I729LSO9s70jvb
+0jvSO9K/3tLS3t4NO9IQO9vS3APeADghzKuhq6uYyJiqwKqZicSGuYWIubmI
+xMTIzcjEyH3Jq8idnZyxsZyNnrKyjsqOn5/KjjXW5ENDAgQEAAXl6uxG8wAD
++wFFB/sABfnv5APkAAMDAAjkA+TkA+QD5AQDAQUBBGsCBwQDBf8DCgMAAAAW
+O97XuJNbW49ekJGRg39/coGBf3OBcgOBABN/f4GBf4GCcZBwgX9ygoGRf3J/
+AAORABtygpFeXn+BgX9ecn+Cf4KBkZGQf15/kXF/gV4AA4IALZF/f4F/XoGB
+Xn9/goJygXB/gqOjgnJ/cX+BgYKmgoJegXKTf3Bzkr3R3r/XvwAD0gAk3NI7
+2zs72zvS2zvbO9zS3NLe0t6/3r/e0hA72zsQDd4N3t7HA6sAB5irmJmZqsAA
+A6wATIiphbnCt6y5ucTBwa/Eq7rJrq6xnZycnZ2wnrLKjsrhvMrK0+d+Q0ME
+QwRDBAMD6ejk6Pr6+Pf7+/r7+vv6+UYD5AMD5OQD5AMD5OQDAwAG5AMDBQUE
+agIHBAMF/wMKAwAAADDSO9LRw5KBgG9xgoKTgoGPf16kf4F/cV5/XoGRf16C
+gpCCf3J/gZGCkZJ/kYJygqQEfwFyAX8DgQN/AB+BgX+RcaaCXn+CgV5egqRz
+gpGCcY9egn9/gV6Cf3B/AASCABeEkX+BXoJeXoFeg3+BgYJygnFJqMfRvwAG
+0gA23NI72zvS2zvbOzvbO9s72zvb0t7e0tLd3tLb29zbOw0N0tI4x6u9q6u9
+mIuomcTEqqmsuamFBLkAI8HBnLDIwc3Mya7InZ2xnJ2cjbKyyo6fsp/KytNs
+fuRDBAQFAAMEABwD5eXkGfT6+vT1Rfr6+/v69eUD5APkA+QD5OQFAwMB5AUD
+AAMFBAQAaQIHBAMF/wMKAwAAADzdOzjXB9Cqj4+Df4KTgXRegYJxkYJ/f4+B
+XoF/Xn9epJGDf4F/kZFxkIKDf3F/gV5egXJef49egXBegXEEfwAag4NwcX+B
+goGBkXNwkaN1pHGCf16kXoF/gYIDfwAGdJGRkHGkA38AII+Bf16CXpFxppNz
+qM/ev97ev9I729LSO9s70tzSO9LcA9IAGDvS0jsN3tve19Le3Q3bO9vc29ze
+0r/RyQOrADOYq8iLmcCGqIaIqYW3woXEmpqxCN/5zGXIw6vIq52xnLGdjX2d
+so6Osp+fjspC537kAwUABQQBAwTkAAfs8/ofEvf7AAP6AAr47eTkA+QD5APk
+AwMADAUD5APkA+QDAwUEBGkCBwQDBf8DCgMAAAXSACUHxquWkZJ/gpN/pH+B
+f3GBpIF0gY9/coJ/gYJdkXCBf3J/gpOCAAORAA9/cX9/gX9/XoF/XIGBf5EA
+A14BggOSAGCBf4FxgYGkgpKRgYJxcH9/gnJ/gYF/XnFygYJ/gpZ/XIGCk4Ny
+pKZwgpGSlomrz9K/0tI729LSO9I729I729LSO9vSO9s70tzS3NLSO97e0t3e
+3tzc0tvS3N7Sv8aYq6sDmAGZAcgDmQAiirmsrJaWuay5wcGxyMniusOvyMiw
+wa2wsZ2cr42fsjfT0wPKAAfTM2zl4wUEAAMCAB8EBAPl5OXk5uv3+vfzHvr7
++PTn5APkA+TkAwPkAwMFAAcDAAMFBAQAZQIBAQMCCAQDBf8DCgMAAAXSADDX
+3dS4mX+SosVvgZF/Xn+Bgn9/gX+Bf3+Bcn+Qc39ef4N/gpGCf3+Rgn9/gV5/
+gYIDfwAtpHKRf4OBf6SCopKDgoGPf15yf39xg4KRgYKRf15/gV5/gX9/cX+B
+goORj6VxAANyAApwkpKQt7etuNS/BdIAHDvS29LS2zvS0jvSO9s70tw70tzS
+Ow07ENvS3tID3gHbAdsD3AAF0ty/IboABKsABJiZyKoDigAFrKyIiKkAA8IA
+D7nBxMLIfUFXw7ivwcCwwQADnAASsI2cjtPTQkLTN8rTQublLQUEBQIAGOXo
+5+Xl5uz19fj49/r69uzk5AMD5APk5AQDAQUHAwEFAQRmAgEBAwIIBAMF/wMK
+AwAABNIAPDvS0tfXz7iZqJJ/XoGBpKRyg3J/Xl6BgoJef4ORgX+BcHCRkV2R
+f3+Rg3+Rf3+Bf3B/cn9ygpGRk5F/ggOTAAN/f3EAA38AV4GBj16DkZCCcIKB
+g3+BgYOCcH+Bf4FdhJKmpoKCf3KDW4KpwKvG193SO9LSO9Lc0jvSO9LS2zvS
+0ts7O9vS2zvbO9sQDTve3tLS3tLbO9vc0tve0tfGrgADqwA0mJjAiorBiqq5
+iIWplrnCubnBmsHIyQnivc2cr6/BnIyxnbCwso7TQjTTjo7KNGox5eQEBAQC
+ABQE5OTp6ebm5+rp7Sb4+fjz5wPkAwPkAAMD5OQAAwMBBQEFBQMABQUFBAIB
+AGQCAQEDAggEAwX/AwoDAAAG0gBpv9K/0tfRw5indoJeXo+Cf4Fef16Bf39e
+pH9xg49ef4KCkaSCgXKCgn91gn9wgnKBf6SBcYKCkn+CcoKSgpOBgYKCcYGC
+XoF/f4KCcX+BgoGCgl5/cIOBf4KFo11IcreShKK9q7jO0QvXAAPSAAU70tIN
+OwAD0gAl3NLb0jvb0jvS0ts73DvcO9I70t7S3b/S0ts729zc0tvc3t2/zAAE
+qwAxmZmqiaqGxLmIiIfCeMK5mrHBmrnI1eBXmJidnLGxnLGcsLCeCI7T047T
+yp+OQjPWRAADAwEEAwIAGATp5uTn6ezo5OXl4Pj48+0D5APkA+QD5AYDBwUA
+BAQCAgFkAgEBAwIIBAMF/wMKAwAAB9IADTvSO7/S3dHHvaiRj4EAA3IAJ39e
+f16CgYJwgYKBcYGBgn+Rg5Fxf3KCkYGRcZF/pIKCXn9/goJ/cAAEfwAqgpN/
+XpOmkYJ/f4KCf39xf4F/cqRygoGRkYKRcYKmk3iouMPDy8bU3d4QAzsACtw7
+297bO9IQ2zsD0gARO9LSO9LSO9s7O9s729LSv9IABL8E0gAD2zvbAAPcAAje
+0iLJq5iLiwOqADGGrKyGuYiIwpKswsGxsYwInMS41dCizZycsLGcnAiNjbLT
+047TyrKOn8rT6OblQwMDAAQCABEE8PDp5eUwRufl5fT59vDoAwAG5AMDAAQE
+BQMDBgUABQQEAgEBAGQCAQEDAggEAwX/AwoDAAAABdvc0tI7AAPSABu/0tK/
+0r/XB9HDq6iGc1tepV5/gl5bj15/goIAA38AP4J/cn9/gn9epHF/f5Fzf39y
+gV5/coGCcX9/goJypYGCf4KBgpJzgoKSkX9wcV6Bf4KBpF5/cXGPgX94q9HX
+vwAE0gBQO9I73Dvb0ts72zvb0tI70jvbO9s73NI7DTs7DTs70jvS3t7d3b/d
+0t3b0g072zvbDQe/IbirmMivmYrAhqnEiKyGp7eExLfBwZwIycl9scEDyAAL
+sLGMnLGxnJywnbIABI4ADNPTjuHKQmrmROQDBAMCABgEBfP39u7m7OXo7vT4
+9u/q5OQDA+QD5OQDAwUFBQRaAgUECwEDAgYEAAMCAgUA/wMMAwAAAAQ73NI7
+BtIBvwTSACE4v9LRxsO9hExegYFepIKCgYJ/kXORcIKBgn9egYN/cYEAA4IE
+fwAzpJGRg3+Cf3WCc4KRg4KCgYFepJF/f5FdkYKCf4JwXl5/XoGDpIKCpHWY
+0de/0r/Sv7/SAAQ7ABrbOzvbO9LSO9vS0ts72zvS2zsNO9ve0jve/gPeAd0B
+0gS/ACwH0ts729sN3r/ev8yuq6vIi8DAmYqJrLmGwoW3wrm5sbGduxU8zI2N
+yMScsQOcA7EABbCwnbLTAAWOAAvKyo5Caubk5AMCBAADAgAQ5OD19/jzE+UD
+EyX4MOzmAwbkAAQD5AUDBQUFBGwCBwQAAwIEBQD/AwwDAAAABdLbO9LbAATS
+Ab8E0gG/A9IADr/S3r/LvYReSIGAW4GDA4IAGpGRk5FxgnF/f4J/f4Jzf16B
+f15egpGSf5F/A4IAJZN/gnGRgl6PXoGCf3J/goN/j39/j4J/gYF/pI9tpHa4
+0d3e0r8ABdIAMjvS2zvbO9vS3NI70tI72zvS0tzbO9s73NLe3jvdv96/3d2/
+190H3b8N0g3b0tIN3b/HA6sAKa6umIuLrImamojEqMTCiLmMZbEIq8nMzsyv
+yZywsQiMsZ2xnK+Nso6yAAOOA8oAEI7TQmzlRC0EAQECBAPn9vgD9wAV8Ubm
+6/kS6kbk5APk5APkA+QD5AMDAAMFBgRaAgUBDAIJBAEFAQX/AwwDAAAE3AE7
+B9IABL/S0r8E0gAlvwfS0ca4qEhIXoGCgn9/kaRxXZJ/f4KBcoJ/f5GCgYFe
+gV6CfwAEggAbgYJxf3+BgoKSXo+Bf4KBf4J/gl6BXqSSwoN/AANeAAVyqKvL
+1wAH0gG/A9IAHDs70jvbOzvb0ts729I70jvc0jvbO9vS3tLe3d4E3QAlv92/
+3dLXDdLb0t4N19e/JMmrrq6Yq66KwYqsuYiJwre5xMSswQADsQAVya+41auc
+sLCxnLGdsbGcsK+dso5VAASOAAvTjsrKQmwv5AMEAQADAgAXBev4+vr59vP0
+7/T06UbmA+QD5APkA+QABAMBBQQEbwIABAQEBQUFBP8DDwMAAATcAATSO9s7
+CNIALb/S0r/S0t7e/tHPuKdMcEhef15wcpGgkn+BgoGBcpF/kZGCkYJ/gX9w
+kZOScAADfwAPgX9ypHGSkoJeXoF/f4GDAANxABKCt6ineHGBcqfDxt3X19I7
+3NsH0gAf29zbOzvbO9I70jvS0ts729Lc0tzb3L/e3d3e3b/SvwAE3QAM19LS
+O9sN0tIL0v0iBKsAEYvJmYtSiYmIUYipucDEq8jEAAOxAAzBqKvJ0MmxwMGM
+jMEDsQAFnLCNnbIABI4AJtOOytM300JsfkRDAgECAQID8Pr6+/n39fj59+rm
+6Bnk5AMD5APkBQMFBF8CEgQBBQEFBQQEAwEF/wMKAwAAA9wAB9vc2zvb0twA
+A9IBOwE7C9IAFN7d0cOYp11Ic16BkpKTf3+BgqR1A4IAFqRxf3+CpIKRf5GR
+XoGCgpJepIKkpJEDfwASpIOBcnBwqL24xtfRxszG1L+/A9IAD7/bO9LS2zvS
+29LbOzvS3AAD0gAt2zvb0ts70jvS0tw72zs70tIQDdLe3tLe3b8H19La0toN
+0tLb0tK/z7iurquLAAPAAYoDmgAfU3u5uZbNwJjBwbHBsYzEyM3NsJycjLCM
+jJyxnMGvsgAHjgAT046O09O15uXjAwIEAgID5O34+wAE+gAF+fr06OgAA+QA
+BQPk5APkAAUDAQUKAgMBBwIBBAMCAQEFBC0CFAEFBAECAQIUBAEFAQX/AxAD
+AAAADtvb3A3b0tvbO9LcO9LbD9IAINfRz8O9qF1LcV5/gX9/goJef3J/gpNx
+c3OEp5ODgoKTA4IAHZGTgnKBcnOCcZGSkV2nmLjG0b/SO96/O7/e0tK/AAPS
+ADo70jvbO9LSO9I70ts70ts70jvS3NI72zvS2zs729Lc0t7e29Le19Ld3t3d
+B9LX29vS0g3S29LX0czJA6sADYutisHBmapTiZq5icEAA8gEwQAMCLGcwcGx
+sbCxjLGMA7EABbCvnLJlAAeOAAo30zfT6dYuLQUEAwIABQTk6Oz4AAT6AAz7
++e3o5gPk5APkA+QFAwEFAQUKAgEBAQEIAgEEAQRJAgUEAQIBAhQEAQUBBf8D
+EAMAAAAHO9Le19Lb0gAG2wE7ATsL0gA2v9LSOL/Sv7/Ry7iohJJzk3NeW3Nw
+SHBwkpCRkqOot5F/kXGCf15/goJ/cn9vf5GShJi9w8/XA9IBvwXSAb8H0gAt
+3NI70jvb0tLc0jvbO9I72zvbOzvbO9LSO9vSOzvSEN4N0te/0tfe3t3dDdrS
+AATbAB7SC97XIcyumK6uq4uKiYrArKyae7m5wcDM1dW4yMAFsQAGnJywsYyM
+A7EABZyxsLCcAASOAbUD0wALyo7KjkJsfkRDBQQAAwIABQTk6OfvAAX7AAr0
+6ufkA+QD5APkBQMDBQoCAQEDAgkEAQIBAgUBQQIFBAECAQIPBAADBQQEAAMF
+/wMRAwAAAdEDvwHSA9cAD9Lb0ts729LbO9I70tI72wAD0gHbA9IANdfS0jvS
+3dfRz8/Hw7jDuL29mKeGXUlccJCnhHGRkX9/Xl5/j3+RkYSGobjDy8/R3ju/
+v9LXAAPSAAPX0tcABNIAHTvSO9LSO9vS0jvS29I729I72zvSO9Lc0jvbO9s7
+AAfSABfe19LX19LS2zvb0jsNO9vb0tvS0jjMrgADqwAhmK6tUsGaxHu5rHt7
+ubHI4NnO1a/AsYzBnLGxnMGMwbGMAAOxAASwyJydBI4ABNOO044DygAe02ox
+fuTkAwQBAQQE5ujoRvEd+vv58Ebl5APk5APkAwMABgUDBQUEBA0CBwQABAUF
+BARHAgUEAQIBAg0EBwX/AxIDAAAAA8bPOAAEvwHXAdcE2wAV0ts70tLbO9zb
+OzvbOzvb29I70tLXAAPSAFfev9LS19LXv9e/0c/Gw72iXUtdkZORk4OmpsWj
+qqi4w8vG1L/S3t7Sv9LSO9LeO9s7O9I7O9I70ts72zvb3NLS3NI70jvbOzvb
+O9w72zvbOzvS0jvS0jsABdIACDvb29Lb0ts7BtsAJ9zS29L9Icyuq66YrouL
+ioqaiYm5uXu5UZqxsdDH1dDIrbCxjJycCAADjAGcBLEADMGvr7GOjrKOjtPT
+jgTKABfT6THlREMDBQECAgPm5+noRvn7+/Xt5gAD5AAHAwPkA+QDAwAEBQEE
+AQQMAggEAQUBBQgELQIZBAECAQINBAYF/wMTAwAAACO4uMfGISE4OL/X0tLb
+29LS3Ds70ts73Ns70tvSO9LbO9LbOwAE0gG/BtIACb/Sv7/d0tHGxwAFwwAN
+x8fG1NHa0t3X2zvS2wAD0gE7BNIAD9w73NLcO9s72zvbOzvbOwAD0gE7BdIA
+G9s70ts70tvbO9zS29Lb3NLbO9s72zvbO9vSDQAD2wAP0tvS29LbO9vS0t6/
+0biuAASrABmvUsGamqyswcCaubnEmpqMyL3QuMiwr6/EAAaxADGbsZyxwZyv
+nbKOnY7K09M3ytPK09NCbNZE5AMDAgEEBAPrRulG7PD29vDn5OQD5APkAAYD
+AQUBBQMECgIUBA8CCgEPAhQEAAUCAgQEBQAKBA0F/wMWAwAAAAe4q6vDw8bG
+AAO/AAbS0tvS19IE2wATO9vS2zvbOzvS3NI70jvbO9LSOwAM0gAEv93e3QS/
+BdIB3gHbBNIAA9vSOwAF0gAqO9s7O9vSO9vSO9s70tI72zvS3NI72zvSO9s7
+O9s70jvbOzvb0tzb3DvbA9wABtvc3Nvb3AjbAC3S29Lb29cN0r8huMmrq66Y
+i62aU8HEyMDEwbnEfMSawZrIw9WrxLCtyM3IsbEABIwACLGMsbCvnLKdA44B
+0wE3A9MAIjfTQtNCbH5ELUMFAgIEBANG7urp7Uby8UbkBOTkA+QDA+QDAwMF
+AQQBBAsCFAQoAhQEAQIDBAAFBQUEBAUABgQNBf8DFgMAAAO4AAaruLjDxiID
+vwAG0r+/19HXA9sAFTvbO9s72zvb0tzS3NI729w72zvbOwAI0gAHv9LX0tI7
+0gAKOwAz0jvSO9vSO9LS29LSO9vSO9s70tzS0ts70tzS2zvS3NI729LbO9s7
+0jvbO9Lb0jvc2zvbAAPcAATb3NzbA9wB2wHcCNsALQ3S29Le0r8jyZiryauu
+i62tiqyawXzJzMzJr6e5wZrEwMDBsZubBo3IqMGxsQAEjAAGsZuvsJ1lBI4A
+JdOOjtM009NC6Wox5S1DBQQEBQIE5ebr8edG6e/r5uTkA+QDA+QABAMBBQEF
+AwQHAigECgIlBAEFBgMGBA0F/wMWAwAAAA3DvauruKuruMPHIyEhAAO/ABXR
+v9rb3Nvb0ts7O9vcO9I70jvbO9sAEtIAGds729vS29vS2zvSO9w7O9s7O9s7
+2zs72zsABdIAENzS3Ds70tvSOzvb0tLc0tIDOwAQ0ts72zvS2zvc2zvc29zb
+3ATbAdwD2wHcCdsAB9fb2t3dvyQABKsDrgAOmK2awZpTwbHM1dXL0MADwQAL
+wMi3yLCNnLCwwMAABrEABpyMsK+dsgOOAbUD0wE3AcoD0wAKQkJs5i5DA0MC
+BQMDABLm5+n07Ebp7OfkA+QD5APkA+QDAwEFAwQIAigECgIkBAEFCAMEBAEF
+AwMKBf8DFgMAAAm4AASrw8PGAyEDOAAavzs729zS29zSO9s729zbO9LS3Dvc
+3NI72zsG0gBBO9I70jvbOzvbO9s729s729Lb2zvb0tLbO9Lb0tI72zvbO9I7
+0tvS0js729s73DvS3Dvc29LbOzvSO9LcO9s73NsABNwB2wHcCdsB0gPbAAzX
+C9oL293dv8euq8kDqwAhmIuLrVNSrFKasczG2dWryMGwr82rq62vnbHIwKqw
+wcGMAAOxAAmMra6vsrKOjrUAA9MAGzeO0+rTRtNC6NZEGUMEBAIFA+Tn6PJG
+7+jq6QAD5AAEA+QD5AUDAAQFBQQEAwIBAQUCUQQBBQQEAQUBBQgDAQUBBAgD
+BwX/AxYDAAABwwi4AAOrq7gAA8MBxwHGAzgBvwE4BNIAJzvb3DvbO9I72zvc
+O9vS0jvbO9s73NI72zvb0tvS0jvS29I70tvSOwAD0gE7A9IAFTvS0jvSO9w7
+29I70jvS29I70tw72wADOwAS29LcO9vSO9w73Ns729zb3NzbA9wABtvb3Nzb
+3AXbAdoG2wAJ2trX0r+/IcfJAASrAZgDiwASrVKae4mGrLnI0NXLyZucfT3Z
+A9UAFc2vsJvAwcGxwYyxjIybr6+cjmWOtQAEjgAcytPK047TQuls5URDAwQB
+AQQD5+ru8uvr6kbkAwPkBgMDBQMEAAgCAQIEAgIEBAYFFAQIBREEAAUCAgQE
+BQAFBAUFCgQFBQMDAAQFBAUF/wMwAwAABbgAD6u4yau4uKu4uGe4w8fGIgAD
+OAG/Ab8E0gAQ2zvb3NLc0tzSO9Lc2zvb3APSAAPbO9sAAzsAF9s72zvSO9s7
+0tzSO9s72zvS3NI72zvbAATSAB8729LbO9I70ts70jvbO9s73NLbO9s729s7
+29vc3DvbAATcAdsD3AHbAdwD2wHaA9sAMNrS2tvaDdrX0r+/xriurqurma6Z
+maqKiYlTuVGpe4iGxJjNxLCdyd/My87Lva+cnQOxAAucjLGxjLGvyJydsgAF
+jgAiN9PKjsrK0zfTamzl4wMCAgEEAwLr8PFG7uxG5OQD5AMD5AUDAQUBBQQE
+AAcCAQIEAgQEAAcFFAQHBRIEAQIDBAEFBQQFBQkEAAQFAwUFBQMABAUEBQX/
+AzADAAAAC8PDvbjDuLiruLirAAS4AAiruLjDx8fGIQM4AFa/vzi/0jjSO9I7
+0ts729LSO9I72zs70jvS29LSO9s72zvbO9s70jvbO9s70tzSO9s70tI72zvb
+O9I7O9s72zs72zvbO9Lc0tvcO9vc2zvc0tzc29zb3AjbAdwG2wAO2trb2trb
+C9rSOP3Uuq4DqwAJmIuZi4qLUopTAAOIABeHh4iFqanBjLCxjX3iVsPLvauv
+nLGbnAADsQAIjIybxMiwnZ0DjgAF047Tjo4AA8oAFtM300Iz5kQtAwICBAQF
+5Or17+nqRuYD5AAEA+QD5AQDAwUEBAAGAgECBAUFAwMFBQADBAQFAAQEAQUE
+BAEFBwQHBRQEAwUFBAUFAQQBBAUFAAMDBQUACgMDBf8DLwMAAAAIuL3Dvbi4
+w70GuAANw8y4uKu4uMPDx8YhIQADOAS/A9IACzs70tI70jvSOzvbAAPSADo7
+2zvS0tzSO9s70tI72zvSO9Lc0jvb0tI729I70tI72zvb0tI70ts70tzS3Nvc
+2zvb0ts729vc29vcBNsB0gzbAATa2tfbA9oABtfdv8+4rgOrACWurpmKrYqK
+mlN7UVGFp6mIh4Warcm9rtOcsxfYuL29qpucsYyMAAOxAAubnLDIr5yyCLKO
+0wADjgAD08o3AATKAAk0Qud+5CAFAgQAAwUACejr9PBG6eYD5AADAwHkBQMF
+BQMEAAUCAQIEBAAFAxMFBQQIBRIEAwUBAwUECQUQAwMF/wMvAwAABMMABri9
+uMO4wwe4AcwFuAAJw8PHx8bGISG/AAU4AATS0js7A9IABjvS0jvcOwTSADU7
+0tI70jvbO9zbO9s729zSO9s7O9s73DvbO9zbO9s7O9w72zvb3Nvc29Lb0tvS
+29LbO9vb0gAD2wAI0tvS29LS29cF2wAO2tva29La2gvd3jvRx8kDqwOYAAOL
+qlIAA4kABZpSiYi5AAOHABWIuYibsLjL0JywfRdrzaGiwJubsYwAA7EACYyx
+wa/InJ2yZQAEjgAi08rK08o3yso30+kx5eQDBQQCAgMD6vIq7enm5OQD5OQD
+5AQDBgUDBAAEAgECBBkDBQUIAwEFAQUQBAAEBQUDAwUEBgUBAwEFEgMBBQgD
+AAXkA+QD5AD/AyMDAAAAA73DvQADwwO4AAm9w7jDw7jMuKsAA7gBwwHDA7gE
+wwPHAAzGxr+/OL+/ODi/v9EEvwHSAzsABNvS3DsE0gAi2zvSO9I70jvc2zvb
+Ozvb0jvS2zvS3Dvb3NLbO9zS0tvb0gXbAAXS2tfa1wAE2wAG19rX29faA9sA
+B9Lb2tva29sAA9oAYde/ODjGw8mYq5iumIuti4qsrJqaibmJe3uHh1OJuYW5
+sQjiuJiwsbDIyKLNqMCtjMGbwYyxscGvyLCdnbKOjtPTjo7TjsqOytPK6tNq
+5eRDBQICAwID5vIS7unn5AUFA+QACgMACAUFBAICBQMFLAMBBQcEAAUDBQUE
+BAAPBQsDAAXkA+QDBQD/AzYDAAAABL3Dw9ADuAAMw7jDuMPDuLjDzLirA7gD
+wwG4BMMBuATDAAPLxr8ABDgGvwAHOL84ODs73AAE0gAQ17/Xvzs40tI7O9LS
+3NLbOwbSAA3b0tLc0js729Lc29zSAATbAAPS29oAA9cABNvS29ID1wHaAdoD
+2wAS19vb2trX29ra19vSO7/Rx6uuA6sABYuui4tSAAOKAAeJuZq5iIi5AAOH
+AbkBUQOIAAqbjczDyK+wm4zIA8AALsHBnIzBsbGMwa/Ir52dso6O046Oyo6O
+ytPTNMo300JsfkQDBQIFAgID6fXt6eYD5AADAwPkAAQDBgUABwQEBQUDAwUA
+LgMHBAEDBAUEAwoF/wNHAwAAAAW40Li4wwAHuAAKw7jDuLiruLi9uAPDAATL
+w8PHCMMABcfLy8bLAAPGAAQh0TghBDgDOwHSAdIKvwAD0tI7AATSAAfb0tfX
+0tLbAATSAA7b29LbO9I7DdLb19La2wTXAAXa0tLX2gAD1wAM29rS2trX193R
+29raA78ADdHHzMmuq5mYmIuZi4sAA5oABInBUIkEewAWuYe5h4iHuazAqq+w
+r5ubrcCwsLGcwQObAAWMsYyMmwADrwAEnJ2dVQSOABHTjsrKjjTTRtM3Rmrm
+LuQDBAADAgALBQLo7kbn5OQD5OQABAMDBQUEAAMCAgUAAwMB5AEFLwMFBAMF
+CgMABwUDBQMFAwUAEwMACeQD5APkA+QD5AD/AyoDAAAAB7i4q9C9uNAAA7gA
+CdC4uMO4uKu4uAAEwwfLAcMHywAEw8vDxwPLAcYDywADxsbPAAs4AAS/vzi/
+AzgABtK/0jjSvwfSAb8E0gAJv9K/0tfS19LXAAO/AATX2tfXA9oAUtvX2tva
+19ra0dra3dfXC9K/v9THq66rmJjIyJnAi8FTmpqKmpp7U3uae7mHe4eHl4ep
+xMCtuK+tr62YyKrBnZ2xjMGMjLGxnJvBr6+cnY6djrIEjgAYyjfT00JCNEbT
+6Wx+5EMFAgECBAHk5unnA+QABwPkA+QDAwUACAQBAgEEBQMAA+QD5AAtAwEF
+BAQBBTEDAAPkA+QA/wMlAwAAAATZ2cvMA7gBqwHQBbgBwwW4AcMBwwPLAAnG
+y87Lzs7Ly84ACMsADsbGy8bLx8vHy8fGxs8hBMYEzwAGIcYhz9HRA78B0QG/
+A9EAC7/R0b/R0c/R0c/PAATRAAPP0c8ABNEBvwHRBNcALdLa29rS2tva3dfR
+0dcH3jshx7iYq5iroaiorYqKUol8mq2tr8GaU7l8mpqZiAAEhwARlsLByMfV
+0L3Ar67AyMCcnbEABIwADJyxm63AyLCdnbKOsgSOAAfKjo7TNNM0AANGAA8z
+5+VEAwQCAQEFBOTm5+QABAMB5AMDAAUFBAQCAgADBAQFMAMB5AwDAeQiAwAL
+5APkA+QD5APkA+QA/wMpAwAAAAm9w8vOz9nGx8wAA7gABL24uMwHwwPLAAPO
+y84ACMsADM7LxsbLxsvOxs7OxgPLAAXHy8fLxwADywAIxsvGy8vHy8sExgAR
+zsbPzs/Pzs/Pxs7Gxs7PzsYAA84BzwHOB88B0QTXAAXa19ra2wAD2gAJ19HX
+196/xsyrAASYAC6rmaqKiqqqmlNTe3yt1cPImMSMyNCryHu5iKmpwsGctszL
+1cuYm67At8GMsbGbBLEABZvBwK+wAAOdAAWOso6OsgADjgPKAAtCRkbTN0Lo
+L0QDAwADAQALBAQD5uYD5APkA+QAAwMACQUEBAICBAECBAADAwHkQAMB5BgD
+AAXkA+QD5AAOAwAE5AMD5P8DJAMAAAOhAAm9vbjDz9HZ1cwAA7gACdC4w8O9
+w8PLywAEzgHLDM4AA8bOzgAFxgAGzsbGy8vGA8sADcfLy8bOxs7LxsvGy8YA
+Bc8AA87OzwAEzgADxs7PAATOBc8AB87Pz87Pz9EAA9oAUNfa2tva29oL3d3R
+0cbDq6uYmKuYqJmqioashlNTe3tTfHyay8vJq5vI1cfVvYaJhoiIp8GeGrPQ
+w73IsK/AqsGxsYyMsYyMm8GvyLCcnbKyBI4ABMqOyo4DygAYRtNGRurpbOXk
+AwIBAgEEBeXm5OQD5APkAwMACQUFBAIBAgQEBQADAwHkKgMAA+QD5AAXAwHk
+GwMAD+QD5APkA+QD5APkA+QD5AD/AyYDAAABvQihAAXL0dnOwwADuAHQBMMA
+BMvLzssQzgAdy8bOzsbGzsbGy8bLy8bLy8fLxs7Gz8bPxs/Oz84AGc8BzgPP
+AdkH2gAM3QvX0b/RIcbDyZirA5gALplSiqyKUqxQiImIe1F7fHt8i9C4wJur
+2dWrisCot8S3ksC8Gu7Nvb2sm63ArcEDjAAKmoyMm62tyK+cnQOyBY4AG8qO
+yp+fytM00zdCNeZELQQBAgQCAgPl5AMD5AAFAwAMBQQEAgEBAgUD5APkAwMA
+BuQDA+QD5AMDAA3kA+QD5APkA+QD5APkAAMDAeQlAwAD5APkAAMDABnkA+QD
+5APkA+QD5APkA+QD5APkA+QD5APkAP8DNgMAAAqhABS9w8/P2cPMuNDDw9DL
+y87Oy87Oyw3OAATLxsvLC84DywTOD88BzgPPAdkJzwAGzs/P1NnRBdoADN3a
+3Q3dvyLHq6uYrgSYACuZilLBiopQiVFTe1FTe1N7iXt7U3yaiYqww8vDwLeq
+qqHIt8CeFrOYqKisAAPBAAWMsbGMsQADjAAJrcDAr5ydnbKyAASOAAPTyo4A
+A8oAEp+fytM3RkIx5UNDBAEBAgEDAwPkBgMAAwUEBAAEAgEFBgMB5AcDAeQP
+AwHkAwMAB+QD5APkA+QABwMAA+QD5AADAwHkEwMB5BwDAA3kA+QD5APkA+QD
+5APkAP8DKAMAAAAIoaGgoqKgoqIEoQAHvcvP2svDuAAFwwAFy8vOzssAB84A
+BdnOzs/PAATOAAPLzssAFs4ABc/Pzs/OAAPPAc4DzwHRC88ABc7P2c/RAAXa
+AB3X17+/0dTMq66YmKuZmIuZmYpSqqqJilJRU3tTUQADewAgiKmIrLmvqorA
+isCZmanEyNXDzc2Yr1bJyKKnxLCwsWUEsQAKjJubrZnIsJydsgWOAAXTN9PK
+ygADnwAIyso3ykLo5kQDBQAHAQECAQQD5AAFAwQFAAYEAgQFBQQDAwHkBQMA
+A+QD5AAFAwAN5APkA+QD5APkA+QD5AADAwHkEwMB5BEDAeQFAwAZ5APkA+QD
+5APkA+QD5APkA+QD5APkA+QD5AATAwEF/wMjAwAAAAaRkaFwbW4EoAShAAe9
+y9nZx9DQAATDA8sDzgHLBs4B2QPOAc8EzgHLCc4AD8/Oz8/Oz87Pzs7PzsbO
+zgAFzwHOA88ABNHPz9EHzwAFzs7U2dEABNoE1wAE0cfDqwWYABCZra2KUouK
+qlOJmVN7TlFTA3sAIId7e1OIe3zJ0L3QvcSshYiJsMzL1cvLw72ZqqrAhq2M
+BLEEjAAQsIrIr42dnY6yjo7TjtPK0wPKAA2f68rKN8pGM+dE4wRDAAUCAQUB
+5AMDBQUEBAAGAgMD5APkAwMB5AcDAAPkA+QAEAMB5AMDACjkA+QD5APkA+QD
+5APkA+QD5APkA+QD5APkA+QD5APkA+QD5AMD5APkGwMAA+QD5AD/AzMDAAAA
+DKCQj49wbqNdbqCgogShAAS9ztnOA8MAA9XD1QAFyxvOAdkDzgAFz87Oz88A
+A84IzwAD0c/ZAAXPAAbZz9nPzs4D2QAM0drX19rX17/PPKurBJgBiwOZAANS
+maoAA4oABZqJU4m5AAZ7AAlTU3tQhYi5yMcAA9UAEcu4qIeJwbJrzMPV0L2h
+qKetAAPBABGxwYyxmoyajMGKyK+wnJ2dsgAEjgPTABHK08rKLJ8syjc3QjUv
+RC1DBAAFAgAFBOQDBQUABQQBBQEFBgMAA+QD5AAEAwAF5APkA+QABgMACeQD
+5APkA+QD5AADAwHkAwMB5CsDABnkA+QD5APkA+QD5APkA+QD5APkA+QD5APk
+AP8DNgMAAAHNAX8DbQAHcKBIW22PXQAFogARocPP2dW4w9XDy8vVy87LzssA
+A84B1QfOAdkFzgAGy87Oy87LA84B2QbOA88ABs7Pz9nP2QXPAAPZz9kAA88A
+Fs7Uz9nZ0dHa3b/X0r/UxsyrmKurmJkDigALi6qsUYmJUsGJwbkAA1MADrl7
+e3x7fHyLmK2Je4x9A9UAE9CLrZnEiYnhF8m9vaGYilKEm7EAA4wBsQOMAAub
+m8TAyMCwnJ2ysgADjgAFyo7Tyo4AA8oDnwAKyjfKRmrW5QMDBAUCAQUFAwQE
+AQUMAwHkBwMABeQD5APkAAsDAATkAwPkBgMAJ+QDA+QD5APkA+QD5APkA+QD
+5APkA+QD5APkA+QD5APkAwPkA+QD5AD/A1ADAAAAG21vbW1uWV5vbVlucJFd
+kKCgoaG9y9nO0MPD1QAKywADzs7LAAjOAdkOzgAK2c7ZztnOz9nP2QPPAAPZ
+z9kABs8F2QAL2gva3dK/0cfMuKsABJgAE5mZqqqKhlOJiVOImnuarciqmqwA
+BMEAIXx7fIzN0L2Yr8GbrrjV1cPBmqrCubmdE32hoaiqmpuGmwAHsQATjK2t
+wMiLsJydsrKO047KjsqOjgAEygAMn+ssNzfqQufl5AQCBAEAAwIEBQAGAwME
+AQUEAwAP5AMD5APkA+QDA+QD5APkAAcDAAfkA+QD5APkAAgDAAPkA+QAIwMB
+5AYDABnkA+QD5APkA+QD5APkA+QD5APkA+QD5APkAP8DNgMAAAASgJCQpMVZ
+WW9tbYCQcJBdkJCiA6EACdDO2cvVw9DL1QAGywAFzsvOzssABs4B2Q3OAA7Z
+ztnOztnPz9nPz87P2QTPAdkBzgXPAAvR0doH2tfR0cfMqwADmAAgqJiomKGZ
+iVOIiVFRe1FRe3uKU5nDmarBwKvIyIqiwc0E1QAs0JjErZirw9CrmcShoaiu
+ja6ZqKeqm5rBm7GxjJqMm5utisDIr5ydnp2yjtMDjgADyp+OAATKA58AEcrq
+ykYz5kQDAgQCAgEBAgQFAAkDAAoFAwPkA+TkAwPkBAMB5AMDAeQDAwHkAwMB
+5AgDAATkAwPkBwMACeQDA+QDA+QD5AADAwHkAwMAEeQD5APkA+QD5APkA+QD
+5APkAAQDAAPkA+QAHQMGBf8DLQMAAAAJkMWgzVltWW6AAARtAAZubnGkoKAE
+oQHQAc4D2QAR1cvVy9XVw9DQzs7LzsvVy8sABc4B2QTOAAXZztnO2QAFzgAQ
+2c7O2c/Oz9nPz9nP2c/PzgTZAAna0dfdv9HHuK4ABJgBmQGqBJkAFIaKUol7
+h7lRe6x7rJuJmsSZrMTIA9AAI9WrwMC4y9XQ0IyawMGGodChwMSooaKhqMDB
+qqqEhqyKrKyaAASMAAmbrcTAyMCNjZwAA7IAB46O09PKyo4AA8oAEOGfvJ8s
+yjfq6THlQwUFBAIDAQADAgQFAAkDAeQDAwAE5AMD5AMDA+QABwPkA+QDA+QA
+AwMB5AMDABfkA+QDA+QDA+QDA+QD5AMD5AMD5AMD5AAFAwHkAwMB5BQDAeT/
+A1QDAAAAFMXN1dWib1pZbW1ZvoBcR0dbbqCgBaEABMPVy8YO2QAEztXO1QbO
+AdUGzgAS2c7ZztnO2dnO2dnPztnPzs/PA9kASNHR2toH0cbDq6uumZihqJmZ
+qKqKiqqGilGIUXtRh4l7uay3mcitwaypwcPL1dWrmorBrtXD1b18wcSohanA
+rMHEo6GioafEigOpAAOsUsEAA5oDjAAKm8HAwMivsJycjQOyAAWO09PKjgAF
+ygANnxMynyzKN0JsfuQEAgADBAMBAAMCAgUABwMABuQDA+TkAwPkAEwD5APk
+A+QD5APkA+QDA+QD5APk5AMD5AMD5APkAwPkAwPkAwPkA+QDA+QDA+QD5APk
+A+QD5APkA+QD5APkA+QD5APkA+QD5APkAwPk/wNTAwAAABXN1dnV0IBabY/C
+zdDNlVpIbm6goKIABaEAC6ChzdDVx8vO2cfOAAnZA84ABNXOztkDzgAF2c7L
+ztkABM4ABdnOztnOAAjZAA3R2QvR2cbGw7jJmKGrAAOYAAioqqqGiqyJUwNR
+AAZ7UXtRe2IDewArxL3DzcPVmMGb0NXV0LBksHzBuNXVvZnExMHExKmajMjI
+oqJdhorBiKxSrAADmgOMAAqbm8TAyMiwnLCcBLIABo6O047KjgTKABef7Lzr
+LMrq0zXm5BkCAQIFBAEBAgIFBQAGAwAD5APkAAMDABnkA+QD5APkA+QD5APk
+A+QD5OQD5APkAwPkAAMDAeQDAwAE5AMD5AMDAeQDAwAE5AMD5B8DAeT/A1QD
+AAAD1QAUxb5ib3CB0NnVCsWlWUdvcG5uoqAGoQANoKGooZihmKGYvbjOzgAH
+2QPOAAXVztXO1QAHzgHZAc4H2QXRAAXPx8O4qwAEmAAToZioqKGqhomqhohR
+U4eHe4d7hwAFewAEfGK5rwXVABPIi5uvw9XDva2tiayZw8OhrZrBAAOoABG9
+mYyvr4a3ilKMjFKJiVKamgAEjAAIwcCqyMCwjY0EsgAMjp+O08rKjsqfyp/K
+A58AEevK6kLoMeVDAwQBAgQCAQIEAAMDAArkA+QD5OQD5AMDBOQAKwPkA+QD
+5APk5APkA+QD5AMD5APkA+QD5APkA+QD5AMD5APkA+QD5APkA+QABAMAHeQD
+5APkA+QD5APkA+QD5APkA+QD5APkA+QD5APkAP8DVQMAAAAb1QrVzcmhb1lt
+1dnVzc2hWllHSG5tbXCgoKOiAAihAAyno6KiqJi9uMPHzs8E2QPOBdkBzgjZ
+ACLa2dnRz8bHw8yrq5ihmKGYmKiomKpSiqxRUlBTe1OJUXtRA4cACntiuXua
+uXuIe8kE1QAVyWOGiFOqqKiYmJq3p8DAioqawZnNAAO9ABuom62Khoatm7Fj
+UlKJUomajIybrcSqyMiwjZ0ABbIFjgAWyp/hn5/hn58y6yzrNzPn5eQFAQIE
+AgMBBwMB5AEDBuQAAwPkAwAI5AEDA+QAIwPk5APk5APkA+QD5APkA+QD5APk
+5APkA+QD5APk5AMD5APkACIDFQX/AzwDAAAAE6DN0MvLo1pZWqHZ2dXQo1tH
+b1sABG4AFG1ubqCgo6OnoKeEoqenqFCEqKOiA6gABKu9w8sJ2QHaAdEE2QAK
+zsvLw8O4q6uYmAOhA5gAIqiYqKiZqKqGiVFRU4iJmlN7e1FRYoWHiFHCubnE
+waypfK8E1QAmq7FShayJuYisucihqoqsiZrBr8iYoqiqi1KMwVCsioyMfFJQ
+iZoDmwAtsMTAyK+vsI2cjbKyjrKOysrTysqfyp/hvJ+8Mp+fyjfp537kAwQC
+AQECBAQFAAMDAeQBAwjkAAsD5OQD5OQD5APkAwAE5AAhA+TkA+TkA+TkA+Tk
+A+QD5APkA+QDA+QD5APkAwPkAwPkAAQDABbkA+QD5APkA+QD5APkA+QD5APk
+AwPk/wNdAwAAADdZbVtIf49akFpfoaJIX29uWVlHR0hubVuPcG5ukJDFo6ej
+kJGnp5NOdnino4SioaGooau40MPDAAPLBcMADbirvauYmKGYmKGiqKEAA6gD
+mQBYqoaGUlBQiFGFh4diUYd7YrlRiIdOUVF7rJqrmKjIucGavdDQzsu9iomq
+wLmsiMC9ocS9mJuasX2wyKfAisGailKsrImaiVKsiJqbm8HBwKrIwK2wnJyy
+nQOyAAThso6OA8oEnwAZvBOfn+uf6kZq5kQZBQICAQICBQMFAwPkAwAI5AAD
+A+QDAAPkAQMG5AAiA+QD5APk5APk5APk5APkA+QD5AMD5APkAwPkAwPkA+QD
+5AQDAeQVAwHk/wNeAwAAABdfbY9tkJBtj19elVpaR1nFpk9NXFpvWQAEbQAV
+bo+PxZCgxY+mzc2ngKLCt1BQhKOjAAOoAaIDqAAEoaihmQSoAB2YmKGZqKii
+mKeqqqiooainhKinUFGIhIV4T1CHiAADewANYoesqKyJuYioiYW5yAAD0AA4
+1dDEiU9SyKvImnu5vci5xJrN0NC90L2hr4ydsMCGiq2afIaKwYmIqVKIwZqt
+msTAwKjIwLCcnJ0FsgAEyo7KjgPKABGfn7zsvJ+8n+yfyjRq5uXkAwADAgAH
+AQICBQPkAwAM5AAEA+TkAwTkAAQD5OQDBeQADQPk5APk5APk5APk5AMAA+QA
+BAPkA+QDAwHkBQMAA+QD5AAEAwAV5APkA+QD5APkA+QD5APkA+QD5APkAP8D
+XQMAAAAVWm2Aj25uoc3NwmJ6T2GRuGVkY2NhAANZB20ALI/Fvo+TvZjFvr65
+uXuHh6l2hKihqKeooZioqKephqqGmaGGp6ioqqiqqqmsA4YACIWpUIiIUVFM
+A1EAToXBqXt7h7maqKvNmZqIqrl7e6vV0NXQvYuKU3uMmprEwYmqmKzBwJiY
+vb2hqJmZrZubrKyJmlOaiImamqy5icGamsHExKrIi62wnJyNngWyACDKssrK
+n8qf4Z+fvBO8EzKfLNPo5+XkAwQBAgIBAgUDAw3kAC4D5APk5APkA+TkA+Tk
+A+QD5APkA+TkA+TkA+TkA+TkA+QD5APkA+QD5APkAwPkBAMAA+QD5AD/A3MD
+AAAATFpZbW6goqHQ1dXAYmRiR8fMzHxkYmFaWllZb1lZbcXFzc3CW5GkbcXN
+zcRje3pOdUujo6enqKeihlCFiFGIhaeEUISnhlCnhIW5qYcDiAASUIiIUWJR
+YoeIiKynzbfEiJesA9UAKsHEuXt7ipqr1dXQ0MRjmrnBucTEp4asrIqsm7DI
+oaGoqoutmnyMjMFSUgOaAcEBiQaaAAnBxMDEqJmLrZwAA40BnQOyAAiesp+y
+yrLKygSfABq8n7zsn+vK6ukx5uQDBAIBAgQBAgUD5APkAwvkAAQD5OQDA+QA
+BAPk5AME5AEDA+QABAPk5AMD5AAEA+TkAwXkAAwD5OQD5OQD5OQD5OQGAwAJ
+5APkA+QD5APkAA4DBgX/A1UDAAAAC1ltWW1tbqCgzc23AARjAAhTi3xkZGNi
+XwRZACFtb23F0ArV1ZJtbcXNzdU8nGRikndxXZKEhJOpUISIU6kAA3gALoWE
+UYe5rIqEeYiFuYiGuYiHoXuIe3lRh3uszb3IzbmsdarV0NDBqnuswKl7xKED
+0AAZvam5ucSiqLmh0L2hiomMrq+Lp6rArZuxfAAFmgAJuYnBfJq5iZqbAAPB
+AAqqqsjAr7CwjZyNBLIAJJ6evLLhn8qfyp/hn+vrn+yf65/qQmzm5AMFAgQC
+AQEEAwPkAwzkABkD5APkA+TkA+TkA+TkA+QD5OQD5APk5APkAAMDABnk5APk
+AwPkAwPkAwPk5APkA+TkA+QD5APkAA8DAQX/A2QDAAAAH1pZWllZbW1uoG5d
+fGNjfFNjZGRjYl9ZWVqPj25vWdAAA9UAN81jgY/N1dUKEQhVYpRNTnJ1d3iW
+kqOEkreoubl7h3mHh7m9p4ephamnrImpiHuph3uHe1F2e80AA9AAHdXQxLlS
+0MvVvay5zb3ImnusqNDVvYmaxKHQoaG9AAOhABWZiXybyMCKiqzBjHxkmlN7
+mnyaibkABJoADsHBxMCnqsDAr7CwjZ2NBbIACbyynryyn7zh4QADnwAV4Z/r
+n5/KN0Lo5kQtBAICBQIBAgQDAAfkAQMG5AEDA+QADwPk5APk5APkA+TkA+Tk
+AwAE5AASA+QD5APkAwPkA+QD5APkAwPkAwMB5AMDAeQGAwAL5APkA+QD5APk
+A+QAAwMBBf8DZAMAAAAGWlpfgFxZA0cADF2hfGNTZGNiqcBTYQNZADltbpBu
+bVnN1dUKzamPj9DV1Q8PzM1hqVBidUhyf3OEgre3zc3IuXt7U4d7h6iKh3m3
+p83Nt4eHe6kAA7kAF3qHe2LN1dDV0Mh8iIWFq72Je6q9vauGAAO3ACOomKy5
+fMjQvb2hoaiomYuKwXytxIqswZqaZbGauZp8fJq5jAADmgAOwcHEqqfIyMCt
+sJyNnY0FsgADnryeAAO8ACLhn7yfn+Hryusy68o3QugxfuQDAQICBAICBQXk
+5APkA+QDA+QADwPk5APk5APkA+TkA+TkAwAD5AEDA+QAEgPk5APkA+QD5OQD
+5OQD5AMD5AQDAA/kA+QD5APkA+QD5APkA+QADwMBBf8DZAMAAAAXWlpfgGBf
+WllHblJkSl18Yl2h0M1gWlkAA20AP6DFbVlyzdDQ1aJcbsXV2dXNzcWlX6WV
+YGBJTWB/gMXNzdCouU56eYWpuYeHhJPC0NDNxId6haHNzcR5h7mHpwAD0AAs
+zcRjY4d5qYm5eanQoYbEp6e5qYeIuZvImL2hoaiZqoqtjIyafMGJrImamnwD
+mgAQfJp8mnx8scHEwLeoyMjAwAOwAAONnJ4ABLIAC7yyvJ5rvLyfvOG8AASf
+AAzqLOGfN0JqMeVEAwUEAgAFBAUD5AMAA+QAHgPk5APkA+TkA+QD5OQD5OQD
+5APk5APkA+QDA+TkAwTkAA8D5OQD5APk5APkAwPkA+QAHwMBBf8DZAMAAANa
+BF8AblpZd2RhWmNkX6CgqFNhX21tbluizaBvWVpbxYBcbpBto9DQxW2Pb76+
+pZV/blxcbY/N0NDVsmR4T4eWvr6XuZOWp9DQzayWh8LQ0M2al6iohHmi1dDQ
+zad7eYWslre5uaeoqYepiHu5mrmJisiZA6gAC8CKrZuxjGNSU5qaAAO5AASJ
+mnt7A3wAE7F8mozBwcTFosjIwK+wsI2wnZwABbIABLyynmsDvAAU4bwTvGuf
+4co3yiw30zPnfkQtBAUDAgAMBQMD5APkA+QD5OQDBOQBAwPkAQMD5AEDBOQA
+DwPkA+QD5OQD5OQD5APk5AADAwHkAwMB5CUDAQX/A2QDAAABXwVaAI1fX2Fi
+X1pae2RfR26TVWNaWW2goqHN0M1aR25bWm6jo5Btf1lHW23F0NXNuWFcX4+A
+WaHV0NAGm09ywpKgxc3Fl6STzb29wrmHT6HQoXmHp6hTe4eq0L2ouYd7qrfE
+vaGqe4e5hbeqqJiixHuaqKqnqoaKipuxVGRkUlOauZq5mrlTfHyMfJp8jJvB
+xMAAA6gADcjAr7CwjY2ynrKenrIABbwBawGeA7wAEuxra7yfn8rqRkLpaud+
+5EMDAwMEADgFAwPkA+TkA+QD5APkA+QDA+QD5APkA+QD5APkAwPkA+QD5OQD
+5OQD5APkAwPkA+QD5APkA+QD5P8DhwMAAAFhAV8DWgNfAA9hYmJfWo9iYkdH
+SFFiWm0AA24AH6CgoaFgW72XXG6gzc3FuWJIWaDQ0MXCYl9ZbW5vWoQAA9AA
+Bs2qeneloATNAE+5l5SWhLm5vahPUaeGUXuIoYlQhGJ5eHmHe6ehoqKhoVCH
+hJepoqGiqKKqU3uGhqmpiorBmoxlZXyae3x7e5pTmnt7mnyxfIzBxMSoqMiq
+AAPAAAavsJyNnY0EsgAIvLKyvJ5rnmsFvAAP7J+fytM0Quhs537l5AMEAAQC
+AQUDAwAZ5AMD5APkA+QD5APk5APkA+QD5APkA+QD5AADAwHkAwMB5AMDAeQD
+AwHk/wOSAwAAAAViYWFfXwADWgAOYWRjYVpZY2RhR0h6X1oDbQRuAA94Y2Ft
+W3Cgoc3Q0LhTYoAAA80AEm9fYl9tj6CgbW9HoKKTek9gjwTNADQGfHtOl3uH
+hb2KY2Jih4eIl7m5ibljYnqHUYmhzaGhmKKFUVGXt6PFt4aKiolTuaypqayJ
+A5oAE4x8fJp7fHt8e3t8fIx8jIzBxMAAA6gAEcjAwK+vsLCNjZ2esp6ynrKe
+AAS8A2sAE7zsvOxrvDLhN9NC6GzmL0RDAwQABAEBBQMDAC/kA+QDA+QDA+QD
+5AMD5AMD5AMD5AMD5APkA+QD5APkA+QD5APkA+QD5APkA+QD5AD/A40DAAAA
+BWRjYmJhAANfAA1hZGNhWlqHVGNhYWJaAANZAF1tbW5tboJ8Y1ptbm6goKGi
+yHxjYW7N0M2gvlptkJCgoI9gYGFgdEp0gKGgzaDIfHtPh4i5h7maY3tOiHti
+t6LCwqepiXtiUYejoaGop4l7iIeIham3qaxSwXx8U1EAA4gAKYmJmpp7U1N7
+fHx7fFN8U3yamsHBxMjFyKrAxK+vsLCNjZ2NsrKesp6eAAO8ABeevGuea2u8
+vGu87J/rNzdC6DHm5UTkAwAEAgAOBAUDA+TkA+QDA+QDA+QDAwHkAwMAB+QD
+A+QDA+QA/wOmAwAAABtjY2JiYWFfWmFiY2FhWmJUZGRhX19aWkdZbW0AA24A
+A5FfWQAGbgAbS2RUZGJabZCPbVltoKDN0M2hjGRjYWBgX2CQAAOgABKiqU96
+h6Onlodie2KjUGN6oqAEogAVp6iIe0+FhISGUIeHUYe5e4iFhYmaAAR8AAp7
+h3tRiZqaUVFTA3wAEpp8U3yampvBwcS3yMXIwMCtrwOwABKNjZ2esrKesp6e
+vLyevGtrnmsDvAAP7GvsvOss0+noMdZEREMDAAMEABkBBQUD5APkAwPkA+QD
+5AMD5APkA+QD5APkAAMDAATkAwPk/wOkAwAAAAZkY2JiYV8DWgFhAWIDYwAK
+ZGRjYVpaYV9aWQVtABZuR1pZbUdtbVtxcUtTY2JabW9ZWW2gBaEADr2YZGRh
+SFxgYVpwf6SkA3oAMF2goKKiqFJ7e1F7UaKip6qGilJQhYeHT4dOiHmFU4dP
+UYd7iIW5iXx8Y3t8e3x7ewNTAAu5U5p7e3xTfJrBwQADxAASp6jAyMDAr6+N
+nI2NnY2enZ68Bp4ABGuevJ4EawAVn7y865/KNOls5+Xl5C0DAgUFBAIEAAMD
+AAbkA+QDA+QOAwAF5APkA+QA/wOmAwAABGMADGFhWlphYmNkVGRjYwVhAV8D
+WgAabVltR1laWlltbUdtbUhteFNidG6hoaBtbaEFoAAhhmNkZGJPYWB0XI+U
+lr57UU+QoISnhoSLU2JiT0yEqVBQAANSAApTe1FiYlF5T3lRA3sBUQN7ABZR
+iVFTe3x7fHt8e1N7uZp8e3x8mnzBBcQAEaqop6jIwMCvsLCNjZ2Nnp2yAAie
+ABU6nmu2a7ZrvOy8E5+fykbpbDHlROQAAwMABQIEBQQEAAQDAAnk5APkA+QD
+A+QA/wO2AwAAAZUEYgRhAANiY2QABGMBYgdhBF8DYQFaAVoEWQAPR1lcYmBf
+R6BuoqJbj6CgAANuAAVdiGVUZAADYQAeTUpfSF2QhHl6YktdS4iIUppkZGNR
+TniFiFGJmlNjBHsAFlFOTk9Re3tiU3t7YntPhXt7fGJ8Y3wDewAJU3uamnua
+wcTAAAO3AAioo6inyMDArwOwAAicjZ2ejZ2ejQSeAAl9s7M6tp5rnrYAA2sA
+D7wTnyzKRkJs5n7kGQMDBQADBAAHBQMFA+QD5AAFAwAD5APkAP8DtwMAAAAF
+X19aX5UACWIDYwAHYmNiYmFfYQADYgAEY2RkYQRaAVkEWgAsXEdHWY9uXU1f
+R25uoG5uR0tSZGNfXEpNTV9ITE5Mdnh6T0xRUVNTfGVkY2IEUQANuVNTfGN7
+YnxiYntiUQADewAWfHxjfHtie1FTe3t8e3x7e3xTe5q5wQPEABWqxaeozcXI
+p8jAr6+wsI2Nno2yjZ0ABZ4AHbaes56ztp46tmu2a2u8vOvK6kYzbObl5OQD
+AwUFAAQEAAgFA+QD5AMD5P8DvQMAAAFfBFoBdANgA2EAFGJhYmNjZGNjYmFa
+cmFiYWNjYWFfCVoACVltWlpvlmJfWQADbQAvbm1wSVFkY0dHSU1hSU5PUU9R
+e3tiT1FTe1N8fGR8Yk95UVFTmnx7fHt8Ynx7e3wAA3sAA3xjfAADYwAHfFFi
+e2NiewADfAASe5qaucTEwsinxcWizcWoqsjIA68AB7CwjZ6NnbIACp4Eswa2
+AA9r7J/KRkYzNebl5AMDAgQAAwIABQQEAwPkAAQDAeQKAwoF/wOqAwAAAAVi
+YmFgYAADWgFZAVoDXwRhBGIBYQGVB2EAA2JhYQAFXwAZYGFgX1xiYWJjYVpa
+WW1ZbW90Y2RjYUdNTwADYgAKT2J8e2RkYk9iewNTABZifGJjYmNie4eHUXti
+Yk9Pe2J8fGNjA3sABnxkZGNjYgR7AAN8U3sAA5oAD7nBt6fFosWiqM3FqsjA
+wAADrwAOsLCNso2dno2ejZ6Nnn0DngAJtp62s7M/P7a2AARrAA2f4eo0aufm
+5OQDBQMFAAMEAQUBBAQDAAPkA+QA/wPAAwAAAANjY2IAA2EABHpgX1wDXwNa
+AAVfYGFhYgAGYQZiA2EADF9hlXpiYmNjYmFhXwVaAAZgYWJjY2IDYQAZYmNi
+YWJifGNkZGNTYmNiY2J8YmN8Y3xiYgADewFiBHsEfAAZY2N8e3t8Y3x8e4d7
+e1O5U7mJrKzEt7enowADogALqKiqqsjAr6+wr7AABY0ABZ6Nno19AAWeAAqz
+nrazs7aztrO2A2sAE+yfykZC6Ofm5QMDBAQFBAQCBAUABAMB5P8DwwMAAAFk
+AWQDYwZiAANPYV8ABFoAB19flWFhX18AA2EIYgAFYV9hlWIAA2QABGJhYV8E
+WgNhAWIBYgRhBmIBYwFiA2MACGJiY2NiYntiA2MAFmJje2JjYmJ7e2J7Ynt7
+Y3t8Ynp6h3kFhwO5AYkBrAO3A6MDogAHqKeoqqrArwAEsAGNAZwFjQAFno19
+jX0ABJ4AKbOes562s7azsz8/try8n+HKNOls5+blAwMEBQQCBAICBAQD5APk
+AwPkAP8DwQMAAAADVGRUAARkBmMABmJhX1paWQRaAAhfWl9fYWBhegNiABFj
+YmFhX2FiY2RjYmJhYV9hXwAFYQAGYmFiYmFhBGIABWNiY2JiAApjAA9iY2Ni
+Y2NiY3tiYntie3sAA08ADnp3eZd3d5Z5lrm5iKm3BMUAEqe3p7enqqeqi8DA
+r7CwjZyNnASNAAmejZ6NfZ59nrMAA54DswE/A7MAGz9WtrZrnyzT0+no537l
+5AMEAwUFBAIFBAQD5AAEAwHk/wPDAwAAAVQBWANUAARkZGNkBWMAE3xhYV9f
+WllaWVpaX2BfYF9hemEAB2IABmNkY2JjYgNhAANfYGEABWIBYwZiAWMBYhRj
+AXwBYwViABJ7Ynt7h093l3mIeYe5iKmpt8UEowAFp6e3qsQAA6oABIuKwK0D
+sAGcAZwFjQF9BI0ABp59fbN9ngezABM/sz+zP7a2MsrTQuhs5i/l5AMEAAQC
+AQUGAwHkCAMBBf8DvgMAAAAEZlRUZgRUAWQDYwAOYmNiYntiYnphX1pHWlwE
+XwAGYF9gemJ6A2IAA2NjYgADYwAIYmJhX19hYmIHYwADYmNiABNjAWIBYwRi
+AXsBYgV7ABa5h4dRUXiWwsK3xcWjoKCio6Kjo6inA6oACIutr62wsI2wB40A
+BJ6Nno0DngAFfbN9s30ABLMAFra2sz+zP7O2tmufytNq6OZ+5eTkAwUDBAAD
+AgIFAAQDAeQDAwHk/wPFAwAAAAO0VFgABVQDZAAEY2NiYgNjABd7Y2J6YFpZ
+WlxaXF9aX1xgemJie2JiewADYgAIe2J6YF9gYGEKYgxjAWIEYwADfGJ8AAV7
+AA2He4eIeZaFhbmFqcK3AAOQAAijo6CjoKKjowOEAAiZUIuKi62vrQWwB40A
+CJ6NfY2eno2zA30BswF9BLMBtgSzABa2tmtrvMrT6Gx+5S7k4wUEAgECAwMF
+BAMB5AMDAeT/A8YDAAADZgAEVFhUWANUAB1kZGNjYmJ8Y2RjYmJPYU1aXF9a
+WVpZWoB6ek9iYgAEegAIlWB0WlxfYE8DegAUh2J7Yntih3tie2N8Y2N8Y3xj
+e2MHewARubmHuZZ4lpbCpMKSf5KQxZAABKAAF6OgoKOio4SGi4qLi1KvrYut
+rZuwsI2cAAiNABF9jZ6Nnn2es32zfVZ9VrNWswAEtgAUa7Y6a5+f6kJsMebl
+RC1DAwICAQIHAwAE5AMD5P8DyAMAAAAIWGZYVGZUZlgFVAFkBmMABXtiT09i
+AARgAAxfXFxHb4B0TXRKXoADbwSAAAd0lJdPd09PAASXAAR5eZeXA4cEewAG
+fHx7h1G5A4cBuQGmA6QACI/Fj8WQkKCQA6AAA26joAADowATp12EqktQi1KL
+Uq1SsLBSsJuwsAADjQADsI2wAASNAAR9jZ6NA30AD559s319VrN9s7NWsz+2
+tgADawASMp/KRkJq5+Z+5URDBUMDBQQEBQMB5AMDAAXkA+QD5AD/A8YDAAAA
+BrS0ZlhmWANUAANYVGYAA1QEZAAUY2N7YmJ7ek97ek9fX1lcXFpcXEcGbQAZ
+b1xagHeUpYCBSoFegW9vgYGDlpSWeXmHuQADhwF4AXgDlgAIgoKPkJBuoJAF
+oASjAB6oXaeEhFBQi1JQi1JSsFKbUo1SnJuwnLCNsI2wjbAHjQV9AbMBfQOz
+AX0EVgAbsz+ztmtrvJ/K6kIzbOZ+5eTkQwMFAwUDBQQFAAMDAeT/A88DAAAA
+BLS0WGYDtAAHZlhUZlRUZgAEVARkAAdjfGJ7fGJ7AANPBk0ABFxcR28DbQAE
+j49/jwptBHABjwNwAB9bcHGTeJOCcXBdkJCRkJCRkXBdo12nXYRdS4RQS1BQ
+AANSABGwUlKwm5tSnJucm7CcsI2csAAGjQAFfY2NfY0ABn0ADbN9s32zVn1W
+VrNWs1YAA7YAEOy84TdCamznL+Xl5OQFBAQDAgAKBAQFBQMD5APkBf8DzQMA
+AAAMWLS0WLRYZlhUZlRmCVQDZAAFZWRjfGMAA3sABFNiT08ETQAMdFxeXlyB
+dFyBXlteA1sJSAAGXUhdXUhLA0kBSAZdBEsBUAVLA1AAF1JSsFKbUpxSUrBS
+m1KNm5ywnJywnLCcAASNABSwjbCNsH2NfY2efbN9Vn19s32zfQVWABE/sz+2
+a7yfytNCNTHmfuXk5AADAwAFBQUEBQUA/wPXAwAAAAO0tFgAA7QADli0tGZY
+VFhUWGZUWFRmBFQEZAADZWRjAAR8ABN7U3t7UU95d05OT4dRT05OSkxMAANK
+A0wBSgRJBEgBSQRMA0kDSwFQAUsEUAFSAVAEUgGwA1IAIZtSsFKMm5ucjI1T
+jVKcm7CcsI2NsI2NsI19sH2wfY19swAFfQAGVn1Ws1azBVYAF7M/tra8n9NC
+6GzW5uVE5AMDBQUEBQQFAAcDAAXkA+QDBQD/A80DAAAEtAF+CbQABVRmZlRm
+AAdUAVUDZAADZWRjAAZ8AWMDfAASU4dRUXtRT1FRTlFOUE5RUU9QA04DTAAK
+SUxQUE5QTFBQUgVQCVIAH41SU7BTm5uMm5ybnJucUpywnI2NnLCNjbB9jX2N
+jbAAB30ACLN9s31WfVZ9BVYAGj+zP7Y6a5/K0zNsMeblLkQZBQMDBAUEAgIE
+BAMB5P8D1AMAAAAEtNa01ga0AAZmZrRmZlgGZgZUAAVVZFRkZQADZAAPfGR8
+fLF8fGN8e3xTfFN8AA1TAAtSU1BTUlNSU1JTUAAGUgARU4xSUoxSU41TUoxT
+jYyNm5wAA5sABJybnLADjQAMsI2wsI2NsI2NsI2wB30BswN9AAhWfVZ9Vlaz
+VgOzAA4/trZra5830zXn1i/lRAMDAAQFBQQEAwMBBQMDAeQIAwEF/wPNAwAA
+B7QBZgq0AWYBtAVmA1QAFGZVVFVUVWRlZGVkZWRlfGV8ZXxlCXwABVOMfFOM
+AARTAAmMU4xTU4xTjVMAA1IAC1NSnFJSU5xTjJxSAAOMAAyNUoyMnJuNnJyw
+sI0EsAAIjbCNfY2wfY0MfQAEVrNWfQRWAbMDVgAWPz+2a7yfN0Iz5+Z+5UTk
+AwQCBQMFBQQDAATkAwPkBAMBBf8D0gMAAAa0AWYDtAADZrRmAAW0AWYBtAdm
+AANUVGYAA1QAE1VUVVVkZWRlZGVkZWVkfGV8fLEAA3wAGrF8fFOMU4xTZYxT
+U4xTjFOMU1OcU4xTjVOcBIwAII1TnIyMjVKMjZuNm5ybsI2wjbCNsI2wjX2w
+jX2NsH2vCX0ABVZ9fVazAAZWABizP7a2a7yfykLobDF+5eTkA0MFAgQFBAQH
+AwHkBQMBBf8D0gMAAAi0AWwKtAFmAbQIZgAIVGZVZlVUVVQDVQAGZFVkZWRV
+BWUAEXxlfLF8fIxlU2VTZVOMjGVTAAiMAVIBnAWMAB6NjIyNjIyNUpycm5yb
+jbCNjbCNsI2wfbB9sI19jbAGfQAKrn19Vn19Vn1WVgOzACBWsz8/trY6vJ/K
+RkIzbDHm5UTk5EMDAwIEBQUEBQMD5AYDAeQDAwEF/wPSAwAAAAe0bLS0bLRs
+AAO0AARstLRsBLQABGa0ZrQGZgFVBWYADlVmVWZVVFVUZVVVZWVVB2UAA51l
+ZQADsQAEZbGMZQOMAWUEjAAEnYyMZQOMAAWNjI2MjAAEnAAWm5ycsI2wjbCN
+sLCNsH2wfa99sH19jQh9ACJWfVZ9fVZ9s1azs1azs7aztmu8yjfpamzn5n7l
+RETkAwMFAwIEBQ4DAQX/A9IDAAAAA7S0bAAEtAAEbLS01gS0AWwEtAADZma0
+AAlmAAZVZlRmVVQFVQAHZVVlVWVlVQAHZQGdA2UAC52MZZ1ljGWMnYydAASM
+AAONjI0AA4wJnAAQsJywjbB9sH2NsH2wfbB9jQp9AANWfVYAA30BVgF9A1YB
+swGzA7YAEWu8n8rqNGpsMS9+5URE5AMDAAMFAAgEBAIDAwQD5A0DAQX/A9ID
+AAADtAAKbLRstLRstLRsbAO0AWYFtAFmAWwDZgAMamZmamZmVWZVZlVmBlUA
+CGVVZVVlZY5VBWUAF51lnWVlsYxlnbGdjJ2MnZydjJ2MnJyNAAicAAWNnI2N
+sAADjQAGsI19sH2wCn0AB1Z9fVZ9Vn0AA1YAE7OznrO2tmtrvJ/KRkIzbOfm
+fuUAA+QBAwEDBAQEBQMDAAbkAwPkA+T/A90DAAAAA2xmbAADtAAFbLS0ZmwA
+A7QABmy0bGxmbAVmAWwDZgALVWZVZmpUtWZValQACFUBZQFVA2UAC51VZZ1l
+ZZ1lnZ1lAAadAAWxnZycnQADnAGdAY0DnAGNAZwHjQAIfY19sH2NfbAMfQAK
+Vn19Vn1WfbOzfQOzABG2a2u8Mp/K00JqbOfmL+UuRAADQwAPAwUCBAMFBQQF
+BQMD5APkAAYD/wXbBQAAAApmbGZsZmy0bLRsA7QBbAq0ABRsZmZsZmpmZrVU
+tWZVZlVVtVVVjgNVABFljmWOZWVVZZ1lsmWdZbJlsgAGnQALnJ2NnY2cjZ2N
+nJ0ACI0ACn2NjbCNjX2NfY0MfQAFs319s30ABLMBtgG2A2sAFryfysrTQmrn
+5+Z+5URE5AMDBAQFBAIDAQAFAgIDA+QABwMEBQEDBAUBAwQFAQMEBQEDBAUB
+AwQFAQMEBQEDBAUBAwQFAQMEBQEDBAUBAwQFAQMEBQEDBAUBAwQFAQMEBQED
+BAUBAwQFAQMEBQEDBAUBAwQFAQMEBQEDBAUBAwQFAQMEBQEDBAUBAwQFAQME
+BQEDBAUBAwQFAQMEBQEDBAUBAwQFAQMEBQEDBAUBAwQFAQMEBQEDBAUBAwQF
+AQMEBQEDBAUBAwQFAQMEBQEDBAUBAwQFAQMEBQEDBAUBAwQFAQMDBesDAAAA
+FGpmbLRsZmxmtGy0bGy0bDFstGwxA2wAEGZmbGpmamZqtWa1ZlVqVWoHVQGO
+AVUDZQALjmWyZbJlsmWyZbIABp0ADo2dso2djZ2NnY2cjY2eA40ADH2NfY2N
+sH2NfY19jQd9AAlWfVZ9s32zfZ4ABLMAFbaetry8n8rK09NC6DXnMeZ+5eVE
+5AADAwkFAAkD5APkA+TkA+QA9gPrBQAAAApsZmxmbLS0bLRmDbQAIWy0Zmxm
+bGZqZmpmampVtVW1VbVVtVWOVY5VjlVlsmWyZQANnQAInJydjZyNjZwLjQAG
+fY19jX2NDX0BswF9BLMAA7azngADvAAen8o300Iz6GznMeZ+5UTk5C0DBAIE
+AgIFAgIDBAIDBuQFAwD/BAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQD
+BAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQD
+BAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQD
+BAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQD
+BAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQD
+BAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQDBAQFAgIFAgIFAgIF
+AADhAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIF
+AgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIF
+AgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIF
+AgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIF
+AgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIFAgIF
+AgIFAAAABfAB7wE2Eu8ABzbi7zbi8DYAA/AAD0E5QTlBObs5Obs5VzlXOQAD
+VwALaVdpaVdpV2lpaFcABWgBaQFpBGgABLpoumgGugAKZ7pnume6Z7pnugZn
+AARAZ7pnBkAADSoqaPPzK/Ly8fFB8PAAA+8J7gAL7e7u7e7u7e7u7e0ACe4A
+/+3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u
+7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u
+7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u
+7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u
+7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u
+7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7gAA5e3u7u3u7u3u7u3u
+7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u
+7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u
+7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u
+7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u
+7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u3u7u0AAAAjAAb/
+AAsA/wD/AP8A/wD/AAAI/wEACf8DAAAI/wD/AP8A/wAK/wADAP8AAAb/AQAB
+/wQAAAP/AP8A/wD/ABUAAAAGAAH/EgAABf8A/wD/AAYAAAT/AP8ACv8KAAH/
+JwAF/wUAAAX/AP8A/wADAAH/Af//AP8ACgAAADMAAf8JAAAJ/wD/AP8A/wAA
+AAP/AQAB/woAAAr/AP8AAP8A/wD/FAAB/wcAAf8LAAAJ/wD/AP8A/wD/ABUA
+AO//AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/
+AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A
+/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/
+AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A
+/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/
+AP8A/wD/AP8A/wD/AP8A/wDsAAAAagAAA/8A/wD/AP8AFQAAAP8A/wCCAAAA
+/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAAD//CH8
+Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh
+/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8
+Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh
+/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8
+Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh
+/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8AAD/Ifwh/CH8Ifwh/CH8Ifwh
+/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8
+Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh
+/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8
+Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh
+/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8
+Ifwh/CH8Ifwh/CH8IfwhAACC/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8
+Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh
+/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8Ifwh/CH8
+Ifwh/CH8Ifwh/CH8IQAA/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/AoIC
+AAD/Av8CggIAAP8C/wKCAgAA/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/
+AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA
+/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/AoICAAD/Av8CggIAAP8C/wKC
+AgAA/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/AoICAAD/Av8CggIAAP8C
+/wKCAgAA/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/AoICAAD/Av8CggIA
+AP8C/wKCAgAA/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/AoICAAD/Av8C
+ggIAAP8C/wKCAgAA/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/AoICAAD/
+Av8CggIAAP8C/wKCAgAA/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/AoIC
+AAD/Av8CggIAAP8C/wKCAgAA/wL/AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/
+AoICAAD/Av8CggIAAP8C/wKCAgAA/wL/AoICAAE=
+====
diff --git a/images/debian-de_16c.dat b/images/debian-de_16c.dat
new file mode 100644 (file)
index 0000000..b8c91d1
--- /dev/null
@@ -0,0 +1,14 @@
+# Lilo boot menu background configuration  (Lilo 23)
+#
+# color palette: 0 black,         3 magenta,       7 pink,
+#                8 middle grey,  10 bright grey,  13 white
+#
+# bmp-table  = <x>,<y>;<ncol>,<nrow>,<xsep>,<spill>
+# bmp-colors = <fg>,<bg>,<sh>;<high-fg>,<high-bg>,<high-sh>
+# bmp-timer  = <x>,<y>;<fg>,<bg>,<sh>
+
+bitmap = debian-de.bmp
+
+bmp-table  = 16,12;1,12,16
+bmp-colors = 10,0,;7,0,
+bmp-timer  = 34,28;13,0,
diff --git a/images/debian-de_16c.uu b/images/debian-de_16c.uu
new file mode 100644 (file)
index 0000000..68a01df
--- /dev/null
@@ -0,0 +1,503 @@
+begin-base64 644 debian-de.bmp
+Qk3wVwAAAAAAADYEAAAoAAAAgAIAAOABAAABAAgAAQAAALpTAAAgHAAAIBwA
+AAABAAAAAQAAAAAAACIiIgAzMzMAVQDdAFVVVQBVVXcAd3d3AHdV3QCIiIgA
+qqqqAMzMzADMzN0A3d3dAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8A
+/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAA
+AP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8A
+ggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/
+AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIA
+AAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/
+AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA
+/wCgAAECAQQSBs0AAAByAAEEBgAABwEEBgIAAAEABAIBAQMAAAYCAAAEBgQD
+AAEBBAIACQAAAQQGAgAAAQAEAgAHAAIAAAQGBAAFAAAHAQQGAgAAAQAEAgEB
+BAIACQAAAQYEAQQCAQADAAAEAQQGAgcACgIBAQMAAAYCBgQBAAAEAgAFAQAA
+BAQABAABBAEBnQABAgMGBAcOAwADBwYGANEAAAByAAEMAQYEAAANAgwNDQwJ
+AAEJDQ0JAQADAABICAwKBgIMDAEAAgwNDQQAAgwNDQwJAAIMDQ0CAAgKCgYC
+DAoBAAACDA0NDAkAAQoNDQQBCg0NBAACDQ0JCgwNDQYAAgwNDQwJBgAAIwgN
+DQwEBgkMDQ0JAAAIDQ0MDAIACA0NCQAACQ0NCgAACQ0MAJcAAAMCBwcAFQMB
+BwEF1gAAAHEAAAMEDQoABAAADAoNDAEAAgYABA0NAgQAAEkIDQ0AAAYNCgAA
+CQ0MAAAKDQwBAAIGAAkNDAAACA0NAAAGDQoAAAoNDAEAAgYACA0NAAAIDQ0A
+AAwNCQABDA0KAAAKDQwBAAIGAAYAAAQMDQ0EBAAAGgoKAAQNDQgAAAgBAQ0N
+BgAADQ0IAgQACQ0MkgABBQEHFgMBB9wAAABxAAAKCQ0NAgAAAg0NCAUAAAQE
+DQ0BBAAAEggNDQAABA0NAgAJDQwAAg0NCAUAABIJDQwAAAgNDAAABA0NAgIN
+DQgFAAAXCA0NAAAIDQwAAg0NBgAACg0JAAINDQgACgAABQQNDQwBAAMAAAcB
+DAAJDQ0BAAQAAAkBDQ0GAAENDQYAAwAAAwEGAgCOAAECFAMAAwcHAgDhAAAA
+cAAACwENDQgIAAAEDQ0EAAUAAAQEDQ0BBAAAEggNDQAAAg0NBgAJDQwABA0N
+BAUAABIJDQwAAAgNDAAAAg0NBgQNDQQFAAAXCA0NAAAIDQwABA0NBAAACg0J
+AAQNDQQACwAABAoNDQgEAAAFCQAMDQwABQAACQENDQYAAQ0NBgCRAAEFEgMA
+BAcHBgLlAAAAcAAAFAgNDQEJAAAEDQ0JCQoMCAAEDQ0BBAAASQgNDQAAAg0N
+BgAJDQwABA0NCQkKDAgACQ0MAAAIDQwAAAINDQYEDQ0JCQoMCAAIDQ0AAAgN
+DAAEDQ0EAAAKDQkABA0NCQkKDAgABwABAQMNAQIFAAARCg0MCQkMDAEBDQ0G
+AAENDQYAjgABBxIDAAMHBgYA6QAAAHAAAGEMDQkABAYAAQ0NAgAGDQgABA0N
+BAABAQAIDQ0AAAYNDQQACQ0MAAENDQIACA0IAAkNDAAACA0MAAAGDQ0CAQ0N
+AgAIDQgACA0NAAAIDQwAAQ0NCAAACg0JAAENDQIACA0IAAgAAAQIDQ0KBQAA
+EQkNCQAADQ0AAQ0NBgABDQ0GAAMAAAMCCQQAhQABBxEDAQcDBuwAAABvAABi
+Bg0NBAAACgAACQ0EAAgNAgAEDQ0JCA0MAAgNDQEACg0MAAAJDQwAAAkNBAAJ
+DQIACQ0MAAAIDQ0BAQoNDAAACQ0EAAkNAQAIDQ0GAQoNCQAACQ0KAQENDQkA
+AAkNBAAJDQIJAAAEDA0NBgQAABEBDQwAAQ0JAAENDQYAAQ0NBgADAAAECg0N
+AYEAAQcRAwEHBAbuAAAAbgAAJwIMDQ0JAAQNCAAACQwGDQYAAQoNDQIMDQkA
+CA0NCAwNDAIAAAkNDAADAAAwCQwIDQQABAwNDAAACA0NCAwNDAIAAAEJDAgN
+BAACDA0MBA0NDAIAAAEKDQwJDA0JAwAABQkMBg0GAAoAAAUEDQ0MAQAEAAAW
+BAwICgoBAAkNDQYACg0NDAoBAAgNCn8AAQcSAwEHBAbwAAAAbwAEAQADAAAB
+AAQAAQEBAgQAAwEACwAAAQAACA0NAAECAAQAAAMJDQwABAABAQECBAABAQEB
+AwAABggNDAABAgYAAQEBAgQAAwEAAwAAAgAGAAAGAQEACg0JBAABAQECCAAB
+AgEEAwAABAkNDQkGAAECAQEDAAMBAAcAAAQNDQYBAAMAAQF+ABMDAQcEBvIA
+AACIAAADCA0NAAcAAAMJDQwACgAACAEGAgAACA0MHgAAAwoNCQAOAAAGAQwB
+AAABAw0BAgsAAQQBBgMAAAMGDQYAgAABBxQDBQbzAAAAiAAAAwkNDQAHAAAD
+CQ0MAAoAAAgJDQwAAAkNDB4AAAMMDQkADgAACgENCQEAAAYNDQoKAAAEAQ0N
+BgMAAQgBBn4AAQcUAwEHBAb1AAAAhwABBAMMBgAABAQMDAoKAAAFBg0JAAQA
+AwwcAAAFAQgMDAkADwAEDAEJAQkDDAEECgAAAwwNAgCBABYDBQb2AAAAoAAB
+AUsAAQF/AAECFwMFBvcAAAD/AGsAAQIXAwEHBQb4AAAA/wBpAAEFGAMBBwUG
++QAAAP8AZwABAhkDAQcFBvoAAAD/AGYAGgMBBwUG+wAAAP8AZAAbAwEHBQb8
+AAAA/wBiAAEHGwMBBwUG/QAAAP8AYAABBxwDAQcFBv4AAAD/AF8AGgMBBwMD
+AwABBgEG/wAAAP8AXQAaAwMGAQMBAwMAAQYBBv8AAQAAAG4AAQLOBh0AAQcY
+AwEHAwYAAwUHAwAEAAEG/wABAAEAAABuAAECAQLNBhwAGAMBBwQGAAMAAAMA
+BAABBv8AAwAAAG4AAwLMBhoAAQcXAwEHBAYDAAEH/wAJAAAAbgADAskEAwYZ
+ABgDBQb/AA4AAABuAAMCyQQDBhcAAQcYAwUG/wAPAAAAbgADAskEAwYWABgD
+AQcEBv8AEQAAAG4AAwLJBAMGFAABBxgDBAYBAv8AEgAAAG4AAwLJBAMGEwAY
+AwQG/wAVAAAAbgADAskEAwYSABcDAwYBAv8AFwAAAG4AAwLJBAMGEAABBxUD
+BQYBAv8AGAAAAG4AAwLJBAMGDwAWAwcG/wAYAAAAbgADAskEAwYOABgDBwb/
+ABcAAABuAAMCyQQDBgwAAQcaAwcG/wAWAAAAbgADAskEAwYLAAEHGwMBBwYG
+/wAWAAAAbgADAskEAwYKAB4DBAb/ABgAAABuAAMCyQQDBgkAHAMBBwQG/wAa
+AAAAbgADAskEAwYHAAEFGwMBBwQG/wAcAAAAbgADAskEAwYGAAEHGwMFBv8A
+HQAAAG4AAwLJBAMGBQABBxsDBQb/AB4AAABuAAMCyQQDBgQAGwMBBwUG/wAf
+AAAAbgADAskEAwYDABsDAQcEBgEF/wAgAAAAbgADAskEAwYBAAEAGwMBBwQG
+AQX/ACEAAABuAAMCyQQDBgEAGwMBBwUG/wAiAAAAbgADAskEAwYbAwEHBQb/
+ACMAAABuAAMCyQQDBhoDAQcFBv8AJAAAAG4AAwLJBAMGGgMFBv8AJQAAAG4A
+AwLIBAEFAwYZAwUGAQX/ACUAAABuAAMCxwQBBQEFAwYYAwEHAwABAgEC/wAm
+AAAAbgADAsYEAwUDBhIDBQYBAv8ALAAAAG4AAwLFBAQFAwYRAwUG/wAuAAAA
+bgADAsQEBQUDBhADBgb/AC4AAABuAAMCwwQGBQMGDwMBBwUG/wAvAAAAbgAD
+AsIEBwUDBg8DBQb/ADAAAABuAAMCwQQIBQMGDgMFBv8AMQAAAG4AAwLABAkF
+AwYNAwYG/wAxAAAAbgADAsAECQUDBgwDAQcFBv8AMgAAAG4AAwK/BAoFAwYM
+AwUG/wAzAAAAbgADAr4ECwUDBgsDBgb/ADMAAABuAAMCvQQMBQMGCwMFBv8A
+NAAAAG4AAwK8BA0FAwYKAwYG/wA0AAAAbgADArsEDgUDBgkDAQcFBv8ANQAA
+AG4AAwK6BA8FAwYJAwYG/wA1AAAAbgADArkEEAUDBggDAQcFBv8ANgAAAG4A
+AwK4BBEFAwYIAwYG/wA2AAAAbgADArgEEQUDBggDAwYAAwAGBgD/ADYAAABu
+AAMCtwQSBQMGBQMACQYDAwYGAgAABQD/ADYAAABuAAMCtgQTBQMGBAMDBgAD
+BwYGAP8AOgAAAG4AAwK1BBQFAwYDAwEHBQb/ADsAAABuAAMCtAQVBQMGAwMF
+Bv8APAAAAG4AAwK0BBUFAwYBAwEDBQYBBP8APAAAAG4AAwKzBBYFAwYBAwEH
+BQb/AD0AAABuAAMCsgQXBQMGAQcFBv8APgAAAG4AAwKxBBgFCAb/AD8AAABu
+AAMCsQQYBQcGAQT/AD8AAABuAAMCsAQZBQcG/wBAAAAAbgADAq8EGgUGBv8A
+QQAAAG4AAwKuBBsFBQb/AEIAAABuAAMCrgQaBQYG/wBCAAAAbgADAq0EGwUF
+Bv8AQwAAAG4AAwKsBBsFBQb/AEQAAABuAAMCqwQbBQYG/wBEAAAAbgADAqsE
+GgUHBv8ARAAAAG4AAwKqBBsFBwb/AEQAAABuAAMCqQQbBQgG/wBEAAAAbgAD
+AqkEGgUJBv8ARAAAAG4AAwKoBBsFBQYBBAMG/wBEAAAAbgADAqcEGwUGBgEE
+Awb/AEQAAABuAAMCpwQbBQUGAQQBBAMG/wBEAAAAbgADAqYEGwUGBgEEAQQD
+Bv8ARAAAAG4AAwKmBBsFBQYDBAMG/wBEAAAAbgADAqUEGwUHBgEEAQQDBv8A
+RAAAAG4AAwKkBB0FBwYBBAMG/wBEAAAAbgADAqQEHgUFBgEEAQQDBv8ARAAA
+AG4AAwKjBB4FBQYDBAMG/wBEAAAAbgADAqMEHQUFBgQEAwb/AEQAAABuAAMC
+ogQdBQUGBQQDBv8ARAAAAG4AAwKhBB0FBQYGBAMG/wBEAAAAbgADAqEEHAUF
+BgcEAwb/AEQAAABuAAMCoAQcBQYGBwQDBv8ARAAAAG4AAwKgBBwFBQYIBAMG
+/wBEAAAAbgADAp8EHAUHBgcEAwb/AEQAAABuAAMCnwQdBQcGBgQDBv8ARAAA
+AG4AAwKeBB8FBgYGBAMG/wBEAAAAbgADAp0EIAUGBgYEAwb/AEQAAABuAAMC
+nQQgBQUGBwQDBv8ARAAAAG4AAwKcBCAFBQYIBAMG/wBEAAAAbgADApwEHwUG
+BggEAwb/AEQAAABuAAMCmwQgBQUGCQQDBv8ARAAAAG4AAwKbBB8FBQYKBAMG
+/wBEAAAAbgADApoEHwUGBgoEAwb/AEQAAABuAAMCmgQfBQUGCwQDBv8ARAAA
+AG4AAwKZBB8FBgYLBAMG/wBEAAAAbgADApkEHwUFBgwEAwb/AEQAAABuAAMC
+mAQfBQUGDQQDBv8ARAAAAG4AAwKYBB4FBgYNBAMG/wBEAAAAbgADApgEHgUF
+Bg4EAwb/AEQAAABuAAMClwQeBQYGDgQDBv8ARAAAAG4AAwKXBB4FBgYOBAMG
+/wBEAAAAbgADApYEHwUFBgQEAQYBBgkEAwb/AEQAAABuAAMClgQeBQQGAQUB
+BQMEAwYJBAMG/wBEAAAAbgADApUEHwUDBgMFAQQBBAMGCgQDBv8ARAAAAG4A
+AwKVBB4FAwYDBQEEAQQEBgoEAwb/AEQAAABuAAMClQQeBQEGAQYEBQUGCwQD
+Bv8ARAAAAG4AAwKUBCQFBgYLBAMG/wBEAAAAbgADApQEJAUGBgsEAwb/AEQA
+AABuAAMCkwQlBQUGDAQDBv8ARAAAAG4AAwKTBCQFBgYMBAMG/wBEAAAAbgAD
+ApMEJAUFBg0EAwb/AEQAAABuAAMCkgQkBQUGDgQDBv8ARAAAAG4AAwKSBCMF
+BgYOBAMG/wBEAAAAbgADApEEJAUFBg8EAwb/AEQAAABuAAMCkQQjBQYGDwQD
+Bv8ARAAAAG4AAwKRBCMFBQYQBAMGgAABBRIGAQWvAAAAbgADApAEIwUFBhEE
+AwZ6AAEFAQcRAwEHCQYBBasAAABuAAMCkAQiBQUGEgQDBnUAAQcbAwEHsQAA
+AG4AAwKQBCEFBQYTBAMGcQABBw0DAAMHBwIAwQAAAG4AAwKPBCEFAwYWBAMG
+bgABBwkDAQcBBskAAABuAAMCjwQeBQEGGwQDBmsAAQcHAwAEBwYGAswAAABu
+AAMCjwQZBQUGHAQDBmgAAQcGAwEHAwbQAAAAbgADAo4EGQUFBh0EAwZlAAEC
+BgMBBwQG0gAAAG4AAwKOBBgFBgYdBAMGYwABBwYDAQcEBtQAAABuAAMCjgQY
+BQUGHgQDBmEAAQcHAwUGHQAAAwICBQAEArEAAABuAAMCjQQYBQUGHwQDBl8A
+CAMBBwQGEwABAgcGAQcUBgECpgAAAG4AAwKNBBcFBgYfBAMGXQAJAwUGDgAA
+AwUHBwAZAwEHDAahAAAAbgADAo0EFwUFBiAEAwZbAAEHCAMBBwQGAQUJAAEC
+AQcmAwEHCgYBApwAAABuAAMCjQQWBQYGIAQDBlkAAQcJAwEHBAYBAgYAAQcv
+AwEHCgaZAAAAbgADAowEFwUGBiAEAwZXAAECCgMDBgEFAQYEAAEHNwMBBwkG
+lgAAAG4AAwKMBBcFBQYhBAMGVgAIAwAFBwcDBgYAAwAAAwIABwA9AwEHCQaT
+AAAAbgADAowEFgUGBiEEAwZUAAEHBwMBBwQGAwABAkQDAQcIBgECkAAAAG4A
+AwKLBBcFBQYiBAMGUwAIAwQGAwABB0kDCQaOAAAAbgADAosEFgUGBiIEAwZR
+AAEHBwMFBgADAAAHAE0DAQcIBowAAABuAAMCiwQWBQYGIgQDBlAABwMBBwQG
+BABQAwEHCAaKAAAAbgADAosEFgUFBiMEAwZOAAAEBQMHBwQDAQAEBgQAUwMB
+BwgGiAAAAG4AAwKKBBYFBgYjBAMGTQAABAcDAAADAwEHAQADBgQAAQVWAwEH
+CAaGAAAAbgADAooEFgUGBiMEAwZMAAAEAwMAAAMDAQABAAMGBAABBx4DAAMH
+BwUADwABBQEHJwMBBwcGAQKEAAAAbgADAooEFgUHBiIEAwZLAAAEAwcAAAMD
+AQABAAMGBAAcAwADBwYGABgAAQclAwEHBwaDAAAAbgADAooEFwUGBiIEAwZJ
+AAANBQMFAAADAwcAAAYGAgAEABkDAQcDBh4AAQIkAwgGgQAAAG4AAwKJBBgF
+BgYiBAMGSAAADAcDAgAAAwMCAAAGBgQAAQcXAwEHAwYkAAEHIgMBBwcGgAAA
+AG4AAwKJBBgFBQYjBAMGRwAADAcDAgAAAwMCAAAGBgQAAQcWAwQGLAABBR4D
+CAZ+AAAAbgADAokEFwUGBiMEAwZGAAAMAwMCAAAHAwIAAAUGBAAVAwEHBAYx
+AAEFHAMBBwcGfQAAAG4AAwKJBBcFBQYkBAMGQgAACwYAAAMDAgAABwMFAAMA
+AQYEABQDAQcEBjYAHAMIBnsAAABuAAMCiQQWBQYGJAQDBjwAAQcEAAALBgAA
+AwMFAAAGAwYAAwABBgMAAQUTAwEHBAY6ABsDAQcHBnoAAABuAAMCiAQXBQUG
+JQQDBjsAAQMEAAALBgYAAwMHAAAGBwYAAwABBgMAAQcSAwEHBAY9AAEHGwMH
+BnkAAABuAAMCiAQWBQYGJQQDBjoAAQcBAwMAAAsGBgAHAwcAAAYHBgADAAEC
+AwABBxIDBAYBAkAAGwMIBncAAABuAAMCiAQWBQUGJgQDBjkAAQcBAwMAAAsC
+BgYHAwMAAAUGBgAHABIDBQZDABsDAQcHBnYAAABuAAMCiAQVBQYGJgQDBjgA
+AAMCAwcAAwAABQYGBwMDAAMAAQYBBgcAEgMEBgECRQAbAwEHBwZ1AAAAbgAD
+AogEFQUHBiUEAwY4AAEDAQMDAAAFBgYCAwMAAwABBgEGBwARAwUGSAADAwEA
+AQcXAwcGdAAAAG4AAwKIBBYFBgYlBAMGNwAABQMDAgAAAAMGAQMBAwMAAQYB
+BgcAEQMFBkoAAQMBBwMAAQcWAwcGcwAAAG4AAwKHBBcFBgYlBAMGNgAAAwcD
+AwADAAAEBgYDAwMAAAMGBgIABgAQAwEHBAYBAkwAAQcFABYDBwZyAAAAbgAD
+AocEFwUGBiUEAwY2AAEDAQMDAAAKBgYHAwIAAAIGBQYAEAMFBk8AAQcFAAEH
+FQMHBnEAAABuAAMChwQXBQYGJQQDBjUAAAUDAwcAAAADBgEDAQcDAAEGAQYG
+ABADBQZXAAECFQMHBgECbwAAAG4AAwKHBBcFBgYlBAMGNAAACgcDAwAAAgYG
+AwcDAAEGAQYGABADBQZaABUDBwYBAm4AAABuAAMChwQXBQYGJQQDBjMAAAMC
+AwMAAwAABAYGBwcEAAEGBgAQAwUGXAAVAwcGAQJtAAAAbgADAocEFwUGBiUE
+AwYzAAAFAwMHAAAAAwYBBwsAEAMFBl4AAQcUAwcGAQJsAAAAbgADAocEFwUG
+BiUEAwYyAAMDAAYAAAUGBgULAA8DAQcFBmAAAQUUAwcGAQJrAAAAbgADAoYE
+GAUGBiUEAwYxAAAGBQMDBwAAAwYLABADBQZjABQDBwYBBAQAAQZlAAAAbgAD
+AoYEGAUFBiYEAwYxAAMDAQABAAMGAQIKABADBQZlABQDAQcEBgADBwYFAAMA
+AQZlAAAAbgADAoYEFwUGBiYEAwYwAAAJBwMDAgAAAgYGAAoAAQcPAwUGZwAU
+AwEHAwYBAwMGAAMAAAYAZQAAAG4AAwKGBBcFBQYnBAMGMAAAAwIDAwAEAAEG
+CgABBw8DBQZpAAEHEwMABAcGBgMEBgADAAUGAGQAAABuAAMChgQWBQYGJwQD
+BjEAAQMFAAEGBAABBwQAAQYPAwUGawABBxMDAAQHBgcHBgZkAAAAbgADAoYE
+FgUFBigEAwYxAAEDCQABBwUADwMFBgEFbAABBxQDAQcBBwUGAQVkAAAAbgAD
+AoYEFQUGBigEAwY7AAEDBAABBw4DAQcFBm4AAQIUAwEHBQZlAAAAbgADAoYE
+FQUGBigEAwY6AAEHAQUDAAECDwMFBnEAEwMGBmUAAABuAAMChgQVBQUGKQQD
+BjoAAQcEAA8DBQZzABIDBgZlAAAAbgADAoYEFAUGBikEAwY5AAEHBAABBw4D
+BgZ0ABEDBwZkAAAAbgADAoUEFQUGBikEAwY5AAECAwABAg4DAQcFBnYAEAMB
+BwYGZAAAAG4AAwKFBBUFBgYpBAMGOAABBwQADwMFBjYAAQUFBjwAEAMGBgEC
+YwAAAG4AAwKFBBUFBgYpBAMGPAABBw4DBgYwAAEHBQMHBgECOwABBw4DBwZj
+AAAAbgADAoUEFQUFBioEAwY8AA4DAQcFBi0AAQIKAwgGOwABBw4DBgYBAgYA
+AQJbAAAAbgADAoUEFAUGBioEAwY7AAEHDgMFBgECKwABBw0DAQcHBjsADgMH
+BgECBQABBlsAAABuAAMChQQUBQYGKgQDBjsADgMGBioAAQIQAwEHBAAAAwQG
+BgA6AAEHDgMGBgEHBAABBgEGWwAAAG4AAwKFBBQFBgYqBAMGOgABBw4DBQY7
+AAADBQcHAEEADgMBBwQGAQMBAwMAAwZbAAAAbgADAoUEFAUGBioEAwY6AA4D
+BgZ/AA8DAwYABgcDAwYAAgMGWwAAAG4AAwKFBBQFBgYqBAMGOQABBw4DBQaA
+ABADAQYBBgMDBgZbAAAAbgADAoUEFAUGBioEAwY5AA4DBgaAABUDBwZaAAAA
+bgADAoUEFAUGBioEAwY4AAECDgMFBoAAAQIVAwEHBgZaAAAAbgADAoUEFAUG
+BioEAwY4AA4DBgaAAAECFgMGBloAAABuAAMChQQUBQYGKgQDBjgADgMFBgEE
+gQAWAwcGWQAAAG4AAwKFBBQFBgYqBAMGNwABBw0DAQcFBoIAFwMGBlkAAABu
+AAMChQQUBQYGKgQDBjcADgMGBoIAAQcWAwcGWAAAAG4AAwKFBBQFBgYqBAMG
+NwANAwEHBQZcAAEFJwAWAwEHBgZYAAAAbgADAoUEFAUGBioEAwY2AAEHDQMG
+BlYAAQUEAAADBQYGACYAAQcWAwcGVwAAAG4AAwKFBBQFBgYqBAMGNgAOAwYG
+VQAABQcDAwAAAAQGAQImAAEHFQMBBwYGVwAAAG4AAwKFBBQFBgYqBAMGNgAN
+AwEHBQZVAAEHAwMBBgMAAAMFBgYAKAABBxQDBwZWAAAAbgADAoUEFAUGBioE
+AwY2AA0DBgZTAAEHAwAAAwUDAwAFAAEGAQYpAAEHEgMBBwYGVgAAAG4AAwKF
+BBQFBgYqBAMGNQABBw0DBgZTAAEFBQABBwEHBQABBisAEgMHBlUAAABuAAMC
+hQQUBQYGKgQDBjUADgMFBgECVAABAwUAAQcGAAEGKgASAwEHBgZVAAAAbgAD
+AoUEFAUGBioEAwY1AA0DBgZVAAEHBgABBwUAAQYqAAEHEgMHBlQAAABuAAMC
+hQQUBQYGKgQDBjUADQMGBlYAAQMFAAEHAQUFAAEGKgASAwEHBgZUAAAAbgAD
+AoUEFAUGBioEAwY1AA0DBgZWAAEHAQcFAAEHBQABBCoAEwMGBgEFUwAAAG4A
+AwKFBBQFBgYqBAMGNAABBQ0DBgZXAAEDBQABBQEGBQABAikAAQISAwEHBgYL
+AAECRwAAAG4AAwKFBBQFBgYqBAMGNAABBwwDAQcFBgECWAABBwUAAQUFAAEC
+KgATAwYGBQABAgUAAQJHAAAAbgADAoUEFAUGBioEAwY0AA0DBgZZAAECBQAB
+AgEGLwABBxIDBwYEAAECTQAAAG4AAwKFBBQFBgYqBAMGNAANAwYGWgABBzYA
+EwMGBlIAAABuAAMChQQUBQYGKgQDBjQADQMGBpEAEwMGBgECUQAAAG4AAwKF
+BBQFBgYqBAMGNAANAwYGkQABBRIDBwYKAAECRgAAAG4AAwKFBBQFBwYpBAMG
+NAANAwYGkgATAwYGBAABAgUAAQJGAAAAbgADAoUEFQUGBikEAwY0AAwDAQcG
+BpIAEwMGBgQAAQUFAAECRgAAAG4AAwKFBBUFBgYpBAMGNAAMAwEHBQYBBZIA
+AQUSAwYGAQUDAAECTAAAAG4AAwKFBBUFBgYpBAMGNAAMAwEHBQYBApMAEgMB
+BwYGUAAAAG4AAwKFBBUFBgYpBAMGNAAMAwYGAQKTABMDBgZQAAAAbgADAoUE
+FQUGBikEAwY0AAoDAQcBAwQGAAMAAAIAkwABBxIDBgZQAAAAbgADAoUEFQUG
+BikEAwYzAAECCgMGBpYAAQUSAwYGUAAAAG4AAwKFBBUFBgYpBAMGMwABAgoD
+BgaXABIDBgZQAAAAbgADAoUEFQUGBikEAwYzAAECCgMGBpcAEgMGBlAAAABu
+AAMChQQVBQYGKQQDBjQACgMGBpcAEgMGBlAAAABuAAMChQQVBQcGKAQDBjQA
+CgMGBpcAEgMGBlAAAABuAAMChQQWBQYGKAQDBjQACgMGBpcAEgMHBk8AAABu
+AAMChQQWBQYGKAQDBjQACgMGBpUAAQcBABIDAQcHBgEFTQAAAG4AAwKFBBYF
+BgYoBAMGNAAKAwYGlQABAwEAFAMBBwUGAAQFAAAGSgAAAG4AAwKFBBYFBgYo
+BAMGNAAKAwYGAQKUAAEHAQcUAwAKBwYGBwYGBQAABkoAAABuAAMChQQWBQYG
+KAQDBjQACgMGBgEFlAABBRUDAAoHBgYDBgYFAAUGSgAAAG4AAwKFBBYFBgYo
+BAMGNAAKAwEHBgaVABUDAAQHBgcDAwYAAwAGBgBKAAAAbgADAoUEFgUGBigE
+AwY0AAoDAQcGBm4AAQImABUDAAQHBgMDAwYAAwAGBgBKAAAAbgADAoUEFgUG
+BigEAwY0AAsDBgZoAAECBAABBQEGJgAVAwAEBwYDAwYGSgAAAG4AAwKFBBYF
+BgYBBScEAwY0AAsDBgZnAAEHAQMEAAEGAQYmABYDAAMHAwMABgZKAAAAbgAD
+AoUEFgUHBicEAwY0AAEHCgMGBmcAAQMBAwQAAQYBBiYAGQMGBgEFSQAAAG4A
+AwKFBBcFBgYnBAMGNAABBQoDBgYBAmYAAQMBAwMAAwYmAAEHGAMBBwYGSQAA
+AG4AAwKFBBcFBgYnBAMGNQAKAwcGZQAAAwcDAwADAAMGJgABBxkDBgZJAAAA
+bgADAoYEFgUGBicEAwY1AAoDAQcGBmUAAwMDAAMGJgABBxkDBgZJAAAAbgAD
+AoYEFgUGBicEAwY1AAEHCgMGBmUAAwMDAAMGJgABBRkDBwZIAAAAbgADAoYE
+FgUGBicEAwY2AAoDBgZlAAMDBAABBgEGJgABAhkDAQcGBkgAAABuAAMChgQW
+BQYGJwQDBjcACQMHBmUAAQMBAwQAAQYBAicAGgMGBkgAAABuAAMChgQWBQYG
+JwQDBjcACQMBBwYGZQABBwEFLQAaAwcGRwAAAG4AAwKGBBYFBgYnBAMGNwAB
+AgkDBgaUABoDAQcGBkcAAABuAAMChgQWBQcGJgQDBjgACQMHBpMAGwMGBgEC
+RgAAAG4AAwKFBBgFBgYmBAMGOAABBwgDAQcGBpMAGwMHBkYAAABuAAMChQQY
+BQYGJgQDBjkACQMGBpMAHAMGBkYAAABuAAMChQQYBQYGJgQDBjkACQMHBpIA
+HAMGBgEFRQAAAG4AAwKFBBgFBgYmBAMGOQABBwkDBgaSABwDAQcGBkUAAABu
+AAMChQQYBQYGJgQDBjoACQMHBpEAHQMGBkUAAABuAAMChQQYBQYGJgQDBjoA
+CQMBBwYGkQAdAwMGAAQAAAYCRAAAAG4AAwKFBBgFBgYmBAMGOgABBwkDBgYB
+ApAAGgMABQYGBwYGAEkAAABuAAMChQQYBQcGJQQDBjsACQMHBpAAGQMGBkkA
+AABuAAMChAQaBQYGJQQDBjsACgMGBgEEjwAZAwYGSQAAAG4AAwKEBBoFBgYl
+BAMGOwABAgkDAQcGBo4AAQIYAwEHBQYBBUkAAABuAAMChAQaBQcGJAQDBjwA
+CgMHBo0AAQUYAwEHBQZKAAAAbgADAoUEGgUGBiQEAwY8AAEHCQMBBwYGjQAB
+BRgDBgZKAAAAbgADAoUEGgUGBiQEAwY9AAoDBwaMAAEFGAMGBkoAAABuAAMC
+hQQaBQcGIwQDBj0AAQcKAwYGAQKLAAEHGAMGBkoAAABuAAMChgQaBQYGIwQD
+Bj4ACgMHBosAAQcYAwYGSgAAAG4AAwKGBBoFBwYiBAMGPgABBwoDBwaKAAEH
+GAMGBkoAAABuAAMChgQbBQYGIgQDBj8ACwMGBgEFiQABBxgDBgZKAAAAbgAD
+AocEGgUHBiEEAwZAAAoDAQcGBokAAQcYAwYGSgAAAG4AAwKHBBsFBgYhBAMG
+QAABAgoDBwaIAAEHGAMGBgECSQAAAG4AAwKHBBsFBwYgBAMGQQABBwoDBwaH
+AAEHGAMIBkgAAABuAAMCiAQbBQYGIAQDBkIAAQcKAwcGhgABBxkDAQcGBkgA
+AABuAAMCiAQbBQcGHwQDBkMAAQUJAwEHBwaFAAEHGQMBBwUGSQAAAG4AAwKI
+BBwFBgYfBAMGRQAJAwEHBwaEAAEHGQMFBkoAAABuAAMCiQQbBQcGHgQDBkUA
+AQcJAwEHBwaDAAEHGAMGBkoAAABuAAMCiQQcBQcGHQQDBkYACgMBBwcGggAB
+BxcDAQcFBksAAABuAAMCiQQdBQYGHQQDBkYAAQcKAwEHBwaAABkDBgZLAAAA
+bgADAooEHAUHBhwEAwZHAAsDAQcHBn8AGAMBBwUGTAAAAG4AAwKKBB0FBgYc
+BAMGSAAMAwcGfgAYAwYGTAAAAG4AAwKKBB0FBwYbBAMGSAABBwwDBwYBAkcA
+AQI0ABgDBgZMAAAAbgADAosEHQUGBhsEAwZJAA0DCAZAAAECBAABBjUAFwMB
+BwUGBAABBEgAAABuAAMCiwQdBQcGGgQDBkoADQMBBwcGPgABBwQAAQY2ABcD
+BAYBBwEGAwABBgUAAQIFAAECPQAAAG4AAwKCBAEFBQQAAwYEBAAeBQYGGgQD
+BksADgMIBjsAAQMDAAEFAQY2AAEFFwMDBgAHAwYGAAAFBgAFAAEFQwAAAG4A
+AwKCBAEFBQQBBgMEHQUHBhkEAwZMAA4DAQcHBgEFNwABBQEDAwABBgEGNwAB
+BxYDAAsHBgYHAwYCAAAGBgBJAAAAbgDMAgMGTQAPAwEHBwYBAjQAAAQDAwAA
+AwY4ABcDAwYABQMDBgAAAAMGCgABBj4AAABuAM0CAQYBBk4AEAMIBgECMAAA
+BAcDAwAEBjkAFwMACwYGBwMHBgAFBgYCAAQAAQcFAAEEPgAAAG4AzgIBBk8A
+EQMBBwgGLAABBwMDBQY6ABcDAAQGBwMDBgYFAAEFRAAAAPMAAQMBAwQAAQYB
+BgMAHgMGBmsAEgMBBwgGKAABBwQDBQY7ABsDBgYKAAEGPwAAAPMAAQMBAwQA
+AQYBBgMAAQcdAwcGawABBxIDAQcJBiMABQMBBwQGPAABBRsDBgYEAAEHBQAB
+Bj8AAADzAAEDAQMFAAEGBAAdAwEHBAYBBW0AAQUUAwEHCQYdAAEHBgMFBj0A
+HAMFBgEFBAABBwUAAQI/AAAA9AABAwUAAQYBBQMAGwMBBwEHBAZxABYDAQcK
+BhYAAQcIAwQGAQI+ABsDAQcFBgUAAQUEAAEGQAAAAPQAAQMBBwUAAQYDAAEC
+GQMBBwYGcgABBxgDAQcMBgECCQAAAwIFBwAKAwUGQAAbAwYGBAABBwUAAQZA
+AAAA9QABAwUAAQIEABoDBwZzAB0DAQcBBwoGAQcBBw4DAQcEBkEAAQUbAwYG
+BAABAwUAAQZAAAAA9QABBQoAAQcaAwcGcwABAjYDBAZDABwDBgYEAAEHBAAB
+BkEAAAD/AAEAAQAaAwEHBgZ1AAEFMgMEBkUAGwMBBwUGAQUDAAEHBQABBkEA
+AAD/AAEAAQAbAwcGdgABAi4DBAZHABsDAQcFBgQAAQMFAAEGQQAAAP8AAAMA
+AAIAGwMHBngAAQcoAwEHAwYBAkgAAQcbAwYGBAABBwQAAQZCAAAA/wADABwD
+BgYBBXkAAQIkAwMGAQJLABwDBgYDAAEHBQABBkIAAAD/AAMAAQcbAwEHBgZ8
+AAECAQcdAwADBgYCAE8AHAMGBgMAAQMEAAECAQZCAAAA/wAEABwDBwZ/AAEC
+AQcUAwEHAQVUAAEHHAMGBgAEAAACBwQAAQZDAAAA/wAEAB0DBwaFAAECAQIH
+BwECAQJaABwDAQcFBgMAAQMFAAEGQwAAAP8ABQAdAwcG6QAcAwAGBgYABgYE
+AwABAwQAAQYBBkMAAAD/AAUAHQMBBwYGAQXnABkDAAUGAwMHBgADAAEGAwAB
+BwEHBAABBkQAAAD/AAUAAQUdAwEHBgYBAuYAGAMDBgADAwYFAAcAAQMEAAEF
+AQZEAAAA/wAGAB4DBwblAAEHFwMBBwUGBwABBQEDBAABBgEGRAAAAP8ABgAB
+Bx4DBwbkABgDBgYHAAEDAQMDAAADAgYGAEQAAAD/AAcAHwMHBuIAAQIYAwYG
+BgAAAwIDAwADAAMGRAAAAP8ABwABBx8DBwbhABgDAQcFBgcAAwMDAAMGRAAA
+ABoAAAkCBgkMDAoJCAQABAABAQUIAQEHAAEJAQQHAAAHBAkKDAoJBAAEAAAD
+Ag0MAAUAAQQNCAADAQAGAAQIAQYBAAUIAQQBAQUIAA8CAAABCQoJBAAJCAQB
+AAIAAwgAAwQABgAECAEGeQAgAwcG4AAYAwYGBwADAwEAAQAEBkQAAAAZAAAM
+CA0NBgEAAAYNDQwIAwAABQQKDQoEAAcAAAMGDQQABQAACwEMDQ0KBgIECQoB
+AAMAAAMMDQIABAABAQEGBA0ABQoEBAYIAAMNAAQEAAIMAw0AAwIABAADDQAE
+DAIACAMNAAoIAAABDA0NDAwJAw0ACQwGAQYNCgEABAAEDQEEeQAhAwcG3gAZ
+AwYGBgAEAwEAAQIEBkQAAAAXAAAFAQwNDQYABQADDQEMBAAAAwINAgAHAAAE
+BA0NBAQAAAUBDA0NCgAFAAEGAQkDAAADCQ0IAAYAAQoDDQECBAAACgEKDQYA
+AAgNDQwDAAAHCg0NCQAAAQADDQAKAgAABg0NDAAABgMNAQYDAAAFBgwAAAQA
+Aw0BBnoAIQMBBwcG3QAZAwYGBQABAgQDAQAFBkQAAAAXAAAECQ0NDAYAAAQM
+DQ0MBAABAQENBwABAQMNAQQEAAEGAw0BBAYAAAcMAgAABA0MAAYAAQkDDQEC
+BQAACQENCQAACA0NCgADAAAHCg0NCAAAAQADDQAHAgAACA0NCgADAAMNAQQE
+AAAHCQgBDA0NCgB8AAEHIAMBBwcG2wAaAwYGBQAFAwECBQZEAAAAFgABBAMN
+AQYGAAAEDA0NDAQAAQEBDQYAAQEBDAMNAQQEAAEJAw0BAQYAAQgBBgMAAAMM
+DQIABQABCQMNAQIGAAAIBgoAAAgNDQoDAAAHCg0NCAAAAQADDQAHAgAACA0N
+CgADAAMNAQQFAAEKAQoDDQECfQABAwEHHwMBBwYGAQXaABoDBgYEAAEFBAMB
+BwUGAAQFAAACQQAAABYAAQoDDQECBQABAQQNBAABAQENBgABCgQNAQQEAAEK
+Aw0HAAEGAQgDAAADCQ0IAAUAAQkDDQECBwAABwoAAAgNDQoAAwAABwoNDQgA
+AAEAAw0ABwIAAAgNDQoAAwADDQEEBQABBgMNAQiBAB8DAQcGBgEF2AAbAwcG
+AAMAAAIABQMBBwUGAAQCAAACQQAAABYABA0BAQMAAAMBBAkABA0ABgkEAAAB
+DQUAAQgEDQEMAQQEAAAEDA0NDAcAAQQBCQMAAAMEDQwABQABCQMNAQIKAAAE
+CA0NCgMAAAcKDQ0IAAABAAMNAAcCAAAIDQ0KAAMAAw0BBAQAAAUBDA0NDACD
+AAEHHgMBBwYGAQLXABsDAAMHBgYAAwcDBgEHBQMGBgADAAAGAEIAAAAVAAEC
+BA0EAAEBCAQABAAAAQ0EAAEEBA0AAwYJBAAEAAAEDA0NDAcAAQQBCQQAAAMM
+DQIABAABCQMNAQIKAAAECA0NCgMAAAcKDQ0IAAABAAMNAAcCAAAIDQ0KAAMA
+Aw0BBAQAAQkDDQEKAQGDAAEHAQcdAwcGAQLVACMDAQYBBgYDAAMGBgMABgZC
+AAAAFQABBAMNAQwPAAEBAQ0DAAECBA0ABAkACQQEAAAEDA0NDAcAAQQBCQQA
+AAMJDQgABAABCQMNAQIKAAAECA0NCgMAAAcKDQ0IAAABAAMNAAcCAAAIDQ0K
+AAMAAw0BBAMAAQIDDQADCAQJAIQAHwMHBgEC0wABAiMDAQYHAwADBwcDAAUG
+AQJCAAAAFQABAQQNDwAABgENAAABDAMNAAUKAAAJBAAEAAAEDA0NDAcAAQQB
+CQQAAAMEDQwABAABCQMNAQIKAAAECA0NCgMAAAcKDQ0MBAAGAAMNAAcBAAAJ
+DQ0KAAMAAw0BBAMAAAgMDQ0MAAAJCIQAHwMHBgEC0gAuAwYGQwAAABYABA0B
+AQ4AAAUBDQAACgADDQAGDAEAAAkEBAAABAwNDQwHAAEEAQkFAAADDA0CAAMA
+AQkDDQECCQAACAEKDQ0KAAACAw0AAwgJDAADDQALCQAAAQwNDQoAAAYAAw0A
+BAQAAQoDDQAHCQAABg0JAQCCACADBwYBBdAAAQcuAwYGQwAAABYAAQoDDQEB
+CAABAQEEBAAABAENAAkEDQECAwABCQEEBAAABAwNDQwHAAEEAQkFAAADCQ0I
+AAMAAQkDDQECCQABBgMIAAMGAAAABAgABgQABgkKBgMAAQYDCAADBgACAAQI
+AAMCAAQABQgBAgECAwgBBIMAIAMBBwYGAQXPAC4DAQcFBkQAAAAWAAEEAw0B
+BAgAAQkBCAQAAAMBDQYABA0BBgQAAQkBBAQAAAQMDQ0MBwABBAEJBQAAAwQN
+DAADAAEJAw0BArkAAQMBBx8DAQcHBs0ALwMGBkQAAAAXAAAECQ0NCgcAAAMC
+DQgABAABAQUNAQgFAAEJAQQEAAAEDA0NDAcAAQQBCQYAAAYNDQIAAAkDDQEC
+CwAAAwQGAQCrAAECAQcgAwEHBwbLAAECLwMFBgEFRAAAABcAAAUBDA0NAgAF
+AAAEAQwNCAQAAQIEDQEKBgABDAEGBAAEDQEBBgABCAEKBgAABgkNCAAACgMN
+AQQKAAAEBg0NCawAIgMBBwcGygAvAwEHBQZFAAAAGQAABAkNDAIDAAAFBgwN
+DQgAAwABBAQNAQwBAQUAAAcGDQoBAAAGAAQNAQYFAAAEAgwNBAUAAAUEDQwA
+AgAEDQEJAQEJAAAECQ0NDKwAAQcBByEDAQcHBsgAAQcvAwYGRQAAABoAAAsE
+CAoMCgkIBAAGCAADAAUJAQIFAAUJAQEBCAcJAAQCAAAGBAkBBgUAAAMNDQgA
+BwkBBggAAAQCCgwErQAkAwcGxwAvAwEHBQZGAAAATwABAQEBwgAlAwcGxQAw
+AwYGRgAAAP8AFQAlAwcGAQLCAAEHMAMFBkcAAAD/ABUAJgMIBsAAAQIwAwYG
+RwAAAP8AFQABByYDAQcHBr8AMQMFBkgAAAD/ABYAKAMHBr0AMQMGBkgAAAD/
+ABYAAQcoAwgGugABBzEDBQZJAAAA/wAXACkDAQcHBrkAMQMGBkkAAAD/ABcA
+KwMHBgEFtgAxAwEHBQZKAAAA/wAYACsDAQcHBrQAMgMGBkoAAAD/ABgALQMI
+BrEAAQcxAwEHBQZLAAAA/wAZAC4DCAauAAEHMgMFBgECSwAAAP8AGQAvAwEH
+CAYBAqoAAQIyAwYGTAAAAP8AGgAxAwoGAQKmADMDBQZNAAAAYgABCQEJBgoA
+AwkJBgAbAAADBgkJAAcKAQmGADQDAQcKBqIAMwMGBk0AAAAgAAEKAQwHDQAD
+DAwJAAkAAAYJDAwLCgoGCQADCgsMABgAAAMJCwwAEQ0AAwwMCgAOAAAECQoM
+DBENAQwBCh0AAAUKCwoJAgAJAAADCQoLABEAAQoBDAgNAAMMCwIADAAABQwM
+CwoKAAUJAAQKCgwLCwAABQsKCQkCAAMAAAoCBAkJCgsMAAAHDwMAAwsKCQAJ
+AwAECQoLDBgDAwYBAgMGoAAzAwEHBQZOAAAAHgABDA4NAQoHAAEKDg0VAAEJ
+AQwaDQEJBwABBAEKGw0BChsADw0BDA8AAQsPDQEJCgANDQEJCwAPDQQADgMB
+Cg8NFAMABwcGAwMHBgYAAwABBp8ANAMFBk8AAAAcAAEMEg0BAgUAAQoNDQEL
+EwABDB0NAQsFAAEMIA0BDBkAAQwODQEJDQABCRMNAQQIAA0NDAABCg0NAQwE
+AAEHDQMBCQ4NAQkUAwEHAwYBAwMGAwABAp0ANAMGBk8AAAAbABUNAQkEAAEK
+DQ0BCREAAQsfDQELBQABDCINAQsXAAELDg0NAAEKFQ0BCQYAAQQMDQELDAAB
+CQ0NAQsFAA4DDg0WAwEHBwafAAEHMwMBBwUGUAAAABkAAQkXDQQAAQsNDRAA
+AQkhDQEMBQABCiQNAQYVAAEJDg0MAAEKFw0BCgUAAQkMDQEGDQANDQEKBQAO
+Aw4NFwMBBwcGnQABBzQDBQZRAAAAGAABCRkNAwABCw0NDwABCyINAQwFAAEC
+JQ0BChUADQ0BCwsAAQkZDQEKBAABCQwNDgANDQEJBQABAg0DDQ0BDBgDAQcH
+BpsAAQc0AwYGUQAAABgAGg0ABAwAAAsMDQEMDgABDCQNBgAmDQEMFAANDQEK
+CwAbDQQAAQkMDQ4ADQ0HAA0DDQ0BDBkDAQcHBpkAAQc0AwEHBQZSAAAAFwAc
+DQADAAALAAwNAQoNAAEMJQ0GAA8NAAMMCgkAAwYAAwkJDAAPDQELEwANDQEJ
+CgABChwNAwABCgsNAQwOAA0NCAAMAw0NAQwbAwcGlwA2AwUGUwAAABYAAQwc
+DQADDAAMAAwNAQkMAAEMFg0BDAEMAwsBDAEMCQ0GAA0NAQkKAAADAgYKAA0N
+AQsSAA0NAQYKAB0NAAQLAAAKCw0BDA4ADQ0IAAEHCwMNDQELHAMHBgEClAA2
+AwUGVAAAABUAAQkeDQEGAQwMDQwAAQoSDQEMAQoNAAEKAQwEDQYADQ0BBg0A
+AQYBDAwNAQoRAA0NCgABCh4NAAMAAAoACw0BDA4ADQ0JAAsDAQwMDQEKHQMI
+BpIANgMGBlQAAAAVABUNAQwBDAgNAQwBDAwNDAARDQEMEwAABAoNDQkFAA0N
+AQYOAAECAQoMDREADQ0KAAEMEQ0ABQsKCQoMAAgNAAMMAAoACw0BCw4ADQ0K
+AAoDAQwMDQEKHgMBBwcGkAA2AwEHBQZVAAAAFAABCRENAAMKBgIABAAAAwIJ
+DAASDQsAAQwPDQEMFwABCgEKBQABDAwNAQYQAAEKDA0QAAEMDA0KAA8NAQsB
+BgYAAAMCBgwABg0BAAEKCw0BCw4ADQ0KAAECCQMBDAwNAQogAwgGjQA3AwUG
+VgAAABQAAQwPDQEMAQQJAAECAQoRDQoAAQkPDQEKHwABDAwNAQYQAAECAQoL
+DQEKDwABDAwNCQABCg4NAQkBAgkAAQIBCQUNAQwBCwsNAQoOAA0NCwABBwgD
+AQsMDQEJIgMIBokAAQI3AwUGVwAAABMAAQIPDQELAQIMAAEKEA0KAA8NAQkg
+AAEMDA0BBhEAAQIBDAsNDwABDAwNCQABDA0NAQoNAAEGEQ0BCg4ADQ0MAAEH
+BwMBCgwNAQkkAwgGAQWFAAEHNwMFBgECVwAAABMAAQwODQELAQINAAECAQsO
+DQEMCQABCQ4NAQkhAAEMDA0BBhIAAQYLDQEMDgABDAwNCQANDQEMAQIOAAEG
+EA0BCg4AAQwMDQ0ABwMBCgwNAQkmAwEHCgYBAn8AOAMGBlgAAAATAA4NAQwB
+Ag8AAQYODQELCQAODQEKIgABDAwNAQYTAAEMCw0OAAELDA0JAA0NAQYQAAEJ
+Dw0BCg4AAQwMDQ4ABgMBCgwNAQkqAwEHDgYBAnYAOAMBBwUGWQAAABIAAQkO
+DQEGEQABDA0NAQoJAA0NAQwjAAEMDA0BBhMAAQYLDQELDQABCwwNCQANDQEC
+EAABAgEMDg0BCg4AAQwMDQ8ABQMBCgwNAQkyAwEHCQYBBXEAAQU4AwEHBQZa
+AAAAEgABDA0NAQwSAAEJDQ0BCggAAQsNDSQAAQwMDQEEEwABAgEMCw0NAAEL
+DA0IAAEEDA0BChIAAQYODQEKDgABDAwNEAAEAwEJDA0BCTYDAQcDAAECAwZv
+ADoDBQZbAAAAEgAODQEGEgABBA0NAQkIAA0NAQwkAAELDA0BBBQAAQkLDQEJ
+DAABCgwNCAABCQwNAQkSAAECAQwNDQEKDgABDAwNEQADAwEJDA0BCTADBQYA
+AwcDAwAGAAECbQA6AwUGXAAAABIADQ0BDAECEgABAgEMDA0BCQgADQ0BBCQA
+AQsMDQEEFAABBAsNAQwMAAEKDA0IAAEJDA0BBhMAAQkNDQEKDgABDAwNEgAA
+AwMDCQAMDQEJMQMJBnAAAQc6AwUGXQAAABEAAQkNDQEJFAABDAwNCAABCg0N
+JQABCwwNAQQVAAEMCw0MAAEKDA0IAAEJDA0BBBMAAQINDQEKDgABDAwNEwAB
+AwEJDA0BCTMDAQcJBmsAAQI7AwUGXgAAABEAAQoNDQEGFAABCgwNCAABDAwN
+AQolAAELDA0BBBUAAQoLDQEKCwABCgwNCAABCQwNAQIUAAEMDA0BCg4AAQwM
+DRQAAQkMDQEJNgMBBwgGAQVnADwDBQZfAAAAEQABDA0NAQIUAAEJDA0IAA0N
+JgABCwwNAQQVAAEGCw0BDAsAAQoMDQgAAQkMDQECFAABCgwNAQoOAAEMDA0U
+AAEJDA0BCTkDAQcIBmMAAQc8AwUGYAAAABEADQ0BChUAAQkMDQgADQ0mAAEL
+DA0BBBUAAQQMDQsAAQoMDQkADA0BAhQAAQYMDQEKDgABCwwNFAABCQwNAQk7
+AwEHCAZfAAEFPQMFBmEAAAARAA0NAQkVAAEGDA0HAAEJDA0BDCYAAQsMDQEE
+FQABAgwNCwABCgwNCQAMDQECFAABBgwNAQoOAAELDA0UAAEJDA0BCT0DAQcH
+BgEEWwABAj4DBQZiAAAAEQANDQEGFQABBgwNBwABCgwNAQomAAELDA0BBBYA
+DA0BCQoAAQoMDQkADA0BBBQAAQQMDQEKDgABCwwNFAABCQwNAQk/AwEHBwZY
+AAEFPwMFBmMAAAAQAAEJDQ0BBBUAAQYMDQcAAQwMDQEJJgABCwwNAQQWAAEL
+Cw0BDAoAAQkMDQkADA0BBhQAAQIMDQEKDgABCwwNFAABCQwNAQlBAwgGVAAB
+B0ADBQZkAAAAEAABCQ0NAQIVAAEGDA0HAAEMDA0BBCYAAQsMDQEEFgABCgwN
+CgABCQwNCQABDAsNAQkVAAEMCw0BCg4AAQoMDRQAAQkMDQEJQgMBBwcGAQJP
+AAECQgMFBmUAAAAQAAEKDQ0WAAEGDA0HAA0NJwABCwwNAQQWAAEJDA0KAAEJ
+DA0JAAEJCw0BDBUAAQwLDQEKDgABCgwNFAABCQwNAQlEAwgGSwABAgEHQwMF
+BmYAAAAQAAELDA0BDBYAAQYMDQcADQ0nAAELDA0BBBYAAQYMDQoAAQkMDQoA
+DA0BBhQAAQwLDQEKDgABCgwNFAABCQwNAQlGAwgGAQJFAAECAQdFAwUGZwAA
+ABAAAQwMDQEKFgABBgwNBwANDScAAQsMDQEEFgABBgwNAQkJAAEJDA0KAAEM
+Cw0BDAECEwABDAsNAQoOAAEKDA0UAAEJDA0BCUgDCQZAAAEHSAMFBmgAAAAQ
+AAEMDA0BCRYAAQQMDQcADQ0nAAELDA0BBBYAAQYMDQEKCQABCQwNCgABCQwN
+AQoTAAELCw0BCg4AAQoMDRQAAQkMDQEJSgMBBwkGAQU4AAEFSgMBBwUGaQAA
+ABAAAQwMDQEJFgABBAwNBwANDScAAQsMDQEEFgABBgwNAQsJAAEJDA0LAAEM
+DA0BChIAAQsLDQEKDgABCgwNFAABCQwNAQlOAwEHCgYBBQcAAAMGBgQAJAAB
+BQEHTQMBBwQGAQJqAAAAEAABDAwNAQYWAAEEDA0HAA0NAQwgCwEKBQABCwwN
+AQYWAAEEDA0BDAkAAQkMDQsAAQkNDQEKAQQQAAEKCw0BCg4AAQoMDRQAAQkM
+DQEJUgMBBwEHBwYDBwwGAQQBAhQAAAQCBgYHUgMFBmwAAAAQAAEMDA0BBhYA
+AQQMDQcALw0FAAELDA0BBhYAAQQMDQEMCQABCQwNDAABDA4NAQkBAg4AAQoL
+DQEKDgABCgwNFAABCQwNAQkBB1kDAQcIAwEHAQcWBgEHAQdYAwUGbQAAABAA
+AQwMDQEGFgABBAwNBwAvDQUAAQsMDQEGFgABBAwNAQwJAAEJDA0NABANAAUM
+CQYCAgAJAAEKCw0BCg4AAQoMDRQAAQkMDQADCQAFANIDBQZuAAAAEAABDAwN
+AQYWAAEEDA0HAC8NBQABCwwNAQYWAAEEDA0BDAkAAQkMDQ4AEw0KDAwNAQoO
+AAEKDA0UAAEJDA0ABAkAAAXPAwEHBAYBAm8AAAAQAAEMDA0BBhYAAQQMDQcA
+Lw0FAAELDA0BCRYAAQYMDQEMCQABCQwNDwAoDQEKDgABCgwNFAABCQwNAQkD
+AAECAwMBB8kDBQZxAAAAEAABDAwNAQYWAAEEDA0HAC8NBQABCwwNAQkWAAEG
+DQ0JAAEJDA0QAAEMJg0BCg4AAQoMDRQAAQkMDQEJBAAABQIDAwACAMcDBQZy
+AAAAEAABDAwNAQYWAAEEDA0HAC8NBQABCwwNAQoWAAEGDQ0JAAEJDA0RAAEK
+JQ0BCg4AAQoMDRQAAQkMDQEJBQABBQEDAwDEAwEHBAZ0AAAAEAABDAwNAQYW
+AAECDA0HAC8NBQABCwwNAQoWAAEGDQ0JAAEJDA0TAAEMIw0BCg4AAQoMDRQA
+AQkMDQEJCwDCAwEFBAZ1AAAAEAABCwwNAQYWAAECDA0HAA0NFgwMDQUAAQsM
+DQEMFgABCQ0NCQABCQwNFQABCQEMIA0BCg4AAQoMDRQAAQkMDQEJDAABB7gD
+AAMHBgcAAwMBBwEAAwYBAnYAAAAQAAEKDA0BCRYAAQIMDQcADQ0VAgEGDA0F
+AAELDA0BDBYAAQoMDQEMCQABCQwNGAAAAwkLDAAcDQEKDgABCgwNFAABCQwN
+AQkNAAEHtgMDBgMDAQIBAAMGeAAAABAAAQkMDQEJFgABAgwNBwABDAwNFQAB
+BAwNBQABCwwNAQwBAhUAAQwMDQEMCQABCQwNHgAABAkJCgoDCwAGCgoJCQIA
+DA0BCg4AAQsMDRQAAQkMDQEJDwCzAwEHAwYABwMDBwAABgYAegAAABEADA0B
+ChYAAQIMDQcAAQsMDQECFAABBAwNBQABCw0NAQQVAA0NAQwJAAEJDA0rAAEM
+Cw0BCg4AAQsMDRQAAQkMDQEJEAABB7ADBAYBBwEDAwABBgEFewAAABEADA0B
+DBYAAQIMDQcAAQoMDQECFAABBAwNBQABCw0NAQYUAAECDQ0BDAkAAQkMDSsA
+AQwLDQEKDgABCwwNAQQTAAEKDA0BCREAAQKtAwEHBAYBBwEHAwABBn0AAAAR
+AA0NFgABAgwNBwABBgwNAQIUAAEEDA0FAAELDQ0BCRQAAQQNDQEMCQABCgwN
+KwABDAsNAQoOAAELDA0BCRMAAQoMDQEJEwABB6oDBQYBB4MAAAARAAEMDA0B
+AhUAAQIMDQgADA0BBBQAAQQLDQEMBQABCw0NAQwUAAEJDQ0BCwkAAQoMDSsA
+AQwLDQEKDgABDAwNAQoTAAEKDA0BCRUAqAMFBgEChAAAABEAAQoMDQEGFQAB
+AgwNCAAMDQEGFAABBgsNAQwFAAELDg0BAhMAAQoNDQEKCQABCgwNKwABDAsN
+AQsOAAEMDA0BDBMAAQoMDQEJFgABB6UDBgaFAAAAEQABCQwNAQkVAAECDA0I
+AAEMCw0BCRQAAQYLDQELBQABCw4NAQYSAAECAQwNDQEJCQABCgwNKwABDAsN
+AQsOAAEMDA0BDBMAAQsMDQEJGACkAwUGhgAAABIADA0BDBUAAQIMDQgAAQkL
+DQEKFAABCQsNAQoFAAELDg0BChIAAQYODQoAAQoMDSsADA0BCw4AAQwNDRMA
+AQwMDQEJGgChAwYGhgAAABIADQ0BBBQAAQIMDQkACw0BDBQAAQoLDQEJBQAB
+Cw4NAQwBAhEAAQsODQoAAQoMDSsADA0BCw4AAQwNDRMADQ0BCRsAAQKfAwUG
+hwAAABIAAQsMDQEJFAABAgwNCQABDAoNAQwBAhMAAQwLDQYAAQsPDQEJEAAB
+BA4NAQwKAAEKDA0rAAwNAQoOAAEMDQ0BChIADQ0BCR0AAQeJAwEHBAYBBwwD
+AQcDBooAAAATAAwNAQwBAhMAAQIMDQkAAQoLDQEGEgABAgwNBgABCw8NAQwB
+Ag8AAQsODQEKCgABCwwNKgABCQwNAQoOAA8NEgANDQEJHwABB4YDBAYFAAEH
+BgMBB5AAAAATAAEMDA0BCRMAAQIMDQoACw0BChIAAQYMDQYAAQsQDQEKDgAB
+Bg8NAQkKAAELDA0OAAEJAQIaAAELDA0BCg4ADw0BBBEADQ0BCSEAAQeCAwQG
+nwAAABMAAQoNDQEEEgABAgwNCgABDAsNAQIRAAEKCw0BCgYAAQsLDQEMAQwE
+DQEJDAABBAEMDw0LAAEMDA0OAAADDA0KABkADQ0BCQ4ADw0BDBAAAQoNDSQA
+AQd+AwQGoQAAABQADQ0BDAECEQABAgwNCgABBgsNAQkQAAECDA0HAAELCw0B
+DAEJBQ0BCQoAAQYBDBANCwABDAwNDgAEDRcAAQoNDQ8AEA0BCg8ADg0mAAEH
+eQMBBwQGowAAABQAAQoNDQEKAQIQAAECDA0LAAEMCw0BAg8AAQkLDQEMBwAB
+CwsNAAMMAAwABQ0BCwEEBgABAgEJEQ0BCQsAAQwMDQ4ABQ0BCxUADg0PABEN
+AQkNAAEKDg0oAAEHdQMBBwMGAQSlAAAAFQAODQELAQIPAAEEDA0LAAEJCw0B
+Cg4AAQYMDQEKBwABCwsNAAMMAAkABw0ABwwJBgYJCgwAEg0MAA0NDQABCgcN
+AQwBBhEADw0PAAwNAQwBCwQNAQkLAAEKDw0qAAEFcQMBBwMGqAAAABUAAQkP
+DQEGAQILAAECAQkNDQwAAQsLDQEKDAABBA0NCAABCwsNAAMMAAAAHw0BCwwA
+DQ0NAAsNAQwBCQwAAQwPDQEKDwAMDQEMAQAGDQEJBwABAgEMDw0BCywAAQJs
+AwEHAwYBAqoAAAAWAAEMDw0ABwwJBAICAAAAAwIAAwYKDAAODQ0ADA0BCwEE
+CQABBgEMDA0BCggAAQwLDQAEDAAACh4NDQANDQwAAQYODQMMAQsDCgADCwwM
+ABENDwABBgwNAAMMAAoABw0ABQwMCwsMABINAQkvAGgDAAQHBgYFrQAAABcA
+Ew0FDBINDQABCQ0NAAMKBgIAAwAAAwIGCwAODQkAAQwLDQEMAwABDBwNAQoM
+AAEEDQ0MAAEMKA0BDA8AAQoMDQADDAAAAB4NMgABB2IDAAQHBgYCsAAAABgA
+KQ0OAAEKIg0BCQkAAQwLDQEMBAAcDQ0AAQoNDQwAKQ0QAAEMDA0ABAwAAAkc
+DQEMNAABB10DAAQHBgYCswAAABgAAQkoDQ8AAQogDQELCgABDAsNAQwEAAEK
+Gg0OAAEMDQ0LAAEMKA0BCRAADQ0BDAMAAQwbDQEENgABAlcDAQcDBrcAAAAZ
+AAEEJw0QAAELHg0BDAsAAQwLDQEMBQABDBgNAQIOAA4NCwABDCcNAQwQAAEJ
+DQ0BDAQAGg0BDDoAAQcpAwEHBgYABQIAAAUHABEDAQcKAwAEBwYGBboAAAAb
+AAEMJQ0RAAEJHA0BDAwAAQwLDQEMBgABDBYNDwAPDQEJDAABCyQNAQoRAA4N
+AQwFABgNAQw9AAEFKAMJBgUAAQIBBwgDAQcBAgMABwMABAcGBgW9AAAAHAAB
+CSQNEwABDBkNAQoNAAEMCw0BDAcAAQsTDQEMDwABCwEMDg0BCg4AAQoBDCAN
+AQkRAAEMDg0BDAYAAQwVDQEMQQAoAwADBwYCABgABAMABAcABgXAAAAAHgAB
+CyINFAABCRcNDwABDAsNAQwIAAEKEQ0BChUAAAMJCgwACA0BChAAAQIBDBwN
+AQoWAAADCQoLAAkNAQwHAAEKEw0BDEQAAQcUAwEGAQcJAwADBwcCABIAAQYL
+AAEDAQfGAAAAIAABCQEMEQ0AAwwKDAALDRcAAQsRDQELEQABDAsNAQwKAAEK
+DQ0BCh0AAQoBDAMNAQwUAAEKAQwVDQELAQkeAAADBAoMAAMNAQwJAAEKDw0B
+DEgAAQISAwEHBwYBBREAAAQHAAACAwYBBdIAAAAkAAEJAQsEDAENAQ0DDAEL
+AQoEAAELCw0aAAEKAwwGDQADDAwKABQAAQwLDQEMDQABCgMMAQ0DDAEKIwAA
+AwoMDQAYAAADAgkLAAUMAw0EDAEKAQkmAAADCw0MAAsAAAQGCgwMBQ0ABAwM
+CwlNAAMDAAUHAAACBwAKAwEHBwYBAgwAAQUDBwEF2AAAADUAAQsLDTsAAQwL
+DQEMOwABCVEAAQpnAAEHAQIIAAEHBwMABAIAAAUEBugAAAA1AAELCw0BBjoA
+AQwLDQEM/wAFAAEHAQcDAwEC7QAAADUAAQsLDQEGOgABDAwN/wD4AAAANQAB
+CwsNAQk6AA0N/wD4AAAANQABCwsNAQk6AA0N/wD4AAAANQABCwsNAQk6AA0N
+/wD4AAAANQABCwsNAQk6AA0N/wD4AAAANQABCwsNAQo6AA0N/wD4AAAANQAB
+DAsNAQo6AA0N/wD4AAAANQABDAsNAQo6AA0NMwABAwED/wDDAAAANQABDAsN
+AQs6AA0NMgAEA/8AwgAAADUAAQwLDQEMOgANDTEABgP/AMEAAAA1AAEMCw0B
+DDkAAQkNDTAACAP/AMAAAAA1AAwNAQw5AAEKDQ0vAAoD/wC/AAAANQANDTkA
+AQwNDS4ADAP/AL4AAAA1AA0NOQAODS0ADgP/AL0AAAA0AAEKDQ05AA4NAQYr
+ABAD/wC8AAAANAABDA0NOAABCw4NAQkqABID/wC7AAAANAAODTgADw0BCSkA
+FAP/ALoAAAAzAA8NNwAQDQEKKQAUA/8AugAAADIAAQkBDA4NNgAABAkLDAwN
+DQEKKgASA/8AuwAAADYAAAMGCgwACQ08AAEJAQwJDQELKwAQA/8AvAAAADsA
+AQIBCgUNAQY/AAEJAQwFDQEMLAAOA/8AvQAAAD8AAAQLDQ0JQgAABQkMDQ0M
+AC0ADAP/AL4AAABBAAEJAQpFAAEMAQwuAAoD/wC/AAAAuQAIA/8AwAAAALoA
+BgP/AMEAAAC7AAQD/wDCAAAAvAABAwED/wDDAAAA/wD/AIIAAAD/AP8AggAA
+AP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8A
+ggAAAP8A/wCCAAAB
+====
diff --git a/images/debian_16c.dat b/images/debian_16c.dat
new file mode 100644 (file)
index 0000000..2b38f81
--- /dev/null
@@ -0,0 +1,14 @@
+# Lilo boot menu background configuration  (Lilo 23)
+#
+# color palette: 0 black,         3 magenta,       7 pink,
+#                8 middle grey,  10 bright grey,  13 white
+#
+# bmp-table  = <x>,<y>;<ncol>,<nrow>,<xsep>,<spill>
+# bmp-colors = <fg>,<bg>,<sh>;<high-fg>,<high-bg>,<high-sh>
+# bmp-timer  = <x>,<y>;<fg>,<bg>,<sh>
+
+bitmap = debian.bmp
+
+bmp-table  = 16,12;1,12,16
+bmp-colors = 10,0,;7,0,
+bmp-timer  = 34,28;13,0,
diff --git a/images/debian_16c.uu b/images/debian_16c.uu
new file mode 100644 (file)
index 0000000..2725ea6
--- /dev/null
@@ -0,0 +1,501 @@
+begin-base64 644 debian.bmp
+Qk2SVwAAAAAAADYEAAAoAAAAgAIAAOABAAABAAgAAQAAAFxTAAAgHAAAIBwA
+AAABAAAAAQAAAAAAACIiIgAzMzMAVQDdAFVVVQBVVXcAd3d3AHdV3QCIiIgA
+qqqqAMzMzADMzN0A3d3dAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8A
+/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAA
+AP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8A
+ggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/
+AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIA
+AAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/
+AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAADoAAAHCg0MCQwMBAD/AJIA
+AADnAAADCQ0MAAMAAAMJDQYA/wCRAAAA5wAAAwkNCQADAAADBA0NAK8AAQIB
+BBIGzQAAAHMAAAUCBAQAAAAEBAECAQIDBAECAQAEBAEABAQBAgMAAwkBBggA
+BAQBAgUAAQYDCQADAgAAAAQEAQABAgMEAQIBAAQEAAcAAAkJAgACAAMJAQAE
+BAEABAQBAAEABAQBAAQEAQIBAgMEAQIBAAQEAAoAAg0MAAIGDA0MAwABCQEE
+oQABAgMGBAcOAwADBwYGANEAAAByAAEGBA0AHwQJDQ0KBgYMDQwGAgoNDQkA
+CQ0NCgYABA0NDAkMDQIABgAABQkNDQoGAAQAABkMDQ0JCg0JAAkNDQoCBgwN
+DAYCCg0NCQIJAAMNACgKCg0MCQIKDQ0JAgkNDQoCAgoNDQkACQ0NCgYGDA0M
+BgAJDQ0KAgAABQ0ABwwEAAAJDQ0AmwAAAwIHBwAVAwEHAQXWAAAAcgAAAwkN
+DAAEAAANDQ0EAAAJDQkAAAQNDQADAAAIDQ0EAAANDQkDAAEGAQQHAAADDQ0E
+AAQAAAMKDQwAAwAAIAIJAAANDQQAAAkNCQAABA0NAAANDQkAAAoNCQAABA0N
+AwAACA0NBAAABA0NAwAACA0NBAAACQ0JAwAAAw0NBAADAAAFDQwJBAIABAAA
+AwkNCgCWAAEFAQcWAwEH3AAAAHIAAAMJDQkABAAADQ0NBAAACQ0JAAAEDQ0A
+AwAABw0NBAAGDQ0ADQAAAw0NBAAEAAADDQ0EAAcAABwNDQQAAAkNCQAABA0N
+AAANDQQAAAkNCQAABA0NAwAACA0NBAAABA0NAwAACA0NBAAACQ0JAwAAAw0N
+BAADAAAEBgoEAgYAAQSTAAECFAMAAwcHAgDhAAAAcgAAAwkNCQAEAAANDQ0E
+AAAJDQkAAAQNDQADAAAHDQ0EAAkNCQANAAADDQ0EAAMAAAMEDQ0ACAAAHA0N
+BAAACQ0JAAAEDQ0AAAQNDAIACQ0JAAAEDQ0DAAAIDQ0EAAAEDQ0DAAAIDQ0E
+AAAJDQkDAAALDQ0EAAAEDQwJDQwAlgABBRIDAAQHBwYC5QAAAHIAAAMJDQkA
+BAAADQ0NBAAACQ0JAAAEDQ0AAwAABw0NBAAJDQwABQkBAgcAAAMNDQQAAwAA
+AwQNDQAFCQAQBgAADQ0EAAAJDQkAAAQNDQQAAQkDDAAHDQkAAAQNDQADAAAI
+DQ0EAAAEDQ0DAAAIDQ0EAAAJDQkDAAAMDQ0EAAANDQIABg0KkgABBxIDAAMH
+BgYA6QAAAHIAAAMJDQkABAAADQ0NBAAACQ0JAAAEDQ0AAwAABw0NBAAGDQoA
+AwQAAw0NBAAHAAAJDQ0EAAACAA0NAAMEABIKDQkAAA0NBAAACQ0JAAAEDQ0H
+AAAICg0JAAAEDQ0DAAAIDQ0EAAAEDQ0DAAAIDQ0EAAAJDQkDAAAMDQ0EAAQN
+DQAABA0NBAABCQECiQABBxEDAQcDBuwAAAByAAADCQ0JAAQAABcNDQQAAAkN
+CgAACQ0NAAAEDQ0EAAANDAADAAENAQ0IAAAtDQ0MBAwJAAoNAgAACg0EAAAN
+DQYAAAwNCgAACQ0NAAAJDQ0AAAkNCQAABA0NAAMAAAgNDQYAAAoNDQMAABcN
+DQQAAAkNCgAABg0NBAACDQ0AAAQNDAADAAADCQ0MAIYAAQcRAwEHBAbuAAAA
+cQABCQUNAQQDDQAGBAAJDQ0MBA0BCgEMAw0BDAMAAAcEDQkECQ0JAAYAAQQD
+DQAOCQwNCQAADAwEBg0MAAADDQEMBA0BCQQNAQkDAAAJDA0EBg0NAgAEAAMN
+AQABAAMNAQwEDQADCQAAAAMNAAYEAAkNDQwEDQEMAwAABQkNCQQMAAMNAAUJ
+AAkNDACDAAEHEgMBBwQG8AAAAHIAAAMJDQkABAAAEQYJAgAABAkGAAYJBgAA
+BAkJAAYAAwkBAggAAAcCBAkCAAkJAAMAAAQGCQkGBAAADAQJAgIJCQIAAAYJ
+BgUAAQQDCQECAwAAAwIJCQADAAAHBAkCAgkJBgAEAAAMBgkCAAAECQYABgkJ
+BQAABAIJCQYGAAEEggATAwEHBAbyAAAAcwABDAEJ/gABBxQDBQbzAAAAcwAB
+AgECBAAAAwkNBABMAAEMAQwOAAADCQ0EAJYAAQcUAwEHBAb1AAAAeQAAAw0N
+CQBLAAAEBA0NBA0AAAMNDQkAlAAWAwUG9gAAAHkAAQQBCU0AAQkBCQ4AAQQB
+CZIAAQIXAwUG9wAAAP8AawABAhcDAQcFBvgAAAD/AGkAAQUYAwEHBQb5AAAA
+/wBnAAECGQMBBwUG+gAAAP8AZgAaAwEHBQb7AAAA/wBkABsDAQcFBvwAAAD/
+AGIAAQcbAwEHBQb9AAAA/wBgAAEHHAMBBwUG/gAAAP8AXwAaAwEHAwMDAAEG
+AQb/AAAA/wBdABoDAwYBAwEDAwABBgEG/wABAAAAbgABAs4GHQABBxgDAQcD
+BgADBQcDAAQAAQb/AAEAAQAAAG4AAQIBAs0GHAAYAwEHBAYAAwAAAwAEAAEG
+/wADAAAAbgADAswGGgABBxcDAQcEBgMAAQf/AAkAAABuAAMCyQQDBhkAGAMF
+Bv8ADgAAAG4AAwLJBAMGFwABBxgDBQb/AA8AAABuAAMCyQQDBhYAGAMBBwQG
+/wARAAAAbgADAskEAwYUAAEHGAMEBgEC/wASAAAAbgADAskEAwYTABgDBAb/
+ABUAAABuAAMCyQQDBhIAFwMDBgEC/wAXAAAAbgADAskEAwYQAAEHFQMFBgEC
+/wAYAAAAbgADAskEAwYPABYDBwb/ABgAAABuAAMCyQQDBg4AGAMHBv8AFwAA
+AG4AAwLJBAMGDAABBxoDBwb/ABYAAABuAAMCyQQDBgsAAQcbAwEHBgb/ABYA
+AABuAAMCyQQDBgoAHgMEBv8AGAAAAG4AAwLJBAMGCQAcAwEHBAb/ABoAAABu
+AAMCyQQDBgcAAQUbAwEHBAb/ABwAAABuAAMCyQQDBgYAAQcbAwUG/wAdAAAA
+bgADAskEAwYFAAEHGwMFBv8AHgAAAG4AAwLJBAMGBAAbAwEHBQb/AB8AAABu
+AAMCyQQDBgMAGwMBBwQGAQX/ACAAAABuAAMCyQQDBgEAAQAbAwEHBAYBBf8A
+IQAAAG4AAwLJBAMGAQAbAwEHBQb/ACIAAABuAAMCyQQDBhsDAQcFBv8AIwAA
+AG4AAwLJBAMGGgMBBwUG/wAkAAAAbgADAskEAwYaAwUG/wAlAAAAbgADAsgE
+AQUDBhkDBQYBBf8AJQAAAG4AAwLHBAEFAQUDBhgDAQcDAAECAQL/ACYAAABu
+AAMCxgQDBQMGEgMFBgEC/wAsAAAAbgADAsUEBAUDBhEDBQb/AC4AAABuAAMC
+xAQFBQMGEAMGBv8ALgAAAG4AAwLDBAYFAwYPAwEHBQb/AC8AAABuAAMCwgQH
+BQMGDwMFBv8AMAAAAG4AAwLBBAgFAwYOAwUG/wAxAAAAbgADAsAECQUDBg0D
+Bgb/ADEAAABuAAMCwAQJBQMGDAMBBwUG/wAyAAAAbgADAr8ECgUDBgwDBQb/
+ADMAAABuAAMCvgQLBQMGCwMGBv8AMwAAAG4AAwK9BAwFAwYLAwUG/wA0AAAA
+bgADArwEDQUDBgoDBgb/ADQAAABuAAMCuwQOBQMGCQMBBwUG/wA1AAAAbgAD
+AroEDwUDBgkDBgb/ADUAAABuAAMCuQQQBQMGCAMBBwUG/wA2AAAAbgADArgE
+EQUDBggDBgb/ADYAAABuAAMCuAQRBQMGCAMDBgADAAYGAP8ANgAAAG4AAwK3
+BBIFAwYFAwAJBgMDBgYCAAAFAP8ANgAAAG4AAwK2BBMFAwYEAwMGAAMHBgYA
+/wA6AAAAbgADArUEFAUDBgMDAQcFBv8AOwAAAG4AAwK0BBUFAwYDAwUG/wA8
+AAAAbgADArQEFQUDBgEDAQMFBgEE/wA8AAAAbgADArMEFgUDBgEDAQcFBv8A
+PQAAAG4AAwKyBBcFAwYBBwUG/wA+AAAAbgADArEEGAUIBv8APwAAAG4AAwKx
+BBgFBwYBBP8APwAAAG4AAwKwBBkFBwb/AEAAAABuAAMCrwQaBQYG/wBBAAAA
+bgADAq4EGwUFBv8AQgAAAG4AAwKuBBoFBgb/AEIAAABuAAMCrQQbBQUG/wBD
+AAAAbgADAqwEGwUFBv8ARAAAAG4AAwKrBBsFBgb/AEQAAABuAAMCqwQaBQcG
+/wBEAAAAbgADAqoEGwUHBv8ARAAAAG4AAwKpBBsFCAb/AEQAAABuAAMCqQQa
+BQkG/wBEAAAAbgADAqgEGwUFBgEEAwb/AEQAAABuAAMCpwQbBQYGAQQDBv8A
+RAAAAG4AAwKnBBsFBQYBBAEEAwb/AEQAAABuAAMCpgQbBQYGAQQBBAMG/wBE
+AAAAbgADAqYEGwUFBgMEAwb/AEQAAABuAAMCpQQbBQcGAQQBBAMG/wBEAAAA
+bgADAqQEHQUHBgEEAwb/AEQAAABuAAMCpAQeBQUGAQQBBAMG/wBEAAAAbgAD
+AqMEHgUFBgMEAwb/AEQAAABuAAMCowQdBQUGBAQDBv8ARAAAAG4AAwKiBB0F
+BQYFBAMG/wBEAAAAbgADAqEEHQUFBgYEAwb/AEQAAABuAAMCoQQcBQUGBwQD
+Bv8ARAAAAG4AAwKgBBwFBgYHBAMG/wBEAAAAbgADAqAEHAUFBggEAwb/AEQA
+AABuAAMCnwQcBQcGBwQDBv8ARAAAAG4AAwKfBB0FBwYGBAMG/wBEAAAAbgAD
+Ap4EHwUGBgYEAwb/AEQAAABuAAMCnQQgBQYGBgQDBv8ARAAAAG4AAwKdBCAF
+BQYHBAMG/wBEAAAAbgADApwEIAUFBggEAwb/AEQAAABuAAMCnAQfBQYGCAQD
+Bv8ARAAAAG4AAwKbBCAFBQYJBAMG/wBEAAAAbgADApsEHwUFBgoEAwb/AEQA
+AABuAAMCmgQfBQYGCgQDBv8ARAAAAG4AAwKaBB8FBQYLBAMG/wBEAAAAbgAD
+ApkEHwUGBgsEAwb/AEQAAABuAAMCmQQfBQUGDAQDBv8ARAAAAG4AAwKYBB8F
+BQYNBAMG/wBEAAAAbgADApgEHgUGBg0EAwb/AEQAAABuAAMCmAQeBQUGDgQD
+Bv8ARAAAAG4AAwKXBB4FBgYOBAMG/wBEAAAAbgADApcEHgUGBg4EAwb/AEQA
+AABuAAMClgQfBQUGBAQBBgEGCQQDBv8ARAAAAG4AAwKWBB4FBAYBBQEFAwQD
+BgkEAwb/AEQAAABuAAMClQQfBQMGAwUBBAEEAwYKBAMG/wBEAAAAbgADApUE
+HgUDBgMFAQQBBAQGCgQDBv8ARAAAAG4AAwKVBB4FAQYBBgQFBQYLBAMG/wBE
+AAAAbgADApQEJAUGBgsEAwb/AEQAAABuAAMClAQkBQYGCwQDBv8ARAAAAG4A
+AwKTBCUFBQYMBAMG/wBEAAAAbgADApMEJAUGBgwEAwb/AEQAAABuAAMCkwQk
+BQUGDQQDBv8ARAAAAG4AAwKSBCQFBQYOBAMG/wBEAAAAbgADApIEIwUGBg4E
+Awb/AEQAAABuAAMCkQQkBQUGDwQDBv8ARAAAAG4AAwKRBCMFBgYPBAMG/wBE
+AAAAbgADApEEIwUFBhAEAwaAAAEFEgYBBa8AAABuAAMCkAQjBQUGEQQDBnoA
+AQUBBxEDAQcJBgEFqwAAAG4AAwKQBCIFBQYSBAMGdQABBxsDAQexAAAAbgAD
+ApAEIQUFBhMEAwZxAAEHDQMAAwcHAgDBAAAAbgADAo8EIQUDBhYEAwZuAAEH
+CQMBBwEGyQAAAG4AAwKPBB4FAQYbBAMGawABBwcDAAQHBgYCzAAAAG4AAwKP
+BBkFBQYcBAMGaAABBwYDAQcDBtAAAABuAAMCjgQZBQUGHQQDBmUAAQIGAwEH
+BAbSAAAAbgADAo4EGAUGBh0EAwZjAAEHBgMBBwQG1AAAAG4AAwKOBBgFBQYe
+BAMGYQABBwcDBQYdAAADAgIFAAQCsQAAAG4AAwKNBBgFBQYfBAMGXwAIAwEH
+BAYTAAECBwYBBxQGAQKmAAAAbgADAo0EFwUGBh8EAwZdAAkDBQYOAAADBQcH
+ABkDAQcMBqEAAABuAAMCjQQXBQUGIAQDBlsAAQcIAwEHBAYBBQkAAQIBByYD
+AQcKBgECnAAAAG4AAwKNBBYFBgYgBAMGWQABBwkDAQcEBgECBgABBy8DAQcK
+BpkAAABuAAMCjAQXBQYGIAQDBlcAAQIKAwMGAQUBBgQAAQc3AwEHCQaWAAAA
+bgADAowEFwUFBiEEAwZWAAgDAAUHBwMGBgADAAADAgAHAD0DAQcJBpMAAABu
+AAMCjAQWBQYGIQQDBlQAAQcHAwEHBAYDAAECRAMBBwgGAQKQAAAAbgADAosE
+FwUFBiIEAwZTAAgDBAYDAAEHSQMJBo4AAABuAAMCiwQWBQYGIgQDBlEAAQcH
+AwUGAAMAAAcATQMBBwgGjAAAAG4AAwKLBBYFBgYiBAMGUAAHAwEHBAYEAFAD
+AQcIBooAAABuAAMCiwQWBQUGIwQDBk4AAAQFAwcHBAMBAAQGBABTAwEHCAaI
+AAAAbgADAooEFgUGBiMEAwZNAAAEBwMAAAMDAQcBAAMGBAABBVYDAQcIBoYA
+AABuAAMCigQWBQYGIwQDBkwAAAQDAwAAAwMBAAEAAwYEAAEHHgMAAwcHBQAP
+AAEFAQcnAwEHBwYBAoQAAABuAAMCigQWBQcGIgQDBksAAAQDBwAAAwMBAAEA
+AwYEABwDAAMHBgYAGAABByUDAQcHBoMAAABuAAMCigQXBQYGIgQDBkkAAA0F
+AwUAAAMDBwAABgYCAAQAGQMBBwMGHgABAiQDCAaBAAAAbgADAokEGAUGBiIE
+AwZIAAAMBwMCAAADAwIAAAYGBAABBxcDAQcDBiQAAQciAwEHBwaAAAAAbgAD
+AokEGAUFBiMEAwZHAAAMBwMCAAADAwIAAAYGBAABBxYDBAYsAAEFHgMIBn4A
+AABuAAMCiQQXBQYGIwQDBkYAAAwDAwIAAAcDAgAABQYEABUDAQcEBjEAAQUc
+AwEHBwZ9AAAAbgADAokEFwUFBiQEAwZCAAALBgAAAwMCAAAHAwUAAwABBgQA
+FAMBBwQGNgAcAwgGewAAAG4AAwKJBBYFBgYkBAMGPAABBwQAAAsGAAADAwUA
+AAYDBgADAAEGAwABBRMDAQcEBjoAGwMBBwcGegAAAG4AAwKIBBcFBQYlBAMG
+OwABAwQAAAsGBgADAwcAAAYHBgADAAEGAwABBxIDAQcEBj0AAQcbAwcGeQAA
+AG4AAwKIBBYFBgYlBAMGOgABBwEDAwAACwYGAAcDBwAABgcGAAMAAQIDAAEH
+EgMEBgECQAAbAwgGdwAAAG4AAwKIBBYFBQYmBAMGOQABBwEDAwAACwIGBgcD
+AwAABQYGAAcAEgMFBkMAGwMBBwcGdgAAAG4AAwKIBBUFBgYmBAMGOAAAAwID
+BwADAAAFBgYHAwMAAwABBgEGBwASAwQGAQJFABsDAQcHBnUAAABuAAMCiAQV
+BQcGJQQDBjgAAQMBAwMAAAUGBgIDAwADAAEGAQYHABEDBQZIAAMDAQABBxcD
+BwZ0AAAAbgADAogEFgUGBiUEAwY3AAAFAwMCAAAAAwYBAwEDAwABBgEGBwAR
+AwUGSgABAwEHAwABBxYDBwZzAAAAbgADAocEFwUGBiUEAwY2AAADBwMDAAMA
+AAQGBgMDAwAAAwYGAgAGABADAQcEBgECTAABBwUAFgMHBnIAAABuAAMChwQX
+BQYGJQQDBjYAAQMBAwMAAAoGBgcDAgAAAgYFBgAQAwUGTwABBwUAAQcVAwcG
+cQAAAG4AAwKHBBcFBgYlBAMGNQAABQMDBwAAAAMGAQMBBwMAAQYBBgYAEAMF
+BlcAAQIVAwcGAQJvAAAAbgADAocEFwUGBiUEAwY0AAAKBwMDAAACBgYDBwMA
+AQYBBgYAEAMFBloAFQMHBgECbgAAAG4AAwKHBBcFBgYlBAMGMwAAAwIDAwAD
+AAAEBgYHBwQAAQYGABADBQZcABUDBwYBAm0AAABuAAMChwQXBQYGJQQDBjMA
+AAUDAwcAAAADBgEHCwAQAwUGXgABBxQDBwYBAmwAAABuAAMChwQXBQYGJQQD
+BjIAAwMABgAABQYGBQsADwMBBwUGYAABBRQDBwYBAmsAAABuAAMChgQYBQYG
+JQQDBjEAAAYFAwMHAAADBgsAEAMFBmMAFAMHBgEEBAABBmUAAABuAAMChgQY
+BQUGJgQDBjEAAwMBAAEAAwYBAgoAEAMFBmUAFAMBBwQGAAMHBgUAAwABBmUA
+AABuAAMChgQXBQYGJgQDBjAAAAkHAwMCAAACBgYACgABBw8DBQZnABQDAQcD
+BgEDAwYAAwAABgBlAAAAbgADAoYEFwUFBicEAwYwAAADAgMDAAQAAQYKAAEH
+DwMFBmkAAQcTAwAEBwYGAwQGAAMABQYAZAAAAG4AAwKGBBYFBgYnBAMGMQAB
+AwUAAQYEAAEHBAABBg8DBQZrAAEHEwMABAcGBwcGBmQAAABuAAMChgQWBQUG
+KAQDBjEAAQMJAAEHBQAPAwUGAQVsAAEHFAMBBwEHBQYBBWQAAABuAAMChgQV
+BQYGKAQDBjsAAQMEAAEHDgMBBwUGbgABAhQDAQcFBmUAAABuAAMChgQVBQYG
+KAQDBjoAAQcBBQMAAQIPAwUGcQATAwYGZQAAAG4AAwKGBBUFBQYpBAMGOgAB
+BwQADwMFBnMAEgMGBmUAAABuAAMChgQUBQYGKQQDBjkAAQcEAAEHDgMGBnQA
+EQMHBmQAAABuAAMChQQVBQYGKQQDBjkAAQIDAAECDgMBBwUGdgAQAwEHBgZk
+AAAAbgADAoUEFQUGBikEAwY4AAEHBAAPAwUGNgABBQUGPAAQAwYGAQJjAAAA
+bgADAoUEFQUGBikEAwY8AAEHDgMGBjAAAQcFAwcGAQI7AAEHDgMHBmMAAABu
+AAMChQQVBQUGKgQDBjwADgMBBwUGLQABAgoDCAY7AAEHDgMGBgECBgABAlsA
+AABuAAMChQQUBQYGKgQDBjsAAQcOAwUGAQIrAAEHDQMBBwcGOwAOAwcGAQIF
+AAEGWwAAAG4AAwKFBBQFBgYqBAMGOwAOAwYGKgABAhADAQcEAAADBAYGADoA
+AQcOAwYGAQcEAAEGAQZbAAAAbgADAoUEFAUGBioEAwY6AAEHDgMFBjsAAAMF
+BwcAQQAOAwEHBAYBAwEDAwADBlsAAABuAAMChQQUBQYGKgQDBjoADgMGBn8A
+DwMDBgAGBwMDBgACAwZbAAAAbgADAoUEFAUGBioEAwY5AAEHDgMFBoAAEAMB
+BgEGAwMGBlsAAABuAAMChQQUBQYGKgQDBjkADgMGBoAAFQMHBloAAABuAAMC
+hQQUBQYGKgQDBjgAAQIOAwUGgAABAhUDAQcGBloAAABuAAMChQQUBQYGKgQD
+BjgADgMGBoAAAQIWAwYGWgAAAG4AAwKFBBQFBgYqBAMGOAAOAwUGAQSBABYD
+BwZZAAAAbgADAoUEFAUGBioEAwY3AAEHDQMBBwUGggAXAwYGWQAAAG4AAwKF
+BBQFBgYqBAMGNwAOAwYGggABBxYDBwZYAAAAbgADAoUEFAUGBioEAwY3AA0D
+AQcFBlwAAQUnABYDAQcGBlgAAABuAAMChQQUBQYGKgQDBjYAAQcNAwYGVgAB
+BQQAAAMFBgYAJgABBxYDBwZXAAAAbgADAoUEFAUGBioEAwY2AA4DBgZVAAAF
+BwMDAAAABAYBAiYAAQcVAwEHBgZXAAAAbgADAoUEFAUGBioEAwY2AA0DAQcF
+BlUAAQcDAwEGAwAAAwUGBgAoAAEHFAMHBlYAAABuAAMChQQUBQYGKgQDBjYA
+DQMGBlMAAQcDAAADBQMDAAUAAQYBBikAAQcSAwEHBgZWAAAAbgADAoUEFAUG
+BioEAwY1AAEHDQMGBlMAAQUFAAEHAQcFAAEGKwASAwcGVQAAAG4AAwKFBBQF
+BgYqBAMGNQAOAwUGAQJUAAEDBQABBwYAAQYqABIDAQcGBlUAAABuAAMChQQU
+BQYGKgQDBjUADQMGBlUAAQcGAAEHBQABBioAAQcSAwcGVAAAAG4AAwKFBBQF
+BgYqBAMGNQANAwYGVgABAwUAAQcBBQUAAQYqABIDAQcGBlQAAABuAAMChQQU
+BQYGKgQDBjUADQMGBlYAAQcBBwUAAQcFAAEEKgATAwYGAQVTAAAAbgADAoUE
+FAUGBioEAwY0AAEFDQMGBlcAAQMFAAEFAQYFAAECKQABAhIDAQcGBgsAAQJH
+AAAAbgADAoUEFAUGBioEAwY0AAEHDAMBBwUGAQJYAAEHBQABBQUAAQIqABMD
+BgYFAAECBQABAkcAAABuAAMChQQUBQYGKgQDBjQADQMGBlkAAQIFAAECAQYv
+AAEHEgMHBgQAAQJNAAAAbgADAoUEFAUGBioEAwY0AA0DBgZaAAEHNgATAwYG
+UgAAAG4AAwKFBBQFBgYqBAMGNAANAwYGkQATAwYGAQJRAAAAbgADAoUEFAUG
+BioEAwY0AA0DBgaRAAEFEgMHBgoAAQJGAAAAbgADAoUEFAUHBikEAwY0AA0D
+BgaSABMDBgYEAAECBQABAkYAAABuAAMChQQVBQYGKQQDBjQADAMBBwYGkgAT
+AwYGBAABBQUAAQJGAAAAbgADAoUEFQUGBikEAwY0AAwDAQcFBgEFkgABBRID
+BgYBBQMAAQJMAAAAbgADAoUEFQUGBikEAwY0AAwDAQcFBgECkwASAwEHBgZQ
+AAAAbgADAoUEFQUGBikEAwY0AAwDBgYBApMAEwMGBlAAAABuAAMChQQVBQYG
+KQQDBjQACgMBBwEDBAYAAwAAAgCTAAEHEgMGBlAAAABuAAMChQQVBQYGKQQD
+BjMAAQIKAwYGlgABBRIDBgZQAAAAbgADAoUEFQUGBikEAwYzAAECCgMGBpcA
+EgMGBlAAAABuAAMChQQVBQYGKQQDBjMAAQIKAwYGlwASAwYGUAAAAG4AAwKF
+BBUFBgYpBAMGNAAKAwYGlwASAwYGUAAAAG4AAwKFBBUFBwYoBAMGNAAKAwYG
+lwASAwYGUAAAAG4AAwKFBBYFBgYoBAMGNAAKAwYGlwASAwcGTwAAAG4AAwKF
+BBYFBgYoBAMGNAAKAwYGlQABBwEAEgMBBwcGAQVNAAAAbgADAoUEFgUGBigE
+AwY0AAoDBgaVAAEDAQAUAwEHBQYABAUAAAZKAAAAbgADAoUEFgUGBigEAwY0
+AAoDBgYBApQAAQcBBxQDAAoHBgYHBgYFAAAGSgAAAG4AAwKFBBYFBgYoBAMG
+NAAKAwYGAQWUAAEFFQMACgcGBgMGBgUABQZKAAAAbgADAoUEFgUGBigEAwY0
+AAoDAQcGBpUAFQMABAcGBwMDBgADAAYGAEoAAABuAAMChQQWBQYGKAQDBjQA
+CgMBBwYGbgABAiYAFQMABAcGAwMDBgADAAYGAEoAAABuAAMChQQWBQYGKAQD
+BjQACwMGBmgAAQIEAAEFAQYmABUDAAQHBgMDBgZKAAAAbgADAoUEFgUGBgEF
+JwQDBjQACwMGBmcAAQcBAwQAAQYBBiYAFgMAAwcDAwAGBkoAAABuAAMChQQW
+BQcGJwQDBjQAAQcKAwYGZwABAwEDBAABBgEGJgAZAwYGAQVJAAAAbgADAoUE
+FwUGBicEAwY0AAEFCgMGBgECZgABAwEDAwADBiYAAQcYAwEHBgZJAAAAbgAD
+AoUEFwUGBicEAwY1AAoDBwZlAAADBwMDAAMAAwYmAAEHGQMGBkkAAABuAAMC
+hgQWBQYGJwQDBjUACgMBBwYGZQADAwMAAwYmAAEHGQMGBkkAAABuAAMChgQW
+BQYGJwQDBjUAAQcKAwYGZQADAwMAAwYmAAEFGQMHBkgAAABuAAMChgQWBQYG
+JwQDBjYACgMGBmUAAwMEAAEGAQYmAAECGQMBBwYGSAAAAG4AAwKGBBYFBgYn
+BAMGNwAJAwcGZQABAwEDBAABBgECJwAaAwYGSAAAAG4AAwKGBBYFBgYnBAMG
+NwAJAwEHBgZlAAEHAQUtABoDBwZHAAAAbgADAoYEFgUGBicEAwY3AAECCQMG
+BpQAGgMBBwYGRwAAAG4AAwKGBBYFBwYmBAMGOAAJAwcGkwAbAwYGAQJGAAAA
+bgADAoUEGAUGBiYEAwY4AAEHCAMBBwYGkwAbAwcGRgAAAG4AAwKFBBgFBgYm
+BAMGOQAJAwYGkwAcAwYGRgAAAG4AAwKFBBgFBgYmBAMGOQAJAwcGkgAcAwYG
+AQVFAAAAbgADAoUEGAUGBiYEAwY5AAEHCQMGBpIAHAMBBwYGRQAAAG4AAwKF
+BBgFBgYmBAMGOgAJAwcGkQAdAwYGRQAAAG4AAwKFBBgFBgYmBAMGOgAJAwEH
+BgaRAB0DAwYABAAABgJEAAAAbgADAoUEGAUGBiYEAwY6AAEHCQMGBgECkAAa
+AwAFBgYHBgYASQAAAG4AAwKFBBgFBwYlBAMGOwAJAwcGkAAZAwYGSQAAAG4A
+AwKEBBoFBgYlBAMGOwAKAwYGAQSPABkDBgZJAAAAbgADAoQEGgUGBiUEAwY7
+AAECCQMBBwYGjgABAhgDAQcFBgEFSQAAAG4AAwKEBBoFBwYkBAMGPAAKAwcG
+jQABBRgDAQcFBkoAAABuAAMChQQaBQYGJAQDBjwAAQcJAwEHBgaNAAEFGAMG
+BkoAAABuAAMChQQaBQYGJAQDBj0ACgMHBowAAQUYAwYGSgAAAG4AAwKFBBoF
+BwYjBAMGPQABBwoDBgYBAosAAQcYAwYGSgAAAG4AAwKGBBoFBgYjBAMGPgAK
+AwcGiwABBxgDBgZKAAAAbgADAoYEGgUHBiIEAwY+AAEHCgMHBooAAQcYAwYG
+SgAAAG4AAwKGBBsFBgYiBAMGPwALAwYGAQWJAAEHGAMGBkoAAABuAAMChwQa
+BQcGIQQDBkAACgMBBwYGiQABBxgDBgZKAAAAbgADAocEGwUGBiEEAwZAAAEC
+CgMHBogAAQcYAwYGAQJJAAAAbgADAocEGwUHBiAEAwZBAAEHCgMHBocAAQcY
+AwgGSAAAAG4AAwKIBBsFBgYgBAMGQgABBwoDBwaGAAEHGQMBBwYGSAAAAG4A
+AwKIBBsFBwYfBAMGQwABBQkDAQcHBoUAAQcZAwEHBQZJAAAAbgADAogEHAUG
+Bh8EAwZFAAkDAQcHBoQAAQcZAwUGSgAAAG4AAwKJBBsFBwYeBAMGRQABBwkD
+AQcHBoMAAQcYAwYGSgAAAG4AAwKJBBwFBwYdBAMGRgAKAwEHBwaCAAEHFwMB
+BwUGSwAAAG4AAwKJBB0FBgYdBAMGRgABBwoDAQcHBoAAGQMGBksAAABuAAMC
+igQcBQcGHAQDBkcACwMBBwcGfwAYAwEHBQZMAAAAbgADAooEHQUGBhwEAwZI
+AAwDBwZ+ABgDBgZMAAAAbgADAooEHQUHBhsEAwZIAAEHDAMHBgECRwABAjQA
+GAMGBkwAAABuAAMCiwQdBQYGGwQDBkkADQMIBkAAAQIEAAEGNQAXAwEHBQYE
+AAEESAAAAG4AAwKLBB0FBwYaBAMGSgANAwEHBwY+AAEHBAABBjYAFwMEBgEH
+AQYDAAEGBQABAgUAAQI9AAAAbgADAoIEAQUFBAADBgQEAB4FBgYaBAMGSwAO
+AwgGOwABAwMAAQUBBjYAAQUXAwMGAAcDBgYAAAUGAAUAAQVDAAAAbgADAoIE
+AQUFBAEGAwQdBQcGGQQDBkwADgMBBwcGAQU3AAEFAQMDAAEGAQY3AAEHFgMA
+CwcGBgcDBgIAAAYGAEkAAABuAMwCAwZNAA8DAQcHBgECNAAABAMDAAADBjgA
+FwMDBgAFAwMGAAAAAwYKAAEGPgAAAG4AzQIBBgEGTgAQAwgGAQIwAAAEBwMD
+AAQGOQAXAwALBgYHAwcGAAUGBgIABAABBwUAAQQ+AAAAbgDOAgEGTwARAwEH
+CAYsAAEHAwMFBjoAFwMABAYHAwMGBgUAAQVEAAAA8wABAwEDBAABBgEGAwAe
+AwYGawASAwEHCAYoAAEHBAMFBjsAGwMGBgoAAQY/AAAA8wABAwEDBAABBgEG
+AwABBx0DBwZrAAEHEgMBBwkGIwAFAwEHBAY8AAEFGwMGBgQAAQcFAAEGPwAA
+APMAAQMBAwUAAQYEAB0DAQcEBgEFbQABBRQDAQcJBh0AAQcGAwUGPQAcAwUG
+AQUEAAEHBQABAj8AAAD0AAEDBQABBgEFAwAbAwEHAQcEBnEAFgMBBwoGFgAB
+BwgDBAYBAj4AGwMBBwUGBQABBQQAAQZAAAAA9AABAwEHBQABBgMAAQIZAwEH
+BgZyAAEHGAMBBwwGAQIJAAADAgUHAAoDBQZAABsDBgYEAAEHBQABBkAAAAD1
+AAEDBQABAgQAGgMHBnMAHQMBBwEHCgYBBwEHDgMBBwQGQQABBRsDBgYEAAED
+BQABBkAAAAD1AAEFCgABBxoDBwZzAAECNgMEBkMAHAMGBgQAAQcEAAEGQQAA
+AP8AAQABABoDAQcGBnUAAQUyAwQGRQAbAwEHBQYBBQMAAQcFAAEGQQAAAP8A
+AQABABsDBwZ2AAECLgMEBkcAGwMBBwUGBAABAwUAAQZBAAAA/wAAAwAAAgAb
+AwcGeAABBygDAQcDBgECSAABBxsDBgYEAAEHBAABBkIAAAD/AAMAHAMGBgEF
+eQABAiQDAwYBAksAHAMGBgMAAQcFAAEGQgAAAP8AAwABBxsDAQcGBnwAAQIB
+Bx0DAAMGBgIATwAcAwYGAwABAwQAAQIBBkIAAAD/AAQAHAMHBn8AAQIBBxQD
+AQcBBVQAAQccAwYGAAQAAAIHBAABBkMAAAD/AAQAHQMHBoUAAQIBAgcHAQIB
+AloAHAMBBwUGAwABAwUAAQZDAAAA/wAFAB0DBwbpABwDAAYGBgAGBgQDAAED
+BAABBgEGQwAAAP8ABQAdAwEHBgYBBecAGQMABQYDAwcGAAMAAQYDAAEHAQcE
+AAEGRAAAAP8ABQABBR0DAQcGBgEC5gAYAwMGAAMDBgUABwABAwQAAQUBBkQA
+AAD/AAYAHgMHBuUAAQcXAwEHBQYHAAEFAQMEAAEGAQZEAAAA/wAGAAEHHgMH
+BuQAGAMGBgcAAQMBAwMAAAMCBgYARAAAAP8ABwAfAwcG4gABAhgDBgYGAAAD
+AgMDAAMAAwZEAAAA/wAHAAEHHwMHBuEAGAMBBwUGBwADAwMAAwZEAAAAGgAA
+CQIGCQwMCgkIBAAEAAEBBQgBAQcAAQkBBAcAAAcECQoMCgkEAAQAAAMCDQwA
+BQABBA0IAAMBAAYABAgBBgEABQgBBAEBBQgADwIAAAEJCgkEAAkIBAEAAgAD
+CAADBAAGAAQIAQZ5ACADBwbgABgDBgYHAAMDAQABAAQGRAAAABkAAAwIDQ0G
+AQAABg0NDAgDAAAFBAoNCgQABwAAAwYNBAAFAAALAQwNDQoGAgQJCgEAAwAA
+AwwNAgAEAAEBAQYEDQAFCgQEBggAAw0ABAQAAgwDDQADAgAEAAMNAAQMAgAI
+Aw0ACggAAAEMDQ0MDAkDDQAJDAYBBg0KAQAEAAQNAQR5ACEDBwbeABkDBgYG
+AAQDAQABAgQGRAAAABcAAAUBDA0NBgAFAAMNAQwEAAADAg0CAAcAAAQEDQ0E
+BAAABQEMDQ0KAAUAAQYBCQMAAAMJDQgABgABCgMNAQIEAAAKAQoNBgAACA0N
+DAMAAAcKDQ0JAAABAAMNAAoCAAAGDQ0MAAAGAw0BBgMAAAUGDAAABAADDQEG
+egAhAwEHBwbdABkDBgYFAAECBAMBAAUGRAAAABcAAAQJDQ0MBgAABAwNDQwE
+AAEBAQ0HAAEBAw0BBAQAAQYDDQEEBgAABwwCAAAEDQwABgABCQMNAQIFAAAJ
+AQ0JAAAIDQ0KAAMAAAcKDQ0IAAABAAMNAAcCAAAIDQ0KAAMAAw0BBAQAAAcJ
+CAEMDQ0KAHwAAQcgAwEHBwbbABoDBgYFAAUDAQIFBkQAAAAWAAEEAw0BBgYA
+AAQMDQ0MBAABAQENBgABAQEMAw0BBAQAAQkDDQEBBgABCAEGAwAAAwwNAgAF
+AAEJAw0BAgYAAAgGCgAACA0NCgMAAAcKDQ0IAAABAAMNAAcCAAAIDQ0KAAMA
+Aw0BBAUAAQoBCgMNAQJ9AAEDAQcfAwEHBgYBBdoAGgMGBgQAAQUEAwEHBQYA
+BAUAAAJBAAAAFgABCgMNAQIFAAEBBA0EAAEBAQ0GAAEKBA0BBAQAAQoDDQcA
+AQYBCAMAAAMJDQgABQABCQMNAQIHAAAHCgAACA0NCgADAAAHCg0NCAAAAQAD
+DQAHAgAACA0NCgADAAMNAQQFAAEGAw0BCIEAHwMBBwYGAQXYABsDBwYAAwAA
+AgAFAwEHBQYABAIAAAJBAAAAFgAEDQEBAwAAAwEECQAEDQAGCQQAAAENBQAB
+CAQNAQwBBAQAAAQMDQ0MBwABBAEJAwAAAwQNDAAFAAEJAw0BAgoAAAQIDQ0K
+AwAABwoNDQgAAAEAAw0ABwIAAAgNDQoAAwADDQEEBAAABQEMDQ0MAIMAAQce
+AwEHBgYBAtcAGwMAAwcGBgADBwMGAQcFAwYGAAMAAAYAQgAAABUAAQIEDQQA
+AQEIBAAEAAABDQQAAQQEDQADBgkEAAQAAAQMDQ0MBwABBAEJBAAAAwwNAgAE
+AAEJAw0BAgoAAAQIDQ0KAwAABwoNDQgAAAEAAw0ABwIAAAgNDQoAAwADDQEE
+BAABCQMNAQoBAYMAAQcBBx0DBwYBAtUAIwMBBgEGBgMAAwYGAwAGBkIAAAAV
+AAEEAw0BDA8AAQEBDQMAAQIEDQAECQAJBAQAAAQMDQ0MBwABBAEJBAAAAwkN
+CAAEAAEJAw0BAgoAAAQIDQ0KAwAABwoNDQgAAAEAAw0ABwIAAAgNDQoAAwAD
+DQEEAwABAgMNAAMIBAkAhAAfAwcGAQLTAAECIwMBBgcDAAMHBwMABQYBAkIA
+AAAVAAEBBA0PAAAGAQ0AAAEMAw0ABQoAAAkEAAQAAAQMDQ0MBwABBAEJBAAA
+AwQNDAAEAAEJAw0BAgoAAAQIDQ0KAwAABwoNDQwEAAYAAw0ABwEAAAkNDQoA
+AwADDQEEAwAACAwNDQwAAAkIhAAfAwcGAQLSAC4DBgZDAAAAFgAEDQEBDgAA
+BQENAAAKAAMNAAYMAQAACQQEAAAEDA0NDAcAAQQBCQUAAAMMDQIAAwABCQMN
+AQIJAAAIAQoNDQoAAAIDDQADCAkMAAMNAAsJAAABDA0NCgAABgADDQAEBAAB
+CgMNAAcJAAAGDQkBAIIAIAMHBgEF0AABBy4DBgZDAAAAFgABCgMNAQEIAAEB
+AQQEAAAEAQ0ACQQNAQIDAAEJAQQEAAAEDA0NDAcAAQQBCQUAAAMJDQgAAwAB
+CQMNAQIJAAEGAwgAAwYAAAAECAAGBAAGCQoGAwABBgMIAAMGAAIABAgAAwIA
+BAAFCAECAQIDCAEEgwAgAwEHBgYBBc8ALgMBBwUGRAAAABYAAQQDDQEECAAB
+CQEIBAAAAwENBgAEDQEGBAABCQEEBAAABAwNDQwHAAEEAQkFAAADBA0MAAMA
+AQkDDQECuQABAwEHHwMBBwcGzQAvAwYGRAAAABcAAAQJDQ0KBwAAAwINCAAE
+AAEBBQ0BCAUAAQkBBAQAAAQMDQ0MBwABBAEJBgAABg0NAgAACQMNAQILAAAD
+BAYBAKsAAQIBByADAQcHBssAAQIvAwUGAQVEAAAAFwAABQEMDQ0CAAUAAAQB
+DA0IBAABAgQNAQoGAAEMAQYEAAQNAQEGAAEIAQoGAAAGCQ0IAAAKAw0BBAoA
+AAQGDQ0JrAAiAwEHBwbKAC8DAQcFBkUAAAAZAAAECQ0MAgMAAAUGDA0NCAAD
+AAEEBA0BDAEBBQAABwYNCgEAAAYABA0BBgUAAAQCDA0EBQAABQQNDAACAAQN
+AQkBAQkAAAQJDQ0MrAABBwEHIQMBBwcGyAABBy8DBgZFAAAAGgAACwQICgwK
+CQgEAAYIAAMABQkBAgUABQkBAQEIBwkABAIAAAYECQEGBQAAAw0NCAAHCQEG
+CAAABAIKDAStACQDBwbHAC8DAQcFBkYAAABPAAEBAQHCACUDBwbFADADBgZG
+AAAA/wAVACUDBwYBAsIAAQcwAwUGRwAAAP8AFQAmAwgGwAABAjADBgZHAAAA
+/wAVAAEHJgMBBwcGvwAxAwUGSAAAAP8AFgAoAwcGvQAxAwYGSAAAAP8AFgAB
+BygDCAa6AAEHMQMFBkkAAAD/ABcAKQMBBwcGuQAxAwYGSQAAAP8AFwArAwcG
+AQW2ADEDAQcFBkoAAAD/ABgAKwMBBwcGtAAyAwYGSgAAAP8AGAAtAwgGsQAB
+BzEDAQcFBksAAAD/ABkALgMIBq4AAQcyAwUGAQJLAAAA/wAZAC8DAQcIBgEC
+qgABAjIDBgZMAAAA/wAaADEDCgYBAqYAMwMFBk0AAABiAAEJAQkGCgADCQkG
+ABsAAAMGCQkABwoBCYYANAMBBwoGogAzAwYGTQAAACAAAQoBDAcNAAMMDAkA
+CQAABgkMDAsKCgYJAAMKCwwAGAAAAwkLDAARDQADDAwKAA4AAAQJCgwMEQ0B
+DAEKHQAABQoLCgkCAAkAAAMJCgsAEQABCgEMCA0AAwwLAgAMAAAFDAwLCgoA
+BQkABAoKDAsLAAAFCwoJCQIAAwAACgIECQkKCwwAAAcPAwADCwoJAAkDAAQJ
+CgsMGAMDBgECAwagADMDAQcFBk4AAAAeAAEMDg0BCgcAAQoODRUAAQkBDBoN
+AQkHAAEEAQobDQEKGwAPDQEMDwABCw8NAQkKAA0NAQkLAA8NBAAOAwEKDw0U
+AwAHBwYDAwcGBgADAAEGnwA0AwUGTwAAABwAAQwSDQECBQABCg0NAQsTAAEM
+HQ0BCwUAAQwgDQEMGQABDA4NAQkNAAEJEw0BBAgADQ0MAAEKDQ0BDAQAAQcN
+AwEJDg0BCRQDAQcDBgEDAwYDAAECnQA0AwYGTwAAABsAFQ0BCQQAAQoNDQEJ
+EQABCx8NAQsFAAEMIg0BCxcAAQsODQ0AAQoVDQEJBgABBAwNAQsMAAEJDQ0B
+CwUADgMODRYDAQcHBp8AAQczAwEHBQZQAAAAGQABCRcNBAABCw0NEAABCSEN
+AQwFAAEKJA0BBhUAAQkODQwAAQoXDQEKBQABCQwNAQYNAA0NAQoFAA4DDg0X
+AwEHBwadAAEHNAMFBlEAAAAYAAEJGQ0DAAELDQ0PAAELIg0BDAUAAQIlDQEK
+FQANDQELCwABCRkNAQoEAAEJDA0OAA0NAQkFAAECDQMNDQEMGAMBBwcGmwAB
+BzQDBgZRAAAAGAAaDQAEDAAACwwNAQwOAAEMJA0GACYNAQwUAA0NAQoLABsN
+BAABCQwNDgANDQcADQMNDQEMGQMBBwcGmQABBzQDAQcFBlIAAAAXABwNAAMA
+AAsADA0BCg0AAQwlDQYADw0AAwwKCQADBgADCQkMAA8NAQsTAA0NAQkKAAEK
+HA0DAAEKCw0BDA4ADQ0IAAwDDQ0BDBsDBwaXADYDBQZTAAAAFgABDBwNAAMM
+AAwADA0BCQwAAQwWDQEMAQwDCwEMAQwJDQYADQ0BCQoAAAMCBgoADQ0BCxIA
+DQ0BBgoAHQ0ABAsAAAoLDQEMDgANDQgAAQcLAw0NAQscAwcGAQKUADYDBQZU
+AAAAFQABCR4NAQYBDAwNDAABChINAQwBCg0AAQoBDAQNBgANDQEGDQABBgEM
+DA0BChEADQ0KAAEKHg0AAwAACgALDQEMDgANDQkACwMBDAwNAQodAwgGkgA2
+AwYGVAAAABUAFQ0BDAEMCA0BDAEMDA0MABENAQwTAAAECg0NCQUADQ0BBg4A
+AQIBCgwNEQANDQoAAQwRDQAFCwoJCgwACA0AAwwACgALDQELDgANDQoACgMB
+DAwNAQoeAwEHBwaQADYDAQcFBlUAAAAUAAEJEQ0AAwoGAgAEAAADAgkMABIN
+CwABDA8NAQwXAAEKAQoFAAEMDA0BBhAAAQoMDRAAAQwMDQoADw0BCwEGBgAA
+AwIGDAAGDQEAAQoLDQELDgANDQoAAQIJAwEMDA0BCiADCAaNADcDBQZWAAAA
+FAABDA8NAQwBBAkAAQIBChENCgABCQ8NAQofAAEMDA0BBhAAAQIBCgsNAQoP
+AAEMDA0JAAEKDg0BCQECCQABAgEJBQ0BDAELCw0BCg4ADQ0LAAEHCAMBCwwN
+AQkiAwgGiQABAjcDBQZXAAAAEwABAg8NAQsBAgwAAQoQDQoADw0BCSAAAQwM
+DQEGEQABAgEMCw0PAAEMDA0JAAEMDQ0BCg0AAQYRDQEKDgANDQwAAQcHAwEK
+DA0BCSQDCAYBBYUAAQc3AwUGAQJXAAAAEwABDA4NAQsBAg0AAQIBCw4NAQwJ
+AAEJDg0BCSEAAQwMDQEGEgABBgsNAQwOAAEMDA0JAA0NAQwBAg4AAQYQDQEK
+DgABDAwNDQAHAwEKDA0BCSYDAQcKBgECfwA4AwYGWAAAABMADg0BDAECDwAB
+Bg4NAQsJAA4NAQoiAAEMDA0BBhMAAQwLDQ4AAQsMDQkADQ0BBhAAAQkPDQEK
+DgABDAwNDgAGAwEKDA0BCSoDAQcOBgECdgA4AwEHBQZZAAAAEgABCQ4NAQYR
+AAEMDQ0BCgkADQ0BDCMAAQwMDQEGEwABBgsNAQsNAAELDA0JAA0NAQIQAAEC
+AQwODQEKDgABDAwNDwAFAwEKDA0BCTIDAQcJBgEFcQABBTgDAQcFBloAAAAS
+AAEMDQ0BDBIAAQkNDQEKCAABCw0NJAABDAwNAQQTAAECAQwLDQ0AAQsMDQgA
+AQQMDQEKEgABBg4NAQoOAAEMDA0QAAQDAQkMDQEJNgMBBwMAAQIDBm8AOgMF
+BlsAAAASAA4NAQYSAAEEDQ0BCQgADQ0BDCQAAQsMDQEEFAABCQsNAQkMAAEK
+DA0IAAEJDA0BCRIAAQIBDA0NAQoOAAEMDA0RAAMDAQkMDQEJMAMFBgADBwMD
+AAYAAQJtADoDBQZcAAAAEgANDQEMAQISAAECAQwMDQEJCAANDQEEJAABCwwN
+AQQUAAEECw0BDAwAAQoMDQgAAQkMDQEGEwABCQ0NAQoOAAEMDA0SAAADAwMJ
+AAwNAQkxAwkGcAABBzoDBQZdAAAAEQABCQ0NAQkUAAEMDA0IAAEKDQ0lAAEL
+DA0BBBUAAQwLDQwAAQoMDQgAAQkMDQEEEwABAg0NAQoOAAEMDA0TAAEDAQkM
+DQEJMwMBBwkGawABAjsDBQZeAAAAEQABCg0NAQYUAAEKDA0IAAEMDA0BCiUA
+AQsMDQEEFQABCgsNAQoLAAEKDA0IAAEJDA0BAhQAAQwMDQEKDgABDAwNFAAB
+CQwNAQk2AwEHCAYBBWcAPAMFBl8AAAARAAEMDQ0BAhQAAQkMDQgADQ0mAAEL
+DA0BBBUAAQYLDQEMCwABCgwNCAABCQwNAQIUAAEKDA0BCg4AAQwMDRQAAQkM
+DQEJOQMBBwgGYwABBzwDBQZgAAAAEQANDQEKFQABCQwNCAANDSYAAQsMDQEE
+FQABBAwNCwABCgwNCQAMDQECFAABBgwNAQoOAAELDA0UAAEJDA0BCTsDAQcI
+Bl8AAQU9AwUGYQAAABEADQ0BCRUAAQYMDQcAAQkMDQEMJgABCwwNAQQVAAEC
+DA0LAAEKDA0JAAwNAQIUAAEGDA0BCg4AAQsMDRQAAQkMDQEJPQMBBwcGAQRb
+AAECPgMFBmIAAAARAA0NAQYVAAEGDA0HAAEKDA0BCiYAAQsMDQEEFgAMDQEJ
+CgABCgwNCQAMDQEEFAABBAwNAQoOAAELDA0UAAEJDA0BCT8DAQcHBlgAAQU/
+AwUGYwAAABAAAQkNDQEEFQABBgwNBwABDAwNAQkmAAELDA0BBBYAAQsLDQEM
+CgABCQwNCQAMDQEGFAABAgwNAQoOAAELDA0UAAEJDA0BCUEDCAZUAAEHQAMF
+BmQAAAAQAAEJDQ0BAhUAAQYMDQcAAQwMDQEEJgABCwwNAQQWAAEKDA0KAAEJ
+DA0JAAEMCw0BCRUAAQwLDQEKDgABCgwNFAABCQwNAQlCAwEHBwYBAk8AAQJC
+AwUGZQAAABAAAQoNDRYAAQYMDQcADQ0nAAELDA0BBBYAAQkMDQoAAQkMDQkA
+AQkLDQEMFQABDAsNAQoOAAEKDA0UAAEJDA0BCUQDCAZLAAECAQdDAwUGZgAA
+ABAAAQsMDQEMFgABBgwNBwANDScAAQsMDQEEFgABBgwNCgABCQwNCgAMDQEG
+FAABDAsNAQoOAAEKDA0UAAEJDA0BCUYDCAYBAkUAAQIBB0UDBQZnAAAAEAAB
+DAwNAQoWAAEGDA0HAA0NJwABCwwNAQQWAAEGDA0BCQkAAQkMDQoAAQwLDQEM
+AQITAAEMCw0BCg4AAQoMDRQAAQkMDQEJSAMJBkAAAQdIAwUGaAAAABAAAQwM
+DQEJFgABBAwNBwANDScAAQsMDQEEFgABBgwNAQoJAAEJDA0KAAEJDA0BChMA
+AQsLDQEKDgABCgwNFAABCQwNAQlKAwEHCQYBBTgAAQVKAwEHBQZpAAAAEAAB
+DAwNAQkWAAEEDA0HAA0NJwABCwwNAQQWAAEGDA0BCwkAAQkMDQsAAQwMDQEK
+EgABCwsNAQoOAAEKDA0UAAEJDA0BCU4DAQcKBgEFBwAAAwYGBAAkAAEFAQdN
+AwEHBAYBAmoAAAAQAAEMDA0BBhYAAQQMDQcADQ0BDCALAQoFAAELDA0BBhYA
+AQQMDQEMCQABCQwNCwABCQ0NAQoBBBAAAQoLDQEKDgABCgwNFAABCQwNAQlS
+AwEHAQcHBgMHDAYBBAECFAAABAIGBgdSAwUGbAAAABAAAQwMDQEGFgABBAwN
+BwAvDQUAAQsMDQEGFgABBAwNAQwJAAEJDA0MAAEMDg0BCQECDgABCgsNAQoO
+AAEKDA0UAAEJDA0BCQEHWQMBBwgDAQcBBxYGAQcBB1gDBQZtAAAAEAABDAwN
+AQYWAAEEDA0HAC8NBQABCwwNAQYWAAEEDA0BDAkAAQkMDQ0AEA0ABQwJBgIC
+AAkAAQoLDQEKDgABCgwNFAABCQwNAAMJAAUA0gMFBm4AAAAQAAEMDA0BBhYA
+AQQMDQcALw0FAAELDA0BBhYAAQQMDQEMCQABCQwNDgATDQoMDA0BCg4AAQoM
+DRQAAQkMDQAECQAABc8DAQcEBgECbwAAABAAAQwMDQEGFgABBAwNBwAvDQUA
+AQsMDQEJFgABBgwNAQwJAAEJDA0PACgNAQoOAAEKDA0UAAEJDA0BCQMAAQID
+AwEHyQMFBnEAAAAQAAEMDA0BBhYAAQQMDQcALw0FAAELDA0BCRYAAQYNDQkA
+AQkMDRAAAQwmDQEKDgABCgwNFAABCQwNAQkEAAAFAgMDAAIAxwMFBnIAAAAQ
+AAEMDA0BBhYAAQQMDQcALw0FAAELDA0BChYAAQYNDQkAAQkMDREAAQolDQEK
+DgABCgwNFAABCQwNAQkFAAEFAQMDAMQDAQcEBnQAAAAQAAEMDA0BBhYAAQIM
+DQcALw0FAAELDA0BChYAAQYNDQkAAQkMDRMAAQwjDQEKDgABCgwNFAABCQwN
+AQkLAMIDAQUEBnUAAAAQAAELDA0BBhYAAQIMDQcADQ0WDAwNBQABCwwNAQwW
+AAEJDQ0JAAEJDA0VAAEJAQwgDQEKDgABCgwNFAABCQwNAQkMAAEHuAMAAwcG
+BwADAwEHAQADBgECdgAAABAAAQoMDQEJFgABAgwNBwANDRUCAQYMDQUAAQsM
+DQEMFgABCgwNAQwJAAEJDA0YAAADCQsMABwNAQoOAAEKDA0UAAEJDA0BCQ0A
+AQe2AwMGAwMBAgEAAwZ4AAAAEAABCQwNAQkWAAECDA0HAAEMDA0VAAEEDA0F
+AAELDA0BDAECFQABDAwNAQwJAAEJDA0eAAAECQkKCgMLAAYKCgkJAgAMDQEK
+DgABCwwNFAABCQwNAQkPALMDAQcDBgAHAwMHAAAGBgB6AAAAEQAMDQEKFgAB
+AgwNBwABCwwNAQIUAAEEDA0FAAELDQ0BBBUADQ0BDAkAAQkMDSsAAQwLDQEK
+DgABCwwNFAABCQwNAQkQAAEHsAMEBgEHAQMDAAEGAQV7AAAAEQAMDQEMFgAB
+AgwNBwABCgwNAQIUAAEEDA0FAAELDQ0BBhQAAQINDQEMCQABCQwNKwABDAsN
+AQoOAAELDA0BBBMAAQoMDQEJEQABAq0DAQcEBgEHAQcDAAEGfQAAABEADQ0W
+AAECDA0HAAEGDA0BAhQAAQQMDQUAAQsNDQEJFAABBA0NAQwJAAEKDA0rAAEM
+Cw0BCg4AAQsMDQEJEwABCgwNAQkTAAEHqgMFBgEHgwAAABEAAQwMDQECFQAB
+AgwNCAAMDQEEFAABBAsNAQwFAAELDQ0BDBQAAQkNDQELCQABCgwNKwABDAsN
+AQoOAAEMDA0BChMAAQoMDQEJFQCoAwUGAQKEAAAAEQABCgwNAQYVAAECDA0I
+AAwNAQYUAAEGCw0BDAUAAQsODQECEwABCg0NAQoJAAEKDA0rAAEMCw0BCw4A
+AQwMDQEMEwABCgwNAQkWAAEHpQMGBoUAAAARAAEJDA0BCRUAAQIMDQgAAQwL
+DQEJFAABBgsNAQsFAAELDg0BBhIAAQIBDA0NAQkJAAEKDA0rAAEMCw0BCw4A
+AQwMDQEMEwABCwwNAQkYAKQDBQaGAAAAEgAMDQEMFQABAgwNCAABCQsNAQoU
+AAEJCw0BCgUAAQsODQEKEgABBg4NCgABCgwNKwAMDQELDgABDA0NEwABDAwN
+AQkaAKEDBgaGAAAAEgANDQEEFAABAgwNCQALDQEMFAABCgsNAQkFAAELDg0B
+DAECEQABCw4NCgABCgwNKwAMDQELDgABDA0NEwANDQEJGwABAp8DBQaHAAAA
+EgABCwwNAQkUAAECDA0JAAEMCg0BDAECEwABDAsNBgABCw8NAQkQAAEEDg0B
+DAoAAQoMDSsADA0BCg4AAQwNDQEKEgANDQEJHQABB4kDAQcEBgEHDAMBBwMG
+igAAABMADA0BDAECEwABAgwNCQABCgsNAQYSAAECDA0GAAELDw0BDAECDwAB
+Cw4NAQoKAAELDA0qAAEJDA0BCg4ADw0SAA0NAQkfAAEHhgMEBgUAAQcGAwEH
+kAAAABMAAQwMDQEJEwABAgwNCgALDQEKEgABBgwNBgABCxANAQoOAAEGDw0B
+CQoAAQsMDQ4AAQkBAhoAAQsMDQEKDgAPDQEEEQANDQEJIQABB4IDBAafAAAA
+EwABCg0NAQQSAAECDA0KAAEMCw0BAhEAAQoLDQEKBgABCwsNAQwBDAQNAQkM
+AAEEAQwPDQsAAQwMDQ4AAAMMDQoAGQANDQEJDgAPDQEMEAABCg0NJAABB34D
+BAahAAAAFAANDQEMAQIRAAECDA0KAAEGCw0BCRAAAQIMDQcAAQsLDQEMAQkF
+DQEJCgABBgEMEA0LAAEMDA0OAAQNFwABCg0NDwAQDQEKDwAODSYAAQd5AwEH
+BAajAAAAFAABCg0NAQoBAhAAAQIMDQsAAQwLDQECDwABCQsNAQwHAAELCw0A
+AwwADAAFDQELAQQGAAECAQkRDQEJCwABDAwNDgAFDQELFQAODQ8AEQ0BCQ0A
+AQoODSgAAQd1AwEHAwYBBKUAAAAVAA4NAQsBAg8AAQQMDQsAAQkLDQEKDgAB
+BgwNAQoHAAELCw0AAwwACQAHDQAHDAkGBgkKDAASDQwADQ0NAAEKBw0BDAEG
+EQAPDQ8ADA0BDAELBA0BCQsAAQoPDSoAAQVxAwEHAwaoAAAAFQABCQ8NAQYB
+AgsAAQIBCQ0NDAABCwsNAQoMAAEEDQ0IAAELCw0AAwwAAAAfDQELDAANDQ0A
+Cw0BDAEJDAABDA8NAQoPAAwNAQwBAAYNAQkHAAECAQwPDQELLAABAmwDAQcD
+BgECqgAAABYAAQwPDQAHDAkEAgIAAAADAgADBgoMAA4NDQAMDQELAQQJAAEG
+AQwMDQEKCAABDAsNAAQMAAAKHg0NAA0NDAABBg4NAwwBCwMKAAMLDAwAEQ0P
+AAEGDA0AAwwACgAHDQAFDAwLCwwAEg0BCS8AaAMABAcGBgWtAAAAFwATDQUM
+Eg0NAAEJDQ0AAwoGAgADAAADAgYLAA4NCQABDAsNAQwDAAEMHA0BCgwAAQQN
+DQwAAQwoDQEMDwABCgwNAAMMAAAAHg0yAAEHYgMABAcGBgKwAAAAGAApDQ4A
+AQoiDQEJCQABDAsNAQwEABwNDQABCg0NDAApDRAAAQwMDQAEDAAACRwNAQw0
+AAEHXQMABAcGBgKzAAAAGAABCSgNDwABCiANAQsKAAEMCw0BDAQAAQoaDQ4A
+AQwNDQsAAQwoDQEJEAANDQEMAwABDBsNAQQ2AAECVwMBBwMGtwAAABkAAQQn
+DRAAAQseDQEMCwABDAsNAQwFAAEMGA0BAg4ADg0LAAEMJw0BDBAAAQkNDQEM
+BAAaDQEMOgABBykDAQcGBgAFAgAABQcAEQMBBwoDAAQHBgYFugAAABsAAQwl
+DREAAQkcDQEMDAABDAsNAQwGAAEMFg0PAA8NAQkMAAELJA0BChEADg0BDAUA
+GA0BDD0AAQUoAwkGBQABAgEHCAMBBwECAwAHAwAEBwYGBb0AAAAcAAEJJA0T
+AAEMGQ0BCg0AAQwLDQEMBwABCxMNAQwPAAELAQwODQEKDgABCgEMIA0BCREA
+AQwODQEMBgABDBUNAQxBACgDAAMHBgIAGAAEAwAEBwAGBcAAAAAeAAELIg0U
+AAEJFw0PAAEMCw0BDAgAAQoRDQEKFQAAAwkKDAAIDQEKEAABAgEMHA0BChYA
+AAMJCgsACQ0BDAcAAQoTDQEMRAABBxQDAQYBBwkDAAMHBwIAEgABBgsAAQMB
+B8YAAAAgAAEJAQwRDQADDAoMAAsNFwABCxENAQsRAAEMCw0BDAoAAQoNDQEK
+HQABCgEMAw0BDBQAAQoBDBUNAQsBCR4AAAMECgwAAw0BDAkAAQoPDQEMSAAB
+AhIDAQcHBgEFEQAABAcAAAIDBgEF0gAAACQAAQkBCwQMAQ0BDQMMAQsBCgQA
+AQsLDRoAAQoDDAYNAAMMDAoAFAABDAsNAQwNAAEKAwwBDQMMAQojAAADCgwN
+ABgAAAMCCQsABQwDDQQMAQoBCSYAAAMLDQwACwAABAYKDAwFDQAEDAwLCU0A
+AwMABQcAAAIHAAoDAQcHBgECDAABBQMHAQXYAAAANQABCwsNOwABDAsNAQw7
+AAEJUQABCmcAAQcBAggAAQcHAwAEAgAABQQG6AAAADUAAQsLDQEGOgABDAsN
+AQz/AAUAAQcBBwMDAQLtAAAANQABCwsNAQY6AAEMDA3/APgAAAA1AAELCw0B
+CToADQ3/APgAAAA1AAELCw0BCToADQ3/APgAAAA1AAELCw0BCToADQ3/APgA
+AAA1AAELCw0BCToADQ3/APgAAAA1AAELCw0BCjoADQ3/APgAAAA1AAEMCw0B
+CjoADQ3/APgAAAA1AAEMCw0BCjoADQ0zAAEDAQP/AMMAAAA1AAEMCw0BCzoA
+DQ0yAAQD/wDCAAAANQABDAsNAQw6AA0NMQAGA/8AwQAAADUAAQwLDQEMOQAB
+CQ0NMAAIA/8AwAAAADUADA0BDDkAAQoNDS8ACgP/AL8AAAA1AA0NOQABDA0N
+LgAMA/8AvgAAADUADQ05AA4NLQAOA/8AvQAAADQAAQoNDTkADg0BBisAEAP/
+ALwAAAA0AAEMDQ04AAELDg0BCSoAEgP/ALsAAAA0AA4NOAAPDQEJKQAUA/8A
+ugAAADMADw03ABANAQopABQD/wC6AAAAMgABCQEMDg02AAAECQsMDA0NAQoq
+ABID/wC7AAAANgAAAwYKDAAJDTwAAQkBDAkNAQsrABAD/wC8AAAAOwABAgEK
+BQ0BBj8AAQkBDAUNAQwsAA4D/wC9AAAAPwAABAsNDQlCAAAFCQwNDQwALQAM
+A/8AvgAAAEEAAQkBCkUAAQwBDC4ACgP/AL8AAAC5AAgD/wDAAAAAugAGA/8A
+wQAAALsABAP/AMIAAAC8AAEDAQP/AMMAAAD/AP8AggAAAP8A/wCCAAAA/wD/
+AIIAAAD/AP8AggAAAP8A/wCCAAAA/wD/AIIAAAD/AP8AggAAAP8A/wCCAAAA
+/wD/AIIAAAE=
+====
diff --git a/images/debianlilo_16c.dat b/images/debianlilo_16c.dat
new file mode 100644 (file)
index 0000000..d9e0fa3
--- /dev/null
@@ -0,0 +1,14 @@
+# Lilo boot menu background configuration  (Lilo 23)
+#
+# color palette: 0 black,         3 magenta,       7 pink,
+#                8 middle grey,  10 bright grey,  13 white
+#
+# bmp-table  = <x>,<y>;<ncol>,<nrow>,<xsep>,<spill>
+# bmp-colors = <fg>,<bg>,<sh>;<high-fg>,<high-bg>,<high-sh>
+# bmp-timer  = <x>,<y>;<fg>,<bg>,<sh>
+
+bitmap = debianlilo.bmp
+
+bmp-table  = 106p,144p;2,9,144p
+bmp-colors = 1,,0;9,,0
+bmp-timer  = 514p,144p;6,8,0
diff --git a/images/debianlilo_16c.uu b/images/debianlilo_16c.uu
new file mode 100644 (file)
index 0000000..39d22b3
--- /dev/null
@@ -0,0 +1,704 @@
+begin-base64 644 debianlilo.bmp
+Qk1cewAAAAAAADYEAAAoAAAAgAIAAOABAAABAAgAAQAAACZ3AAAgHAAAIBwA
+AAABAAAAAQAAAAAAAAAAiAAAiAAAAIiIAIgAAACIAIgAiIgAALu7uwCIiIgA
+AAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8P
+/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8A
+AP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/D/8P
+gg8AAP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//DysPCgdN
+DwAA/w//DyUPAAQHBwgFBgkABAgIBwdPDwAA/w//DyIPAQcBCAYJAAMIBwcA
+VQ8AAP8P/w8fDwEHAQgGCQEIAQdZDwAA/w//DxwPAQcBCAcJAQhcDwAA/w//
+DxoPAQcBBQcJAQUBB10PAAD/D/8PGA8BBwEFCAkBBV8PAAD/D/8PFg8BBwEF
+CQkBBWAPAAAxDwcHTw8BBwEHDwgBBwEHIw8BBwEHDwgBBwEHYw8IB9cPAQcB
+BQoJAQVhDwAALA8AAwcICAALAAEIAQcODwQIBAcIDwQHAQgBCCIPAAMHCAgA
+GAAABAgIBwcVDwAEBwcICBgAAAMICAcAKQ8ABAgIBwcSDwADBwgIABgPAQcB
+CAwAAQgBBxIPBAgEBwYPBAcDCA4PAAQICAcHDg8BBwEHAwgYDwADCAgHABAP
+AAUHBwgIBwBWDwEICQkAAwUIBQBiDwAAKg8BCBIAAQgBBwsPFQABCB4PAQcB
+CCIAAAMICAcADQ8AAwcICAAhAAEIAQgmDwEICQAHCAcAAQgVDwEHAQgSAAEI
+AQcPDxQAAQcODxYAAQgYDwcABwgJAAEHVA8BBwkJAAQFBw8HYw8AACgPAQgW
+AAEICQ8BBxUAHA8BBwEIKAAKDwEIAQgoAAEIAQckDxcAAQcTDwEHAQgXAAEH
+DQ8TAAEIDw8BCBUAAQcYDwEIFgBUDwEICQkBB2cPAAAmDwEHGgABBwcPAQcU
+AAEIGg8BBwEIKgAHDwEIAQguAAEHIg8BCBYAEw8BCBoAAQgBBwoPAQcTAAEH
+Dw8BBxUAGQ8BBxUAAQhSDwEHCQkBBQEHaA8AACUPAQgcAAEIBg8BBxQAAQgY
+DwEHLQAHDzIAAQcgDwEIFQABCBIPAQgdAAEHCQ8BBxMAEQ8VABoPFQABB1EP
+AQgICQEIAQdqDwAAIw8BBx8AAQgFDwEHFAABBxcPAQguAAcPAQgyAAEIHw8B
+BxUAAQcRDwEIHwABCAgPAQcSAAEIEQ8BCBMAAQgaDxUAUA8BBwEFCAkBBWwP
+AAAiDwEHIQABCAQPAQcUABYPAQcwAAEHBg8BBzQAAQceDxUAEQ8BCCEAAQgH
+DwEIEgABBxEPAQgTAAEIGg8BCBQATw8BBwsJAQhrDwAAIQ8BByMAAQgDDwEH
+EwABCBUPAQgxAAEHBw81AAEIHQ8VABAPAQgjAAEIBg8BCBIAEg8BCBMAAQga
+DwEIEwABCE4PAQcLCQEHbA8AACAPAQclAAAEBw8PBxMAAQgUDwEIMgABBwcP
+NgABCBwPAQgTAAEIDw8BByUAAQcFDwEIEgASDwEHEwABBxoPAQgTAAEITQ8B
+CAoJAQVuDwAAIA8mAAAECA8PBxMAAQcSDwEHNAABCAcPAQg2AAEIGw8BCBMA
+AQgPDycAAQcEDwEIEQABCBIPAQcTAAEHGg8BCBMAAQhMDwEFCgkBCG8PAAAf
+DwEIJwAAAwcPBwATABMPNQABCAcPAQg3AAEIGg8BCBMAAQcODwEIKAAEDwEI
+EQABCBIPAQcTAAEHGg8BBxMAAQhLDwEFCgkBCHAPAAAeDwEIKQABDwEHEwAS
+DzYAAQgHDwEIFAADCAEHBw8AAwcICAAWAAEIGQ8BCBMAAQcNDwEHKQABCAMP
+AQgRAAEIEw8TABsPAQcTAAEHSg8BBQoJAQVxDwAAHQ8BByoAAQcBBxMAEQ8B
+CDcABw8BCBMAEA8BBwEIFAABCBgPAQcTAAEHDQ8BCCoAAAQHDw8IEQABCBMP
+EwAbDwEHEwABB0kPAQUICQAEBQgIB3EPAAAdDysAAQgBBxIAAQgQDwEIHQAD
+CAEHCQ8ABAcHCAgKAAcPAQcTABMPAQgTAAEIFw8BBxMADg8rAAAECA8PCBEA
+AQcTDxMAGw8BBxMAAQdIDwEFCAkBBXUPAAAcDwEILAABCBIAAQgPDwEHGwAB
+CAEHFA8BBwEIBgABBwYPAQcTABQPAQcTAAEHFg8BBxMADQ8BCCwAAAMHDwgA
+EQABBxMPEwAbDwEHEwABB0cPAQUJCQEHdQ8AABwPQAABCA8PGgABBxoPAQgE
+AAEIBg8BBxMAFg8BCBIAFw8TAA0PGgAGCA0AAAMIDwgAEQABBxMPEwAcDxMA
+Rw8BBQkJAQd2DwAAGw8BCBoAAQgBBwYPAQcBCBwAAQcODwEIGAABBx4PAAQI
+AAAIBg8BBxMAFw8BCBEAAQgWDxMADA8BBxcAAQgBBwkPAQgLAAEHAQgRAAEH
+Ew8TABwPEwBGDwEFCQkBBXcPAAAbDxkAAQgMDwEHGgABBw0PAQcXAAEIIg8B
+CAEIBw8TABgPAQgRAAEHFQ8TAAwPAQgWAAEHDQ8BCAkAAQgBCBEAAQcTDxMA
+HA8TAEUPAQgKCQEHdw8AABoPAQcXAAEIEA8BCBgADg8BCBYAAQcsDxMAGQ8S
+ABUPEwAMDwEIFAABCBEPAQgIAAEIEQABBxMPEwAcDxMARA8BCAoJAQV4DwAA
+Gg8BCBYAAQgSDwEIFwANDwEHFgABBy0PEgABCBkPAQcRAAEIFA8TAAwPFAAB
+CBMPAQgZAAEHEw8TABwPEwBDDwEHCgkBCAEHeA8AABkPAQcWAAEIFA8XAA0P
+AQgVAAEHLg8SAAEIGg8BCBEAFA8SAAEIDA8UAAEHFA8BCBgAFA8TABwPEwBC
+DwEHCgkBCHoPAAAZDwEIFQABCBUPAQcWAAwPAQcVAAEHLw8SAAEIGw8RAAEI
+Ew8SAAEICw8BBxMAAQgWDwEIFwAUDxMAHA8TAEIPCgkBBXsPAAAZDxYAFw8B
+CBQAAQgMDwEIFAABCDAPEgABCBsPAQgRABMPEgABCAsPAQgTABgPFwAUDxMA
+HA8TAEEPAQUKCQEHew8AABgPAQcVAAEHFw8BBxQAAQgMDxQAAQgxDxIAAQgc
+DxEAAQgSDxIAAQgLDwEIEgABCBgPAQcWABQPAQgSABwPEwBADwEICgkBB3wP
+AAAYDwEIFAABCBkPFAABCAsPAQgUADIPEgABCBwPAQgRABIPEgABCAsPAQgS
+AAEHGQ8BCBUAFA8BCBIAHA8TAD8PAQcKCQEIfQ8AABgPAQgUAAEHGQ8BCBMA
+AQgLDwEIEwABCDIPEgABCB0PEQABBxEPAQgRAAEICw8BCBIAGg8BBxUAFA8B
+CBIAHA8TAD8PCwl+DwAAGA8UAAEIGg8BBxMAAQgLDxQAMw8SAAEIHQ8BCBAA
+AQgRDwEIEQABCAsPAQgSABsPAQgUABQPAQgSABwPEwA+DwEICgkBB34PAAAX
+DwEHFAABBxsPEwABCAoPAQcTAAEIMw8SAAEIHQ8BCBEAEQ8BCBEAAQgLDxIA
+AQgbDwEHFAAUDwEIEgAcDxMAPQ8BBwoJAQh/DwAAFw8BCBQAHA8TAAEHCg8B
+CBMANA8SAAEIHg8RAAEIEA8BCBEAAQgLDxIAAQgcDxQAFA8BCBIAHA8TAD0P
+CwmADwAAFw8BCBMAAQgcDwEIEgABBwoPEwABCDQPEgABCB4PAQgQAAEIEA8B
+CBEAAQgLDxIAAQgcDwEIEwAUDwEIEgAcDwEIEgA8DwEICgkBCIAPAAAXDxQA
+AQccDwEIEgABBwoPEwABBzQPEgABCB4PAQgRABAPAQgRAAEICw8SAAEHHA8B
+CBMAFA8BCBIAHA8BCBIAOw8BBwsJAQUBB38PAAAXDxQAHQ8BCBIAAQcJDwEH
+EwA1DxIAAQgeDwEHEQABBw8PAQgRAAEICw8SAAEHHA8BBxMAFA8BCBIAHA8B
+CBIAOw8BBQsJAQeADwAAFg8BBxMAAQgdDwEHEgABBwkPAQgSAAEINQ8SAAEI
+Hw8RAAEIDw8BCBEAAQgLDwEIEQABBx0PEwAUDwEIEgAcDwEIEgA6DwEHCwkB
+B4EPAAAWDwEIEwABCB0PAQcSAAoPAQgSAAEINQ8SAAEIHw8SAA8PAQgRAAEI
+Cw8BCBEAAQcdDwEIEgAUDwEIEgAcDwEIEgA6DwsJAQiCDwAAFg8BCBMAAQcd
+DwEHEgAKDxMAAQc1DxIAAQgfDwEIEQAPDwEIEQABCAsPAQgRAAEHHQ8BCBIA
+FA8BCBIAHA8BCBIAOQ8BCAsJAQWCDwAAFg8BCBMAHw8SAAoPEwA2DxIAAQgf
+DwEIEQABBw4PAQgRAAEICw8BCBEAAQcdDwEIEgAUDwEIEgAcDwEIEgA5Dw0J
+gg8AABYPFAAfDxIACQ8BBxMANg8SAAEIHw8BBxEAAQgODwEIEQABCAsPAQcR
+AAEIHQ8BBxIAFA8BCBIAHA8BCBIAOA8BCAwJAQeCDwAAFg8TAAEIHw8SAAkP
+AQgSAAEINg8SAAEIHw8BBxIADg8BCBEAAQgLDwEHEQABCB0PAQcSABQPAQgS
+ABwPAQgSADgPDAkBCIMPAAAWDxMAAQgfDxIACQ8BCBIAAQg2DxIAAQggDxIA
+Dg8BCBEAAQgMDxIAHg8SABQPAQgSABwPAQgSADcPAQgMCYQPAAAVDwEHEwAB
+Bx8PEgAJDwEIEgABCDYPEgABCCAPEgABBw0PAQgRAAEIDA8BCBEAHg8SABQP
+AQgSABwPAQgSADcPDAkBB4QPAAAVDwEHEwABBx8PEgAJDwEIEgABCDYPEgAB
+CCAPEgABBw0PAQgRAAEIDA8BCBEAAQgdDxIAFA8BCBIAHA8BCBIANg8BBwwJ
+hQ8AABUPAQcTACAPEgAJDxMAAQc2DxIAAQggDxIAAQgNDwEIEQABCAwPAQcS
+AB0PEgAUDwEIEgAcDwEIEgA2DwwJAAMIDwcAgw8AABUPAQgTACAPEgAJDxMA
+AQc2DxIAAQggDwEIEQABCA0PAQgRAAEIDQ8SAAEHHA8SABQPAQgSABwPAQgS
+ADUPAQcMCQADBwUIAIMPAAAVDwEIEwAgDxIACQ8TAAEHNg8SAAEIIA8BCBIA
+DQ8BCBEAAQgNDwEIEgAcDwEIEQAUDwEIEgAcDwEIEgA1DwEFDAkAAwUJBwCD
+DwAAFQ8BCBIAAQggDxIACQ8TAAEHNg8SAAEIIA8BCBIADQ8BCBEAAQgNDwEH
+EgABCBsPAQgRABQPAQgSABwPAQgSADQPAQcOCQEIhA8AABUPAQgSAAEIIA8S
+AAkPEwABBzYPEgABCCAPAQgSAA0PAQgRAAEIDg8BCBIAAQgaDwEIEQAUDwEI
+EgAcDwEIEgA0DwEIDgkBB4QPAAAVDwEIEgABCCAPEgAJDxMAAQc2DxIAAQgg
+DwEIEgABBwwPAQgRAAEIDg8BBxMAAQgZDwEIEQAUDwEIEgAcDwEIEgA0Dw4J
+AQiFDwAAFQ8BCBIAAQggDxIACA8BB0IAAQgHDxIAAQggDwEIEgABBwwPAQgR
+AAEIDw8BCBMAAQgBBxcPAQgRABQPAQgSABwPAQgSADMPAQcNCQEFOg8ABQcH
+CAgFAAMJAAQFBQgHQA8AABUPAQgSAAEIIA8SAAgPAQdDAAcPEgABCCAPAQgS
+AAEHDA8BCBEAAQgPDwEHFQABCBYPAQgRABQPAQgSABwPAQgSADMPAQgMCQEI
+OA8ABgcICQkFCAUHRA8AABUPAQgSAAEIIA8SAAgPAQdDAAcPEgABCCAPAQgS
+AAEIDA8BCBEAAQgQDwEIFgABCAEHEw8BCBEAFA8BCBIAHA8BCBIAMw8KCQEI
+AQc3DwAGBwgJBQcHTA8AABUPAQgSAAEIIA8SAAgPAQdDAAcPEwAgDwEIEgAB
+CAwPAQgRAAEIEQ8BCBgAAAMICAcADw8BCBEAFA8BCBIAHA8TADIPAQcJCQEI
+Nw8ABQcJCQgHAE8PAAAVDwEIEgABByAPEgAIDwEHQwAHDxMAIA8BCBIAAQgM
+DwEIEQABCBIPHgAMCBIAFA8BCBIAHA8TADIPAQgJCTYPAQcDCQEHBQ8DBwAG
+CAgFBQkJAwUABAgIBwc8DwAAFQ8BCBIAAQcgDxIACA8BB0MABw8TACAPAQgS
+AAEIDA8BCBEAAQgTDzsAFA8BCBIAHA8TADIPCQkBBzQPAQcDCQEFAw8AAwcI
+BQASCQADBQcHADgPAAAVDwEIEgABByAPEgAIDwEHQwABBwYPEwAgDwEIEgAB
+CAwPAQgRAAEIFA86ABQPAQgSABwPEwAxDwEHCQkzDwAFBwUJCQgAAwcBBRoJ
+AQgBBzUPAAAVDwEIEgABByAPEgAJD0MAAQcGDxMAIA8BCBIAAQgMDwEIEQAB
+CBUPAQg4ABQPAQgSABwPEwAxDwEHCAkBCDIPAAcHCQkIDw8HAB8JAQUBBzMP
+AAAVDwEIEgABByAPEgAJD0MAAQcGDxMAIA8BCBIAAQgMDwEIEQABCBYPAQg3
+AAEHEw8BCBIAHA8TADEPAQgICQEHMQ8ABwgICQcPDwcADgkEBRAJAQUBBzEP
+AAAVDwEIEgABByAPEgAJD0MAAQcGDxMAAQcfDwEIEgABCAwPAQgRAAEIFw8B
+BwEINQABBxMPAQgSABwPEwAxDwkJAQcvDwAEBwgHBQMPAQcKCQADCAcHAAgP
+AAMHBwUADQkBBQEHLw8AABUPAQgSAAEIIA8BCBEACQ9DAAEHBg8TAAEHHw8B
+CBIAAQgMDwEIEQABCBkPAQc0AAEHEw8BCBIAHA8TADAPAQcJCQEHLg8ABAcI
+BwgDDwEICAkBCAEHDw8ABAcIBwULCQEILg8AABUPAQcSAAEIIA8BCBEACQ9D
+AAEHBg8TAAEHHw8TAAEIDA8BCBEAAQgbDwEHAQgxAAEHEw8BCBIAHA8TADAP
+AQcJCSsPAAcHDw8HCAcHAAMPAQUHCQEIFw8BBwsJAQcsDwAAFQ8BBxIAAQgg
+DwEIEQAJDxMAHggSAAEHBg8TAAEIHw8TAAEIDA8BCBEAAQgdDwEHAQgvAAEH
+Ew8BCBIAHA8TADAPAQgICQEIKg8ACggPDwcIDwcPDwcHCQEIGw8BCAoJAQgr
+DwAAFQ8BBxIAAQggDwEIEQAJDwEIEgAeDwEIEQABBwYPEwABCB8PEwABCAwP
+AQgRAAEIIA8AAwcICAArAAEHEw8BCBIAHA8TADAPAQUICQEHKQ8ACgcHDwcF
+DwcPDwcGCQEFAQcdDwEICgkBBSoPAAAWDxIAAQggDwEIEQAJDwEIEgAeDwEI
+EQABBwYPEwABCB4PAQcTAAEIDA8BCBEAAQglDwEHAwgSAAEIEgABBxMPAQgS
+ABwPEwAwDwkJAQcoDwAFBwUPDwUABA8BBwYJAQggDwADCAcHAAgJAQUpDwAA
+Fg8SAAEIIA8BCBEACQ8BCBIAHg8BCBEAAQcGDxQAHg8BBxMAAQgMDwEIEQAB
+CC4PBwcHDxIAAQcTDwEIEgAcDxMAMA8JCQEHKA8ABAUHDwgEDwEHBgkBByIP
+AAQHDwcFCAkBBycPAAAWDxMAIA8BCBEACQ8BBxIAHg8BCBEAAQcGDxQAHg8B
+CBMAAQgMDwEIEQABCDwPEgABBxMPAQgSAAEHGw8TAC8PAQcJCQEHJw8ABQgH
+DwcHAAMPAQcGCQEHJw8BCAgJAQcmDwAAFg8BCBIAIA8BCBEACQ8BBxIAHg8B
+CBEABw8UAAEHHQ8BCBMAAQgMDwEIEQABCDwPEgABBxMPAQgSAAEHGw8TAC8P
+AQcJCQEHJg8BBwEFBg8BBwYJAQcpDwEHCAkBByUPAAAWDwEIEgAgDwEIEQAK
+DxIAHg8BCBEABw8UAAEIHQ8UAAEHDA8BCBEAAQg8DxIAAQcTDwEIEgABBxsP
+EwAvDwEHCQknDwEFAQcDDwADBw8HAAYJAQcrDwEHCAkBBwEIIw8AABYPAQgS
+AAEHHw8BCBEACg8SAAEHHQ8BCBEABw8UAAEIHQ8UAAEHDA8BCBEAAQg8DxIA
+AQcTDwEIEgABCBsPEwAvDwEICAkBBycPAQgDDwAEBw8PBQUJAQctDwEHCAkB
+CAEHIg8AABYPAQcSAAEIHw8BCBEACg8BCBEAAQcdDwEIEQAHDxUAHA8BBxQA
+DQ8BCBEAAQg8DxIAAQcTDwEIEgABCBsPEwAvDwEICAksDwADCA8IAAUJAQgv
+DwEHAQUHCSMPAAAXDxIAAQgfDwEIEQAKDwEIEQABBx0PAQgRAAcPFQAcDwEI
+FAANDwEIEQABCDwPEgABBxMPAQgSAAEIGw8TAC8PAQUHCQEFKw8AAwcPBwAF
+CQEFMg8BBQYJAQciDwAAFw8TAB8PAQgRAAoPAQcRAAEIHQ8RAAEIBw8VAAEH
+Gw8BCBQADQ8BCBEAAQg8DxIAAQcTDwEIEwAbDxMALw8BBQcJAQgrDwEHAQ8G
+CQEHFA8ABAcHCAgbDwEFBQkBByIPAAAXDwEIEgABBx4PAQgRAAsPEQABCB0P
+EQABCAcPFQABCBsPFAABCA0PAQgRAAEIPA8SAAEHEw8BCBMAGw8TAC8PAQUH
+CQEHLA8BBwUJAQgTDwEHBQkBBRsPBgkAAw8PBwAfDwAAFw8BBxIAAQgeDwEI
+EQALDxIAHQ8RAAEIBw8WABoPAQgUAAEIDQ8BCBEAAQg8DxIAAQcTDwEIEwAB
+BxoPEwAvDwgJAQcsDwYJGg8BBwEHGg8BCAUJAAMIDwUAHw8AABgPEwAeDwEI
+EQALDwEIEQAcDwEHEQABBwcPFgABBxkPFQABCA0PAQgRAAEIOw8BBxIAAQcT
+DwEIEwABCBkPAQcTAC8PCAkBBysPAQcFCQEHNg8BCAYJAAMFCQcAHg8AABgP
+EwABBx0PAQgRAAsPAQcRAAEHGw8BBxEAAQcHDxcAGA8BBxUAAQcNDwEIEQAB
+CDsPAQcSAAEHEw8UAAEIGQ8BBxMALw8ICQEHKw8BBQUJNw8BCAgJAQgeDwAA
+GA8BCBIAAQgdDwEIEQAMDxEAAQgbDwEIEQAIDxcAAQcXDwEIFQAODwEIEQAB
+CDsPAQgSAAEHEw8VABkPAQgTAC8PCAkBByoPAQcFCQEINw8BBwkJHg8AABgP
+AQcTAB0PAQgRAAwPAQgQAAEIGw8BCBEACA8YABYPAQcWAA4PEgABCDsPAQgS
+AAEHEw8VAAEHGA8BCBMALw8ICQEHKg8BBwUJAQckDwEHAQcSDwEFCAkBBx0P
+AAAZDxMAAQgcDwEIEQAMDwEHEQAbDxEAAQgIDxgAAQgVDxYAAQgODxIAAQgT
+DwEHAQgmDxMAFA8VAAEIGA8BCBMALw8BBQcJAQcqDwEFBQkkDwAEBwcFBxIP
+AQcBBQcJBQ8BBxcPAAAZDwEIEwAcDwEIEQANDxEAAQcZDwEHEQABBwgPGQAB
+BxMPAQgWAAEHDg8SAAEIEw8AAwgACAAkDwEHEwAUDxYAAQcXDxQALw8BBQcJ
+AQcqDwUJAQgkDwAEBwcPBxMPAQcHCQEHBA8BBxcPAAAaDxMAAQgbDwEIEQAN
+DwEIEAABCBkPAQgRAAkPGgASDwEHFwAPDxIAAQgTDwEIAwABByIPAQgTABQP
+FgABCBYPAQcUAC8PAQUHCQEHKg8FCQEHJQ8ABAcPDwcTDwEFBwkEDwEHFw8A
+ABoPAQgTAAEHGg8BCBEADg8RAAEHGA8SAAkPEgABCAgAEA8BBxcAAQgPDxIA
+AQgTDwUAAQghDxMAAQgUDxcAAQgVDwEIEwABCC8PCAkBBykPAQcFCQEHJg8A
+AwcPBwATDwEHBwkBBxsPAAAaDwEHFAABBxkPAQgRAA4PAQgQAAEIFw8BCBEA
+AQgJDxIAAQ8JAAEHDQ8BCBgAAQgPDxIAAQgSDwEHBwABBx4PAQgTAAEIFA8Y
+AAEHEw8BBxQAAQgvDwgJAQcpDwEHBQknDwEHFg8HCQEFBA8BBxYPAAAbDwEI
+FAABBxgPAQgRAA8PEQABBxYPEgABBwkPEgABDwEICQABCAoPAQcBCBkAEA8S
+AAEIEg8BCAgAAQgBBxsPAQgUAAEIEw8BBxkAAQcSDxUAAQgvDwgJAQcpDwEH
+BAkBBT4PAQgHCQQPAQcWDwAAGw8BBxUAAQcXDwEIEQAPDwEIEQAVDwEIEQAB
+CAoPEgABDwEHCwAACQgIBw8PBwcICAAaAAEIDw8BBxMAEg8MAAEIGA8BCBUA
+AQcTDwEHGgABBxAPAQgVAAEHLw8ICQEIKQ8BCAQJAQU+DwEHBwkABQcHDw8H
+ABYPAAAcDwEIFQABCBUPAQcSABAPEQABCBMPAQcSAAEICg8SAAADDw8IAC0A
+AQcPDwEHEwARDwEHDgABCAEHFA8BCBYAFA8BBxIAAQgBCAcAAQgNDwEHFwAB
+By8PCAkBCCkPAQgECQEIPw8HCQEIAw8BBxYPAAAdDxcAAQcRDwEHAQgTABAP
+AQgRAAEIEQ8BBxMACw8SAAADDw8HAC0AEA8BBxMAEQ8BCBEAAAQICAcHDA8B
+BwEIFwABCBQPAQgSAAEIAQcJAAEIAQcIDwEHAQgYADAPCAkBBSkPAQgDCQEF
+QA8HCQEIGg8AAB0PAQcYAAEIAQcLDwEHAQgWABEPAQgSAAEHDg8BCBMAAQgL
+DxIAAAQHDw8IKwABBxAPAQgTABEPGAAICBsAAQcUDwEIEgABCAEPDgABCAEI
+HAABCDAPCQkpDwEIAwkBBT8PAQcBBQYJAQgaDwAAHg8BCBoACAgaABIPEwAB
+CAEHCg8BBxUADA8SAAAEBw8PBysAEQ8BCBMAEA8BCDsAFQ8BCBIAAAMIDwgA
+KwABCDAPAQUICSkPAQgDCQEFPw8BBwEFBwkBBxkPAAAfDzwAEg8BBxUAAQgF
+BwEIAQgWAAEHDA8SAAEHAw8BCCkAAQcRDxQAEA87AAEHFQ8TAAADCA8PACsA
+MQ8BBQgJKQ8BBwQJPw8BBwgJAQgBBxgPAAAfDwEHOwATDwEIMQABCA0PEgAB
+BwQPKAABCBIPFAAPDwEHOwAVDwEHEwAABAgPDwcpAAEIMQ8BBQgJAQcoDwEH
+BAk/DwEHCAkBCAEFGA8AACAPAQc6ABQPAQgwAA4PEgABBwQPAQgnABIPAQcU
+AA8POwABBxUPAQgTAAEIAw8BCCgAAQcxDwEFCAkBBygPAQcECS0PAQgRDwEH
+CgkBBxcPAAAhDwEHOQAVDwEILgABBw4PEgABBwUPAQglABMPAQgUAA4PAQg6
+AAEIFg8UAAEIBA8nAAEIMg8BBQgJAQcoDwEHBAkBBysPAQcBBRIPCgkBBxcP
+AAAiDwEHOAAWDwEILAABCA8PEgABBwYPJAABBxIPAQcVAA4PAQg5AAEIFg8B
+BxQAAQgEDwEHJgABBzIPAQUICQEHKQ8BCAMJAQgrDwEHAQgSDwoJAQgXDwAA
+JA8BCDYAAQcWDwEIKgABCBAPEgABBwcPIgABBxMPFgABBw8PAQg2AAEIFw8B
+CBQAAQgFDwEHJAABCDMPAQUICQEIKQ8BBwMJAQUsDwEHEg8LCRcPAAAlDwEI
+NQABBxcPAQcoAAEHEQ8SAAEHCA8gAAEHEw8BCBYAAQcRDwEIMwABCBcPAQgV
+AAEIBg8BByIAAQg0DwEFCAkBBSoPAQUDCT8PCwkBBxYPAAAmDwEHNAABBxkP
+AQglAAEHEg8SAAEHCQ8BCBwAAQgUDwEIFwABCBMPAQcBCC8AAQcXDwEIFgAB
+CAcPAQcgAAEINQ8BBQgJAQUqDwEHAwkBBz4PCwkBBRYPAAAoDwEIMgABBxoP
+AQciAAEIFA8SAAEHCg8BCBoAAQgYDwEHAQcECA8AAQgVDwEHAQgrAAEIGQ8B
+BwUIEQABCAkPAQgdAAEINg8BBQkJKw8DCQEFPg8MCRYPAAAqDwEHAQgvAAEH
+HA8BBwEIHQABCBYPEgABBwsPAQcBCBYAAQgiDwEHAwgJAAEIGA8AAwcICAAl
+AAEIJA8ABAcHCAgKAAEICg8BBxoAAQgBBzcPCgkrDwEIAwkBBz0PCgkBCBcP
+AAAsDwEHAQgaAAEIAQgRAAEHHg8BBwEIGQABCBgPEgABBw0PAQcBCBIAAQgB
+BygPAQcBCAcAHA8BBwEIHwABCAEHKw8AAwcICAAGAAEIDA8BBxYAAQgBBzgP
+AQcKCQEHKg8BBwMJAQU9DwoJAQcXDwAAMA8AAwcICAAQAAADCAgHAAMPAQcR
+AAEHIQ8AAwcICAARAAADCAgHABoPEgABBxAPAQgBCAwAAQgBBy4PAQcBCAQA
+IA8ABAcHCAgUAAADCAgHADMPAQgBCAMAAQgODwADBwgIAA8AAQgBCDwPCgkB
+CCsPAQUDCQEHPA8KCQEHFw8AADUPBAcECAMHCQ8BBxEAAQcmDwEHAQcJCAEH
+AQcfDxIAAQcUDwEHAQcECAEHAQc1DwAEBwgABycPBAcGCAMHOw8ABAcIAAgS
+DwEHAQcJCAEHQA8BCAoJKw8BBwQJPA8KCRgPAABJDwEHEQABB1IPEgABB1MP
+AQcBB3EPAQcBCF4PAQcKCQEIKw8BBQMJAQg7DwoJGA8AAEkPAQcRAAEHUQ8B
+BxIAAQf/DygPCwksDwEFAwkBBzoPCgkBBxcPAABJDwEHEQABB1EPAQcSAAEH
+/w8oDwEICgkBCCwPAQUDCQEHOQ8KCQEIFw8AAEkPAQcRAAEIUQ8BBxIAAQf/
+DygPAQcLCQEHKw8BBwQJAQc3DwEHCgkYDwAASQ8BBxEAAQhRDwEHEgABB/8P
+KQ8LCQEILA8BCAQJAQc2DwEICQkBBxgPAABJDwEHEQABCFEPAQcSAAEI/w8p
+DwEICwkBBywPAQUECQEIHQ8BBxcPAQUJCQYPAQcSDwAASQ8BBxEAAQhRDwEH
+EgABCP8PJQ8BBwMPAQcLCQEILQ8FCQEFAQcaDwEHGA8BBQgJAAMFDwcABA8B
+BxIPAABJDwEHEQABCFEPAQcSAAEI/w8lDwEHAQcDDwwJAQcsDwEHBgkBCBcP
+AQcBCBkPCQkAAwgIBwADDwEHEw8AAEkPAQcRAAEIUQ8BCBIAAQj/DyUPAQcB
+CAMPAQgLCQEILg8BBQYJAQgBBxIPAAMHBQgAGQ8BBwkJAAMFCQcAAw8BBxMP
+AABJDwEHEQABCFEPAQgSAAEI/w8mDwEFAw8BBwsJAQUvDwEIBwkAAwUHBwAM
+DwAFBwgJCQcAGg8BBwsJBA8BBxMPAABJDwEHEQABCFEPAQgSAAEI/w8mDwEH
+BA8BBQoJMQ8BBwEFCQkBBQEIBgcBCAEFAwkBCBwPAQgKCQEIAw8BBxQPAABJ
+DwEHEQABCFEPAQgSAAEISA8BCAEH4A8BBwoJAQgyDwEHAQUSCQEFAQcdDwsJ
+AQcDDwEHFA8AAEkPAQcRAAEIUQ8BCBIAAQhHDwAECAkJB+APCwkBBzMPAQcB
+CA4JAQgBBx4PAQcLCQEHAw8BBxQPAABJDwEIEQABCFEPAQgSAAEIRg8BCAQJ
+AQffDwEICwkBBzUPAAwHBwgFBQkJBQUIBwchDwEICwkABQcPDwcHABQPAABJ
+DwEIEQABCFEPEwABCEUPAQgGCQEH3g8BBwsJAQViDwoJAQUBCAMPAQgVDwAA
+SQ8BCBEAAQhRDxMAAQhEDwEICAkBB94PAQULCQEFYA8BBwkJAQgEDwEHAQgV
+DwAASQ8BCBIAUQ8TAAEIQw8BCAoJAQfdDwEHDAkBCF8PAQUJCQEHBA8BCAEI
+FQ8AAEkPAQgSAFAPAQcTAAEIQg8BCAwJAQfdDwEFDAkBCF0PAQcKCQUPAQkB
+CBUPAABJDwEIEgBQDwEHFABBDwEIDgkBB9wPAQcNCQEHXA8BBQoJBA8AAwgJ
+BwAVDwAASQ8TAFAPAQgUAEAPAQgQCQEH3Q8BBwwJAQdaDwEHCwkEBwAECQkH
+BxQPAABJDxMAUA8BCBQAPw8BCBIJAQfVDwEHBw8BCAwJAQdZDwEFDgkABQUJ
+CQUHABQPAABIDwEHEwBQDxUAPg8BCBQJAQfVDwEFBw8NCQEHVw8BBxIJAQUV
+DwAASA8BCBMATw8BBxUAPQ8BCBYJAQfUDwEFAQcGDwEIDQkBB1YPEwkBBxUP
+AABIDwEIEwABB04PAQgVADwPAQgYCQEH0w8BCAEIBg8BBw4JAQhUDwEIEwkW
+DwAARw8BBxQAAQdNDwEHFgA7DwEIGgkBB9sPAQUOCQEIUg8BBxMJAQgWDwAA
+Rw8BCBQAAQdNDwEIFgA6DwEIHAkBB9oPAQcPCQEFUQ8UCRcPAABGDwEHFQAB
+CEwPAQgXAAEHOQ8BBxsJAQUBB9sPEQkBB04PAQUTCQEIFw8AAEUPAQcWAAEI
+Sg8BBwEIGAABBzoPAQcZCQEF3Q8BBxEJAQhMDwEIFAkYDwAARQ8BCBYAAQhK
+DwEHAQcDCBUAAQc7DwEHFwkBBQEH3g8TCQEISQ8BBxQJAQcYDwAASA8BBwEH
+AwgPAAEIUg8AAwcICAAPAAEHPA8BBxUJAQUBB98PAQcUCQADBQgHAEQPAQcU
+CQEFGQ8AAE8PAAMHCAgACgABCFcPAQgBCAsAAQc9DwEHEwkBBeIPAQcUCQAD
+CAcHAEIPAQcVCQEHGQ8AAFMPAAMHCAgABwBaDwEHAQgIAAEIPg8BBxEJAQUB
+B+MPAQUUCQEHQg8BBxUJAQgaDwAAVw8BCAUAXQ8BBwEIBQABCD8PAQcPCQEF
+AQfkDwEHFQkBB0APAQcVCQEFGw8AAFkPAAQHCAAAYA8BCAMAAQhADwEHDQkB
+BQEH5g8BCBUJAQg+DwEHFgkBBxsPAABcDwEIAQdhDwADBwgIAEEPAQcLCQEF
+AQfoDwEFFQkBBQEHOw8BBxYJAQccDwAA/w8FDwEHCgkBB+oPFwkAAwUHBwA3
+DwEIFgkBBx0PAAD/DwYPAQcHCQEFAQfrDwEHGwkAAwUIBwAwDwEHAQUWCQEI
+Hg8AAP8PBw8BBwUJAQUBB+0PAQcaCQEIAwcuDwEHFwkBBR8PAAD/DwgPAQcE
+CQEH7w8BBwEFGgkBBQEHLA8BBwEFFwkBBSAPAAD/DwkPAAQICQUH8g8BBRwJ
+AQgoDwEHAQgYCQEFIQ8AAP8PCg8BBwEH9A8BBR0JAQckDwEHAQgZCQEFIg8A
+AP8P/w8AAw8PCAAdCQEFAQcfDwEHAQgbCQEFIw8AAP8P/w8DDwEIHgkAAwUH
+BwAYDwADBwcFAB0JAQgkDwAA/w//DwQPAQghCQAGBQgHBwUIBAcFDwQHAAMI
+CAUAIAkBByUPAAD/D/8PBQ8BB1UJAQcmDwAA/w//DwYPAAMHBwgAUAkBBSgP
+AAD/D/8PCQ8BCEsJAAQFBQkHKQ8AAP8P/w8KDwEHSQkABAcHBQcqDwAA/w//
+DwwPAQhFCQAEBQcPBywPAAD/D/8PDQ8BBwEFQwkwDwAA/w//Dw8PAQdBCQEH
+MA8AAP8P/w8RDwEINgkACQgHDwcHBQUIBwAxDwAA/w//DxMPAQgyCQEIAQc6
+DwAA/w//DxUPAQcuCQEIAQc8DwAA/w//DxcPAQcBBSgJAQgBBz8PAAD/D/8P
+GQ8BBwEFIwkBCAEHQg8AAP8P/w8bDwEHAQgQCQEHAw8DBwMIAAYHBwkJCAdF
+DwAA/w//Dx4PAQcBBQYJAQUGBwQPAQcGDwEHAQdIDwAAaA//Bx4HmQ8ACQcH
+DwcHCAUJBwAHDwEHAQdQDwAAYw//BygHnQ8BBwQPAQdTDwAAYg8EB/8IIggE
+B/UPAABiDwAEBwcICP8JIgkABAgIBwf1DwAAYg8AAwcHCAD/CSQJAAMIBwcA
+9Q8AAGIPAQcBCP8JJgkBCAEH9Q8AAGEPAAMHBwgABAmMCAQJjAgFCQADCAcH
+APQPAABhDwADBwcIAAMJAQgBCIoHAAYICAkJCAiKBwEIAQgECQADCAcHAPQP
+AABhDwADBwcIAAMJAQiMBwAECAkJCIwHAQgECQADCAcHAPQPAABhDwADBwcI
+AAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwAD
+BwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABh
+DwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQP
+AABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcH
+APQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQAD
+CAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAE
+CQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcH
+CAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8A
+AwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcH
+iA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJ
+CAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcH
+CAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8A
+CAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcA
+iA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMI
+BwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJ
+AAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcI
+AAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwAD
+BwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABh
+DwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQP
+AABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcH
+APQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQAD
+CAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAE
+CQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcH
+CAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8A
+AwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcH
+iA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJ
+CAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcH
+CAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8A
+CAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcA
+iA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMI
+BwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJ
+AAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcI
+AAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwAD
+BwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABh
+DwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQP
+AABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcH
+APQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQAD
+CAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAE
+CQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcH
+CAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8A
+AwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcH
+iA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJ
+CAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcH
+CAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8A
+CAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcA
+iA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMI
+BwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJ
+AAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcI
+AAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwAD
+BwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABh
+DwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQP
+AABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcH
+APQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQAD
+CAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAE
+CQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcH
+CAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8A
+AwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcH
+iA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJ
+CAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcH
+CAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8A
+CAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcA
+iA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMI
+BwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJ
+AAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcI
+AAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwAD
+BwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABh
+DwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQP
+AABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcH
+APQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQAD
+CAcHAK4PAQBFDwAAYQ8AAwcHCAADCQADCAcHAIgPAAgHBwgJCQgHB4gPAAMH
+BwgABAkAAwgHBwCuDwEARQ8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkI
+BweIDwADBwcIAAQJAAMIBwcAGg8EBwMPBAcDDwEHAQcPDwAIBwcPDwcHDwcD
+DwMHDg8BBwEHAw8BBwEHCA8BBwMPAwcBDwMHAQ8BBwMPAQcBBwMPAwcFDwYH
+AAQPDwcHAw8DBwEPAwcBDwMHAAQPDwcHAw8DBwYPAQcBBwMPAAMADwcABA8A
+AwcHDwADBwMPAAQHBw8PAwcBDwYHKA8AAGEPAAMHBwgAAwkAAwgHBwCIDwAI
+BwcICQkIBweIDwADBwcIAAQJAAMIBwcAGQ8ADwgACA8IAA8PCAgPCAgPCAAD
+AAoPABcHAA8PAAgHCAAACAAIDwAIBwAPDwcABwAJDwAIAAgHDwAIDwgGDwAR
+AAAICA8PAA8PBwAPBwAIDwgAAwADDwEAAQcFDwAIBwgPBwAIDwgDAAMPABMA
+Bw8PCAcPDwAHDwAACAgPDwcAAAYPAAoABwcIDw8AAAcAAw8AGAAIBw8ABw8P
+AAcHCA8PAA8PBwAPAAcPACcPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJ
+CAcHiA8AAwcHCAAECQADCAcHABgPAAMHAAcAAw8ACgcHDwgPDwgIBwADDwEH
+Bw8AAwgACAADDwALAA8PAAcPAAgPDwAAAw8ABwAPDwcIAAgABw8ACQAPDwgI
+Dw8IAAAEDwASAAgPDwcPDwAPDwcADwcIDwcAAw8ABQcPDwAHAAUPAAgHCA8A
+Bw8HAAMPAA8HDw8ABw8PCAcPDwAHCAAAAw8ABAcPBwAFDwAIAAcPDwAIDwAD
+DwAEAA8PAAMPABUABw8ABw8PAAgPAA8PBwAPCA8PAAcAJg8AAGEPAAMHBwgA
+AwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcAGA8BBwEABQ8A
+CQcPDwcIAAcHAAAJDwAECAAIBwQPAQADDwAHCA8ICA8PAAADDwEAAQcDDwAE
+BwAIBwUPAAkADw8ABw8PBwAABA8BAAYPAAsADw8HAA8HCA8HAAAGDwEAAQcF
+DwAIBwAICA8PBwAGDwAMAAcPDwgHDw8ABwgIBQ8BBwEABA8BBwEAAw8ABAgI
+DwADDwAEAAcPAAMPAAQABwcAAw8ADQgIDwAPDwcADw8IAAAAJw8AAGEPAAMH
+BwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcAGA8BBwEA
+BQ8ACQcPCAAHDw8HAAAECAQPAQgBAAcPAQAEDwAGCAAIDw8AAw8BAAEHBQ8A
+AwcABwAEDwAJAA8PAAcPDwcAAAQPAQAECAANDw8ADw8HAA8HCA8HAAAECAAE
+Dw8ABwUPAAMHAAAAAw8BBwEABAgADg8PAAcPDwgHDw8ABwgAAwgABAcPBwAE
+DwEHAQADDwAECAgPAAMPAAQABw8AAw8ABAAHBwADDwAMCAgPAA8PBwAPAAAH
+KA8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMI
+BwcAGA8BBwEABQ8ADQcPCAgPCAcPCA8PCAgABQ8ABAgACAcEDwAPAA8PBwgP
+CAgPDwAHDwgAAAQPAAQHAAgHBQ8ACQAPDwcIDw8ACAAEDwAbCAcPBwAPDwAH
+DwgADwcIDw8IDw8ICA8PAAgHAAQPAAQHCA8IAw8AGggPDwgIDw8ACAcPCAgP
+DwAHBwgPDwAHDwcABQ8ADwgHDw8ABw8ABw8IAA8PAAADDwAUAAcPCAcPDwAH
+DwAHDwgADwAPDwAnDwAAYQ8AAwcHCAADCQADCAcHAIgPAAgHBwgJCQgHB4gP
+AAMHBwgABAkAAwgHBwAYDwEHAQAFDwAMBw8PCAcABw8HAAgACA8AGwgACA8P
+BwAHDw8IBwAHDw8ABwAABw8PBwAABwAGDwAJBwAHDw8ICAAIAAYPABsACAAH
+DwgABwAABw8IAAcPBwAIAA8PCAAIAAcAAw8AIQcIDwAABw8HAAgADw8IAAgA
+CAAHAAAIDw8IAAAIDw8HAAAGDwAlCAcABw8IAAcAAAcPBwAHDwgABw8PCAcA
+Bw8IAAcAAAcPBwgIAAAnDwAAYQ8AAwcHCAADCQADCAcHAIgPAAgHBwgJCQgH
+B4gPAAMHBwgABAkAAwgHBwAYDwEHAQAFDwEHFQ8ABQcADw8IAAkPAQAFDwAD
+BwgHAAkPAQgaDwEIEA8BBwEIHQ8BBwEAEw8BCD4PAABhDwADBwcIAAMJAAMI
+BwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHABgPAQcBAAUPAQcZDwEH
+CQ8BABEPAQcaDwEHEA8BBwEIHQ8BBwEAEw8BBz4PAABhDwADBwcIAAMJAAMI
+BwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHABgPAAMIAAcAAw8BBwEI
+Ig8BCAEAPA8AAwcACAAcDwADBwAAABcPAQABBzkPAABhDwADBwcIAAMJAAMI
+BwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHABcPBAcDDwMHIg8BBz4P
+AQceDwEHFw8BBzoPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8A
+AwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcH
+iA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJ
+CAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8ACAcH
+CAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcAiA8A
+CAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMIBwcA
+iA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJAAMI
+BwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcIAAMJ
+AAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwADBwcI
+AAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAPQPAABhDwAD
+BwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHABcPBAcB
+DwEPBwcAAw8PBwAODwEHAQcDDwMHDg8BBwEHAw8BBwEHBw8DBwUPAQcBBwUP
+AQcEDwEHBQ8DBwQPAQcBBwMPAwcABA8PBwcEDwEHAQcEDwADBw8PAAMHAw8B
+BwMPBgdRDwAAYQ8AAwcHCAADCQADCAcHAIgPAAgHBwgJCQgHB4gPAAMHBwgA
+BAkAAwgHBwAYDwAQCAAHDw8HAAgPDwgIDwcACAkPABEICA8PAAAICA8PCAgP
+DwcABwAJDwAIAAgHDwAIDwgFDwAFBwAHCAgAAw8ADwAHBwgPDwgADwgPDwcA
+CAAEDwAXAAcPAA8PAAAICA8PBwAPDwAACAgPDwgAAwAAFg8PBwAIDwcADw8I
+AA8IDw8HCA8PCAhRDwAAYQ8AAwcHCAADCQADCAcHAIgPAAgHBwgJCQgHB4gP
+AAMHBwgABAkAAwgHBwAYDwEHAQAEDwAJAAcPDwgIDwcIAAcPAA8HCAAHDw8A
+CA8PBw8PCAgAAw8ABAcIAAgHDwAJAA8PCAgPDwgAAAQPAA8HCA8PCAAPAAcP
+DwAIBwAAAw8ABAAPBwgFDwAHCA8PAAcIAAADDwAHBw8HAA8IAAADDwADBwcA
+AAMPAAsHDwcIDw8HAA8HAAADDwAIAA8HCA8PCAhRDwAAYQ8AAwcHCAADCQAD
+CAcHAIgPAAgHBwgJCQgHB4gPAAMHBwgABAkAAwgHBwAYDwEHAQAEDwAJAAcP
+DwgIDwcIAAYPAAMIAAgABA8BAAYPAQgBCAUPAAQHAAgHBQ8ACQAPDwAHDw8H
+AAAEDwAIBwgPDwcABwADDwQIAw8ABAAHBwgGDwAGCAAADwgIBQ8ABQcADwgI
+AAQPAQcBAAUPAAkHCA8PBwAPCAgAAw8ACAAHBwgPDwgIUQ8AAGEPAAMHBwgA
+AwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcAGA8BBwEABA8A
+CQAHDw8ICA8HCAAFDwEAAQgGDwEABg8BCAEIBw8AAwcABwAEDwAJAA8PAAcP
+DwcAAAQPAAgHCA8PBwAHAAMPBAgDDwAEAAcHCAUPAAcAAAcPDwgAAAMIAAcH
+DwcADwgAAAMIAAMHBwgABQ8ACQcIDw8HAA8ICAADDwAIAAcHCA8PCAhRDwAA
+YQ8AAwcHCAADCQADCAcHAIgPAAgHBwgJCQgHB4gPAAMHBwgABAkAAwgHBwAY
+DwEHAQAEBwAJAAcPDwgIDwcIAAYPAAMIAAgABA8ACwgIDwgIDw8IAAcHAAMP
+AAQHAAgHBQ8ACQAPDwcIDw8ACAAEDwAWBwAPBwAADwgHDw8ABw8ADw8IAA8H
+CAUPADAADw8ADwcIDw8ABw8HAA8HCA8PAAcPAA8PAAcPBwgPDwcADw8ADw8I
+AA8HAA8PAAhRDwAAYQ8AAwcHCAADCQADCAcHAIgPAAgHBwgJCQgHB4gPAAMH
+BwgABAkAAwgHBwAYDwEHAQAEDwAKAAcPCAAIDwgABwcPAAMIAAcAAw8ADwAI
+AAcPCAAIAAgPBwAABwAGDwAJBwAHDw8ICAAIAAUPAAUHCAgAAAADDwAPCAcA
+Bw8PBwgIAA8PCAAHAAQPACoHCAgADw8IAAAIDw8HAA8PCAAACA8PBwAHAA8P
+CAAHBwAADw8HCAgADwcDCAEAAQBSDwAAYQ8AAwcHCAADCQADCAcHAIgPAAgH
+BwgJCQgHB4gPAAMHBwgABAkAAwgHBwAYDwEHAQAEDwEAAQcGDwEICg8BCAEI
+DA8AAwcIBwAJDwEIDA8BBwEIEw8BCBEPAQcBAA8PAQhjDwAAYQ8AAwcHCAAD
+CQADCAcHAIgPAAgHBwgJCQgHB4gPAAMHBwgABAkAAwgHBwAYDwEHAQAEDwEA
+AQcGDwEHJA8BBwwPAQcBCBMPAQcRDwEHAQAPDwEHYw8AAGEPAAMHBwgAAwkA
+AwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcAGA8ADAgABw8PBwAI
+Dw8ICDMPAAMHAAgAJA8AAwcAAAASDwEHAQBfDwAAYQ8AAwcHCAADCQADCAcH
+AIgPAAgHBwgJCQgHB4gPAAMHBwgABAkAAwgHBwAXDwQHAQ8BDwQHAAMPBwcA
+NQ8BByYPAQcTDwEHXw8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweI
+DwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkI
+BweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcI
+CQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCIDwAI
+BwcICQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCI
+DwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgH
+BwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkA
+AwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgA
+AwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMH
+BwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEP
+AAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcA9A8A
+AGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcA
+9A8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMI
+BwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJ
+AAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcI
+AAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwAD
+BwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweI
+DwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkI
+BweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcI
+CQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCIDwAI
+BwcICQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgHBwCI
+DwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkAAwgH
+BwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgAAwkA
+AwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcA9A8AAGEPAAMHBwgA
+AwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcAdA8sB1QPAABh
+DwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHAG8P
+NgdPDwAAYQ8AAwcHCAADCQADCAcHAIgPAAgHBwgJCQgHB4gPAAMHBwgABAkA
+AwgHBwBuDwQHMAgEB04PAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcH
+iA8AAwcHCAAECQADCAcHAG4PAAQHBwgIMAkABAgIBwdODwAAYQ8AAwcHCAAD
+CQADCAcHAIgPAAgHBwgJCQgHB4gPAAMHBwgABAkAAwgHBwBuDwADBwcIADIJ
+AAMIBwcATg8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcI
+AAQJAAMIBwcAbg8BBwEINAkBCAEHTg8AAGEPAAMHBwgAAwkAAwgHBwCIDwAI
+BwcICQkIBweIDwADBwcIAAQJAAMIBwcAbQ8AAwcHCAAECSwIBAkAAwgHBwBN
+DwAAYQ8AAwcHCAADCQADCAcHAIgPAAgHBwgJCQgHB4gPAAMHBwgABAkAAwgH
+BwBtDwADBwcIAAMJAQgBCCoHAQgBCAMJAAMIBwcATQ8AAGEPAAMHBwgAAwkA
+AwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMIBwcAbQ8AAwcHCAADCQEI
+LAcBCAMJAAMIBwcATQ8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweI
+DwADBwcIAAQJAAMIBwcAbQ8AAwcHCAADCQADCAcHACgPAAMHBwgAAwkAAwgH
+BwBNDwAAYQ8AAwcHCAADCQADCAcHAIgPAAgHBwgJCQgHB4gPAAMHBwgABAkA
+AwgHBwAaDwEHBAgBBwEPBQcBDwUHAQ8FBwEPAQ8FBwQPAQcBBwMIAQcBBwYP
+BAcHDwQIAQcBDwQHBA8BBwQIAQcEDwADBwcIAAMJAAMIBwcAKA8AAwcHCAAD
+CQADCAcHAE0PAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcH
+CAAECQADCAcHABkPAQcGAAEPBQABBwUAAQ8BCAQAAQcBBwQAAAQIDw8ICAAE
+DwEIBwAEDwsAAAQHDw8HBgAEDwADBwcIAAMJAAMIBwcAKA8AAwcHCAADCQAD
+CAcHAE0PAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAE
+CQADCAcHABkPBwABDwUAAQcFAAEPAQgEAAEHAQcEAAADCA8IAAkAAw8KAAAD
+Bw8IAAsAAAMHDw8ABwAEDwADBwcIAAMJAAMIBwcAKA8AAwcHCAADCQADCAcH
+AE0PAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQAD
+CAcHABkPBwABBwUAAQcFAAEPAQgEAAEHAQcEAAEIAQcFAAMIAAUAAA8PCAAL
+AAEPAQgLAAADBw8PAAcAAQcDDwADBwcIAAMJAAMIBwcAKA8AAwcHCAADCQAD
+CAcHAE0PAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAE
+CQADCAcHABkPBQADDwUAAQcFAAEPAQgEAAEHAQcEAAEIAQgEAAUPAAMHDw8A
+BQABDwEPBQABBwEIBAABCAEPBQAAAwcPDwAFAAYPAAMHBwgAAwkAAwgHBwAo
+DwADBwcIAAMJAAMIBwcATQ8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkI
+BweIDwADBwcIAAQJAAMIBwcAGQ8EAAEIAw8FAAEHBQABDwEIBAABBwEHBAAB
+CAEICwABDwUAAAMPDwcABAABBwEIBAAAAwcPBwAEAAADBw8PAAQAAQgGDwAD
+BwcIAAMJAAMIBwcAKA8AAwcHCAADCQADCAcHAE0PAABhDwADBwcIAAMJAAMI
+BwcAiA8ACAcHCAkJCAcHiA8AAwcHCAAECQADCAcHABkPBAABCAMPBQABBwUA
+AQ8FAAEHAQcEAAEIAQgEAAEIAQgFAAEPBQAAAw8PCAAEAAEHAQgEAAADBw8H
+AAQAAAMHDw8ABAABCAYPAAMHBwgAAwkAAwgHBwAoDwADBwcIAAMJAAMIBwcA
+TQ8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJAAMI
+BwcAFw8BCAEIBQAAAwgIDwAFAAEHEQABCAEHBAABBwEPBQABDwUAAQgBBwUA
+AQcBCAQAAAMHDwcABAAAAwcICAAFAAEIAQgEDwADBwcIAAMJAAMIBwcAKA8A
+AwcHCAADCQADCAcHAE0PAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcH
+iA8AAwcHCAAECQADCAcHABcPAQgIAAEPBQABBxEAAQgBDwoAAAMHDwcACwAB
+DwEIBAAAAwcPBwAEAAEHAQgIAAQPAAMHBwgAAwkAAwgHBwAoDwADBwcIAAMJ
+AAMIBwcATQ8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcI
+AAQJAAMIBwcAFw8BCAgAAQ8FAAEHEQAAAwcPBwAIAAEHAw8BCAkAAAMPDwgA
+BAAAAwcPBwAEAAEHAQgIAAQPAAMHBwgAAwkAAwgHBwAoDwADBwcIAAMJAAMI
+BwcATQ8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwADBwcIAAQJ
+AAMIBwcAFw8BCAgAAQ8FAAEHBAABCAUAAQcBCAQAAQgEDwEIBAABCAEHBQ8B
+BwYAAQgDDwEIBAAAAwcPBwAEAAEHAQgIAAQPAAMHBwgAAwkAAwgHBwAoDwAD
+BwcIAAMJAAMIBwcATQ8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweI
+DwADBwcIAAQJAAMIBwcAGQ8EAAEIAw8FBwQPAQcDDwEHAQcEDwEHAQcUDwQH
+FA8EAAEIBg8AAwcHCAADCQADCAcHACgPAAMHBwgAAwkAAwgHBwBNDwAAYQ8A
+AwcHCAADCQADCAcHAIgPAAgHBwgJCQgHB4gPAAMHBwgABAkAAwgHBwAZDwAF
+CAgAAAgAAw8FADwPAAUICAAACAAGDwADBwcIAAMJAAMIBwcAKA8AAwcHCAAD
+CQADCAcHAE0PAABhDwADBwcIAAMJAAMIBwcAiA8ACAcHCAkJCAcHiA8AAwcH
+CAAECQADCAcHAB0PAQcDDwUAQA8BBwYPAAMHBwgAAwkAAwgHBwAoDwADBwcI
+AAMJAAMIBwcATQ8AAGEPAAMHBwgAAwkAAwgHBwCIDwAIBwcICQkIBweIDwAD
+BwcIAAQJAAMIBwcAIQ8FCEcPAAMHBwgAAwkAAwgHBwAoDwADBwcIAAMJAAMI
+BwcATQ8AAGEPAAMHBwgAAwkBCIwHAAQICQkIjAcBCAQJAAMIBwcAbQ8AAwcH
+CAADCQEILAcBCAMJAAMIBwcATQ8AAGEPAAMHBwgAAwkBCAEIigcABggICQkI
+CIoHAQgBCAQJAAMIBwcAbQ8AAwcHCAADCQEIAQgqBwEIAQgDCQADCAcHAE0P
+AABhDwADBwcIAAQJjAgECYwIBQkAAwgHBwBtDwADBwcIAAQJLAgECQADCAcH
+AE0PAABiDwEHAQj/CSYJAQgBB28PAQcBCDQJAQgBB04PAABiDwADBwcIAP8J
+JAkAAwgHBwBvDwADBwcIADIJAAMIBwcATg8AAGIPAAQHBwgI/wkiCQAECAgH
+B28PAAQHBwgIMAkABAgIBwdODwAAYg8EB/8IIggEB28PBAcwCAQHTg8AAGMP
+/wcoB3EPNgdPDwAAaA//Bx4Hew8sB1QPAAD/D/8Pgg8AAP8P/w+CDwAA/w//
+D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA
+/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+C
+DwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P
+/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8A
+AP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/D/8P
+gg8AAP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/
+D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAALA//B/8H
+NwcfDwAAKQ8EB/8I/wg1CAQHHA8AACcPAwcDCP8J/wk1CQMIAwcaDwAAJg8A
+BQcHCAgFAP8J/wk6CQAECAgHBxkPAAAlDwADBwcIAP8J/wk/CQADCAcHABgP
+AAAlDwEHAQgJCf8I/wgvCAkJAQgBBxgPAAAkDwADBwcIAAYJAwj/B/8HLwcD
+CAYJAAMIBwcAFw8AACQPAQcBCAUJAQgBCAQH/w//Dy0PBAcBCAEIBQkBCAEH
+Fw8AACQPAQcBCAQJAQgDB/8P/w8zDwMHAQgECQEIAQcXDwAAIw8AAwcHCAAE
+CQEIAQf/D/8PNw8BBwEIBAkAAwgHBwAWDwAAIw8BBwEIBAkAAwgHBwD/D/8P
+Nw8AAwcHCAAECQEIAQcWDwAAIw8BBwEIBAkBCAEH/w//DzkPAQcBCAQJAQgB
+BxYPAAAjDwEHAQgECQEIAQf/D/8POQ8BBwEIBAkBCAEHFg8AACMPAQcBCAMJ
+AAMIBwcA/w//DzkPAAMHBwgAAwkBCAEHFg8AACMPAQcBCAMJAQgBB/8P/w87
+DwEHAQgDCQEIAQcWDwAAIw8BBwEIAwkBCAEH/w//DzsPAQcBCAMJAQgBBxYP
+AAAjDwEHAQgDCQEIAQdzDwsHZA8LBykPCwfuDwMHBQgDBx8PAQcBCAMJAQgB
+BxYPAAAjDwEHAQgDCQEIAQcGDyIIAQ8BDxAIAQ8BDyIIEQ8BCAEIDwAAAwgI
+BwAiDxwIAQcBBxsPAQgBCA8AAAMICAcAIA8BCAEIDwAAAwgIBwAdDwEHDwgB
+ByMPAQcMCAEHBA8BBw0IBQ8OCAEPAQ8jCAADDw8HAA0IDA8SCAEHDA8AAwcI
+CAAQAAEIAQcaDwEHAQgDCQEIAQcWDwAAIw8BBwEIAwkBCAEHBg8BCCAAAAQI
+Dw8IDwAAAw8PCAAgAAEIDg8BBxcAAQgBBx8PAQgfAAEIFQ8BBxcAAQgBBxoP
+AQcXAAEIAQcaDwEHDwABByMPAQcMAAEHBA8BBw0ABQ8BCAwAAAMIDw8AIwAA
+Aw8PBwANAAsPAQcSAAEHCg8BCBcAAQgBBxcPAQcBCAMJAQgBBxYPAAAjDwEH
+AQgDCQEIAQcGDwEIIAAABAgPDwgPAAADDw8IACAAAQgMDwEIHAABBx0PAQgh
+AAEIEQ8BCBwAAQcWDwEIHAABBxgPAQcPAAEHIw8BBwwAAQcEDwEIDQABBwQP
+AQgMAAADCA8PACMAAAMPDwcADQALDxMAAQcIDwEIHAABCBUPAQcBCAMJAQgB
+BxYPAAAjDwEHAQgDCQEIAQcGDwEIIAAABAgPDwgPAAADDw8IACAAAQgLDx8A
+AQgcDwEIIwABBw4PHwABCBQPHwABCBcPAQcPAAEHIw8BBwwAAQcEDw4AAQgE
+DwEIDAAAAwgPDwAjAAADDw8HAA0ACg8BCBMAAQcGDwEHIAABBxMPAQcBCAMJ
+AQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEIIAAABAgPDwgPAAADDw8IACAAAQgJ
+DwEHIgABBxoPAQgkAAEHCw8BByIAAQcQDwEHIgABBxUPAQcPAAEHIw8BBwwA
+AQcEDw8ABA8BCAwAAAMIDw8AIwAAAw8PBwANAAoPFAABBwUPAQgiAAEIEg8B
+BwEIAwkBCAEHFg8AACMPAQcBCAMJAQgBBwYPAQggAAAECA8PCA8AAAMPDwgA
+IAABCAgPAQgkAAEHGQ8BCCUACg8BCCQAAQcODwEIJAABBxQPAQcPAAEHIw8B
+BwwAAQcDDwEHDwAEDwEIDAAAAwgPDwAjAAADDw8HAA0ACQ8BCBQAAQcEDwEI
+JAABCBEPAQcBCAMJAQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEIIAAABAgPDwgP
+AAADDw8IACAAAQgHDwEIJgABBxgPAQglAAEICA8BCCYAAQcMDwEIJgABBxMP
+AQcPAAEHIw8BBwwAAQcDDwEIDwABBwMPAQgMAAADCA8PACMAAAMPDwcADQAJ
+DxUAAQcDDwEHJgABCBAPAQcBCAMJAQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEI
+IAAABAgPDwgPAAADDw8IACAAAQgGDwEHKAABBxcPAQgmAAcPAQcoAAEHCg8B
+BygAAQcSDwEHDwABByMPAQcMAAEHAw8BCA8AAQgDDwEIDAAAAwgPDwAjAAAD
+Dw8HAA0ACA8WAAEHAw8oABAPAQcBCAMJAQgBBxYPAAAjDwEHAQgDCQEIAQcG
+DwEIIAAABAgPDwgPAAADDw8IACAAAQgFDwEHKgAXDwEIJgABBwUPAQcqAAkP
+AQcqABIPAQcPAAEHIw8BBwwAAQcDDxAAAQgDDwEIDAAAAwgPDwAjAAADDw8H
+AA0ABw8BBxYAAAQHDw8IKAABCA8PAQcBCAMJAQgBBxYPAAAjDwEHAQgDCQEI
+AQcGDwEIIAAABAgPDwgPAAADDw8IACAAAQgFDywAFg8BCCYAAQgFDywACA8s
+ABEPAQcPAAEHIw8BBwwAAQcDDxEAAw8BCAwAAAMIDw8AIwAAAw8PBwANAAcP
+FwAAAwcPDwAqAA8PAQcBCAMJAQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEIDwAU
+DwEIDwAAAw8PCAAPABYPAQgSAAEIAQcDDwEHAQgTAAEHFQ8BCA4ABw8BBwEI
+DwABCAQPAQgSAAEIAQcDDwEHAQgTAAEHBg8BCBIAAQgBBwMPAQcBCBMAAQcQ
+DwEHDwABByMPAQcMAAAEBw8PBxEAAAQHDw8IDAAAAwgPDwAQABMIAAMPDwcA
+DQAGDwEIFwAAAwcPDwAUAAEIAQgUAA8PAQcBCAMJAQgBBxYPAAAjDwEHAQgD
+CQEIAQcGDwEIDwAUDwEIDwAAAw8PCAAPABYPEQABCAkPAQcSABUPAQgOAAkP
+DwABCAQPEQABCAkPAQcSAAYPEQABCAkPAQcSABAPAQcPAAEHIw8BBwwAAAQH
+Dw8IEQAABAcPDwgMAAADCA8PAA8AAQcVDwEHDQAGDxgAAAMHDwcAEgABCAQP
+AQgSAA8PAQcBCAMJAQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEIDwAUDwEIDwAA
+Aw8PCAAPABUPAQgQAAEIDA8RAAEHFA8BCA4ACQ8BBw4AAQgDDwEIEAABCAwP
+EQABBwQPAQgQAAEIDA8RAAEHDw8BBw8AAQcjDwEHDAAAAwcPDwASAAAECA8P
+CAwAAAMIDw8ADwABBxUPAQcNAAUPAQgYAAADBw8HABEABw8BBxEADw8BBwEI
+AwkBCAEHFg8AACMPAQcBCAMJAQgBBwYPAQgPABQPAQgPAAADDw8IAA8AFQ8Q
+AAEIDg8QAAEIFA8BCA4ACQ8BCA4AAQcDDxAAAQgODxAAAQgEDxAAAQgODxAA
+AQgPDwEHDwABByMPAQcMAAADBw8PABMAAAMPDwgADAAAAwgPDwAPAAEHFQ8B
+Bw0ABQ8ZAAADBw8HABAAAQcIDxEADw8BBwEIAwkBCAEHFg8AACMPAQcBCAMJ
+AQgBBwYPAQgPABQPAQgPAAADDw8IAA8AFA8BBxAADw8BBxAAFA8BCA4ACQ8P
+AAMPAQcQAA8PAQcQAAMPAQcQAA8PAQcQAA8PAQcPAAEHIw8BBwwAAAMHDwcA
+EwAAAw8PCAAMAAADCA8PAA8AAQgQBwUPAQcNAAQPGgAAAwcPBwAQAAkPAQcQ
+AA8PAQcBCAMJAQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEIDwAUDwEIDwAAAw8P
+CAAPABQPAQgPAAEIEA8QAAEHEw8BCA4ACA8BCA4AAQgDDwEIDwABCBAPEAAA
+BAcPDwgPAAEIEA8QAAEHDg8BBw8AAQcjDwEHDAAAAwcPCAATAAADBw8IAAwA
+AAMIDw8AHwABCAUPAQcNAAMPAQcaAAADBw8HAA8AAQgJDwEHEAAPDwEHAQgD
+CQEIAQcWDwAAIw8BBwEIAwkBCAEHBg8BCA8AFA8BCA8AAAMPDwgADwAUDwEI
+DwABBxAPAQgPAAEHEw8BCA4ABggRAAQPAQgPAAEHEA8BCA8AAAQHDw8IDwAB
+BxAPAQgPAAEHDg8BBw8AAQcjDwEHDAAAAwcPCAATAAADCA8IAAwAAAMIDw8A
+HwABCAUPAQcNAAMPGwAAAwcPBwAPAAEICQ8BBxAADw8BBwEIAwkBCAEHFg8A
+ACMPAQcBCAMJAQgBBwYPAQgPABQPAQgPAAADDw8IAA8AFA8QABEPAQcPAAEI
+Ew8BCCQABQ8QABEPAQcPAAADCA8PABAAEQ8BBw8AAQgODwEHDwABByMPAQcM
+AAEHAQ8VAAEPAQgMAAADCA8PAB8AAQgFDwEHDQAAAw8PCAAbAAADBw8HAA8A
+AQgJDwEHEAAPDwEHAQgDCQEIAQcWDwAAIw8BBwEIAwkBCAEHBg8BCA8AFA8B
+CA8AAAMPDwgADwAUDxAAEg8PAAEIEw8BCCMABg8QABIPDwAAAwgPDwAQABIP
+DwABCA4PAQcPAAEHIw8BBwwAAQcBDwoAAQcKAAEPAQgMAAADCA8PAB8AAQgF
+DwEHDQABDwEPHAAAAwcPBwAPAAEICQ8BBxAADw8BBwEIAwkBCAEHFg8AACMP
+AQcBCAMJAQgBBwYPAQgPABQPAQgPAAADDw8IAA8AFA8QABIPDwABCBMPAQgh
+AAEIBw8QABIPDwAAAwgPDwAQABIPDwABCA4PAQcPAAEHIw8BBwwAAQcBBwoA
+AQcKAAEHAQgMAAADCA8PAB8AAQgFDwEHDQABDwEIDgABCA0AAAMHDwcADwAB
+CAkPAQcQAA8PAQcBCAMJAQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEIDwAUDwEI
+DwAAAw8PCAAPABQPEAASDw8AAQgTDwEIHwABCAkPEAASDw8AAAMIDw8AEAAS
+Dw8AAQgODwEHDwABByMPAQcMAAEHAQgKAAEPCgABCAEIDAAAAwgPDwAfAAEI
+BQ8BBw0AAQ8OAAEPAQgNAAADBw8HAA8AAQgJDwEHEAAPDwEHAQgDCQEIAQcW
+DwAAIw8BBwEIAwkBCAEHBg8BCA8AFA8BCA8AAAMPDwgADwAUDxAAAQcRDw8A
+AQgTDwEIHwABCAkPEAABBxEPDwAAAwgPDwAQAAEHEQ8PAAEIDg8BBw8AAQcj
+DwEHDAABBwoAAAMIDwgACQABCAEIDAAAAwgPDwAfAAEIBQ8BBxsAAAMIDwgA
+DQAAAwcPBwAPAAEICQ8BBxAADw8BBwEIAwkBCAEHFg8AACMPAQcBCAMJAQgB
+BwYPAQgPABQPAQgPAAADDw8IAA8AFA8QAAEIEA8BBw8AAQgTDwEIIQABCAcP
+EAABCBAPAQcPAAADCA8PABAAAQgQDwEHDwABCA4PAQcPAAEHIw8BBwwAAQcK
+AAADCA8IAAoAAQgMAAADCA8PAB8AAQgFDwEHGwAAAw8PCAANAAADBw8HAA8A
+AQgJDwEHEAAPDwEHAQgDCQEIAQcWDwAAIw8BBwEIAwkBCAEHBg8BCA8AFA8B
+CA8AAAMPDwgADwAUDwEIEAAQDwEIDwABBxMPAQgiAAEIBg8BCBAAEA8BCA8A
+AAQHDw8IEAAQDwEIDwABBw4PAQcPAAEHIw8BBwwAAQgKAAADBw8HABcAAAMI
+Dw8AHwABCAUPAQcaAAAECA8PCA0AAAMHDwcADwABCAkPAQcQAA8PAQcBCAMJ
+AQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEIDwAUDwEIDwAAAw8PCAAPABQPAQgQ
+AAEHDw8QAAEHEw8BCCMAAQcFDwEIEAABBw8PEAAABAcPDwgQAAEHDw8QAAEH
+Dg8BBw8AAQcjDwEHFwADDxcAAAMIDw8AHwABCAUPAQcaAAMPAQgNAAADBw8H
+AA8AAQgJDwEHEAAPDwEHAQgDCQEIAQcWDwAAIw8BBwEIAwkBCAEHBg8BCA8A
+FA8BCA8AAAMPDwgADwAUDwEHEQAODwEIEAAUDwEIDgAGCBAABQ8BBxEADg8B
+CBAAAw8BBxEADg8BCBAADw8BBw8AAQcjDwEHFwADDxcAAAMIDw8ADwABBxUP
+AQcZAAEHAw8BCA0AAAMHDwcADwABCAkPAQcQAA8PAQcBCAMJAQgBBxYPAAAj
+DwEHAQgDCQEIAQcGDwEIDwAUDwEIDwAAAw8PCAAPABUPEQABCAwPAQcQAAEI
+FA8BCA4ABw8BCA4AAQcFDxEAAQgMDwEHEAABCAQPEQABCAwPAQcQAAEIDw8B
+Bw8AAQcjDwEHFwADDwEIFgAAAwgPDwAPAAEHFQ8BBxkABA8BCA0AAAMHDwcA
+DwABCAkPAQcQAA8PAQcBCAMJAQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEIDwAU
+DwEIDwAAAw8PCAAPABUPAQgRAAEICg8BCBEAAQcUDwEIDgAIDw4AAQgFDwEI
+EQABCAoPAQgRAAEHBA8BCBEAAQgKDwEIEQABBw8PAQcPAAEHIw8BBxYAAQgD
+DwEHFgAAAwgPDwAPAAEHFQ8BBxgAAQcEDwEIDQAAAwcPBwAPAAEICQ8BBxAA
+Dw8BBwEIAwkBCAEHFg8AACMPAQcBCAMJAQgBBwYPAQgPABQPAQgPAAADDw8I
+AA8AFg8TAAEHBg8BCBMAFQ8BCA4ABw8BBw4AAQgGDxMAAQcGDwEIEwAGDxMA
+AQcGDwEIEwAQDwEHDwABByMPAQcWAAEIBA8WAAADCA8PAA8AAQcVDwEHFwAB
+CAUPAQgNAAADBw8HAA8AAQgJDwEHEAAPDwEHAQgDCQEIAQcWDwAAIw8BBwEI
+AwkBCAEHBg8BCA8AFA8BCA8AAAMPDwgADwAWDwEIFAAECBQAAQcVDwEIDgAH
+DwEIDwAGDwEIFAAECBQAAQcGDwEIFAAECBQAAQcFDwsHAQgPAAEIDAcXDwEH
+FgABBwQPFgAAAwgPDwAQABMIAAMPDwcAFwAGDwEIDQAAAwcPBwAPAAEICQ8B
+BxAADw8BBwEIAwkBCAEHFg8AACMPAQcBCAMJAQgBBwYPAQgPABQPAQgPAAAD
+Dw8IAA8AFw8rAAEIFg8BCA4ABgcRAAcPKwABCAgPKwABCAUPAQcnAAEIFw8B
+BxYAAQcEDwEIFQAAAwgPDwAjAAADDw8HABYAAQgGDwEIDQAAAwcPBwAPAAEI
+CQ8BBxAADw8BBwEIAwkBCAEHFg8AACMPAQcBCAMJAQgBBwYPAQgPABQPAQgP
+AAADDw8IAA8AGA8qABcPAQgkAAEICA8qAAoPKgAGDwEHJwABCBcPAQcWAAUP
+AQcVAAADCA8PACMAAAMPDwcAFgAHDwEIDQAAAwcPBwAPAAEICQ8BBxAADw8B
+BwEIAwkBCAEHFg8AACMPAQcBCAMJAQgBBwYPAQgPABQPAQgPAAADDw8IAA8A
+GA8BBygAGA8BCCQAAQgIDwEHKAALDwEHKAAHDwEHJwABCBcPAQcWAAYPFQAA
+AwgPDwAjAAADDw8HABUAAQgHDwEIDQAAAwcPBwAPAAEICQ8BBxAADw8BBwEI
+AwkBCAEHFg8AACMPAQcBCAMJAQgBBwYPAQgPABQPAQgPAAADDw8IAA8AGQ8B
+ByYAAQcYDwEIJAAKDwEHJgABBwwPAQcmAAEHBw8BBycAAQgXDwEHFQABCAYP
+FQAAAwgPDwAjAAADDw8HABUACA8BCA0AAAMHDwcADwABCAkPAQcQAA8PAQcB
+CAMJAQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEIDwAUDwEIDwAAAw8PCAAPABoP
+AQckAAEHGQ8BCCMAAQgLDwEHJAABBw4PAQckAAEHCA8BBycAAQgXDwEHFQAB
+CAYPAQgUAAADCA8PACMAAAMPDwcAFAABBwgPAQgNAAADBw8HAA8AAQgJDwEH
+EAAPDwEHAQgDCQEIAQcWDwAAIw8BBwEIAwkBCAEHBg8BCA8AFA8BCA8AAAMP
+DwgADwAbDwEHIgAbDwEIIwANDwEHIgARDwEHIgAKDwEHJwABCBcPAQcVAAEH
+Bg8BCBQAAAMIDw8AIwAAAw8PBwAUAAkPAQgNAAADBw8HAA8AAQgJDwEHEAAP
+DwEHAQgDCQEIAQcWDwAAIw8BBwEIAwkBCAEHBg8BCA8AFA8BCA8AAAMPDwgA
+DwAdDwEIHgABCBwPAQgiABAPAQgeAAEIFA8BCB4AAQgLDwEHJwABCBcPAQcV
+AAEHBg8BBxQAAAMIDw8AIwAAAw8PBwATAAEHCQ8BCA0AAAMHDwcADwABCAkP
+AQcQAA8PAQcBCAMJAQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEIDwAUDwEIDwAA
+Aw8PCAAPAB4PAQcbAAEIHg8BCCAAAQgSDwEHGwABCBcPAQcbAAEIDQ8BBycA
+AQgXDwEHFQAIDxQAAAMIDw8AIwAAAw8PBwASAAEICg8BCA0AAAMHDwcADwAB
+CAkPAQcQAA8PAQcBCAMJAQgBBxYPAAAjDwEHAQgDCQEIAQcGDwEIDwAUDwEI
+DwAAAw8PCAAPACEPAQgWAAEIIA8BCB8AAQcWDwEIFgABCBwPAQgWAAEIDw8B
+BycAAQgXDwEHFQAIDxQAAAMIDw8AIwAAAw8PBwASAAsPAQgNAAADBw8HAA8A
+AQgJDwEHEAAPDwEHAQgDCQEIAQcWDwAAIw8BBwEIAwkBCAEHBg8BCA8AFA8B
+CA8AAAMPDwgADwAjDwADBwgIAA4AAAMICAcAIg8BCBsAAQgBCBsPAAMHCAgA
+DgAAAwgIBwAgDwADBwgIAA4AAAMICAcAEQ8BBycAAQgXDwEHFAABCAgPAQgT
+AAADCA8PACMAAAMPDwcAEQABCAsPAQgNAAADBw8HAA8AAQgJDwEHEAAPDwEH
+AQgDCQEIAQcWDwAAIw8BBwEIAwkBCAEHdA8KB2UPCgcqDwoH/w8ZDwEHAQgD
+CQEIAQcWDwAAIw8BBwEIAwkAAwgHBwD/D/8POQ8AAwcHCAADCQEIAQcWDwAA
+Iw8BBwEIBAkBCAEH/w//DzkPAQcBCAQJAQgBBxYPAAAjDwEHAQgECQEIAQf/
+D/8POQ8BBwEIBAkBCAEHFg8AACMPAQcBCAQJAAMIBwcA/w//DzcPAAMHBwgA
+BAkBCAEHFg8AACMPAAMHBwgABAkBCAEH/w//DzcPAQcBCAQJAAMIBwcAFg8A
+ACQPAQcBCAUJAwf/D/8PMw8DBwEIBAkBCAEHFw8AACQPAQcBCAUJAQgBCAQH
+/w//Dy0PBAcBCAEIBQkBCAEHFw8AACQPAAMHBwgABgkDCP8H/wcvBwMIBgkA
+AwgHBwAXDwAAJQ8BBwEICQn/CP8ILwgJCQEIAQcYDwAAJQ8AAwcHCAD/Cf8J
+PwkAAwgHBwAYDwAAJg8ABAcHCAj/Cf8JOwkABAgIBwcZDwAAJw8DBwMI/wn/
+CTUJAwgDBxoPAAApDwQH/wj/CDUIBAccDwAALA//B/8HNwcfDwAA/w//D4IP
+AAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//
+D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA
+/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+C
+DwAA/w//D4IPAAD/D/8Pgg8AAP8P/w+CDwAA/w//D4IPAAE=
+====
diff --git a/images/inside_16c.dat b/images/inside_16c.dat
new file mode 100644 (file)
index 0000000..70e4906
--- /dev/null
@@ -0,0 +1,14 @@
+# Lilo boot menu background configuration  (Lilo 23)
+#
+# color palette: 0 black,         3 magenta,       7 pink,
+#                8 middle grey,  10 bright grey,  13 white
+#
+# bmp-table  = <x>,<y>;<ncol>,<nrow>,<xsep>,<spill>
+# bmp-colors = <fg>,<bg>,<sh>;<high-fg>,<high-bg>,<high-sh>
+# bmp-timer  = <x>,<y>;<fg>,<bg>,<sh>
+
+bitmap = inside.bmp
+
+bmp-table  = 21,284p;2,7,175p,4
+bmp-colors = 14,11,;15,9,0
+bmp-timer  = 73,29;12,8,0
diff --git a/images/inside_16c.uu b/images/inside_16c.uu
new file mode 100644 (file)
index 0000000..1be414f
--- /dev/null
@@ -0,0 +1,503 @@
+begin-base64 644 inside.bmp
+Qk0CWAAAAAAAADYEAAAoAAAAgAIAAOABAAABAAgAAQAAAMxTAAAgHAAAIBwA
+AAABAAAAAQAAAgIEAA0TGAAOV3kAE5rOAK1CQwD/TlAAg56rAPOrrAAIsvEA
+CMXtAAvC8gBn2vEA5ObvAPDo7QDe9/cA+/n7AAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8O
+/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4A
+AP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8O
+gg4AAP8O/w5DDiYAGQ4AAP8O/w5BDgEAAQAmCAEAAQAXDgAA/w7/DkAOAQAq
+CAEAFg4AAP8O/w4/DgEALAgBABUOAAD/Dv8OPg4BAC4IAQAUDgAA/w7/Dj4O
+AQAuCAEAFA4AAP8O/w49DgEAMAgBABMOAAD/Dv8OPQ4BADAIAQATDgAA/w7/
+Dj0OAQAwCAEAEw4AAP8O/w49DgEAMAgBABMOAAD/Dv8OPQ4BADAIAQATDgAA
+/w7/Dj0OAQAwCAEAEw4AAP8O/w49DgEAMAgBABMOAAD/Dv8OPQ4BADAIAQAT
+DgAA/w7/Dj0OAQAwCAEAEw4AAP8O/w49DgEAMAgBABMOAAD/Dv8OPQ4BADAI
+AQATDgAA/w7/Dj0OAQAwCAEAEw4AAP8O/w49DgEAMAgBABMOAAD/Dv8OPg4B
+AC4IAQAUDgAA/w7/Dj4OAQAuCAEAFA4AAP8O/w4/DgEALAgBABUOAAD/Dv8O
+QA4BACoIAQAWDgAA/w7/DkEOAQABACYIAQABABcOAAD/Dv8OQw4mABkOAAD/
+Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIO
+AAD/Dv8Ogg4AAP8OGg4DAP8OZQ4AAP8OGw4BACAOAQD/DkUOAAD/DhsOAQAh
+DgEA/w5EDgAApg4DAAMOAwABDgMAAAMOAAAADg4BAAEAAw4FAAEOAQ4DAA8O
+AQABAAMOAwAIDgMAAQ4BDgMAAQ4DAAADDgAAAAMOAwABDgEOAwAIDgMAAw4A
+BAAOAAADDgADAAAOAAMAAQ4BDgMAAQ4BDgMAAQ4DAAEOAwAABA4OAAAPDgMA
+AQ4BDgMADw4BAAEAAw4DAAgOAwAEDgMABA4DAAMOAQABAAYOAwAEDgMAAQ4B
+DgMAAQ4BDgMABA4DAAMOAAMAAA4AAwABDgEOAwABDgEOAwABDgMAvw4AAKcO
+AQAFDgEAAw4ABgAODgAOAA0OAAUADgAOAAADDgAEAA4OAAMOAQAODgAFAA4A
+DgAAAw4BAAYOAQADDgAEAA4OAAMOAAgADg4ADgAOAAMOAAQADg4ACA4BAAMO
+ABIADg4AAA4OAA4OAA4ADgAODgADDgAEAA4OAAMOAAcADg4ADg4AABEOAQAD
+DgAEAA4OABAOAAUADgAOAAADDgEABg4BAAMOAAQADg4AAw4ABAAODgADDgAG
+AA4OAA4ABQ4ABwAODgAODgAAAw4ABwAODgAODgAAAw4ABAAODgADDgALAA4O
+AA4ADgAODgAAAw4ABAAODgADDgEAwA4AAKcOAQAFDgEAAw4ABAAODgAMDgAE
+AA4OAAMOAQADDgAEAA4OAAMOAAQADg4ACw4BAAMOAQADDgEABg4BAAYOAQAD
+DgAEAA4OAAMOAQAGDgEACA4BAAMOAAQADg4AAw4ABAAODgADDgAEAA4OAAMO
+AAQADg4AAw4BAAUOAQAODgAEAA4OAAYOAQAEDgEACw4BAAMOAQADDgEABg4B
+AAMOAAQADg4AAw4ABAAODgADDgAEAA4OAAoOAAQADg4ABg4ABAAODgAGDgEA
+Bg4BAAMOAAQADg4AAw4ABAAODgADDgEAwA4AAKcOAQAFDgEAAw4ABAAODgAK
+DgEAAQADDgEABA4EAAADDg4AAAMOAQADDgEAAQAJDgEAAw4BAAMOAQAGDgEA
+Bg4BAAMOAAQADg4AAw4BAAYOAQAIDgEAAw4ABAAODgADDgAEAA4OAAMOAAQA
+Dg4AAw4ABAAODgADDgEAAw4BAAEADQ4BAAEAAw4BAAYOAQAFDgEAAQAJDgEA
+Aw4BAAMOAQAGDgEAAw4ABAAODgADDgAEAA4OAAMOAAQADg4ACA4BAAEAAw4B
+AAYOAAQADg4ABg4BAAYOAQADDgAEAA4OAAMOAAQADg4AAw4BAMAOAACnDgEA
+BQ4BAAMOAAQADg4ACA4BAAEABQ4BAAcOAAQADg4AAw4BAAUOAQABAAcOAQAD
+DgEAAw4BAAYOBQAAAw4OAAADDgAEAA4OAAMOBQAAAw4OAAAIDgEAAw4ABAAO
+DgADDgAEAA4OAAMOAAQADg4AAw4ABAAODgADDgAEAA4OAA0OAQABAAUOAQAG
+DgEABw4BAAEABw4BAAMOAQADDgEABg4BAAMOAAQADg4AAw4ABAAODgADDgAE
+AA4OAAcOAQAFDgUAAAUODgAODgAFAAADDg4AAAYOAQADDgAEAA4OAAMOAAQA
+Dg4AAw4BAMAOAACnDgcAAAcODgAADg4AAAcOAQAHDgEAAw4BAAMOAAgADg4A
+AA4OAAcOAQAGDgEAAw4BAAMOAQAGDgEAAw4BAAEOAwAABg4OAA4OAAMOAQAD
+DgEAAQ4DAAcOAQADDgEAAQ4DAAANDg4ADg4ADg4AAA4OAAADDgEAAQ4DAAAJ
+Dg4ADg4ADg4AAAkOAQAHDgEAAw4BAAEOAwAIDgEABg4BAAMOAQADDgEABg4A
+CAAADg4ADg4AAw4ABAAODgADDgAEAA4OAAcOAAcADg4ADg4AAAMOAAcADg4A
+Dg4AAAMOAAQADg4AAw4ACwAODgAODgAADg4AAAMOAQABDgMAAAMODgAAwA4A
+AKcOAQAFDgEAAw4BAAEOBAAGDgEAAQAEDgQAAQ4BDgMAAw4ABAAOAAAGDgEA
+AQAGDgQAAQ4BDgMACA4DAAMOAAYADgAADg4EAAEOAQ4DAAMOAAQADgAABg4D
+AAMOAAYADgAADg4EAAEOAQADDgMAAw4ABAAOAAAEDgMACg4BAAEABg4DAAMO
+AAQADgAABA4BAAEABg4EAAEOAQ4DAAcOAAQADgAABA4DAAQOAwABDgEOBAAG
+DgMAAw4DAAMOAQADDgMABA4DAAEOAQ4EAAEOAQADDgMAAw4ABAAOAADBDgAA
+pw4BAAUOAQAGDgEACg4BAAEAAw4BAAoOAQAHDgEAAQAJDgEAHA4BACEOAQAk
+DgEAAQAQDgEAAQAJDgEADg4BABQOAQAUDgEAEA4BANIOAACnDgEABQ4BAAYO
+AQAMDgAEAA4OAAoOAQAGDgEACw4BABwOAQAhDgEAJg4BAA4OAQALDgEADg4B
+ABQOAQAUDgEAEA4BANIOAACmDgMAAw4DAB8OAQABAKEOAQABACgOAQABAOMO
+AACxDgEAHQ4BAFUOAQBMDgEAKQ4BABQOAQDODgAA/w7/DoIOAAD/Dv8Ogg4A
+AP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8O
+gg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/
+Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAAnQ6UABsO
+lACgDgAAmw4BAAEAlAsBAAEAFw4BAAEAlAsBAAEAng4AAJoOAQCYCwEAFQ4B
+AJgLAQCdDgAAmQ4BAJoLAQATDgEAmgsBAJwOAACYDgEAnAsBABEOAQCcCwEA
+mw4AAJgOAQCcCwEAEQ4BAJwLAQCbDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACX
+DgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4BAJ4LAQCaDgAAlw4BAJ4L
+AQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEAmg4AAJcOAQCeCwEADw4B
+AJ4LAQCaDgAAlw4BAJ4LAQAPDgEAngsBAJoOAACXDgEAngsBAA8OAQCeCwEA
+mg4AAJgOAQCcCwEAEQ4BAJwLAQCbDgAAmA4BAJwLAQARDgEAnAsBAJsOAACZ
+DgEAmgsBABMOAQCaCwEAnA4AAJoOAQCYCwEAFQ4BAJgLAQCdDgAAmw4BAAEA
+lAsBAAEAFw4BAAEAlAsBAAEAng4AAJ0OlAAbDpQAoA4AAP8O/w6CDgAA/w7/
+DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA
+/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6C
+DgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/DqwOAAQMBQUH
+Bg4ABAcFBQ3HDgAA/w6sDgAFDAUFBw0ABQ4ABQcFBQcNAAUOAAMMDQwAvg4A
+AP8OrA4BDAQFAQcFDgENAwcBDAQOAAMHBQcAvg4AAP8OrA4BDQQFAQcBDAUO
+AAUNBQUHDAADDgAEBwUHDb0OAAD/DqwOAQwFBQQHAw4DBQAFBwwODg0ABAcB
+DLsOAAD/DqwOAQwJBQAEBw4OBwMFAQcBDAMOAAQHBQUHuw4AAP8OrA4BDAEH
+CAUABQcHDQcHAAMFAAoHDA4ODAcFBwcMmQ4DDB0OAAD/Dq4OAQcJBQAEBw4M
+BwMFAAkHDA4ODAcFBQcAmA4ABAwHBQcdDgAA/w6vDgEHCQUAAw0ODAAEBQAI
+BwwODgwHBQeXDgAFDAcFBQcAHQ4AAP8OsA4BBwEHBwUABQcHDA0HAAMFAAcH
+DA4ODAcNAJYOAAYNBwUHBwwdDgAA/w6xDgEHCQUABAwODQcDBQEHAQyaDgAE
+BwUFDB8OAAD/DrIOAQcIBQAFBw0MDQcAAwUBBwEMiw4BDQEMCg4BDAQHIA4A
+AP8Osw4BDQkFAAQHDgwHAwUBBwEMiQ4ABAwHBQcIDgAFDAcFBw0AIQ4AAP8O
+tA4BBwgFAAQHDA4HBAUBBwEMBg4BDYAOAAUMBwUFBwAIDgAEBwUFByIOAAD/
+DrQOAQwBBwgFAQcBBwYFAQcBDAQOAwd+DgEMAQcDBQEHBg4BDAEHAwUBByIO
+AAD/DrYOAQcQBQEHAQwDDgAEBwUFDX0OAQcEBQENBg4BBwQFAQciDgAA/w62
+DgEMAQcQBQAFBwwODg0ABAcBDHcOAQ0DBwMFAQcBDQUOAQwBBwQFAQcBDCIO
+AAD/DrgOAQcQBQEHAQwDDgAEBwUFB3YOAQ0GBQEHAQ0GDgEHBAUBByQOAAD/
+DrkOAQcQBQAKBw0NDg0HBQcMDHMOAQ0BBwcFAQcBDAQOAQcEBQEHJQ4AAP8O
+uQ4BDAEHEAUEBwAFDQ0HBQcAcg4BBwoFAAUHDA4OBwAEBQEHAQwlDgAA/w67
+DgEHEgUABwcMDgcFBQ0AcA4BDAEHCwUAAwwODQAEBQEHJw4AAP8Ouw4BDAEH
+EgUAAwcMDQAEBwEMbQ4BBwEHCgUABAcHDQcEBQEHAQwnDgAA/w5EDgMMdg4B
+BxMFAAYNDgwFBQdsDgENCwUABAcMDgcEBQEHKQ4AAMEOBAYwDgEMAwYBDBAO
+AAMMBgwAMw4BBgEGBQIBBgEMNA4EBjAOAQwLBgEHEgUAAwcMDQADBwEMAQwi
+DhEGNg4BDQEHCgUABAcHDg0EBQEHAQwpDgAAwQ4DAgEGMA4BDAMCAQYPDgAE
+DAICDDEOAQwKAgEGMw4DAgEGMA4BDAwCAQcSBQAHBwcODQcFBwAiDgEGEAI1
+DgENAQcKBQAEBwwOBwQFAQcBDCoOAADBDgMCAQYwDgEMAwIBBg4OAQwDAgEM
+MA4BDAwCAQYyDgMCAQYwDgEMDQIBBxIFAAcHDA4HBQcNACEOAQYQAjQOAQwB
+BwsFAAMHDg0ABAUBBywOAADBDgMCAQYwDgEMAwIBBg0OAQwBBAMCAQwvDgEM
+BQIEBgUCAQYxDgMCAQYwDgEMDQIAAwYHBwARBQAEBwcNDAMHAQwfDgEGEAIz
+DgEHAQcMBQMHAwUBBwEMLA4AAMEOAwIBBjAOAQwDAgEGDQ4BBgQCAQwvDgEG
+BAIBBgQOAQwBBAMCAQQxDgMCAQYwDgEMAwIBBgQOAwwDBgECAQcTBQAGDQ4M
+BQUMHw4BBgMCPw4BDAEHEgUBBy4OAADBDgMCAQYwDgEMAwIBBgwOAQYFAgEM
+Lg4BBgQCAQYGDgEMBAIBDDAOAwIBBjAOAQwDAgEGCg4AAwwGBwASBQADBw0N
+AAQHAQwdDgEGAwI4DgADDA0NAAMOAQwBBxMFAQwuDgAAMw4BBgEGAwEBAgEG
+Lg4BBgEGBgEBBgEGTw4DAgEGMA4BDAMCAQYLDgEGBgIBDC4OAAUMBAICBgAI
+DgEGAwIBBjAOAwIBBjAOAQwDAgEGDA4BDAEHEwUABgcODQcFBx0OAQYDAjgO
+AAYHBQcODgwVBQEHLg4AADAOAQYJAgADAQIGACkOAAMGAQEACgIBBk0OAwIB
+BjAOAQwDAgEGCg4BBgcCAQwwDgADBgYMAAgOAQYDAgEGMA4DAgEGMA4BDAMC
+AQYNDgEMAQcSBQAIBwwNBwUHDQwbDgEGAwI3DgAHDQcFBw0MBwAUBQEHAQwu
+DgAALQ4BBgEGDAIAAwEBBgAnDgECAQEOAgEGSw4DAgEGMA4BDAMCAQYJDgEM
+CAIBDDsOAQYDAgEGMA4DAgEGMA4BDAMCAQYODgMHEQUABAcHDQwDBxsOAQYD
+AjYOAAcHBQcHDAcHABQFAQcBDC8OAAArDgEGEQIBAQEGJQ4BAgEBEAIBBkoO
+AwIBBjAOAQwDAgEGCA4BDAUCAQYDAgEMOg4BDAQCAQwwDgMCAQYwDgEMAwIB
+Bg8OAQIBBxIFAAcHDA4HBQUMABoOAQYDAjUOAAcNBQUHDgwHABQFAQcBDDAO
+AAAnDgEGAQYVAgEBAQYjDgEGAQEFAgkDBAIBBkkOAwIBBjAOAQwDAgEGBw4B
+DAUCAQwBBgMCAQw5DgEMAQYEAjEOAwIBBjAOAQwDAgEGDw4ABAYEBwcRBQEH
+AQ0FBwEMGA4BBgMCMw4BDAUHAQ0BBxQFAQcBDTEOAAAjDgEGAQYJAgoDBwIA
+AwEAAQAhDgYCDAMDAgEGSA4DAgEGMA4BDAMCAQYGDgEMAQQEAgADBw4GAAMC
+AQw4DgEMAQYEAgEGMQ4DAgEGMA4BDAMCAQYPDgAEDAICBxMFAAYMDg0HBQcY
+DgEGAwIzDgAHBwUFDA4NBwAUBQEHAQwyDgAAIA4BBgoCDwMFAgAEAQEABh0O
+AwYBAQQCDwMAAwICBgBHDgMCAQYwDgEMAwIBBgYOAQYEAgAEBg4OBgMCAQw3
+DgEMAQYEAgEGMg4DAgEGMA4BDAMCAQYPDgAFDAIGBwcAEgUABgcOBwUFBxgO
+AQYDAjEOAAgMDAcFBw0MBxUFAQczDgAAHA4BBgEDCAILAwUIBQMFAgEBBwAU
+BgYAAQEBAQMCBgMFCAcDAQIBAkYOAwIBBjAOAQwDAgEGBQ4BBgQCAQYDDgEG
+AwIBDDYOAQwFAgEEAQwyDgMCAQYwDgEMAwIBBhAOAwcAAwYNBwARBQEHAwUB
+BxgOAQYDAjEOAAcHBQcMDQcHABYFAQczDgAAGA4AAwsGAwADAg8DCwgEAwQC
+AQEBASAAAQEBAQMCBAMKCAcDRQ4DAgEGMA4BDAMCAQYEDgEGBAIBBgQOAQYD
+AgEMNQ4BBgUCAQQBDDMOAwIBBjAOAQwDAgEGEA4ABgcFBQcPDRUFAQcYDgEG
+EAIjDgAHDAcFBw4MBwAXBQEHMw4AABQOAAMLBgMAAwIQAw8IBAMEAgEBIAAA
+BAEBAgIFAwwIBgMBC0MOAwIBBjAOAQwDAgEGAw4BBgQCAQYFDgEGAwIBDDQO
+AQYFAgEGAQw0DgMCAQYwDgEMAwIBBhAOAAgHBQUHDQ8HBxQFAQcBDBYOAQYQ
+AiEOAQwFBwENAQcXBQEHAQwzDgAAEg4BCxEDFggDAwQCAQEgAAAEAQECAgQD
+DggGAwEGQg4DAgEGMA4BDAMCAAQGDg4MBAIBBAEMBQ4BBgMCAQwyDgEMAQYF
+AgEGNg4DAgEGMA4BDAMCAQYPDgEMAQcEBQADDQ8NABUFAQcBDBUOAQYQAiEO
+AAcMBQUHDg0HABcFAQc1DgAAEQ4BCw0DGwgEAwMCAQEgAAEBAwIDAxEIBgMB
+C0AOAwIBBjAOAQwDAgADBg4MAAUCAQwGDgEGAwIBDDIOAQYFAgEGNw4DAgEG
+MA4BDAMCAQYPDgEGAQcEBQAFBw0PBwcAFAUBBwEMFA4BBgMCDQYgDgENAwcA
+AwwMBwAXBQEHNg4AABEOAQsGAyMIAwMAAwICAQAhAAEBAwIDAxQIBQM/DgMC
+AQYwDgEMAwIBBgEMBQIBDAcOAQYDAgEMMQ4BBgQCAQQBDDgOAwIBBjAOAQwD
+AgEGDw4BBgEHBQUABQcHDgwHABQFAQcBDBMOAQYDAiwOAwcABA0OBwcXBQEH
+Nw4AABEOAQsEAyUIAwMAAwICAQAhAAAEAQECAgMDFwgDAwEGPQ4DAgEGMA4B
+DAMCAQYBBAQCAQcIDgEGAwIBDDAOAQwEAgEGAQw5DgMCAQYwDgEMAwIBBg4O
+AAMMAgcABgUABAcMDgcVBQEHAQwSDgEGAwIrDgAHDAcFBwwOBwAXBQEHOA4A
+ABEOAQsDAyYIAwMAAwICAQADAAAEAQECBAMGAwIBAQEBEwAABQECAgMDABkI
+BAMBCzsOAwIBBjAOAQwIAgEGCQ4BBgMCAQwwDgEGBAIBDDoOAwIBBjAOAQwD
+AgEGDg4ABQYCBAcHAAUFAwcWBQEHAQwRDgEGAwIqDgEMAQcDBQEHAQcWBQAD
+BwcMADgOAAARDgELAwMmCAMDAAgCAQABBAYMDQgPAAYNDQwGBgEPAAAFAQIC
+AwMAGwgFAzkOAwIBBjAOAQwHAgEGCg4BBgMCAQwwDgEGAwIBBjsOAwIBBjAO
+AQwDAgEGDQ4BBgQCAQcBBx4FAQcRDgEGAwIpDgEMAQccBQEHOg4AABIOAwMn
+CAAGAwMCAQYMEg8AAwwGAQAMAAAFAQICAwMAHggDAwELNw4DAgEGMA4BDAYC
+AQYLDgEGAwIBDDAOAQYDAgEMBg4AAwwGDAAyDgMCAQYwDgEMAwIBBgwOAQYE
+AgAEBA4HBx4FAQcBDA8OAQYDAigOAQ0BBxwFAQc7DgAAEg4BCwMDJAgABgkI
+AwIBBxcPAQYBAQoAAAUBAgIDAwAgCAMDAQs1DgMCAQYwDgEMBQIBBgwOAQYD
+AgEMMA4BBgMCAQYFDgEMAwIBBjEOAwIBBjAOAQwDAgEGCg4BDAEGBQIABQwO
+DgwHAB4FAQcBDA4OAQYDAicOAQwBBxwFAQ08DgAAEw4DAyMIAAYJCQgDAgYZ
+DwADDQYBAAgAAAUBAgIDAwAhCAMDAQs0DgMCAQYwDgEMBAIBBAEMDA4BBgMC
+AQwwDgEGBAIBDAMOAQwBBAQCMQ4DAgEGMA4BDAMCAQYGDgAEDAwGBgYCAQYE
+DgEHHwUBBwEMDQ4BBgMCJg4BDAEHHAUBBz0OAAATDgQDIQgABgoJCggDBhwP
+AQ0BBgcAAAUBAgIDAwAjCAEDAQM0DgMCAQYwDgEMBAIBDA0OAQYDAgEMMA4B
+DAUCAwYFAgEGMQ4DAgEGMA4BDAMCAQQDBgEECwIBBgYOAQwBBx4FAQcBDAwO
+AQYDAg0GGA4BDAEHGwUAAwcHDAA9DgAAEw4BCwMDIQgABgoKCQMCDR4PAQwB
+AQYAAAQCAgMDJAgBAwEDMw4DAgEGMA4BDAMCAQwODgEGAwIBDDEOAQYLAgEG
+Mg4DAgEGMA4BDBECAQYBDAgOAQ0fBQEHDA4BBhACFw4BDAEHHAUBBz8OAAAT
+DgELAwMgCAMKAAMDAgwAIA8BDAECBQAABAICAwMlCAEDMw4DAgEGMA4ABAwC
+AgYPDgEGAwIBDDIOAQYJAgEGMw4DAgEGMA4BDA8CAQYBBgsOAQcBBx4FAQcB
+DAoOAQYQAhYOAQ0BBxwFAQdADgAAFA4DAyAIAAUKCQgDBgAiDwENAQYEAAAE
+AQIDAyYIMw4EBjAOAAMMBgYAEA4EBgEMMw4BBgcCAQY0DgQGMA4BDA0GAQwB
+DA4OAQ0BBx4FAQcBDAkOEQYVDgEMAQccBQEHQQ4AABQOAwMgCAAICQkDAQEC
+Bg0hDwAIBgEAAAECAwMmCLQOAQwDBgEMiQ4BBx8FAAQHDQ0MKw4BDAEHHAUB
+B0IOAAAUDgMDHwgABAoJCAIEAAEBAQYhDwAHBgEAAQIDAwAlCAEL/w5DDgEH
+IAUEBykOAQ0BBxsFAQcBB0MOAAAUDgMDHwgABAkJAwEGAAEGIA8ABwwGAQEC
+AwMAIwgBCwEM/w5EDgEHIwUBBwEMJw4BDAEHHAUBB0QOAAAUDgMDHggABAoK
+AwEHAAEBIA8ABwwMBgECAwMAIQgBAwEL/w5GDgEMAQcjBQEHAQ0lDgENAQcd
+BQEHRA4AABMOAQsDAx0IAAQKCQgCCAABAQENHw8ABwwMBwYCAwMAHggAAwoI
+AwD/DkoOAQckBQENIw4BDAEHHgUBB0QOAAATDgADCwMDAB4IAAQKCQMBCAAB
+ASAPAAQMDAcHAwMKCAEDAQMTCAED/w5LDgEMAQcjBQEHAQ0hDgEMAQceBQEH
+AQxEDgAAEw4AAwYDAwAdCAAECgkDAgkAAQYfDwENAQwDBwMDBggJAw8IAQP/
+Dk0OAQwBByQFAQ0fDgENAQceBQEHAQ1FDgAAEw4AAwYDAwAdCAADCgkCAAkA
+AQEBDB8PAQ0BDAMHAwMFCAsDDQgBA/8OUA4BByMFAQcBDB0OAQwBBx4FAQcB
+DEYOAAATDgMDHAgABAoJAwEIAAEBAQYgDwENAQwDBwEDAQMFCA0DCwgBA/8O
+UQ4BDAEHIwUBBwEHGw4BDAEHHgUBBwEMRw4AABMOAwMcCAADCQgCAAgAAQEB
+BiEPAQ0BDAMHAQMBAwUIDgMKCAEL/w4VDgMGAQEFAAAEAQYGDDEOAQcjBQEH
+AQwZDgEMAQceBQEHAQxIDgAAEw4DAxsIAAQKCQMBBwABAQEGIg8BDQEMAwcB
+AwEDBAgQAwgIAQsxDgEMKwQBBgkOAQYrBAoOAQYoBAwOAQYnBAEGFw4BBgEC
+DwABBAEGFA4SBgEMBw4BDAEHIwUBBwENFw4BDQEHHgUBBwENSQ4AABMOAwMb
+CAADCQgCAAcAAQIBDCQPAQwDBwEDAQMECAQDAQIBAgUBAQIBAgQDAAMICAoA
+BAgyDgEGKwABBgkOAQIrAAoOAQYoAAwOAQEnAAEGFQ4BBgEBEwAAAwEGDAAR
+DgEGGQAAAwYOBwAjBQEHAQ0VDgENAQceBQEHAQxKDgAAEw4BCwMDGQgAAwoJ
+AwAGAAADAQYMACUPAQwDBwEDAQMECAMDAQIBAQgAAQEBAgMDBQgBAzIOAQYr
+AAEGCQ4BBCsACg4BBigADA4BAScAAQYTDgEGAQEYAAEGEA4BBhkAAAQGDgwH
+IwUBBwEMEw4BDAEHHgUBBwEMSw4AABQOBAMBCAEIBAMSCAADCQMBAAUAAAMB
+Bg0AJg8ADg0MBwcDCAgKCAgDAwIBCwAABQEDAwgKAAMIAQMyDgEGKwABBgkO
+AQIrAAoOAQYoAAwOAQEnAAEGEQ4BDAECHAABBg4OAQIZAAAFBg4ODAcAIwUB
+BwEHEQ4BDQEHHgUBBwENTA4AABQOAQsMAw4IAAMKCAIABQAAAwEGDQAoDwAE
+DQ0MAwUIAAMDAwEADQAAAwEDCQADCgEIAQMyDgEGKwABBgkOAQIrAAoOAQYo
+AAwOAQEnAAEGEA4BBgEBHgABAgEMDA4aAAEGBA4BByMFAQcBDQ8OAQwBBx4F
+AQcBDE0OAAAWDgELAQsKAw0IAQoBAwUAAQIBDC0PAQMECAAECgMCAQ4AAAcC
+CAoKCAoDADIOAQYrAAEGCQ4BBCsACg4BBigADA4BAScAAQYPDgEGIgABBgsO
+GgABBgQOAQwBByMFAQcBDQ0OAQ0BBx8FAQdODgAAHg4BCwQDCwgAAwoDAQAD
+AAADAQQMAAwPAw0fDwEDBAgAAwoIAgAQAAAGAwoKCQoLMw4JDAADBgYBABQA
+AQQBBgkMCg4JDAADBgYEABQAAAMCBgYACQwKDgcMAAMGBgIAFQAAAwIGBgAH
+DAwOBgwDBgEBFQAAAwQGBgAHDA4OAQYkAAEECg4RAAADAQYGAAYMBg4BDAEH
+JAUBDQsOAQ0BByAFAQdODgAAIA4DAwoIAAMKCAIAAwAAAwEGDQANDwADDAwN
+AB8PAQMDCAMKAQIQAAAGAQMKCQkLPw4BBhEAAQIiDgEMAQIQAAEBAQYgDgEM
+AQIRAAEBAQwgDgEGAQERAAEGGA4BBhcAAAQBAgIBCwABAQgOAQwPAAEBAQwR
+DgEHIwUBBwEMCQ4BDAEHIQUBB04OAAAhDgMDCggBAgMAAQEBBg8PAAMMDA0A
+Hw8ABAMICAoDCQEDDQADAQAFAAIKCQsAQQ4BBg8AAQIlDgEBDwABDCMOAQYP
+AAEBJA4BAQ8AAQYZDgEBEgAAAwEGDAAHDgADDAYEAAgAAQEBDAYOAQYOAAEC
+Ew4BDAEHIwUBBwENBw4BDQEHIAUAAwcHDABODgAAIQ4AAwsDAwAJCAECAwAB
+AQEMEA8BDAEMIA8BCgEIBQkBAwEBDQAEAQEDRA4BAg4AJg4BDA4AAQYlDgEC
+DgABDCQOAQwOAAEBGQ4BBBEAAQIBBg4OAQYBAQYAAQEBDAUOAQYNAAECFg4B
+ByMFAQcBDAUOAQwBByEFAQdQDgAAIg4BAwEDCAgBAgMAAQIBDBEPAAMMDA0A
+Hw8AAw4ICAADCgADCAMBAA0ABAEBAAEGQw4BBg0AAQEnDgEBDQABBiUOAQYN
+AAECJg4BAg0AAQYYDgEMEAABAQEGEg4BBgEBBgABBgQOAQYNAAEMFg4BDAEH
+IwUBBwEMAw4BDQEHIAUBBwEHUQ4AACIOAQsBAwcIAQIDAAECAQwSDwEMAQwh
+DwEOBAwAAwYBAQANAAAGAQICAQAGRA4NAAEEJw4BBg0AJw4NAAEGJg4BBg0A
+AQwYDgECDwABARYOAQIGAAEMAw4BBgwAAQIZDgEHIwUABQcMDgwHACEFAQxS
+DgAAIw4BAgEDBQgBAgMAAQIBDBMPAAMMDA0AJQ8ABAcAAQEMAAAGAQYCAAAG
+RA4BAQwAAQQnDgEGDQAnDg0AAQYmDgEMDQAYDgEMDwABAhgOAQYFAAAFAQwO
+DgIADAABBhkOAQ0kBQADBw0HACEFAQdTDgAAIg4ABAYAAQIDAwECAwABAQEG
+FA8AAwwMDQAlDwAFDQEAAQEACQAABAEBAgEEAEQOAQEMAAEEJw4BBg0AJw4N
+AAEGJg4BDA0AGA4BBg4AAQEaDgEGBQAABAEMDgEMAAEMGQ4BDSUFAQcgBQEH
+AQ1UDgAAIg4KAAADAQEGABQPAAMMDA0AJg8AAwEAAAAEAQEAAQAGAQYARA4B
+AQwAAQQnDgEGDQAnDg0AAQYmDgEMDQAYDgEBDgABDBsOAQYFAAADAQ4BAAwA
+Gg4BDUYFAQdVDgAAIg4JAAAEAQEABhQPAAMMDA0AJg8BBAQAAwEBAAMBCQAB
+BkMOAQEMAAEEJw4BBg0AJw4NAAEGJg4BDA0AFw4BDA4AAQYdDgEGBQABAQ0A
+Gw4BDQEHQgUBBwEHVg4AACIOCAAABQECAAAGABQPAAMMDA0AJg8BBgUAAQEB
+AQ0AAQZDDgEBDAABBCcOAQYNACcODQABBiYOAQwNABcOAQYNAAEBHw4BAhIA
+HA4BDAEHQQUBDVcOAAAiDgcAAAYBAgIAAAYUDwADDAwNACYPAQYGAAEBDQAB
+BkMOAQEMAAEEJw4BBg0AJw4NAAEGJg4BDA0AFw4BAg0AAQYgDgEBEQAdDgEN
+AQc/BQEHWA4AACIOAQEFAAAHAQEEAQAABgAUDwADDAwNACYPAQYGAAEBDQAB
+BkMOAQEMAAEEJw4BBg0AJw4NAAEGJg4BDA0AFw4NAAEBIQ4BBhEAHg4BDAEH
+PAUBBwENWQ4AACIOAQYFAAAHAQECAQAABgAUDwADDAwNACYPAQYGAAEBAQEM
+AAEGQw4BAQwAAQQnDgEGDQAnDg0AAQYmDgEMDQAWDgEMDQABBiIOAQQQAB8O
+AQwBBzsFAQdaDgAAIg4BBgYAAAYBAgEAAAYUDwADDAwNACYPAQYHAAEBDAAB
+BkMOAQEMAAEEJw4BBg0AJw4NAAEGJg4BDA0AFg4BBg0AAQYiDgEMEAAgDgEN
+AQc6BQEHWg4AACMOBgABAQECAwABAgENEw8AAw0MDQAmDwEGBwABAQwAAQZD
+DgEBDAABBCcOAQYNACcODQABBiYOAQwNABYOAQYNACQOAQIPACEOAQwBBzkF
+AQdaDgAAIw4BBgYAAQIDAAECAQ0TDwADDQwNACYPAQYHAAEBAQELAAEGQw4B
+AQwAAQQnDgEGDQAnDg0AAQYmDgEMDQAWDgEGDAABASQOAQwPACIOAQ0BBzcF
+AQcBDVoOAAAkDgEBBQABAgMAAQEBDRMPAAMNDA0AJg8BBgcAAQEBAQsAAQZD
+DgEBDAABBCcOAQYNACcODQABBiYOAQwNABYOAQIMAAECJQ4BAQ4AIw4BDAEH
+NQUBBwEMWw4AACQOAQYFAAECAwABAQEMEw8AAw0MDQAmDwEGBwABAQEBCwAB
+BkMOAQEMAAEEJw4BBg0AJw4NAAEGJg4BDA0AFg4BAQwAAQYlDgEGDgAkDgEN
+AQczBQEHAQxcDgAAJQ4BAQQAAQEEAAEGEw8AAw0MDQAmDwEGCAABAQsARA4B
+AQwAAQQnDgEGDQAnDg0AAQYmDgEMDQAWDg0AAQYlDgEMDgAlDgENAQcxBQEH
+AQxdDgAAJg4EAAEBBAABBhMPAAMNDA0AJg8BAggAAQELAEQOAQEMAAEEJw4B
+Bg0AJw4NAAEGJg4BDA0AFg4NAAEGJg4BAQ0AJg4BDAEHLwUBBwEMXg4AACYO
+AQYDAAEBAQEDAAEBAQ0SDwADDQwNACYPAQIIAAECCgABAUQOAQEMAAEEJw4B
+Bg0AJw4NAAEGJg4BDA0AFg4NAAEGJg4BBg0AJw4BDQEHLQUBBwEMXw4AACcO
+BAABAgQAAQwSDwADDQwNACYPAQEIAAECCgABBkQOAQEMAAEEJw4BBg0AJw4N
+AAEGJg4BDA0AFg4NAAEGJg4BBg0AKA4BDAEHKwUBBwEMYA4AACcOAQYDAAEC
+BAABBhMPAQwBDSYPAQEIAAECCgABBkQOAQEMAAEEJw4BBg0AJw4NAAEGJg4B
+DA0AFg4NAAEGJg4BBg0AKQ4BDQEHKgUBDWEOAAAoDgMAAQEBAQMAAQEBDRIP
+AQ0BDSUPAQwJAAECAQEJAEUOAQEMAAEEJw4BBg0AJw4NAAEGJg4BDA0AFg4N
+AAEGJg4BDA0AKg4BDQEHKQUBDGEOAAAoDgEGAwABAgMAAQEBBhIPAQ0BDCUP
+AQcJAAECCgBFDgEBDAABBCcOAQYNACcODQABBiYOAQwNABYODQABBicODQAr
+DgEMAQcoBQENYQ4AACgOAQYDAAECAQEDAAEBAQ0RDwENAQwlDwEGCAABAQEB
+CQABBkUOAQEMAAEEJw4BBg0AJw4NAAEGJg4BDA0AFg4NAAEGJw4NACwOAQ0B
+ByUFAQcBDGIOAAApDgAFAQAAAQEAAwABAQEHEQ8BDQENJQ8BAggAAQEBAQkA
+AQZFDgEBDAABBCcOAQYNACcODQABBiYOAQwNABYODQABBicODQAtDgEMAQcj
+BQEHAQxjDgAAKQ4BBgMAAQIEAAECNw8BDQYBAwABAgoARg4BAQwAAQQnDgEG
+DQAnDg0AAQYmDgEMDQAWDg0AAQYnDg0ALg4BByMFAQcBDWMOAAAqDgMAAQEB
+AQMAAQEBDDYPAQcBAAYBAAMAAQEACQABBkYOAQEMAAEEJw4BBg0AJw4NAAEG
+Jg4BDA0AFg4NAAEGJw4NAC4OAQclBQEHAQxhDgAAKg4BAQMAAQIBAQMAAQI2
+DwAKBgAAAQECAQEAAgoAAQZGDgEBDAABBCcOAQYNACcODQABBiYOAQwNABYO
+DQABBicODQAtDgEMAQcmBQEHAQxgDgAAKg4BBgMAAQEBAQQAAQwxDwAHDQwM
+DQEAAAAHAQkAAQFHDgEBDAABBCcOAQYNACcODQABBiYOAQwNABYODQABBicO
+DQAsDgENAQcoBQEHAQxfDgAAKw4EAAEBAQEDAAECAQ0vDwAFDQwMDQcAAwAG
+AQoAAQZHDgEBDAABBCcOAQYNACcODQABBiYOAQwNABYODQABBicODQArDgEM
+AQcqBQEHXw4AACsOAQEDAAEBAQEEAAEGLg8ABg0MBwwPAgcAAQEBAQoASA4B
+AQwAAQQnDgEGDQAnDg0AAQYmDgEMDQAWDg0AAQYnDg0AKg4BDQEHLAUBBwEM
+XQ4AACsOAQYEAAECAQEDAAADAgwNACoPAAcNDQwHDA0HAAcAAQEBAQoAAQFI
+DgEBDAABBCcOAQYNACcODQABBiYOAQwNABYODQABBicODQApDgENLwUBBwEM
+XA4AACsOAQYEAAMBAAYAAAEGDA0oDwAIDQwMBwcMDwIGAAEBAQELAAEGSA4B
+AQwAAQQnDgEGDQAnDg0AAQYmDgEMDQAWDg0AAQYnDg0AKA4BDAEHMAUBBwEM
+Ww4AACwOBgABAQMAAAQBBwwNDQ8BDRcPAAkNDQwMBwcMDQYABgADAQoAAQFJ
+DgEBDAABBCcOAQYNACcODQABBiYOAQwNABYODQABBicODQAnDgENAQcyBQEH
+AQxaDgAALA4BAQkAAAYBBgcMDQ0KDwENAQ0VDwENAwwDBwAEDA0NAQQABAEL
+AAEGSQ4BAQwAAQQnDgEGDQAnDg0AAQYmDgEMDQAWDg0AAQYnDg0AJg4BDAEH
+NAUBB1oOAAAsDgEGCQAABwEBBgcMDA0ACQ8DDQ8PAw0EDAUHAAMMDQQAAwAA
+BAECAQENAEoOAQEMAAEEJw4BBg0AJw4NAAEGJg4BDA0AFg4NAAEGJw4NACUO
+AQ0BBzYFAQcBDFgOAAAtDgEBCAABAQEBAwYABQcMDA0NAAYPAAMNDA0ADA8B
+DQENBQwHBwADDA0GAAQAAQEBAQ4AAQZKDgEBDAABBCcOAQYNACcODQABBiYO
+AQwNABYODQABBicODQAkDgENOQUBBwEMVw4AAC0OAQYJAAEBAwYBBwMMAQ0G
+DwADDQwMAAMNCA8BDQQMCQcABAwMBgEUAEsOAQEMAAEEJw4BBg0AJw4NAAEG
+Jg4BDA0AFg4NAAEGJw4NACMOAQwBBzoFAQdXDgAALg4BAQkAAAQGBgcMBA0D
+DwENAQ0HDAAHDQ0PDw0PDwADDQ4MAQEUAAEGSw4BAQwAAQQnDgEGDQAnDg0A
+AQYmDgEMDQAWDg0AAQYnDg0AIg4BBwEHPAUBBwEMVQ4AAC8OCQAABAYGDA0J
+DwcNDQ8FDQUMAQYUAAEGTA4BAQwAAQQnDgEGDQAnDg0AAQYmDgEMDQAWDg0A
+AQYnDg0AIQ4BDAEHPgUBB1UOAAAvDgEGCAAABAIHDA0MDwENAQ0TDwYNAQYT
+AAEBTQ4BAQwAAQQnDgEGDQAnDg0AAQEmDgEGDQAWDg0AAQYnDg0AIg4BBz8F
+AQcBDFMOAAAwDgEGBwAABAEHDQ0kDwMNAQISAAEBTg4BAQwAAQQnDgEGDQAn
+Dg4AJg4BBg0AFg4NAAEGJw4NACIOAQdABQEHUw4AADEOAQYHAAEGAQ0nDwEM
+AQERAAEBTw4BAQwAAQQnDgEGDQAnDg4AAQwlDgEGDQAWDg0AAQYnDg0AIA4B
+DAEHQgUBBwEMUQ4AADIOAQEGAAECAQ0nDwEHEQABAVAOAQEMAAEEJw4BBg0A
+Jw4OAAEGJQ4BBg0AFg4NAAEGJw4NAB8OAQwBB0QFAQcBDFAOAAAzDgEBBgAB
+Bw0PAQ0ZDwEGEQABBlAOAQEMAAEEJw4BBg0AJw4OAAECJQ4BBg0AFg4NAAEG
+Jw4NAB8OAQdGBQEHUA4AADMOAQYGAAECAQ0LDwMNGA8BAhAAAQZRDgEBDAAB
+BCcOAQYNACcODwAlDgEBDAABARYODQABBicODQAdDgEMAQdIBQEHAQxODgAA
+NA4BBgYAAQYJDwENAQ0EDAENAQ0UDwEMAQEPAAEGUg4BAQwAAQQnDgEGDQAn
+Dg8AAQYkDg0AAQIWDg0AAQYnDg0AHQ4BB0oFAQdODgAANQ4BBgUAAQEBDQcP
+AQ0BDAYHAAMMDA0AEg8BBg8AAQFTDgEBDAABBCcOAQYNACcODwABASMOAQwN
+AAEEFg4NAAEGJw4NABsOAQwBByMFAQcoBQEHAQxMDgAANg4BAQUAAQYBDQUP
+AQ0BDAgHAAQMDA0NDw8BDQEBDwBUDgEBDAABBCcOAQYNACcOEAABBiIOAQYN
+AAEGFg4NAAEGJw4NABoOAQwBByMFAAMHDQcAKAUBBwEMSw4AADcOAAcAAQEA
+AAEMAAUPAQwLBwADDAwNAA4PAQYPAAEGVA4BAQwAAQQnDgEGDQAnDhAAAQEi
+DgECDQABBhYODQABBicODQAZDgEMAQcjBQAFBwwODAcAKAUBB0sOAAA3DgAD
+BgABAAMAAAcCDQ8PDQ0MAAwHAwwBDQsPAQ0BAQ4AAQJVDgEBDAABBCcOAQYN
+ACcOEQABBiAOAQwOAAEMFg4NAAEGJw4NABgOAQwBByMFAQcBDQMOAQwBBygF
+AAcHDA4OBwcNAEQOAAA4DgEGBQAABQYPDQ0MAAwHAAcGBwcMDA0NAAkPAQYO
+AAEBAQZVDgEBDAABBCcOAQYNACcOEgABDB8OAQYOABcODQABBicODQAYDgEH
+IwUBBwEMBQ4BDAEHKAUABgcODQUFB0QOAAA5DgEBBAAABQENDQwMAAYHBAYD
+BwAGBgcHDAwNCA8BDQEBDgABAlYOAQEMAAEEJw4BBg0AJw4SAAEBHg4BDA4A
+AQIXDg0AAQYnDg0AFg4BDAEHIwUBBwENBw4BDQEHKAUBBwENBAcBDUIOAAA5
+DgEGBAAABAEGDAwEBwMGBAIDBgAHBwYGBwcMDQAGDwENAQYPAFcOAQEMAAEE
+Jw4BBg0AJw4NAAEGBQABAh0OAQIOAAEGFw4NAAEGJw4NABUOAQwBByMFAQcB
+DAkOAQwBBygFAAcHDgwHBQcMAEEOAAA6DgEBBAABBgMHAwYKAgEGAQYEBwEM
+AQ0EDwADDQwBAA4AAQZXDgEBDAABBCcOAQYNACcODQABDgEGBQABBhsOAQYP
+ABgODQABBicODQAUDgEMAQcjBQEHAQ0LDgENAQcoBQAHDQ4HBQUHDABADgAA
+Ow4DAAEBAQYDBwAEBgYCAgsDAAcGBwYHBwwMAAMNAQwBBgYAAQEBAQcAWA4B
+AQwAAQQnDgEGDQAmDgEGDQAAAw4OAQAFAAEGGQ4BDAEBDgABAhgODQABBicO
+DQATDgEMAQcjBQEHAQ0NDgENAQcnBQAEBwcNDQMHAQw/DgAAOw4ACwEAAAEG
+BwcGBgICAA0DAwYBBwEHAwwAAwcGAQAFAAAEAgYGAQUAAQZYDgEBDAABBCcO
+AQENACYOAQYNAAADDg4MAAYAAQIXDgEMAQEPAAEGFw4BBg0AAQYmDgEGDQAS
+DgEMAQcjBQEHAQwPDgEMAQcoBQAGDQ4NBQUHPw4AADsOAQYDAAAEBgcGBgMC
+AAMDCAgADAMACAYHBwwMBwcGBQABAQMGAQQBAQMAAQFZDgEBDAABBCYOAQYO
+ACYOAQIMAAEBAw4BBgYAAQEBDBQOAQYBAQ8AAQIYDgEGDQABBiYOAQQNABEO
+AQwBByMFAQcBDREOAQ0BBycFAAMHDQ0ABAcBDD0OAAA7DgEGAwAAAwIHBgAE
+AgEDBAILAwEGAQYEBwEGBQABAgMGAQIEAAEGWQ4BAQwAAQQmDgEBDgAlDgEM
+DQABAgQOAQYHAAEGEg4BBhEAAQYXDgEMDgABBiUOAQwOABAOAQwBByMFAQcB
+DBMOAQwBBygFAAYHDg4HBQc9DgAAOw4BBgMAAQEBBgMCAwMBCQEJAwMDAgkD
+BAYBAQQAAQEEBgEBAwABAVoOAQEMAAEEJQ4BBg8AJQ4BAg0AAQYFDgECBwAA
+AwEGDAANDgEGAQERAAECGA4BAQ4AAQYlDgEBDgAQDgEHIwUBBwENFQ4BDQEH
+JwUABwcMDAcFBQcAPA4AADsOAQYDAAMCAAUDCAoKCQADCgMJAAUKAwMCAgAJ
+AwECBQAABQIGBgIBAAQAAQZaDgEBDAABBCQOAQIQACQOAQQOAAEGBg4BAgkA
+AAQBBgYMBQ4AAwYGAgAUAAEMFw4BAg8AAQYjDgEMAQEPAA4OAQwBByMFAQcB
+DRcOAQ0BBycFAQcBBwQFAQcBDDoOAAA7DgAHBgAAAQICAwAECAAECgkJCgcJ
+AQMBAggDAQIFAAADBgIBAAYAWw4BAQwAAQQiDgEGAQERACMOAQIPAAEGBw4B
+AicAAQYWDgEGAQEQAAEGIQ4BDAECEQAODgEHIwUBBwENGQ4BDAEHLQUBBzoO
+AAA7DgAHBgABAgIDAwADCAMKAQkBCQMKBgkJAwEBBAABAQcAAQZbDgEBDAAB
+BBYOAQwJBgEBFAAgDgADDAYBABAAAQYIDgEGJQABBBAOAQwBDAMGAQITAAEG
+Gw4BDAMGAQIUAAwOAQwBByMFAQcBDRsOAQwBBy0FAQcBDDgOAAA7DgADBgAB
+AAQDAQgBCAUKAAUJCgoLCgAGCQEDAQIGAwEBDAABBlsOAQEMAAEEFg4BBh4A
+GA4GBgECAQETAAoOAQYjAAECDw4BBBoAAQYZDgEBGgAMDgEHIwUBBwEMHQ4B
+DAEHLQUBBzgOAAA7DgADBgABAAUDAQgBCAQKAAYJCQoLCwoHCQYDAQELAAEB
+XA4BAQwAAQQWDgEGHgAYDgEGGgALDgEMAQEgAAECEA4BBBoAAQYZDgEBGgAK
+DgEMAQckBQEHHw4BDQEHLQUBBwEMNg4AADsOAAQGAAECBAMECAAJCgoJCQoK
+CwsKAAcJAAYDAgMIAwILAAEGXA4BAQwAAQQWDgEGHgAYDgEGGQABAQ0OAQYe
+AAEGEQ4BBBoAAQYZDgEBGgAJDgEMAQclBQEHIA4BDAEHLQUBBzYOAAA7DgMA
+AQIFAwMIAwoAAwkJCgADCwEKCQkAAwoIAgALAAEGXA4BAQwAAQQWDgEGHgAY
+DgEGGQABBg4OAQwBBBoAAQEBBhIOAQQaAAEGGQ4BARoACQ4BByYFAQchDgEM
+AQctBQEHNQ4AADsOBAABAgQDAwgDCgMJAQoDCwEKBwkABAoKAwELAF0OAQEM
+AAEEFg4BBh4AAQwXDgEGGQABBhAOAAMMBgEAFQABAQEGFA4BBBoAAQYZDgEB
+GgAHDgENAQcmBQEHAQwiDgENAQctBQEHAQwzDgAAOw4EAAEBAQYDAwMIBAoA
+BwkJCgoLCwoAAwkABwoKCQoIAwIADABdDgEBDAABBBYOAQwJBgQCBAENAAEM
+Fw4BDAQGAAQCAgEBEQABBhMOAAMGBgEADwAAAwEGBgAWDgUGAAUEAgIBAQAR
+AAEGGQ4FBgECAQIDAREABw4BByYFAQclDgEMAQctBQEHMw4AADsOBAAAAwYM
+BgADAwEIAQgDCgMJBgoABQkKCggDAAMGDQBdDgEBDAABBDMOAQwBBiYOCAYA
+BAQBAQAYDgMGAQQBAgQBAQQDBikOAQwJBgADBAIGACgOAQwJBgEEAQEHDgEH
+JQUBBwEMJg4BBy4FAQcBDDEOAAA7DgMAAAUBDA8MAgADAwAECAgKCgUJAA0K
+CgkKCQMCAgwPDwwCAAwAXQ4BAQwAAQT9DgEHJAUBBygOAQcvBQEHMQ4AADsO
+AwAAFgYNDQEAAQIDAwgKCgkIAwMCAwoKAwIDAAAFAgwPDwYACwABAV0OAQEM
+AAEE/A4BDQEHIwUBBykOAQcwBQEHMA4AADsOAwAAAwYNBAADAAAIAQIDAwoK
+CAgDAwAECAMGAQUAAAUCDw8MAQAKAAEGXQ4BAQwAAQT7DgEHAQcjBQEHAQwp
+DgADDAcHAC8FAQcvDgAAOw4ABQAAAQwMAAUAAAMBBgIABgMABAICDAYHAAAE
+DA8NAgoAAQZdDgEBDAABBPoOAQ0kBQEHLQ4BBzAFAQcuDgAAOw4ABQAAAQwG
+AAMAAwEBDQECBwEAAwYNBgAHAAAEBg8NAgoAAQZdDgEBDAABBPkOAQ0BByMF
+AQcBDC4OAQcBBy8FAQcBDCwOAAA6DgAGBgAAAQwGAwADAQEPAQcEAAMBAAMM
+DwYABQAABgEBBg8NAgoAAQZdDgEBDAABBPgOAQckBQEHMQ4BDTAFAQcsDgAA
+Og4ADgYAAAEMBgAAAQQBBg8MAwEABwICAQYMDwYABAAABwECAQwPDwIACgAB
+Bl0OAQEMAAEE9w4BDQEHIwUBBwENMg4BBy8FAQcsDgAAOg4AIwYAAAEMDAEA
+AgYBDA8MAAEAAQAABgwPDQEAAAEGBgENDw0BAAoAAQZdDgEBDAABBPYOAQcm
+BQENMw4BBwEHLQUBBywOAAA6DgAOBgAAAQwPBAABAQYPDwYGAAAOBgwPDwYA
+AAIGAQYPDwwLAAEGXQ4BAQwAAQT1DgENAQclBQEHAQ00DgEHLQUBBwEMKw4A
+ADoOAQYDAAADBg0NAAMGAw8BBAYAAQYBDAMPAAkGAQABBg8PDQYACwABBl0O
+AQEMAAEE9A4BBwEHJQUBBwENNQ4BDAEHLQUBBwENKg4AADoOAQYDAAAEBAYM
+DQQPAQwBAQYAAAMCBw0AAw8ACAwMDQ8PDQYBCwABBl0OAQEMAAEE8w4BDCYF
+AQcBDDgOAQcuBQENKQ4AADoOAQYDAAAJAQYGBwwMBwYEAAcAAAUBBgYMDAAF
+DQADDAYGAAwAAQZdDgEBDAABBPIOAQ0BByUFAQcBDDoOAQctBQEHAQ0oDgAA
+Og4BBgQAAAgGBgcMBwYGAQgAAQEEBgAHBwcMDAcGAQAMAF4OAQEMAAEE8Q4B
+ByYFAQcBDDwOAQctBQEHAQ0nDgAAOg4BBgQAAQEFBgADAQABAAgAAQEGBgAG
+BwcCAAABCgBeDgEBDAABBPAOAQ0BByUFAQcBDD4OAQctBQEHAQwmDgAAOg4B
+BgUAAAgBAQIBAAABAQkAAQEBAgUGAAUCAAABAQAKAF4OAQEMAAEE7w4BBwEH
+JQUBBwENPw4BDAEHLQUBBwENJQ4AADoOAQYKAAEBAQEMAAAEAQECAQMAAQIB
+AQsAXg4BAQwAAQTuDgEMJgUBBwEMQg4BBy0FAQcBDSQOAAA6DgEGCAADARIA
+AAMBAgEACwABBl4OAQEMAAEE7Q4BDAEHJQUBBwENRA4BBy0FAQcBDSMOAAA6
+DgEGHAADAQwAAQZeDgEBDAABBOwOAQcmBQEHAQxGDgEHLQUBBwEMIg4AADoO
+AQYrAAEGXg4BAQwAAQTsDgEHJgUBDUgOAQctBQEHAQwhDgAAOw4rAF8OAQEM
+AAEE7A4BByYFAQxIDgADDAcHACwFAQcBByAOAAA7DioAAQFfDgEBDAABBOwO
+AQcmBQEMSg4BBy0FAQcBDR8OAAA7DioAAQZfDgEBDAABBOwOAQ0BByMFAAMH
+BwwASg4BDC4FAQ0fDgAAOw4BBhoAAQEBAQ0AYA4BAQwAAQTuDgEHIgUBDUwO
+AQcuBQENHw4AADsOAQYZAAUBCgABBmAOAQEMAAEE7g4BDSEFAQdNDgENAQcs
+BQEHAQwfDgAAPA4ZAAAEAQECAgUBBgBhDgEBDAABBO4OAQwfBQADBwcMAE4O
+AQwBBykFAAMHBwwAIA4AADwOAQYYAAAGAQECBAICBAEEAAEGYQ4BAQwAAQTu
+DgEMHwUBB1EOAQwBBygFAQciDgAAPQ4YAAAJAQECBgYCAgEBAAQAAQFiDgEB
+DAABBCgOAAgMBgYCAgYGDL4OAQ0fBQEHUg4BDAEHJwUBByIOAAA9DgEGFwAA
+BgEBAgYGAgMBBAABBmIOAQEMAAEEJw4BBggAAQK9DgEHHwUBB1MOAQwBByYF
+AQciDgAAPg4XAAAIAQECBAICAQEEAAEGYw4BAQwAAQQlDgEMAQEKAAEBAQy7
+DgEMAQcdBQEHAQ1UDgEMAQcGBQEHAQccBQEHAQ0iDgAAPg4BBhcAAAUBAQIB
+AQAFAAEBZA4BAQwAAQQlDgEBDAABAQEMuw4BDAEHGwUBBwENVg4BDAEHBAUA
+BAcMDAcaBQEHAQ0jDgAAPw4BBhYAAwEGAAEGZQ4NAAEEJA4BAg4AAQK8DgEM
+AQcZBQEHAQxYDgEMAQcDBQAEBwwOBxoFAQ0kDgAAQA4BAR0AAQZlDgEGDQAB
+BCMOAQYQAAEGvA4BDAEHCAUBBwEHDQUBBwENWg4BDQEHAwUABQcNDAcHABgF
+AQ0kDgAAQQ4BBhoAAQFnDgECDQABBCMOAQQQAAECvg4BBwYFAAQHDA4HCwUB
+BwEMXA4BDAEHBAUAAw0ODQAYBQENJA4AAEIOAQYBARYAAQEBBmcOAQYOAAEE
+Iw4SAL4OAAwMBwUHBwUHBw4ODQcJBQEHAQxeDgEMAQcDBQAEBwwOBw4FAwcF
+BQEHAQwkDgAARA4BBhMAAQEBBmgOAQwBAQ4AAQQjDhIAvw4BDAUNBA4BDAEH
+BwUBBwEMYA4BDAEHAwUABQcMDgwHAAsFAQcDDQEHAwUBByYOAABGDgEGAQEO
+AAEGag4BBhAAAQQjDhIAAQzJDgENAQcFBQEHAQxiDgEMAQcDBQAEBwwOBwoF
+AQcBDQMOAAQMBwUHJw4AAEkOBQYBAAEBBAZqDgADDAYBABEAAQQjDhIAyw4B
+DQUHAQxkDgEMAQcDBQAFBwcNBwcABAUABQcMDAcNAAUOAwwnDgAAtA4IBgEC
+AQEUAAEEIw4BARAAAQH/DjgOAQwBBwQFAAMMDg0ABAUBBzMOAAC0DgEGHQAB
+BCMOAQYQAAEG/w45DgAFDAcFBQcAAw4BBwQFAQcBDDEOAAC0DgEGHQABBCMO
+AQwQAAEM/w46DgAEDA0NDAQOAQcEBQEHAQwwDgAAtA4BBh0AAQQkDgEGDgAB
+Bv8ORA4BBwMFAQcxDgAAtA4BBh0AAQQlDgECDAABAv8ORQ4BDAMHAQ0xDgAA
+tA4BBh0AAQQmDgEGCgABAv8OfA4AALQOAQwKBgEBAQERAAEEJw4BBgEBBgAB
+AQEG/w59DgAAyA4BDAEMCQYpDgEMBAYBDP8Ofw4AAP8O/w6CDgAA/w7/DoIO
+AAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/
+DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA
+/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6C
+DgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O
+/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4A
+AP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8O
+gg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/
+Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIO
+AAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/
+DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA
+/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6C
+DgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O
+/w6CDgAA/w7/DoIOAAD/Dv8Ogg4AAP8O/w6CDgAB
+====
diff --git a/images/onlyblue_16c.dat b/images/onlyblue_16c.dat
new file mode 100644 (file)
index 0000000..3aeeaac
--- /dev/null
@@ -0,0 +1,14 @@
+# Lilo boot menu background configuration  (Lilo 23)
+#
+# color palette: 0 black,         3 magenta,       7 pink,
+#                8 middle grey,  10 bright grey,  13 white
+#
+# bmp-table  = <x>,<y>;<ncol>,<nrow>,<xsep>,<spill>
+# bmp-colors = <fg>,<bg>,<sh>;<high-fg>,<high-bg>,<high-sh>
+# bmp-timer  = <x>,<y>;<fg>,<bg>,<sh>
+
+bitmap = onlyblue.bmp
+
+bmp-table  = 3,4;4,26,19,1
+bmp-colors = 7,,0;15,,0
+bmp-timer  = 37,2;7,4,0
diff --git a/images/onlyblue_16c.uu b/images/onlyblue_16c.uu
new file mode 100644 (file)
index 0000000..b975f5c
--- /dev/null
@@ -0,0 +1,154 @@
+begin-base64 644 onlyblue.bmp
+Qk2uGgAAAAAAADYEAAAoAAAAgAIAAOABAAABAAgAAQAAAHgWAAAgHAAAIBwA
+AAABAAAAAQAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAMDAwACAgIAA
+AAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8O
+/w6CDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8E
+gAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/
+BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA
+AQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQB
+DgAAAQ7/BP8EgAQBDgAAAQ7/BP8EgAQBDgAA/w7/DoIOAAE=
+====
diff --git a/images/tuxlogo_16c.dat b/images/tuxlogo_16c.dat
new file mode 100644 (file)
index 0000000..195474e
--- /dev/null
@@ -0,0 +1,14 @@
+# Lilo boot menu background configuration  (Lilo 23)
+#
+# color palette: 0 black,         3 magenta,       7 pink,
+#                8 middle grey,  10 bright grey,  13 white
+#
+# bmp-table  = <x>,<y>;<ncol>,<nrow>,<xsep>,<spill>
+# bmp-colors = <fg>,<bg>,<sh>;<high-fg>,<high-bg>,<high-sh>
+# bmp-timer  = <x>,<y>;<fg>,<bg>,<sh>
+
+bitmap = tuxlogo.bmp
+
+bmp-table  = 59,5;1,23,
+bmp-colors = 6,9,0;15,9,0
+bmp-timer  = 66,28;6,8,0
diff --git a/images/tuxlogo_16c.uu b/images/tuxlogo_16c.uu
new file mode 100644 (file)
index 0000000..7d2cac0
--- /dev/null
@@ -0,0 +1,739 @@
+begin-base64 644 tuxlogo.bmp
+Qk14gQAAAAAAADYEAAAoAAAAgAIAAOABAAABAAgAAQAAAEJ9AAAgHAAAIBwA
+AAABAAAAAQAACQgJAB4xPgA1frkAQ7zkAKK50wCtvfcAvsLJAN3i4wACS/8A
+AIv/AACt/wABz/sAWM77ALri+wDl9vsA//v7AAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8F
+/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUA
+AP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8F
+ggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/
+Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIF
+AAD/BWMFAwD/BRwFAAC9BQEApQUBAP8FHQUAAL4FAQCkBQEA/wUdBQAAKAUD
+AAMFAwABBQMAAAMFAAAADwUDAAEFAQUDAA8FAQABAAMFAwAIBQMABAUDAAQF
+AwADBQEAAQAGBQMABAUDAAEFAQUDAAEFAQUDAAQFAwADBQADAAAFAAMAAQUB
+BQMAAQUBBQMAAQUDAAADBQAAAAcFAAYAAAUABQUDAAQFAwAPBQEAAQADBQUA
+AQUBBQMADwUBAAEAAwUDAAgFAwABBQEFAwABBQMAAAMFAAAAAwUDAAEFAQUD
+AAYFAwABBQMAAQUBBQMAAQUBBQMAAQUBBQMAAQUDAAEFAQUDAAEFAQUDAAYF
+AwADBQAEAAUAAAMFAAMAAAUAAwABBQEFAwABBQEFAwABBQMAAQUDAP4FAAAp
+BQEABQUBAAMFAAYABQUABQANBQEAAwUABAAFBQAQBQAFAAUABQAAAwUBAAYF
+AQADBQAEAAUFAAMFAAQABQUAAwUABgAFBQAFAAUFAAcABQUABQUAAAMFAAcA
+BQUABQUAAAMFAAQABQUAAwUACwAFBQAFAAUABQUAAAMFAAQABQUAAwUBAAoF
+AAMABQUAAwAACAUABQUABQUAAwUBAA4FAAUABQAFAAADBQAEAAUFAAMFAQAO
+BQAFAAUABQAAAwUBAAYFAQADBQAEAAUFAAMFAAgABQUABQAFAAMFAAQABQUA
+CAUBAAMFAAQABQUAAwUABAAFBQAEBQEAAwUABAAFBQADBQAEAAUFAAYFAQAD
+BQASAAUFAAAFBQAFBQAFAAUABQUAAwUABAAFBQADBQAHAAUFAAUFAACCBQEJ
+LghMBQAAKQUBAAUFAQADBQAEAAUFAAwFAAQABQUABgUBAAQFAQALBQEAAwUB
+AAMFAQAGBQEAAwUABAAFBQADBQAEAAUFAAMFAAQABQUACgUABAAFBQAGBQAE
+AAUFAAYFAQAGBQEAAwUABAAFBQADBQAEAAUFAAMFAQAKBQEAAwUBAAUFAAQA
+BQUADwUABAAFBQADBQEAAwUABAAFBQADBQAEAAUFAAsFAQADBQEAAwUBAAYF
+AQAGBQEAAwUABAAFBQADBQEABgUBAAgFAAQABQUAAwUBAAYFAQAEBQEAAwUA
+BAAFBQAGBQEABgUBAAMFAAQABQUAAwUABAAFBQADBQAEAAUFAAMFAAQABQUA
+AwUBAAUFAQCBBTIISgUAACkFAQAFBQEAAwUABAAFBQAKBQEAAQADBQEABgUB
+AAUFAQABAAkFAQADBQEAAwUBAAYFAQADBQAEAAUFAAMFAAQABQUAAwUABAAF
+BQAIBQEAAQADBQEABgUABAAFBQAGBQEABgUBAAMFAAQABQUAAwUABAAFBQAD
+BQEACgUBAAMFAQADBQEAAQADBQEADQUBAAEAAwUBAAQFBAAAAwUFAAADBQEA
+AwUBAAEACQUBAAMFAQADBQEABgUBAAYFAQADBQAEAAUFAAMFAQAGBQEACAUD
+AAQFAQAGBQEABAUBAAMFAAQABQUABgUBAAYFAQADBQAEAAUFAAMFAAQABQUA
+AwUABAAFBQADBQAEAAUFAAMFAQADBQEAAQCBBQEJMghKBQAAKQUBAAUFAQAD
+BQAEAAUFAAgFAQABAAUFAQAGBQEABwUBAAEABwUBAAMFAQADBQEABgUBAAMF
+AAQABQUAAwUABAAFBQADBQAEAAUFAAcFAQAFBQUAAAUFBQAFBQAFAAADBQUA
+AAYFAQADBQAEAAUFAAMFAAQABQUAAwUBAAoFAQADBQAEAAUFAAUFBQAHBQEA
+AQAFBQEABwUABAAFBQADBQEABQUBAAEABwUBAAMFAQADBQEABgUFAAADBQUA
+AAMFAAQABQUAAwUFAAADBQUAAAgFAAMABQAABAUFAAADBQUAAAQFAQADBQAD
+AAUFAAUAAAMFBQAABgUBAAMFAAQABQUAAwUABAAFBQADBQAEAAUFAAMFAAQA
+BQUAAwUABAAFBQCCBQEJNAhJBQAAKQUHAAAHBQUAAAUFAAAHBQEABwUBAAMF
+AQABBQMACAUBAAYFAQADBQEAAwUBAAYFAAgAAAUFAAUFAAMFAAQABQUAAwUA
+BAAFBQAHBQAHAAUFAAUFAAADBQAHAAUFAAUFAAADBQAEAAUFAAMFAAsABQUA
+BQUAAAUFAAADBQEAAQUDAAADBQUAAAoFAQADBQAKAAUFAAUFAAUFAAMFAQAG
+BQEABwUBAAMFAQADBQAIAAUFAAAFBQAHBQEABgUBAAMFAQADBQEABgUBAAMF
+AQABBQMAAAYFBQAFBQADBQEAAwUBAAEFAwAHBQAEAAUFAAMFAQADBQEAAQUD
+AAEFAQUDAAAGBQUABQUAAwUABAAFBQAGBQEAAwUBAAEFAwAADQUFAAUFAAUF
+AAAFBQAAAwUBAAEFAwAACQUFAAUFAAUFAAB+BQEJNghIBQAAKQUBAAUFAQAD
+BQEAAQUEAAYFAQABAAYFAwADBQAEAAUAAAQFAQABAAYFBAABBQEFAwAHBQAE
+AAUAAAQFAwAEBQMAAQUBBQQABgUDAAMFAwADBQEAAwUDAAQFAwABBQEFBAAB
+BQEAAwUDAAMFAAQABQAAAwUBAAYFAAYAAAUFAAADBQMAAwUDAAgFAQABAAQF
+BAABBQEFAwADBQAEAAUAAAYFAQABAAYFBAABBQEFAwAIBQMAAwUABgAFAAAF
+BQQAAQUBBQMAAwUABAAFAAAFBQADAAUFAAMAAQUBBQMAAwUACQAFAAAFAAUA
+AAAEBQMAAwUBAAcFAwADBQAGAAUAAAUFBAABBQEAAwUDAAMFAAQABQAABAUD
+AH4FAQk2CEgFAAApBQEABQUBAAYFAQAKBQEAAQAQBQEAAQAJBQEADgUBABQF
+AQAUBQEAEAUBADcFAQABAAMFAQAKBQEABwUBAAEACQUBABwFAQATBQEAIAUB
+ABQFAQCWBQEJNghIBQAAKQUBAAUFAQAGBQEADAUBAA4FAQALBQEADgUBABQF
+AQAUBQEAEAUBADkFAAQABQUACgUBAAYFAQALBQEAHAUBABMFAQAgBQEAFAUB
+AJYFAQk2CEgFAAAoBQMAAwUDADsFAQABACgFAQABAFcFAQABAEIFAQABAB8F
+AQABAKsFAQk2CEgFAAAzBQEAOQUBACkFAQAUBQEAQwUBAEMFAQAgBQEAGAUB
+AJIFAQk2CEgFAAD/Bf8FAwUBCTYISAUAAP8F/wUDBQEJNghIBQAA/wX/BQMF
+AQk2CEgFAAD/Bf8FAwUBCTYISAUAAP8F/wUDBQEJNghIBQAA/wX/BQMFAQk2
+CEgFAAD/Bf8FAwUBCTYISAUAAP8F/wUDBQEJNghIBQAA/wX/BQMFAQk2CEgF
+AAD/Bf8FAwUBCQEJNAgBCUgFAAD/Bf8FBAUBCQEJMggBCUkFAAD/Bf8FBQUB
+CQEJMAgBCUoFAAD/Bf8FBgUBCQEJLggBCUsFAAD/Bf8FBwUFCSYIBAlMBQAA
+/wX/BQsFJwlQBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/
+Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIF
+AAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/
+BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA
+/wX/BYIFAAD/Bf8FggUAAP8FxwWnChMFAAD/BcYFqQoSBQAA/wXFBasKEQUA
+AP8FxAUHCqAJBgoQBQAA/wXEBQYKogkFChAFAAD/BcMFBgqkCQUKDwUAAP8F
+wwUFCqYJBAoPBQAA/wXDBQUKpgkECg8FAAD/BcIFBQqoCQMKDwUAAP8FwgUF
+CqgJAwoPBQAA/wXCBQUKqAkDCg8FAAD/BcIFBAqpCQMKDwUAAP8FLgUBBEUF
+AAMGBQ0ASwUECqkJAwoPBQAA/wUqBQYEAQIFBDoFAQYDBAECAQIEAQAFAgIE
+BAYAQwUECqkJAwoPBQAA/wUpBQAMBAQCAgECAQECAQICAwQ2BQAEBAQCAgsB
+AAQCAgQEQQUECqkJAwoPBQAA/wUnBQADBAQCAAwBAAMCBAQANAUBBAEEDwEA
+BAICBARABQQKqQkDCg8FAAD/BSQFAAQGBAQCBQEAAwIBAgADAQECBAEBAgEE
+MgUBBgECBgEADwIBAgECAgECAQIBAQICBAA/BQQKqQkDCg8FAAD/BSEFAwQA
+DwMCAQECAQIBAgECAQIBAgAHAQEEAQQvBQEEAQIFAQANAgECAQIBAgECAQIB
+AgADAQADAgQEAD0FBAqpCQMKDwUAAP8FHgUABQ0GBAQCAAMBABcCAQECAQIB
+AgECAgECAQIBAQIBAQIEBAAtBQEGAQQEAQAEAgECAQoCAAgBAgECAQIEBDwF
+BAqpCQMKDwUAAP8FGgUABAYFBgQDAgAGAQECAQIBCQIABgECAQIBAgUBAQID
+BCwFAQIEAQAFAgECAgEADAIABwECAQICDQQAOgUECqkJAwoPBQAA/wUWBQAO
+DQYFBAMCAgECAQIBAgEPAgAFAQICAQIABgEABAQEBQQoBQEGBAEBAgEBEgIA
+BAECAQQ7BQQKqQkDCg8FAAD/BRAFAAYNBQYFBgQEAgAGAQECAQIBFQIABAEC
+AQIEAQAEAAABAQMEBAYABAUGBQQbBQAEBwYEAgMBAQIBAQ0CAQoGAgEBAwIB
+BwcFAQYxBQQKqQkDCg8FAAD/BQ4FAAUNBgQEAwAEAgADAQIBAA8CAQoMAgAE
+AQIBAgQBBAADAQMCAQQBAgQEEgYACAUEBQQFBgQCBQEBAgEBCQIABAoCAgoK
+AgAEAQICBzgFBAqpCQMKDwUAAP8FCQUABQ0GDQYEAAYCAQEMAgEKBAIACgoC
+CgICCgIKAgoIAgEBAQIEAQwAHQEEAAMBCQIADAoCAgoCAgoCCgICCgQCAAUB
+AgMGDQA2BQQKqQkDCg8FAAD/BQYFAAUHDQQEAwAYAgAQCgIKCgIKAgoKAgoK
+AgoCCgcCAAQBAgEBLQAABAEBAgEGAgAQCgICCgIKAgoKAgoCCgICCgYCAQQ2
+BQQKqQkDCg8FAAD/BQMFAAQEBQQDFwIBCgMCAAULAgsKAgAECgAJAgoKAgoC
+CgIKAAUCAQEBAgQBLAADAQYCABIKAgIKCgILCgIKAgoCCgIKAgoGAgEECgUB
+BioFBAqpCQMKDwUAAP8FAwUBBA0CAQoFAgAJCgICCgIKAgoCAAQKABACCwoL
+CgILCgoLCgoLAgoKBwIAAwECAQAtAAEBAQEGAgEKAQIDCgAEAgsCCwUKAAcC
+CwIKAgIKAAUCAAUEDQUFBAAwBQQKqQkDCg8FAAD/BQENAQQNAgAVCgICCgIK
+AgoCAgoCCgILCgIKCgILAAMKAA4CCwoKCwoCCwoCCwoCCgUCAQEBAgMBLAAB
+AQEBBQIABgoCCgoCCwQKAAgCCwoCCgoCCwQKBgIAAwMFDQAxBQQKqQkDCg8F
+AAD/BQEECAIBCgMCAQoDAgAHCgICCgIKAgAFCgAQAgsKCgsKCgILCgsKCgsC
+CwQKAQsDCgECAQoFAgMBLAABAQEBBQIADgoCCgIKCgILCwoLCgoLBAoABwIL
+AgsCCgoABQIBBQENMAUECqkJAwoPBQAA/gUACQ0CAgoCCgICCgADAgAECgIK
+AgMKAAQCCwoCAwoADAILAgsKCgMKAgsKCwMKAQIBCwUKAAkDCgoCCwIKAgoA
+AwIAAwECAQAtAAEBBQIBCgECBAoADQsKCgILAgsKAgsKAgsAAwoABwILCgIK
+AgoAAwIAAwwEDQAuBQQKqQkDCg8FAAD9BQALDQUCCgIKAgoCCgIAAwoAEwIK
+CgIKAgoKAgsKAgsKCwoKAgsAAwoAEAsKCgMLCgsKCgMLCgsKCgsDCgECAQoF
+AgEBAQEtAAEBAQEEAgAPCgILAgsKCgILCgoLCgoLAAQKAAYCCwoLAgsECgAL
+AgoCAgMEBQ0FBQQABgUBBiIFBAqpCQMKDwUAAP4FABEEAwIKAgoCCgoCCgoC
+CgoCCwAGCgELAwoACgILCgsKCgMLCgsDCgAEAwoDCwMKAAoDCgsKCwoCCwIK
+BAIBAQEBLQABAQEBAwIACwoCCgIKCgILCgoDAAMKAAUDCgMKCwAECgASAgsK
+AgsCCwoKAgsCAwMEBA0NCAUBBiAFBAqpCQMKDwUAAP0FABsNBQMCCgIKAgoC
+CgoCCwoLCgoCCwoCCwoCCwsABAoAAwMKCwADCgAEAwsKCwQKAAMDCwsABAoA
+BgILCgoCCgMCAQEBAQYACwEBAAEBGwABAQEBBAIGCgAPCwILCgoDCwoLCwoK
+AgsLAAMKABELCgMLAgsLCgoCCwIDAwwNDQAoBQQKqQkDCg8FAAD/BQAGAwIK
+AgoCAwoBCwMKAQIBCwYKAA4LCgoCCwoLCwoLCgsKCwMKABIDCwoLCwoKAgsK
+CwsKCgILAgoDAgAPAQEAAAECBgYHDg8ODw4PAAQOAAUHBwYEBAADARUAAQEB
+AQMCAAYKAgoKAgsDCgAYCwoLCgoDCwILCgsKAgsKCwILCgILCgILBAoABwIL
+AwMMDQYAJgUECqkJAwoPBQAA/gUABQ0DAgoCAAMKABALCgILCgsLCgoLAgsK
+CgILAwoAJwsKAgsDCgMKAwoLAwoKAwoCCwsKCwoKAgsKCgIKAgoCAgEAAgYG
+DgASDwAGDgcGBAEBEwABAQQCACcKAgsKCgILCwoKAgsLCgoLCgoDCgsKCgMK
+CgMKCwoKCwoKCwsKCgIAAwMAAwwNDQAHBQEGHAUECqkJAwoPBQAA/gUACgYF
+AgoKAgoKAgsECgAxAgsKAgsKAgsKCwoKAwoLCgsKCwoLCgsKCwsKCgsKCwIL
+CgILCgoLAgsCCgICAQIEBwAYDwAGDg4GBgEBEAABAQMCABsKAgoKAgsKCgIL
+CgsKCgMLCgoLCgoDCgsKCgsAAwoACAMLCgMKCwILBAoABgIDAwUNDSIFBAqp
+CQMKDwUAAP8FAAQFAgoCAwoACwsKCwoDCwoLCwoLAAUKABUCCwoKAwoKCwIL
+AwsKAwsCCwMKCgMABgoACwsCCwoCCwICBAQOAB0PAAMHBgIADwABAQQCAQoB
+AgMKACoCCwoKCwoKCwoKAwsKCwoLCgMKCwILCgsKCgMKCwoLCgMKCgsKCgID
+Aw0iBQQKqQkDCg8FAAD/BQAEDQIKAgMKAQIBCwYKABECCwoCCwoDCgsKCgsK
+CwMKCwADCgEDAwoAFgsKCgsKCgsLCgoLCgILAgsCCgQNDg4fDwADDgYCAA0A
+AQEDAgEKAQIDCgAtCwoLCwoLAgsDCgsKCgMKCwILCgsKCwoLCgsKCgsKAwoD
+CgsDCgMKAwoDAwQNACAFBAqpCQMKDwUAAP8FAAUNAwIKAgADCgAMAwoDCwMK
+CwoLCgoLBAoADAMKCgMKCwoDCgMLCgMLABUDCgsKAwsKAgsKCgILCgsLAgIN
+Dg4AIQ8ABA4HBgELAAEBAQEDAgAyCgoCCwIKCgILCgoLCgoDCgsKCwoLCwoD
+CgoDCgoDCgsDCgoLCgsKCwsKCwMKAgsDBA0EBQEGGgUECqkJAwoPBQAA/wUA
+Bw0CCQIKAgsABgoBCwMKAA8DCgoDCgsKCwoLCgsCCwsAAwoAGAMKCgILCgML
+CgoDCgsKCwoLCgsCAwQODiUPAAMGAgEACQABAQQCADIKAgsKCgsLCgoDCwoK
+CwoLCgoDCgsCCwoKCwoKCwoLCgsKCwMKAwoLAgsDCgoDCgMDBB8FBAqpCQMK
+DwUAAP8FACAHAwIKAgsKAgsKCwMLCgMKCwoKCwoKAwoLAgsDCgsKAgMLAAQK
+CwoLAwoAEAILCwoLCgsCCwoKCwIDBw4nDwADBwQBAAkAAAcBAgIKAgoCAAMK
+AQIBCwQKACcLAwoKAwsKCwoKCwoLCgMLCgoDCgoDCgoLCgsKCwoLCgMLCgsC
+DA0AHgUECqkJAwoPBQAA/wUABgUCCQIKAgMKACoDCgsCCwoKAwoLAgsKCgMK
+CgsKCgMKCwoKAgsKAwoKAwsKCwILAgsLCgoDCwADAwUOACoPAQcBAggABAID
+CgELAwoAEgsLCgsDCgsKCwoKAwoLAwoKAwMKABYDCwoLCwoLAwoKAwsKCgML
+CgoLCgsDHwUECqkJAwoPBQAA/wUABAUDAgIECgELBAoBCwELBAoACgsKCwoK
+AwsKAwsDCgADAwoLAAMKAQMBCwMKAA0DCgsKCwILCgsCAwQNACwPAAMOBAEA
+BgABAQMCABwKAgoCCwILCgILCgsKCgMKCgsKCwoLCgsKCwoLAwoAFAsCCwoL
+CgsKCgMLCgoDCwoDCwsEHgUECqkJAwoPBQAA/wUAHQUCAgoKAgsKAgsDCgsK
+AgsLCgMKCgMKCwoCCwoCAAMLAAsKCwoDCwsKAgsKCwADCgAKAwoLCgsDCwMN
+Di0PAAQOBgEBBAABAQMCACgKAgoLCgsKCgsKAwoKCwoKCwoDCwILCgsCCwoK
+AwoLCgoLAwoLCgMLAwoADAsLCgMKCwMMDQUFBhoFBAqpCQMKDwUAAP4FAAwG
+BQMCCgILCgoLCgsECgAFCwILCgsAAwoADwMKCgsKCwoKAgsKAwoKAgADCwAO
+CgMKCwsKCwILAwsCBQ4vDwAEDgYBAQMAAQEEAgQKAAsCCwoKCwoLAwoLAwAF
+CgAeCwoKCwoLCgoLCgMLCgoLAgsKCgsKCwMKAwoLAwMNHgUECqkJAwoPBQAA
+/wUAOQUCAgoKAgsKAgsKAwoDCwoLCgMKAwoLCgoLCgMKCgMLCgsKCgsKCwoC
+CwoLCgILCgsKCwIMDg8PDgAvDwEHAQEDAAEBAwIAHQoCCgILCgsKCwILCgoL
+CgoLCgsKCwoCCwoKAgsLAAQKABIDCwoLCgMLAwoDCgsKCwMDDQ0eBQQKqQkD
+Cg8FAAD/BQAJDQMCCgILCgoLAAMKAQsDCgEDBAoABAsKCgMECgELAwoAFQMK
+CwMKAwoLCgoDCgsKCgsLAwMNDgAzDwAFBgEAAAEABAIDCgAMCwoKAgsKCgML
+CgsDAwoAEwMKCgsKAwoKCwILCwoLCgoDCgsAAwoACQsKCwsDAwwNDQAfBQQK
+qQkDCg8FAAD/BQADDQICAAMKAB0CCwoCCwMKCwoLCgoDCwoLAgsLCgMKCwoD
+CgsKAwAECgAOCwoKCwoDCgoLCwIDBA4DDwEOMA8ABQYEAQABAAMCAAYKAgIK
+AgsFCgADCwILAAQKAAQLCgoLBAoAGAsKCgsCCwoDCwoLCgsKAwoLCgMDBQ0F
+Bh8FBAqpCQMKDwUAAP8FABEFAgoKAgsKCwoLCgsKAwoDCwADCgAWAwoKCwIL
+CgsKAwsKAwoLCgsKCwoLAwMKAAcLCgsCAwMNADUPAAUHBgQBAQAEAgUKAAQC
+CwoLAwoABQsCCwoLAAMKABgLAgsKCgsCCwoKCwoLCgoLAwoDCwoDCwwDDSEF
+BAqpCQMKDwUAAP8FABYEAgoCCwsKCgILCgMKCgsKCgMKCwoDBAoAAwsCCwAE
+CgAUAwoDCgoDCwoKCwoLCgsLAwMNDg4zDwAGDgcGBgQBBAIABQoCCwILAAMK
+AAYCCwILAgsDCgECAQsECgELBAoAEQsKAwoKAwsKCgsKAwsDBQ0NACMFBAqp
+CQMKDwUAAP8FADMECgIKCgILCgsKCwoKCwoKCwoKAwsLCgMLAwoKCwoDCwoL
+CgsKCwoKAwsCCwoLCwoCBQ0ANQ8BDgEHAwYEAgEKAQIECgECCQoBAgELAwoA
+BQsKCgsCAAMLBAoBCwMKAAkDCgMLAwwNBQYAIwUECqkJAwoPBQAA/wUABQQC
+CgILAAMKAQMDCgALCwoLCgMKCwoKAgsAAwoBCwEDBAoACAMKCgMKCgsDAwoD
+CwAFAgMDDQ4AAw8BDjEPAQ4EBgUCAA4KCgIKAgsKAgoCCgIKAgQKAAQCCwIL
+BQoADQILCwoLCgMLCgsKCwMAKAUECqkJAwoPBQAA/wUBBAECAwoBCwQKAAYL
+AwoLAgsDCgAfAwoLCgoLAwoLCgMLCgsDCgsKCwMKCgMLCgsCCwMEDgA2DwEH
+BAYBBAMCAAMKAgsABAoACwIKAgoCCgIKAgoCAAcKAAcLCwoKCwILAAMKAAUD
+CgoLAwApBQQKqQkDCg8FAAD/BQAKBAIKAgsCCwsKAwUKAQsBCwMKAAQLCgoD
+AwoBAwMKABMDCgsKAwoLCgoDCgoLCwoDAwcOAAQPAQ4xDwEHBAYDAgAVCgIL
+AgsCCgIKAgoCCgICCQIJAgoCAAQKAAULCgILCwADCgAJCwoLCgsLAwUNACgF
+BAqpCQMKDwUAAP8FAQQBAgUKAAYCCwoKCwMDCgAhAgsLCgoCCwsKAwsKAwsK
+CwoDCwoLCgoDCgsKCgIDAw0OADYPAQ4BBwQGAQQDAgEKAQIDCgAIAgoCAgkC
+AgkEAgAHCQIKAgsCCwAECgAMAgsKCwoDCgsDAwwNKQUECqkJAwoPBQAA/wUA
+BgQCCgIKAgQKAAUCCwoKCwADCgAHAgsKCgsCCwAFCgEDAwoACAMKAwsDCgMK
+AwsABAMEDg42DwEOAQcEBgMCAwoABgsCCgICCgwCABcJAgoKAgsKCwoKCwIL
+CgsKAwwNDQUFBgAmBQQKqQkDCg8FAAD/BQAEBQICAwQKAQIFCgAHAgsKCwoK
+CwAECgAWAwoLCgsKCgMLCgsKCwoLCgoLCgIDDTkPAQcEBgAGBAIKAgoCAwoB
+AgEKDgIBCQECAwoAAwsCCwAECgAGCwoDAw0NKgUECqkJAwoPBQAA/wUABwUE
+AwICCgIABQoAIwILCgoCCgILAgsLCgoLCgoDCgMLCgoDCgsCCwoCCwsDAw0O
+ADgPAQ4BBwQGAAgDAgIKCgsKChMCAAMKAgsAAwoACQsKCwMKCwMFDQArBQQK
+qQkDCg8FAAD/BQAQBQcNBAIDAgMCAgMCCgIKAgYKABICCwoKAwsKCwoKAwsK
+CwoLCgoDCwADAgMOADkPAQ4BBwQGAAoEAgoKAgoCCgIKBgIACAECAQECAQIB
+BAIAAwkCCwADCgAHCwMKCgMDDQAsBQQKqQkDCg8FAAD/BQMFAAcHBQQFBAMD
+AAUCACAKAgoKAgoKCwoDCgoDCgMLCgsCCwMKCgsLCgsCAw0ODjkPAQcEBgAI
+AwIKAgoLCgoGAgQBBAAEAQMCAAwKAgsKAwoLCgsLDA0sBQQKqQkDCg8FAAD/
+BQYFAAcNBgUNBgUDAAQCABwKAgoCCgILCgsLCgsKCgMKCwoLCgsKAgsKAwQO
+Ow8BBwQGAAwEAgoKCwoCCgIJAgIDAQoAAQEBAQMCAAsKAgsKCgMKCgMFDQAD
+BQEGKAUECqkJAwoPBQAA/wULBQAIBw0FAwICCgIFCgALAgsCCwoDCwoLCgMA
+BAoABgsLAwQNDjwPAQcDBgAIAwIKCgILCgoEAgEBDgAADAECAgoLCgMKCwoL
+Ay4FBAqpCQMKDwUAAP8FDAUABA0HDQQDAgAZCgIKAgoLCgoLCgoDCgMKCgsD
+CgsKAwMNDgA+DwAPBwcGBAMKAgsLCgIKAgIBABAAAQEDAgAICwoLCgoLAw0t
+BQQKqQkDCg8FAAD/BQ8FAAYGBQICCgIDCgALAgsLCgMLCgsKCwMAAwoABQML
+AwQOAEEPAAMODAIAAwoABwILCgICAQEAEQAABAECCwoFCwEDAQ0tBQQKqQkD
+Cg8FAAD/BREFAAYEAwICCgIDCgARAgsKCgMKAwoLCgMLCwMMDg4AQQ8ADA4F
+AwoCCwsKAgsCARMAAAoBAgsCCwsDCwMNLQUECqkJAwoPBQAA/wUSBQAYBAIK
+AgoCCgoLCgoLCgsKCwMKCwoDAw0OBA8BDhIPAAMOBw4AKA8ADA4FAgoKCwIL
+CwICARQAAAoBCgsLAwsLAw0ELAUECqkJAwoPBQAA/wUSBQAXDQQCCgIKAgoC
+CwoDCgMKAwsKCwMDBQ0AGA8DBygPAAUOBQMKAgADCwAEAgsCARUAAAgBCwML
+AwsDDS0FBAqpCQMKDwUAAP8FFAUADAMCCgIKCwoKAwoDCwQKAAULAwMNDgAY
+DwMHKA8ADA4FAgoKCwsCCwsCARUAAAsBAgoLCwMFDQUFBgAqBQQKqQkDCg8F
+AAD/BRMFABYNBAIKAgoCCwoLCgsKAwsDCwMCDQ4OGA8AAwcHDgAoDwAMDgUD
+AwoLCwMLAgIBFgABAQMDAAMMDQ0ALQUECqkJAwoPBQAA/wUUBQADDQMCAAQK
+AwsACgoLCgsLCgIEBw4ZDwMHKA8ABA4NAwMFCwADCgIBABcAAAUBAQQNDQAu
+BQQKqQkDCg8FAAD/BRQFABINBQMKCgMLCgMKCwoLCgICAQIbDwADBwcOACkP
+AQ4BBQcDAAMCAQEAEwABAQQAAAMCBg0ALgUECqkJAwoPBQAA/wUWBQARBAIL
+CgoDCwMKCwoLAgEABAcABA8BDhUPAwcqDwAIDg0FBQwEDAIDARIAAwEDAAAD
+AQQEAC4FBAqpCQMKDwUAAP8FFQUAEQYEAgoDCwoDCgMLCgIBAAAEABsPAAMH
+Bw4AKw8GDgAEBgEAAREAAAQBAQYBBAABBAEELgUECqkJAwoPBQAA/wUVBQAN
+BAIBAQoCCwoLCwICAQADAAEEAQcaDwMHMQ8ABgcBAAABAQ4AAAUBAQYCAQAE
+AAEBAQYuBQQKqQkDCg8FAAD/BRUFAAYEAQABAgIDCgADAgIBAAQAAQQBBxoP
+AAMHBw4AKg8BDgYPAQcBAgQAAQEMAAAFAQEGAQEABQAAAwEEBAAtBQQKqQkD
+Cg8FAAD/BRUFAQYBAQMAAAUBAQIBAQAGAAEGAQ4aDwMHKA8BDgkPAQYFAAUB
+AQAFAQAEBAECAQcAAQEBBC4FBAqpCQMKDwUAAP8FFQUBBA8AAQYBDhoPAAMH
+Bw4AKQ8BDggPAQYBAQUAAAkBAQIBBAEEAQQAAwEKAAECAQYtBQQKqQkDCg8F
+AAD/BRUFAQYPAAEGGw8DBzIPAQYBAQYAAwESAAEEAQQtBQQKqQkDCg8FAAD/
+BRUFAQYPAAEGAQ4aDwADBwcOADIPAQYBAQcAAQEBARIAAQEBBy0FBAqpCQMK
+DwUAAP8FFQUBBA8AAQYbDwMHMg8BBgEBCAABARIAAQIBBi0FBAqpCQMKDwUA
+AP8FFQUBBg8AAQYBBxoPAwcyDwEGAQEIAAEBEgABAQEGLQUECqkJAwoPBQAA
+/wUVBQEEDwABBhsPAwcyDwEGAQEIAAEBAQERAAECAQYtBQQKqQkDCg8FAAD/
+BRUFAQQPAAEEAQcaDwMHMg8BBgEBCQABAREAAQEBBi0FBAqpCQMKDwUAAP8F
+FQUBBAEBDgABBAEHGg8DBzIPAQYBAQkAAQERAAECAQYtBQQKqQkDCg8FAAD/
+BRUFAQYBAQ4AAQQBBxoPAwcyDwEGAQEKAAEBEAABAQEHLQUECqkJAwoPBQAA
+/wUWBQEEDgABAgEHGg8DBwEOMQ8BBgEBCQABAQEBEAABAgEGLQUECqkJAwoP
+BQAA/wUWBQEEAQQNAAEBAQcaDwMHMg8BBgsAAQEQAAECAQYtBQQKqQkDCg8F
+AAD/BRcFAQYBAgwAAQEBBhoPAwcyDwEGCwABARAAAQIBBi0FBAqpCQMKDwUA
+AP8FGAUBBAEBDAABBhoPAAMOBwcAMg8BBgsAAQEPAAADAQQEAC0FBAqpCQMK
+DwUAAP8FGQUBBAEBCwABARoPAwcyDwEGCwABAQEBDgABAQEGLgUECqkJAwoP
+BQAA/wUZBQEGAQELAAEBAQcZDwADDgcHADIPAQQLAAEBDwABAS8FBAqpCQMK
+DwUAAP8FGgUBBAEBCgABAQEGGQ8AAw4HBwAxDwEOAQQLAAEBAQEOAAECAQYu
+BQQKqQkDCg8FAAD/BRkFAAQGBAEBCgABBgEHGA8AAw4HBwAyDwEGCwABAQEB
+DQABAQEELwUECqkJAwoPBQAA/wUbBQEEAQEKAAEBGQ8AAw4HBwAyDwECCwAB
+AQEBDQABAQEELwUECqkJAwoPBQAA/wUbBQEGAQIKAAEBAQYZDwADBwcOADAP
+AQ4BAgwAAQENAAECAQYvBQQKqQkDCg8FAAD/BRwFAQQLAAEGAQcYDwEHAQcx
+DwEHAQELAAEBAQENAAEEMAUECqkJAwoPBQAA/wUcBQEGAQEKAAEBGQ8BDgEH
+MQ8BBgEBCwABAQ0AAQEBBjAFBAqpCQMKDwUAAP8FHQUBBAsAAQYYDwADDgcO
+ADAPAQYMAAEBAQEMAAECAQYwBQQKqQkDCg8FAAD/BR0FAQQBAQoAAQIYDwAD
+DgcHAC8PAQ4BBAwAAQENAAEEMQUECqkJAwoPBQAA/wUdBQEEAQEKAAEBAQYY
+DwEHAQ4wDwEEDAABAQwAAQEBBjEFBAqpCQMKDwUAAP8FHQUBBgEECwABBAEH
+Fw8BBwEOLw8BDgEBCwABAQEBDAABATIFBAqpCQMKDwUAAP8FHgUBBAEBCgAB
+AQEGSA8BBwEBCwABAQwAAAMBBAQAMQUECqkJAwoPBQAA/wUeBQEEAQILAAEE
+AQdHDwEGBAABAQEBBQABAQEBDAABAQEEMgUECqkJAwoPBQAA/wUfBQEEAQEE
+AAEBBQABAQEHRw8BBgMABAEEAAEBDQABATMFBAqpCQMKDwUAAP8FHwUBBAEB
+BQABAQUAAQYBDkUPAQcBAQQABAEDAAEBDQABBAEEMgUECqkJAwoPBQAA/wUg
+BQEEBQABAQUAAQFCDwAFDgcPDwYABQADAQMAAQENAAEBAQYzBQQKqQkDCg8F
+AAD/BSAFAQQBAQUAAQEFAAEGQA8FBwECBgABAQMAAQEOAAECAQYzBQQKqQkD
+Cg8FAAD/BSAFAQQBAQUAAQEFAAEBAQc+DwMHAAQGBwYBCgABAQ4AAQQ0BQQK
+qQkDCg8FAAD/BSEFAQQBAQQAAQEBAQQAAAMBBgcAPQ8ABgcGBgcHBAoAAQEO
+AAEBNQUECqkJAwoPBQAA/wUhBQEGAQEFAAEBAQEEAAADAQYHADkPAAkOBwcG
+BgcHBgEACQABAQ8AAQQBBDQFBAqpCQMKDwUAAP8FIQUBBAECBgABAQEBAwAA
+BAECBgc4DwEHAQcDBgADBwcBAAkAAQEPAAEBAQQ1BQQKqQkDCg8FAAD/BSIF
+AQQBAQsAAAQBBgYHNA8ABA4PBwcDBgADBw8GAAkAAQEBAQ8AAQIBBjUFBAqp
+CQMKDwUAAP8FIgUBBAEBCwAABQEEBgYHADIPAAMHDwcABAYDBwEBCAABAQEB
+DwABAQEENgUECqkJAwoPBQAA/wUjBQEEDAABAQMGAQcuDwQHBgYAAwcPBgAI
+AAEBEQABAgEGNgUECqkJAwoPBQAA/wUjBQEEAQELAAEBAQIEBgEHDw8BDhkP
+BQcHBgAEBwcGAQcAAQERAAEBAQQ3BQQKqQkDCg8FAAD/BSMFAQYBBAwAAQQF
+BgEHAQcNDwEOFQ8GBwkGAAQHBw8EBQADARIAAQQBBDcFBAqpCQMKDwUAAP8F
+JAUBBAEBCwAAAwEGAQAEBgAEBwcPDgkPAAUOBwcPDgAPDwEOBAcNBgMHAQEZ
+AAEBAQQ4BQQKqQkDCg8FAAD/BSUFAQQLAAEBAwYBBAMGAQcBBwoPAQ4DBwAD
+Dw8OAAwPAAMOBwcADwYABAcHDwYaAAEEAQQ4BQQKqQkDCg8FAAD/BSUFAQQB
+AQoAAAMBBAIABAYAAwcODgAJDwEOBgcBDgwPAQ4EBwEGAQcKBgAFBwcPDgEA
+GQABAgEGOQUECqkJAwoPBQAA/wUmBQEEAQEKAAEBAwYBBwEHDQ8BBwEOAwcB
+Dg8PAw4BBwEOBgcBBgQHAAMPDwYAGQABAQEEOgUECqkJAwoPBQAA/wUmBQEE
+AQEKAAEBAwYRDwEOAQ4XDwADDg8OAAUHAAUODw8HAQAZAAEEAQQ6BQQKqQkD
+Cg8FAAD/BSYFAAMGBAEACQAABAECBgcvDwEOBA8AAwcGAQAYAAEEAQQ7BQQK
+qQkDCg8FAAD/BSgFAQQKAAADBAYHADUPAQYYAAEBPQUECqkJAwoPBQAA/wUo
+BQEGAQEJAAEBAQY1DwEHAQIXAAEBAQQ9BQQKqQkDCg8FAAD/BSkFAQQKAAEE
+AQc0DwEGAQEWAAADAQQEAD0FBAqpCQMKDwUAAP8FKgUBBAkAAQEBBzQPAQYX
+AAEEAQQ+BQQKqQkDCg8FAAD/BSoFAQQBAgkAAQYzDwEHAQIWAAEEAQQ/BQQK
+qQkDCg8FAAD/BSsFAQQBAQgAAQEBBzIPAQYBARUAAQIBBkAFBAqpCQMKDwUA
+AP8FKwUBBgEECQABBAEHDQ8BDgMHAQ8BBwcPAQ4WDwEEFQABAgEGQQUECqkJ
+AwoPBQAA/wUtBQEECAABAQEGDA8BDgEHBQYBBwEHAw8BDhcPAQcBARQAAQEB
+BEIFBAqpCQMKDwUAAP8FLQUBBAECCAABAQEHCg8BBwEHCQYBBxkPAQYUAAAD
+AQQEAEIFBAqpCQMKDwUAAP8FLgUBBAECCAABAgEHCA8BBwwGAQcBBxYPAQcB
+BBQAAQIBBkMFBAqpCQMKDwUAAP8FLgUAAwYEAQAIAAAEBg8PDgQPAQcBBwUG
+AQQIBgEHFQ8BBgEBEwABAQEGRAUECqkJAwoPBQAA/wUwBQEECAABAQEGBQ8B
+BwEHBQYABAQGBgQHBgEHAQcSDwEOAQQTAAADAQQEAEQFBAqpCQMKDwUAAP8F
+MAUBBAECCAABBAEHAw8BBwEHBwYBBAsGAQcRDwEHAQETAAEBRgUECqkJAwoP
+BQAA/wUxBQEEAQEHAAAGAQYPDwcHCQYABAQGBgQDBgEEBAYBBwEHDw8BBhMA
+AAMBBAQARQUECqkJAwoPBQAA/wUyBQEECAAABQYHDwcHAAgGBAQAAwYGBAAH
+BgEHAQcNDwEGAQETAAECAQZGBQQKqQkDCg8FAAD/BTIFAQYBBAcAAAQEBgcH
+BAYDBAgCAAUEAgYGBAAFBgEHCw8BBwEGEwABAQEGRwUECqkJAwoPBQAA/wUz
+BQEEAQIGAAEBBwYABAQCAgEDAgEBBwIBBgEEBQYBBwEHCA8AAwcGAQATAAAE
+BAUFBkUFBAqpCQMKDwUAAP8FNAUBBAEBBQABBAYGAA0EAgIBAgECAQICAQIB
+AAUCAQYBBAQGAQcHDwADBwYGABMAAQFJBQQKqQkDCg8FAAD/BTUFAQQFAAEB
+BQYABAQCAgEQAgEEAQQEBgEHBA8ABQcHBgYEABIAAAMBBAQASAUECqkJAwoP
+BQAA/wU1BQEEAQEEAAECAwYBBAMCAQEFAgEKDAIBBAEEBQYEBwMGAQEHAAMB
+CAABAgEGSQUECqkJAwoPBQAA/wU1BQEGAQQEAAEBAwYABAQCAgEFAgAGCgIC
+CgIKCQIABAMEBgQIBgECBwAFAQYAAQEBBEoFBAqpCQMKDwUAAP8FNgUBBAEB
+AwAABgEGBgQCAQYCAAMLAgsAAwIABgoCCgICCgYCAQQBBAgGAQEGAAAFAQEG
+AQYABwABAQEGSgUECqkJAwoPBQAA/wU2BQEEBAAAAwEGBAADAgADAQIBAAwC
+AQoKAgEEBwYHAAAGAQEGAgEBBgABBEsFBAqpCQMKDwUAAP8FNQUBBgECBAAA
+BgEEAgIBARICAQoJAgEEBAYBAQYAAAMBAQYAAwEGAAECAQZLBQQKqQkDCg8F
+AAD/BTYFAQIEAAAEAQICAQQCAAgKAwMLAwsCCwoCAAMKAgoABgIABQMEBgIB
+AAYAAQEBBAMBBgABAQEETAUECqkJAwoPBQAA/wU1BQEGAQQEAAAEAQECAQMC
+AAwKAwsLAwsDAwsDCwsLAgEKBwIBAQYABAEHAAADAQQEAEwFBAqpCQMKDwUA
+AP8FNQUBBAECBAABAQEBAwIAEgoLCgsLAwsLAwsLAwsCCwsCCwYCAAUKAgoC
+CgADAgEBAQEGAAEBAQEJAAEBAQZNBQQKqQkDCg8FAAD/BTUFAQYBBAQAAQEB
+AQMCABUKAgsDCgsLAwsLAwsDCwsDCwILAgsABQIACAoCCgIKAgIBEQABAgEG
+TQUECqkJAwoPBQAA/wU1BQEGAQIDAAEBAQEDAgAGCgoLCgoDBQsABQMLAwsD
+AAMLAAQDCwILBAIACAsCCgIKAgIBEAABAQEETgUECqkJAwoPBQAA/wU2BQEC
+AwAEAgAICgIKAgsKCwoECwAIAwsDAwsDCwMDCwADAwsDAAQCAAMLAgoAAwIQ
+AAEBAQROBQQKqQkDCg8FAAD/BTUFAQQBAQMAAQEDAgEKAQIDCgANCwoLCgML
+AwsDCwMLAwADCwECAwsAAwILAwADAgAGCwIKAgIBDwABAgEGTgUECqkJAwoP
+BQAA/wU1BQEGAQIDAAQCAAcKCgILCgsKAAYLAQMBCwMDAQsBAwMLAQIDCwEC
+AQsFAgADCgIBAA4AAAMBBAQATgUECqkJAwoPBQAA/wU1BQEEAQEDAAEBAwIB
+CQECAwoACwsKCgsKAwsDCwMLAAMDAQsBAwMLAQMECwAIAgsCAgsCAgEOAAEB
+AQRPBQQKqQkDCg8FAAD/BTUFAQQBAQQAAQEDAgAICgILCgoDCwoECwEDAQsE
+AwAFCwMLCwMABAsACAMLCwILAwsCDwABAQEETwUECqkJAwoPBQAA/wU1BQEE
+AQEEAAAMAQECAgoCCwoKCwoDAwsAAwMLCwAIAwMLAQIDCwAGAwsDAwIBDwAB
+AQEETwUECqkJAwoPBQAA/wU1BQEEAQEFAAEBAwIDCgAHAwoKCwoLAwADCwED
+AQsDAwAFCwMLCwIABAsABgILAwMCARAAAQIBBk8FBAqpCQMKDwUAAP8FNQUB
+BAEBBgAADwQCAwIKAgsKCwMLCgsLAwADCwEDAQsFAwMLAAcCCwMLAwIBABEA
+AQEBB08FBAqpCQMKDwUAAP8FNQUBBAEBBQAABQEHDQICAAMKAAUDCgsKAwAF
+CwEDAQsEAwQLAAgCCwMDBA0NBBEAAQIBBk8FBAqpCQMKDwUAAP8FNQUBBAEB
+BAAAJgEGBwYCAQICCgoLCgsLCgMLCwMLCwMLAwsLAgsCCwICBwcODwcEEAAB
+AlAFBAqpCQMKDwUAAP8FNQUBBAUAABMBBwcEAAABAgIKAgILCgoLCwMLAAMC
+AwsADgILAgEBAAABBw8HDwcBDwABBAEETwUECqkJAwoPBQAA/wU1BQEGBQAA
+BAQHBgEDAAEBAQEDAgAGCgMLCwILAwIABwsCCwICAQEABQAABgEHDw8HBg8A
+AQQBBE8FBAqpCQMKDwUAAP8FNQUBBAQAAAQBBgcBBgABAgMDAA0LCwILCwIL
+AgIDBAIBAAgAAAYCBw8PBgEOAAEEUAUECqkJAwoPBQAA/wU0BQEGAQQEAAAD
+AQcGAAcAAAMBBwQAAwIBCwQCAAUBAgYHAgAJAAAGAQYPDgYBDgABBlAFBAqp
+CQMKDwUAAP8FNQUBBAQAAAMBBwYABAAABwEBAAIHBwIABgEABgAAAgYHBAkA
+AAYBBgcPBwEOAAENUAUECqkJAwoPBQAA/wU0BQEGAQIEAAADAgcBAAQABAEA
+BA8HAQEGAAAFAQYGDwQACQAABgEGBw8HBA0AAQEBBlAFBAqpCQMKDwUAAP8F
+NQUBAgQAAAMEBgEABAAABwIBAQIHDwQABQAABwEAAQYHDwYACQAABgEGDw8H
+AQ0AAQEBBlAFBAqpCQMKDwUAAP8FNQUBAQQAAAMGBgEABAAABwYBAQYPBwEA
+AwADAQAGAAEGBw8GBgAACQEBAAEHDw8HAgANAAEBAQZQBQQKqQkDCg8FAAD/
+BTUFAQEEAAADAgcBAAMAAAgEBgABBw8HBAcAAAYBBgcPBwEEAAAKAQECAAIH
+DwcGAQ0AAQEBBlAFBAqpCQMKDwUAAEkFAQbpBQEHAQEEAAMGAwADAQAFBgcP
+BwEABwAABgEGBw8HBgQAAAUBBgEBBgADDwEGAQENAAEBUQUECqkJAwoPBQAA
+PwUBBvMFAQYBAQQAAA4CBwcBAQAAAQIHDwcHAQcAAAoBBgcHDwcBAQAAAwEA
+BgYHDw8GAQ4AAQFRBQQKqQkDCg8FAABCBQEEAQ3wBQEBBAAADQEGBwcGBgQG
+BwcPDwYACAAAEwEGBw8PBwcEAQABAQYHDwcHBgEADgABAVEFBAqpCQMKDwUA
+AEEFBQ0HBQEG5QUBBgEBBAABAQMGAQcFDwADBwYBAAkAAAQEBgcHAw8EBwAG
+Dw8HBgYBDwABAVEFBAqpCQMKDwUAAEAFAQ0BDQMMAw3rBQEGAQEEAAADAQQE
+AAMGAwcDBgoAAQEDBgMHAAYPBw8PBwcDBhAAAQEBDVAFBAqpCQMKDwUAAD8F
+AAoNDAwLCwMMDA0N6wUBAQUAAQEJBgEBCwABAQwGAAMCAQEADwABAgEGUAUE
+CqkJAwoPBQAAPgUAAw0MAwAFCwADAwwNAOoFAQYBAQUAAQEBAQYGAAMCAQEA
+CwABAQECCwYBBBEAAQQBBFAFBAqpCQMKDwUAAD0FAAMNDAMABwsAAwMNDQDp
+BQEGAQEGAAEBAQIFBgAEAQAAAQsAAAQBAQYCCAYBAQEBEAABBAEEUAUECqkJ
+AwoPBQAAPAUAAw0NDAAJCwADDA0NAOkFAQEHAAAEAQECAgMBAAMAAQEADQAA
+AwEEAgAGBgAEAQEAAQ8AAQRRBQQKqQkDCg8FAAA8BQENAQwLCwADDAUNAAoF
+AQbcBQEGAQEKAAEBAwABAQEBEAAACwECAgEGAQIBAAEBAA4AAQEBBFEFBAqp
+CQMKDwUAADoFAAQGBQ0MDAsABAMMDg0KBQEG2gUBBgEBDQADARMAAQEBAQMA
+AwEOAAEBAQZRBQQKqQkDCg8FAAA7BQADDQ0DAAgLAQoECwAEAwwNDQsFAQbZ
+BQEBCwADARkAAwEPAAEBAQ1RBQQKqQkDCg8FAAA7BQENAQMPCwAFAwwMDQ0A
+4gUBBgEBJwABAQEBEAABAgEGUQUECqkJAwoPBQAAOwUBDRALAAYKCwMMBQ0L
+BQEG1QUBBgEBOAAAAwEEBABRBQQKqQkDCg8FAAA6BQENAQwPCwEKAwsABQoD
+DA0NAN8FAQYBATgAAQEBBFIFBAqpCQMKDwUAADoFAQ0BDBELAQoECwAEAwMN
+Dd4FAQE4AAEBUwUECqkJAwoPBQAAOwUBDA8LAAQKCwsKBQsABQMMBQ0NANoF
+AQYBATcAAAMBBAQAUgUECqkJAwoPBQAAOwUVCwEKAwsABAoLAwwDDQ4FAQbJ
+BQENAQE3AAEBAQZTBQQKqQkDCg8FAAA6BQEMFgsACwoLCgsLCgsDDAUNAA8F
+AQbHBQEEAQE3AAECAQZTBQQKqQkDCg8FAAA5BQENAQwVCwANCgsKCwsKCwsK
+CwMMDAADDQ8FAQbEBQEENwABBlQFBAqpCQMKDwUAADoFAQwQCwEKCAsADgoL
+CwoLCwoLAwMMBQ0NDwUBBsIFAQQBASQAAQEQAAECAQZUBQQKqQkDCg8FAAA6
+BQEDEgsADQoLCwoLCwoLCwoLCwoAAwsACAoDAwwMBQUNDwUBBr8FAQYBASMA
+BQEMAAEBAQRVBQQKqQkDCg8FAAA4BQENAQUaCwEKBQsADQoLCgsKCwoLAwwF
+BQ0ADwUBBr0FAQQBAiMABwEKAAECAQZVBQQKqQkDCg8FAAA4BQEOAQwRCwEK
+AwsAGwoLCwoLCwoLCwoLCwoLCgsKCwoLCgMDDAUNDQDLBQEEAQEiAAMBAQYE
+AQgAAQEBBlYFBAqpCQMKDwUAADgFAQ0BDBoLABgKCwsKCwsKCwoLCgsKCwoL
+CgsLCgMMBQUDDQ8FAQa2BQEGAQEiAAAFAQIGAQYAAwEIAAEEAQRWBQQKqQkD
+Cg8FAAA4BQENAQMVCwAiCgsLCgsLCgsLCgsLCgsKCwoLCgsKCwoLCgsKAwwM
+BQ0FDQ8FAQa1BQEEAQEhAAMBAQYEAQcAAQIBBlcFBAqpCQMKDwUAADgFAQ0S
+CwEKCAsAIAoLCwoLCwoLCgsLCgsLCgsKCwoKCwoKCwoDAwwFBQ0NwgUBBgEC
+IQAABwEBBgIGAQEABwABAQEGWAUECqkJAwoPBQAANgUAAwYFDQAVCwAdCgsL
+CgsKCwsKCwsKCwoLCwoLCgsKCwoKCwoLCgsAAwoACAsKCwMMBQ0NEQUBBq8F
+AQQBASAABwEGAAEBAQRZBQQKqQkDCg8FAAA4BQENHAsABAoLCwoDCwANCgsK
+CwoLCgsKCwoKCwAECgAJCwoKCwoLAwMMAAMFAQ0BDQ4FAQauBQEGAQEgAAQB
+BwAAAwEEBABZBQQKqQkDCg8FAAA3BQENAQUTCwEKAwsAIAoLCgsKCwsKCwsK
+CwoLCgsKCwoLCgoLCgsKCwoLCgoLBQoACAsDAwwMBQ0NEQUBBqoFAQQBASkA
+AAMBBAQAWgUECqkJAwoPBQAANwUBDQEMHAsAHQoLCwoLCwoLCwoLCgsKCwoL
+CgoLCgoLCgoLCgoLAAcKAwMBDAQNEQUBBqYFAAMGBAEAJwAAAwEEBABbBQQK
+qQkDCg8FAAA3BQENAQwVCwEKAwsAHAoLCgsLCgsLCgsKCwoLCgsKCwoLCgsK
+CgsKCgsFCgAJCwoKCwoKCwoLAAQDBAUBDRAFAQalBQADBAEBACQAAQEBBF0F
+BAqpCQMKDwUAADcFAQ0BDBILAQoECwEKBAsAHAoLCwoLCwoLCgsKCwoLCgsK
+CgsKCwoKCwoLCgsHCgELCAoAAwMDDAC4BQADBAQBACEAAAMBAgYAXgUECqkJ
+AwoPBQAANwUBDQEMGAsACQoLCwoLCgsLCgADCwAKCgsKCwoLCgsKCwMKAAML
+CgsABQoBCwMKAQsNCgMDAAUMBQUNDQCxBQAEBAQCAR4AAAMBBAQAXwUECqkJ
+AwoPBQAANgUAAw0NDAAVCwEKAwsBCgQLABMKCwsKCwoLCgsKCwoLCgsKCwoL
+AAQKAAMLCgsAFwoDAwAEDAUNDQsFAQakBQAEBAQCARoAAQEDBGAFBAqpCQMK
+DwUAADcFAQ4BAxELAQoFCwEKAwsAGgoLCgsLCgsLCgsKCwoLCgsKCwoKCwoK
+CwoLBQoBCxcKAwMABQwMBQUNAAYFAQ0BDQkFAQadBQAEBgQCARMAAAQBAQIG
+ZAUECqkJAwoPBQAANgUAAw0NDAATCwEKBgsBCgQLABoKCwsKCwsKCwoLCgsK
+CwoLCgoLCgsKCgsKCx0KAwMBDAMFAQ0BDawFAAQGBAQCBAEABwAAAQAAAQAA
+BAEBAgMEZgUECqkJAwoPBQAANgUAAw0NDAAVCwEKAwsAGAoLCwoLCgsLCgsL
+CgsKCwoLCgsKCwoKCwMKAQsJCgELEwoABQkKCQoJAAMKAAUDCgMMBAAEBQAD
+DQ0HABIFAQaVBREEaQUECqkJAwoPBQAANgUAAw0NDAARCwEKBQsBCgMLAQoD
+CwEKAwsAGQoLCgsKCwoLCgsKCgsKCwoLCgoLCgsKCgsAHAoABwkKCgkJCgoA
+BAMBBQQNEgUBBpYFAAoGBQUEBQUGBQUGbQUECqkJAwoPBQAANwUBDQEMEwsB
+CgYLAQoDCwATCgsLCgsKCwoLCgsKCwoLCgsKCwADCgELJQoBCQQKAQkDCgMD
+AQwDBQENAQ3/BR0FBAqpCQMKDwUAADYFAAMNDQwAFQsBCgMLABUKCwsKCwsK
+CwsKCwsKCwoLCgsKCgsAAwoACAsKCwoKCwoLHgoABAkKCgkDCgAOCQoKCQoJ
+CgkKCgMDBQwDBQEN/wUZBQQKqQkDCg8FAAA3BQENAQwRCwEKBQsBCgMLABsK
+CwsKCwsKCwoLCgsKCwoLCgsKCwoLCgsKCgsABAoBCyEKAQkDCgEJAwoAEQkK
+CgkKCgkDAgMMAwQFBQ0NAP8FFAUECqkJAwoPBQAANgUAAw0HDAATCwEKBgsA
+BwoLCwoLCwoAAwsACgoLCgsKCwoLCgsDCgAECwoKCwMKAQsFCgELGgoBCQQK
+AQkDCgAUCQoJCgkKCQkKCQoKCQoDCgMMBAUDDf8FEAUECqkJAwoPBQAANwUB
+DQEMFgsAIAoLCwoLCwoLCwoLCgsKCwoLCgsKCwoLCgsKCwoKCwoLJQoBCQQK
+AAoJCgoJCgoJCgkKBQkABgoJCgkKCQQDAAMMBQ0A/wUNBQQKqQkDCg8FAAA3
+BQENAQwRCwAECgsLCgULAQoDCwEKBAsAEAoLCgsKCwoLCgsKCgsKCgsDCgAG
+CwoLCgoLGgoABAkKCgkDCgAKCQoJCgoJCgoJCgMJAAUKCQoJCgALCQALCgID
+DAwEDQ0FDQ0A/wUEBQQKqQkDCg8FAAA3BQEHAQUZCwEKAwsAGQoLCwoLCgsL
+CgsKCwoLCgsKCwoKCwoLCgsAJQoBCQUKAA8JCgoJCgkKCQoKCQoKCQoAAwkB
+CgUJAAYKCQkKCQoEAwADBQUEAAQFAQ39BQQKqQkDCg8FAAA4BQENFwsBCgML
+AQoDCwASCgsKCwsKCwoLCgsKCwoLCgoLAwoBCwMKAQsgCgEJBAoADAkKCQoK
+CQoJCgkKCgMJAAQKCQkKBAkAAwoJCgADCQEKBwkAAwMJCQADAwEEAQUFDfgF
+BAqpCQMKDwUAADgFAQ0RCwAECgsLCgQLAAYKCwsKCwoECwARCgsKCwoLCgsK
+CwoKCwoLCgsAAwoABAsKCgsDCgELHQoBCQUKAQkDCgEJAQoDCQEKAwkABgoJ
+CgoJCgMJAAMKCQoAAwkBCgwJAAQCCQIDAwUACA0NBwUFDQUN7gUECqkJAwoP
+BQAAOAUBDRYLAQoDCwEKBAsAEAoLCgsKCwoLCgsKCwoLCgsDCgAECwoKCyEK
+AAQJCgoJBAoACwkKCQoJCgkKCgkKAAMJAAsKCQoJCgkKCQoJCgAECQEKEwkB
+AgEJAwMBDAoFAQ3nBQQKqQkDCg8FAAA4BQENAQwRCwEKBgsABgoLCwoLCgML
+ABcKCwsKCwoLCgsKCwoKCwoLCgsKCgsKCwAlCgEJBQoAAwkKCQADCgAICQoJ
+CgkKCQoICQEKBgkBChQJAAgCCQMCAwMEDAMFAw3kBQQKqQkDCg8FAAA6BQEM
+EgsABAoLCwoDCwEKAwsAEgoLCgsKCwoLCgsKCwoLCgsKCwMKAQsFCgELHgoB
+CQMKAQkDCgADCQoJAAMKAAkJCgkKCQoJCQoAAwkABwoJCQoJCQoABAkBCiAJ
+AQIDAwAHAgQFBQ0FDQDeBQQKqQkDCg8FAAA6BQEMFwsBCgQLAQoECwANCgsK
+CwoLCgsKCwoKCwADCgELAwoBCwQKAQseCgEJBAoBCQMKABUJCgkKCgkKCQoJ
+CgkKCQoJCQoJCQoAAwkBCgMJAQoZCQEIAwkABQgJCQgCAAMJAAkCCQICAwMM
+DAQABAUBDQcFAQ3MBQQKqQkDCg8FAAA5BQADDQUMAA8LAQoECwEKAwsAGAoL
+CgsLCgsKCwsKCwoLCgsKCwoLCgsKCwMKAAQLCgoLHAoABAkKCgkFCgEJAwoA
+FQkKCQoKCQoJCgkKCQoJCgkJCgkJCgADCQEKCQkBCh4JAQgDCQAOCAkJAgkC
+CAIDAwIDBAwFBQAHBw0FDQUNDQDGBQQKqQkDCg8FAAA5BQAEDQUMAxALAQoF
+CwEKAwsAEAoLCwoLCwoLCgsKCwoLCgsDCgELAwoBCwcKAQsdCgAECQoKCQMK
+ABkJCgkKCgkKCQoJCgkKCQoJCQoJCgkJCgkKAAMJAQoeCQEIEgkACggJCQgJ
+AgkCCQIDAwAFBAMFBQ0AxgUECqkJAwoPBQAAOgUABQ0NBQwDAAsLAAkKCwoL
+CwoLCwoAAwsAFAoLCwoLCwoLCgsKCwoLCgsKCwoLAwoBCwMKAQsGCgELGQoB
+CQYKABMJCgoJCgoJCgkKCQoJCgkKCQkKAAMJAQoFCQEKBQkBChUJAAQICQkI
+AwkBCAQJAA4ICQgJCAkICQgJCAkJCAQJABEICQkICQkICQIIAgIDAgQMBAAF
+BQENuwUECqkJAwoPBQAAPAUABA0NDAwTCwAaCgsKCwsKCwsKCwoLCgsKCwoL
+CgoLCgoLCgsDCgAECwoKCyIKAB4JCgkKCgkKCgkKCgkKCQoJCgkKCQoJCgkK
+CQkKCQoECQEKIgkBCAwJAAYICQkICQgDCQAGCAkICQkIBAkAEQgJCAkICQII
+AgMCDAQEBQUNAAMFAQ2xBQQKqQkDCg8FAAA9BQAFBw0NBQwADwsBCgQLAAQK
+CwsKAwsADQoLCgsKCwoLCgsKCgsABAoBCwYKAQsaCgEJAwoBCQUKABcJCgoJ
+CgoJCgkKCQoJCgkJCgkJCgkJCgAECQEKIQkBCAQJAQgDCQAKCAkICQgJCAkJ
+CAQJAAMICQgAAwkAHggJCAkICQgJCAkICQgJCAkICQgICQIIAgkDDAQFBK8F
+BAqpCQMKDwUAAEAFAQcDBQEMAQMGCwAECgsLCgMLABsKCwoLCwoLCgsKCwoL
+CgsKCwoLCgoLCgoLCgsAAwoBCyAKAQkECgAZCQoJCgoJCgkKCQoJCgkKCQoJ
+CgkJCgkJCgADCQEKBAkBCiAJAQgDCQEICQkBCAMJAC0ICQgJCAkICQgJCAkJ
+CAkICQgJCAkICAkICQgJCAkICQgCCAIICQIJAwIDAwIABQUBDQgFAQ2aBQQK
+qQkDCg8FAABDBQMNAAMFDAMACQsBCgMLAQoECwAQCgsLCgsKCwoLCgsKCwoK
+CwUKAAQLCgoLIgoBCQUKABYJCgoJCgoJCgkKCQoJCgkKCQkKCQkKAwkBCgUJ
+AQoZCQEICQkABwgJCAkICQgABAkAJggJCAkICQkICQkICQgJCAkICQgJCAkI
+CQgICQgICQgJCAkICQgJBAgABgkICAkCCQMCAAQDBAMEAwUBDQENmwUECqkJ
+AwoPBQAARQUBBwMNAAQFDAwDCAsAGgoLCwoLCgsKCwoLCgsKCwoLCgoLCgsK
+CwoLGgoBCQgKAAMJCgkABAoAFAkKCQoKCQoJCgkKCQoJCgkJCgkKAwkABAoJ
+CQoeCQEIBQkABggJCQgJCAkJAAMICQgABgkAJwgJCQgJCQgJCQgJCAkICQgJ
+CAkICQgJCAgJCAgJCAgJCAgJCAkICQADCAAJCQgJCAkICQIIAAMCAAQEBQUN
+lwUECqkJAwoPBQAASAUBBwMNAwUABQwMAwsDAAMLABEKCwoLCgsLCgsKCwoK
+CwoKCwAICgELJgoBCQQKAA4JCgkKCgkKCQoJCgkJCgMJAAUKCQoJCgADCQAE
+CgkJCicJAAcICQgJCAkIAAQJACcICQgJCAkJCAkICQgJCAkICQgJCAkICQgJ
+CAkICAkICAkICAkICAkAEggBCQQIAAcCCAIMBAMEAJEFBAqpCQMKDwUAAE0F
+AAYNBQUNBQUDDAEDAwsAFQoLCgoLCgsKCwoLCgsKCwoLCgsKCwAECgAFCwoL
+CgsAFQoBCQUKAAMJCgkAAwoAFAkKCQoJCgoJCgkKCQoJCQoJCgkKBgkBCgcJ
+AQoaCQEIBAkABAgJCQgJCQADCAkIAAMJADQICQkICQgJCAkICQgJCAkICQgJ
+CAkICAkICQgJCAkICQgICQgICQgJCAkICQgJCAgJCAgJCQgAEQkIAggCCQID
+AgMEDAUEBQ0NAIUFBAqpCQMKDwUAAFEFAAQNBw0OAw0AFAUMDAMDCwsKCwoL
+CwoKCwoKCwoLBQoABQsKCwoLABUKAQkDCgEJCAoBCQMKABUJCgkKCQoJCgkK
+CQoJCgkKCQkKCQoABAkABAoJCQofCQEICQkABggJCQgJCAMJACgICQgJCQgJ
+CQgJCAkICQgJCAkICQgJCAkICQgICQgJCAgJCAgJCAgJEAgBCQMIAQkNCAAK
+AggCCAIDAgQEBQQNfgUECqkJAwoPBQAAWQUBBwMNAQUDDAMDAAQLAwoLBwoB
+Cx0KAQkECgEJAwoBCQQKABMJCgoJCgoJCgkKCQoJCgkJCgkKAAQJAQofCQEI
+BwkABwgJCQgJCQgAAwkBCAUJAQgECQAyCAkICQgJCQgJCAkICQgJCAkICQgI
+CQgJCAkICAkICAkICAkICAkICQgJCAkICAkICAkdCAAKAggCAgUEBQUNDXkF
+BAqpCQMKDwUAAFsFAAQHBQ0NBQUDDAAHAwMLCgMKCwAECgELHAoAAwkKCQAG
+CgATCQoJCgoJCgoJCgkKCQoJCgkJCgADCQADCgkKAAQJAQoECQEKAwkBChcJ
+AQgMCQEIAwkALAgJCAkJCAkICQgJCQgJCAkJCAkICQgJCAkICQgJCAkICQgI
+CQgJCAgJCAgJEggBCR8IAwIBBAEEdwUECqkJAwoPBQAAYgUBDQQFAAQNBQ0F
+AwwAAwMKAwAeCgAJCQoKCQoJCgoJAAQKABIJCgoJCgkKCQoJCQoJCgkKCQoF
+CQEKAwkBCiAJAAoICQkICQkICQkIBAkBCAMJADkICQkICQkICQgJCQgJCAkI
+CQgJCAkICQgJCAkICAkICQgJCAgJCAgJCAgJCAkICQgJCAkICAkICAkAKAgA
+AwIIAgADBAAEBQcFDWwFBAqpCQMKDwUAAGwFAQcDDQAEBQ0MDAQDEAoBCQgK
+AQkHCgAUCQoJCgkKCQoJCgkKCQoJCQoJCQoDCQEKBAkBCi0JAAMICQgAAwkA
+KggJCQgJCQgJCQgJCAkICQgJCAkICQgJCAkICAkICQgICQgJCAkICAkICRoI
+AQkiCAAGAggCAgQEawUECqkJAwoPBQAAcAUABA0HDQ4DDQAGBQUEBQwMAwMA
+BQsKAwoJAAUKAQkICgEJAwoBCQgKABAJCgoJCgkKCQoJCQoJCgkKAwkBCgYJ
+AQoZCQEIAwkABAgJCQgDCQADCAkIAAYJACEICQkICQkICQkICQkICQgJCAkI
+CQgJCAkICQgJCAgJCAkABQgBCQUIAA0JCAgJCAkICQgICQgJAAgIAQktCAMC
+AQRmBQQKqQkDCg8FAABzBQADBwUNAAQFAAMNBQcABQUEDAAMAwMKAwoDCgkK
+CQoJBAoBCQMKABMJCgkKCQoJCgkKCgkKCQoJCgkKAAMJAQoECQADCgkKACUJ
+AQgFCQAzCAkICQgJCQgJCQgJCAkICQgJCAkJCAkICQgJCAkICQgJCAkICQgJ
+CAkICQgJCAkICQgJAA0IAQk3CAMCAQQBBGEFBAqpCQMKDwUAAIEFAAcNBQ0F
+DQcNAAQFACcMDAMDCgMKAwkDCQoJCQoJCgkKCQoJCgkJCgkKCQoJCgkKCQoJ
+CQoAJAkBCAMJAQgFCQEIBwkAJAgJCQgJCQgJCQgJCQgJCAkICQgJCAkICQgJ
+CAgJCAkICAkICQMIAQkGCAAICQgJCAkICAkGCAEJOggABAICBARdBQQKqQkD
+Cg8FAACLBQEHAw0BBQENBAUACwMMAwwDAwkKCgkKAAgJAQonCQEICAkBCAUJ
+AQgECQAmCAkICQgJCQgJCQgJCQgJCQgJCQgJCAkICQgJCAkICQgJCAkICAkD
+CAAKCQgJCAgJCAkICQoIAQlCCAAFAgIEBAYAWAUECqkJAwoPBQAAkwUACAcF
+DQUNBw0NBQUBDAYDDgkBCh8JAQgHCQEIAwkAAwgJCAAFCQEIAwkAIAgJCQgJ
+CQgJCAkICQgJCAkICQgJCAkICAkICAkICQgJBAgBCQcIAAcJCAkICQgJAAMI
+AQlECAAGAgQEBwUHUwUECqkJAwoPBQAAoAUFDQMFAQwBBAQMBAMBCQEDHgkB
+CAUJAAQICQkIAwkABAgJCQgDCQAyCAkICQgJCAkJCAkJCAkICQgJCAkICQgJ
+CAkICQgJCAkICQgJCAkICAkICQgICQgJCAkPCAEJQwgBAgEEVAUECqkJAwoP
+BQAAogUBBwUFAAcHBQ0NBQcNAAYFAQwBBQcDJwkBCAUJACgICQkICQkICQgJ
+CAkICQgJCAkICQgJCAkICQgICQgJCAgJCAgJCAgJBggACQkICQgICQgICQAH
+CAEJQwgAAwIEBABRBQQKqQkDCg8FAACxBQADBw0NAAMFAAQNBQUNBAUABAwF
+DAQDDAAHAgMJAgkJAgAICQAPCAkJCAkJCAkICQkICQkIAAUJAB4ICQgJCAkI
+CAkICQgJCAkICQgJCAkICQgJCAkICAkECAADCQgJAAMIAQkDCAADCQgJAAwI
+AQlKCAADAgQEAE8FBAqpCQMKDwUAAMQFAQ0BBwYNAAsFDQUEAgQCAwIDAwAI
+CQAJCAkJCAkICQkIAAoJABkICQgJCAkICQgJCAkICQgJCAkICQgJCAkJAAMI
+AAcJCAkICQgJAAQIAAYJCAkICAkDCAEJAwgBCUoIAQIBBE4FBAqpCQMKDwUA
+AM8FAQcHDQAPBQQFBAUEDAQMAwIDAgMCAAMJAQgBCQcIBAkAGAgJCAkICQgJ
+CAkICAkICAkICAkICAkICQkIAQlaCAEEAQdNBQQKqQkDCg8FAADRBQEHBQUA
+CgcFDQUNBQUHBQ0IBQAGAwQDDAMFAwMAJAgCCAIICQIICQgJCAkICQgJCAkI
+CQkICQgJCAkICQgJCAkICQMIAAgJCAkICAkICVAIAQIBBE4FBAqpCQMKDwUA
+APEFAQ0JBQAJAggJCAIICQgCAAwIAAMJCAkAAwgAAwkICQAECAEJBAgABAkI
+CAlLCAEETwUECqkJAwoPBQAA9AUBBwYFABYHDQcHDQcNBw0NBAIEAgQDAgQC
+BAgCAwgBCVoIAAMCBQcATwUECqkJAwoPBQAA/wUHBQAWBwUNDQUNDQUNBAUE
+BQUEBQUEBQUCAwcCAQMBAkQIAAMCCAIAAwQBBQENUAUECqkJAwoPBQAA/wUb
+BQEGCQUAHQQFBAQFAwQFBAUDBAUDBAQDAggCCAIIAggCCAgCAAMIAQIFCAEC
+EAgBAgUIAQIEBAAEAgQFBFcFBAqpCQMKDwUAAP8FNgUAAwQFBgAGBQEGBAUB
+BgQFAQYDBQAKBgUFBgUFBgUFBgMFAQYDBQAEBgUFBgYFAQRZBQQKqQkDCg8F
+AAD/BcIFBAqpCQMKDwUAAP8FwgUECqkJAwoPBQAA/wXCBQQKqQkDCg8FAAD/
+BcIFBAqpCQMKDwUAAP8FwgUECqkJAwoPBQAA/wXCBQQKqQkDCg8FAAD/BcIF
+BAqpCQMKDwUAAP8FGQUBBlkFAQZOBQQKqQkDCg8FAAD/BcIFBAqpCQMKDwUA
+AP8FAAYEBgUEBga8BQQKqQkDCg8FAAA7BQA6BAUFBAUEBQQFBAUEBQQFBAUE
+BQQFBAUEBQQFBAUEBQQFBAUEBQQFBAUEBQQFBAUEBQQFBAUEBQQFBAgFAB4E
+BQUEBQQFBAUEBQQFBAUEBQQFBAUEBQQFBAUEBQQKBQAZBAUEBQQFBAUEBQQF
+BAUEBQQFBAUEBQQFBAAMBQAZBAUEBQQFBAUEBQQFBAUEBQQFBAUEBQQFBAAZ
+BQEGAwQACgICBAICBAQGBQQPBQATBAUEBQQFBAUEBQQFBAUEBQQFBAAHBQAU
+BAUFBAUEBQQFBAUEBQQFBAUEBQQPBQAYBAUFBAUEBQQFBAUEBQQFBAUEBQQF
+BAUEUwUECqkJAwoPBQAAOAUBBAEGPgQEBSEEBAUBBgEGHQQIBR0EAQYTBQAE
+DQUGAgMBBQADAQAEAgYEDQsFAQYXBAAFBQUGBAYAFgQKBQEGGwQBBlAFBAqp
+CQMKDwUAADkFAQI9AAEEAQQDBSAABAUBBAEBHQABBAEEBgUBBh0AAQEBBhEF
+AAMGAgEAEAABAQMEBwUBBAEBFQABAQMEAQIXAAEEAQQJBQEBGwAAAwEEBABO
+BQQKqQkDCg8FAAA4BQEGAQE8AAADAQQEAAMFIAAEBQEGAQEdAAECAQYGBQEG
+AQEcAAEBAQYPBQAEBgUBARMAAQEDBAUFAQQBARUAAAUBBAUEBAAXAAEEAQQJ
+BQEBGwABAQEEAwUBBksFBAqpCQMKDwUAADkFAQI9AAEEAQQDBSAABAUBBAEC
+HQABBAEEBgUBBh0AAQEQBQEEAQEXAAEBAwQDBQEEAQEVAAAFAQQFBgIAFwAB
+AgEGCQUBARsAAQEBBE8FBAqpCQMKDwUAADgFAQQBATwAAAMBBAQAAwUgAAQF
+AQQBAR0AAQIBBgYFAQQdAAEBAQYNBQADBAQBABoAAAcBBAQFBAQBABUAAAUB
+BAUEAgAXAAEEAQQJBQEBGwABAQEETwUECqkJAwoPBQAAOAUBBAECPQABBAEE
+AwUgAAQFAAMEAQEAHAABBAEEBgUBBAEBHAABAQEGDQUBBAECHQABAQMEAQEV
+AAAHAQQFBAIAAQAUAAADAQQEAAkFAAMCAQEAGQABAQEETwUECqkJAwoPBQAA
+OAUBBAECAwE5AAADAQQEAAMFAAQEAgECAwESAAAIAQECAQIEAgYEBQAHBAIC
+AQIBAQASAAAEAQECAgMEBgUABwYEAgECAQEAEQAABQEBAgECAAMEDQUBBB8A
+AAQBAgQBDwADAQECAQEDBAAEBQUEBAQBDQADAQADAgYEAAoFAAUGBAQCAQAS
+AAMBAQIDBE8FBAqpCQMKDwUAADkFBgQAAwICAQARABgBDAABBAEEAwUBBgEF
+BQQBAQ8AAQEBAgUEAQUBBAUFAQYBBQUEAQEPAAAHAQIGBAQFBAAJBQUEAQIB
+AQ8AAQEFBAEFAQYNBQEEAQEhAAEBDwABAQUEAQUBBAQFAQYBBQMEAQIBAgoA
+AAcCBgQEBQUGAA0FAQQBBBEAAQIEBFIFBAqpCQMKDwUAAEAFAAMEBAEAEAAB
+AhcEAQEKAAADAQQEAAkFAAMGBAEADgABAQENEwUBBAEBDgABAQENEwUBBgEC
+DgABAQEEFAUBBDIAAQIRBQEEAQIJAAEBAQYTBQEEEAAABAIGBQZUBQQKqQkD
+Cg8FAABCBQEEEAABBAEEFgUBBAsAAQQBBAsFAQEOAAEEAQQTBQEGAQEOAAEC
+AQYUBQECDgABAQEGEwUBBAEBMQAAAwEEBAARBQADBAEBAAgAAQIBBBAFAAMG
+BAEADwABAQEEVwUECqkJAwoPBQAAQgUBBBAAAQQBBBcFAQEJAAADAQQEAAsF
+AQEOAAEEAQQTBQEEAQEOAAEEAQQUBQEEDgABARQFAQQBARMAAAQBAgIGAwQB
+AgEEAwESAAADAQQEABEFAAMGBAEACAAAAwEEBAAPBQEEAQIQAAEEAQRXBQQK
+qQkDCg8FAABCBQEEAQEPAAEEAQQXBQEBCgABBAEECwUBAQ4AAQQBBBMFAQQB
+AQ4AAQQBBBMFAQQBAg4AAQEBBhIFAQYBBBIAAQEDBAgFAAYGBAQCAQEPAAEE
+FAUBBAkAAQEBBg4FAQQBBBAAAQIBBlgFBAqpCQMKDwUAAEIFAQQQAAEEAQQW
+BQEGAQIJAAADAQQEAAsFAQEOAAEEAQQTBQEGAQEOAAECAQYUBQEEDgABARQF
+AQIRAAADAgYEAA0FAwQBAQ0AAAMBBAQAFAUBAgkAAQIBBA0FAQQBAQ8AAQEB
+BFkFBAqpCQMKDwUAAEIFAQQBAQ8AAQQBBBcFAQIKAAEEAQQLBQEBDgABBAEE
+EwUBBAEBDgABBAEEEwUBBgEEDgABAQEGEgUBBgEBEAABAgEGEQUBBAEBDQAA
+AwEEBAAUBQEEAQIJAAEEAQQKBQADBAQCAA8AAAMBBAQAWQUECqkJAwoPBQAA
+QgUBBBAAAQQBBBYFAQQBBAkAAAMBBAQACwUBAQ4AAQQBBBQFAQEOAAEEAQQU
+BQECDgABARMFAQQBAQ8AAQETBQEEAQENAAADAQQEABUFAQQBAQgAAQEBBAsF
+AQQQAAECAQZaBQQKqQkDCg8FAABCBQEEAQEPAAEEAQQXBQEEAQEJAAEEAQQL
+BQEBDgABBAEEEwUBBgEBDgABAgEGEwUBBgEEDgABAQEGEgUBBAEBDwABAgEG
+EgUBBAEBDQAAAwEEBAAWBQEECQABAgEGCAUAAwYEAQAPAAEBAQRbBQQKqQkD
+Cg8FAABCBQEEEAABBAEEFwUBBAEBCAAAAwEEBAALBQEBDgABBAEEEwUBBAEB
+DgABBAEEFAUBBA4AAQESBQADBAQBAA4AAQEBBBMFAQQBAQ0AAAMBBAQAFgUB
+BgEECQABBAgFAQQBAg8AAQEBBFwFBAqpCQMKDwUAAEIFAQQBAQ8AAQQBBBcF
+AQQBAQkAAQQBBAsFAQEOAAEEAQQTBQEEAQEOAAEEAQQTBQEEAQIOAAEBAQYS
+BQEEDwABAQENEgUAAwQEAQANAAADAQQEABgFAQIBAQcAAQEBBAcFAQQPAAAD
+AQIGAFwFBAqpCQMKDwUAAEIFAQQQAAEEAQQXBQEEAQEIAAADAQQEAAsFAQEO
+AAEEAQQTBQEGAQEOAAECAQYUBQEEDgABARIFAQQBAg8AAQIUBQEEAQENAAAD
+AQQEABgFAAMEAQEABwABAQEEBQUBBAEBDwABAQEGXQUECqkJAwoPBQAAQgUB
+BAEBDwABBAEEFwUBBAECCQABBAEECwUBAQ4AAQQBBBMFAQQBAQ4AAQQBBBQF
+AQQOAAEBAQYSBQEEDwABBAEEEwUBBAEBDQAAAwEEBAAYBQADBgQBAAgAAQQB
+BAMFAQQBAg8AAAMBBAQAXQUECqkJAwoPBQAAQgUBBBAAAQQBBBcFAQQBAQgA
+AAMBBAQACwUBAQ4AAQQBBBQFAQEOAAEEAQQTBQEGAQIOAAEBEgUBBAECDwAB
+BAEEEwUBBAEBDQAAAwEEBAAaBQEECAABAQMFAQYBBBAAAQQBBF4FBAqpCQMK
+DwUAAEIFAQQBAQ8AAQQBBBcFAQYBBAkAAQQBBAsFAQEOAAEEAQQTBQEGAQEO
+AAECAQYUBQEEDgABAQEGEgUBBA4AAQEBBBQFAQQBAQ0AAAMBBAQAGgUBBgEE
+CAAABQEEBQQBAA8AAQIBBl8FBAqpCQMKDwUAAEIFAQQQAAEEAQQYBQECCAAB
+AQEEDAUBAQ4AAQQBBBMFAQQBAQ4AAQQBBBMFAQQBAg4AAQESBQEEAQIOAAAD
+AQQEABMFAQQBAQ0AAAMBBAQAGwUBBAECCAAAAwQEAgAPAAEBAQRgBQQKqQkD
+Cg8FAABCBQEEAQEPAAEEAQQXBQADBAQBAAcAAAMBBAQACwUBAQ4AAQQBBBMF
+AQQBAQ4AAQQBBBQFAQQOAAEBAQYSBQEEDgABAQEEFAUBBAEBDQAAAwEEBAAc
+BQEEAQEHAAEBAQIQAAEEAQRgBQQKqQkDCg8FAABCBQEEEAABBAEEGAUBBAkB
+AQYMBQEBDgABBAEEEwUBBgEBDgABAgEGEwUBBgEEDgABARIFAQQBAg4AAAMB
+BAQAEwUBBAEBDQAAAwEEBAAdBQEEAQEXAAECAQZhBQQKqQkDCg8FAABCBQEE
+AQEPAAEEAQQvBQEBDgABBAEEEwUBBAEBDgABBAEEFAUBAg4AAQEBBhIFAQQO
+AAEBAQQUBQEEAQENAAADAQQEAB4FAQQWAAEBAQRiBQQKqQkDCg8FAABCBQEE
+EAABBAEELwUBAQ4AAQQBBBQFAQEOAAEEAQQTBQEGAQQOAAEBEgUBBAECDgAB
+AQEEFAUBBAEBDQAAAwEEBAAcBQAEBgUFAhQAAAMBBAQAYgUECqkJAwoPBQAA
+QgUBBAEBDwABBAEELwUBAQ4AAQQBBBMFAQYBAQ4AAQIBBhQFAQQOAAEBAQYS
+BQEEDgAAAwEEBAATBQEEAQENAAADAQQEAB8FAQQBARMAAQIBBmMFBAqpCQMK
+DwUAAEIFAQQQAAEEAQQvBQEBDgABBAEEEwUBBAEBDgABBAEEEwUBBAECDgAB
+ARIFAQQBAg4AAQEBBBQFAQQBAQ0AAAMBBAQAIAUBBAEBEQABAQEGZAUECqkJ
+AwoPBQAAQgUBBAEBDwABBAEELwUBAQ4AAQQBBBMFAQQBAQ4AAQQBBBQFAQQO
+AAEBAQYSBQEEDgAAAwEEBAATBQEEAQENAAADAQQEACAFAQQBAhAAAQEBBGUF
+BAqpCQMKDwUAAEIFAQQQAAEEAQQvBQEBDgABBAEEEwUBBgEBDgABAgEGFAUB
+BA4AAQESBQEEAQIOAAEBAQQUBQEEAQENAAADAQQEACAFAQQBAQ8AAAMBAgYA
+ZQUECqkJAwoPBQAAQgUBBAEBDwABBAEELwUBAQ4AAQQBBBMFAQQBAQ4AAQQB
+BBMFAQYBAg4AAQEBBhIFAQQOAAEBAQQUBQEEAQENAAADAQQEAB8FAQYBARAA
+AQFnBQQKqQkDCg8FAABCBQEEEAABBAEELwUBAQ4AAQQBBBQFAQEOAAEEAQQU
+BQEEDgABARIFAQQBAg4AAAMBBAQAEwUBBAEBDQAAAwEEBAAeBQEEAQIQAAEB
+AQRnBQQKqQkDCg8FAABCBQEEAQEPAAEEAQQvBQEBDgABBAEEEwUBBgEBDgAB
+AgEGEwUBBAECDgABAQEGEgUBBA4AAQEBBBQFAQQBAQ0AAAMBBAQAHAUAAwYF
+BAARAAEBaAUECqkJAwoPBQAAQgUBBBAAAQQBBC8FAQEOAAEEAQQTBQEEAQEO
+AAEEAQQUBQEEDgABARIFAQQBAg4AAAMBBAQAEwUBBAEBDQAAAwEEBAAdBQEE
+AQESAAEEZwUECqkJAwoPBQAAQgUBBAEBDwABBAEELwUBAQ4AAQQBBBMFAQQB
+AQ4AAQQBBBMFAQQBBA4AAQEBBhIFAQQOAAEBAQQUBQEEAQENAAADAQQEABwF
+AQQBAhMAAQEBBGYFBAqpCQMKDwUAAEIFAQQQAAEEAQQvBQEBDgABBAEEEwUB
+BgEBDgABAgEGFAUBBA4AAQESBQEEAQIOAAEBAQQUBQEEAQENAAADAQQEABwF
+AQQVAAEBAQZlBQQKqQkDCg8FAABCBQEEAQEPAAEEAQQvBQEBDgABBAEEEwUB
+BAEBDgABBAEEEwUBBgECDgABAQEGEgUBBA4AAAMBBAQAEwUBBAEBDQAAAwEE
+BAAbBQEEAQEWAAECAQRkBQQKqQkDCg8FAABCBQEEEAABBAEELwUBAQ4AAQQB
+BBQFAQEOAAEEAQQUBQEEDgABARIFAQQBAg4AAQEBBBQFAQQBAQ0AAAMBBAQA
+GQUAAwYEAQAPAAEBCAABBAEEYwUECqkJAwoPBQAAQgUBBAEBDwABBAEELwUB
+AQ4AAQQBBBMFAQYBAQ4AAQIBBhMFAQQBAg4AAQEBBhIFAQQOAAADAQQEABMF
+AQQBAQ0AAAMBBAQAGgUBAg8AAAMBBAIABwABAQEEYwUECqkJAwoPBQAAQgUB
+BBAAAQQBBC8FAQEOAAEEAQQTBQEEAQEOAAEEAQQUBQEEDgABARIFAQQBAg4A
+AQEBBBQFAQQBAQ0AAAMBBAQAFwUABAYFBAEPAAAEAgYEAQcAAQEBBmIFBAqp
+CQMKDwUAAEIFAQQBAQ8AAQQBBC8FAQEOAAEEAQQTBQEEAQEOAAEEAQQTBQEG
+AQEOAAEBAQQSBQEEDgABAQEEFAUBBAEBDQAAAwEEBAAYBQEEAQEPAAEBAwUB
+BAEBBwABAgEGYQUECqkJAwoPBQAAQgUBBBAAAQQBBC8FAQEOAAEEAQQTBQEG
+AQEOAAECAQYTBQEEAQIOAAEBAQYSBQECDgAAAwEEBAATBQEEAQENAAADAQQE
+ABcFAQQBAg8AAAgBBAQFBQQCAQcAAQIBBmAFBAqpCQMKDwUAAEIFAQQBAQ8A
+AQQBBC8FAQEOAAEEAQQTBQEEAQEOAAEEAQQTBQEEAQEOAAECAQQRBQEGAQQO
+AAEBAQQUBQEEAQENAAADAQQEABcFAQQQAAECAQYEBQEEAQEHAAEBAQRgBQQK
+qQkDCg8FAABCBQEEEAABBAEELwUBAQ4AAQQBBBQFAQEOAAEEAQQSBQEGAQQP
+AAEBAQYSBQECDgAAAwEEBAATBQEEAQENAAADAQQEABYFAQQBAQ8AAQEGBQEG
+AQQIAAEBYAUECqkJAwoPBQAAQgUBBAEBDwABBAEELwUBAQ4AAQQBBBMFAQYB
+AQ4AAQIBBhIFAQQBAg8AAQIBBhEFAQYBBA4AAQEBBBQFAQQBAQ0AAAMBBAQA
+FAUAAwQEAgAPAAEBAQQIBQEECAABAQEGXgUECqkJAwoPBQAAQgUBBBAAAQQB
+BC8FAQEOAAEEAQQTBQEEAQEOAAEEAQQSBQEEAQEPAAECAQYSBQECDgABAQEE
+FAUBBAEBDQAAAwEEBAAVBQEEEAABAgEGCAUBBAEBCAABAgEEXQUECqkJAwoP
+BQAAQgUBBAEBDwABBAEELwUBAQ4AAQQBBBMFAQQBAQ4AAQQBBBEFAQYBARAA
+AQISBQEGAQQOAAADAQQEABMFAQQBAQ0AAAMBBAQAFAUBBAEBDwABAQEECgUB
+BAEBBwAAAwEEBABcBQQKqQkDCg8FAABCBQEEEAABBAEELwUBAQ4AAQQBBBMF
+AQQBAQ4AAQIDBgEFAQQLBQADBAQCABAAAAMBBAQAEgUBAg4AAQEBBBQFAQQB
+AQ0AAAMBBAQAEgUAAwQEAQAPAAADAQQEAAoFAQQBBAgAAQEBBFwFBAqpCQMK
+DwUAAEIFAQQBAQ8AAQQBBCYFAQQBBAYGAQUBAQ4AAQQBBAsFAAQEBAYEAwYA
+AwQGAQAQAAECAQIDBAAMBgYEBAYFBAYGBAQBEQABAQEGDAUACAQFBQQFBQQE
+DgAAAwEEBAAMBQAJBAUGBQQFBQQBAA0AAAMBBAQAEwUBBBAAAQQBBA0FAQII
+AAEBAQZbBQQKqQkDCg8FAABCBQEEEAABBAEEJwUACQQBAgIBAgIBAQAOAAEE
+AQQLBQAKBAQCBAIEAgQCARIAAwEACgICBAQCBAQCAgETAAEBAQ0LBQMEAAYC
+BAQCBAIOAAEBAQQMBQMEAAcCBAQCBAIBAA0AAAMBBAQAEgUBBAEBDwABAQ8F
+AQQBAQgAAAMCBAQAWQUECqkJAwoPBQAAQgUBBAEBDwABBAEEJwUBARYAAQQB
+BAsFAAcEAQABAAABABsAAAMBAAEAFwABBAEECgUACAQEAQEAAQABEAABAQEE
+DAUABwQBAQABAAEAEAAAAwEEBAAQBQADBgQBAA8AAAMBBAQADwUBBAgAAAMB
+BAQAWQUECqkJAwoPBQAAQgUBBBAAAQQBBCcFAQEWAAEEAQQKBQADBAQBADoA
+DQUBBAEBFQAAAwEEBAALBQEEFgAAAwEEBAAOBQAEBAUFAhAAAQQBBBAFAQQB
+AggAAAUBBAYFBABWBQQKqQkDCg8FAABCBQEEAQEPAAEEAQQnBQEBFgABBAEE
+CwUBBDoAAQIBBgsFAQQBBBYAAQEBBAwFAQYBARUAAAMBBAQACgUBBAEGBAQB
+AQEBEAAAAwIGBAALBQMGAAQFBAIBCAAACAECBgQEBgYEUgUECqkJAwoPBQAA
+QgUBBBAAAQQBBCYFAQQBARYAAQQBBAsFAQQBARYAAwEfAAEBAQQNBQEEAQEV
+AAADAQQEAAsFAQYBARUAAAMBBAQACAUDBAECAwETAAAGAQEEAgYECAUAAwQC
+AgADAQsAAwEABAICBgRRBQQKqQkDCg8FAABCBQEEAQEPAAEEAQQnBQAEBAEA
+ARMAAQQBBAsFAAMEAQEAFQAABAIGAgEeAAECAQYNBQADBAEBABQAAQEBBAwF
+AAMEAQEAFAAAAwEEBAAJBQEEAQEaAAAEAQEEBAcFAQEVAAECAQZRBQQKqQkD
+Cg8FAABCBQEEEAABBAEEJwUABQYEBAEBABIAAQQBBAsFAAUGBAQCAQATAAAG
+BAQFBAQBGwABAgEGDgUABQYEBAEBABIAAAMBBAQADAUABAYEAQESAAADAQQE
+AAkFAQQBARwAAQQIBRYAAQIBBlEFBAqpCQMKDwUAAEIFAQQBAQ8AAQQBBCsF
+AAQGBAIBDwABBAEEDwUABQYEAgEBAA8AAQQBBAMFAAMEBAEAGAABARMFAAUG
+BAQBAQAPAAEBAQQQBQAEBAQCAQ8AAAMBBAQACAUBBAEEHQABBAEEBwUBARUA
+AQFSBQQKqQkDCg8FAABCBQEEEAABBAEELQUDBAEBAQEMAAEEAQQRBQAGBgQE
+AgEBDAABAgEGBAUABQYEBAEBABMAAAMBAQYAFgUABQQEAgEBAAwAAQEBBBIF
+AAUGBAQBAQAMAAADAQQEAAkFAQQBARwAAQQIBRYAAAUCBAQFBAADBQAGBAQF
+BQQERQUECqkJAwoPBQAAQgUBBAEBDwABBAEEMAUABQYEBAEBAAkAAQQBBBUF
+AAUEBAIBAQAJAAEEAQQHBQAGBAQCAQABDgAAAwEEBAAaBQAFBgQCAQEACQAA
+AwEEBAAUBQAFBgQEAQEACQAAAwEEBAAJBQEEAQEcAAEEAQQGBQEEAQEVAAAI
+AQUEAgQEBQYIBEMFBAqpCQMKDwUAAEIFAQQQAAEEAQQyBQAFBgQEAgEABwAB
+BAEEFwUDBAADAgEBAAYAAQQBBAkFAAMGBAQAAwEJAAEBAQEDBB0FAAUGBAQC
+AQAHAAEBAQQXBQAGBgQEAgEBBwABBAoFAB8EBAICBAICBAICBAICBAICBAIC
+BAICBAICBAICBAIGAAgFABUEAgIEAgIEAgIEAgIEAgIEAgIEAgIAAwQBAAMB
+AAQFAgAAAwEAAwACBgBDBQQKqQkDCg8FAABCBQEEAQEPAAEEAQQ2BQEGCQQb
+BQoEDAUBBgEFAwQABAIBAgEFBCQFAAgEBAIBAgEBAgMEGgUDBAAFAQIBAgEA
+AwRIBQANAgEBBAUEAQIGBAIABABEBQQKqQkDCg8FAABCBQEEEAABBAEE/wUa
+BQMEAAgBAgYEBAEBAgMBRQUECqkJAwoPBQAAQgUBBAEBDwABBAEE/wUZBQEG
+AwQACwECBAIEAQAAAQAAAEUFBAqpCQMKDwUAAEIFAQQQAAEEAQT/BRoFAA8C
+AQYBBAQBBAEAAgIBAAQARAUECqkJAwoPBQAAQgUBBAEBDwABBAEE/wUZBQAF
+BgIAAgAAAwEACQQAAQQEAQAEBABDBQQKqQkDCg8FAABCBQEEEAABBAEE/wUa
+BQECBgEACQIBAgYFBAECBgBDBQQKqQkDCg8FAABCBQEEAQEPAAEEAQT/BRoF
+CgQBBQEFAwREBQQKqQkDCg8FAABCBQEEEAABBAEE/wVtBQQKqQkDCg8FAABC
+BQEEAQEPAAEEAQQ1BQADBAUEAP8FNQUECqkJAwoPBQAAQgUBBBAAAQQBBDMF
+AAcGBAQCBAIGAP8FMwUECqkJAwoPBQAAQgUBBAEBDwABBAEEMQUABQQEAgEB
+AAMAAAQBAQQE/wUwBQQKqQkDCg8FAABCBQEEEAABBAEEMAUAAwYEAQAJAAEC
+AQb/BS8FBAqpCQMKDwUAAEIFAQQBAQ8AAQQwBQEEAQIMAAEBAQT/BS4FBAqp
+CQMKDwUAAEEFAQYBAhAAAQEwBQEEAQENAAECAQb/BS0FBAqpCQMKDwUAADkF
+AAUEBg0GDQADBAECAQERAAEBAwQEBgEEJQUAAwQEAQAPAAEEAQT/BSwFBAqp
+CQMKDwUAADkFAQQBAgYBFQADAQAFAgECBAQAJQUBBBAAAQIBBv8FLAUECqkJ
+AwoPBQAAOAUBBAEBIgABASUFAQYBBBAAAQEBBP8FLAUECqkJAwoPBQAAOQUB
+AiIAAQEBDSUFAQERAAEEAQT/BSsFBAqpCQMKDwUAADgFAQYBASIAAQElBQEE
+AQERAAEE/wUsBQQKqQkDCg8FAAA5BQECIgABAQENJAUBBAEBEQABBAEE/wUr
+BQQKqQkDCg8FAAA4BQEEAQEiAAEBJQUBBAEBEAABAQEE/wUsBQQKqQkDCg8F
+AAA5BQEEIgIBBAEEJAUBBAEEEAABAQEE/wUsBQQKqQkDCg8FAAA5BQAkBgUE
+BgUEBgUEBgUEBgUEBgUEBgUEBgUEBgUEBgUEBgUEBgUEJgUBBBAAAQIBBv8F
+LAUECqkJAwoPBQAAgwUBBAECDgABAQEE/wUtBQQKqQkDCg8FAACEBQEEAQEN
+AAECAQb/BS0FBAqpCQMKDwUAAIUFAQQBAQsAAQIBBv8FLgUECqkJAwoPBQAA
+hQUABAQEAQEHAAADAQQEAP8FLwUECqkJAwoPBQAAhwUBBAEEBgEDBAADBQUG
+AP8FLQUECqkJAwoPBQAAigUAAwYEBAD/BTUFBAqpCQMKDwUAAP8FwgUECqkJ
+AwoPBQAA/wXCBQQKqQkDCg8FAAD/BcIFBQqoCQMKDwUAAP8FwgUFCqgJAwoP
+BQAA/wXCBQUKqAkDCg8FAAD/BcIFBgqmCQQKDwUAAP8FwwUFCqYJBAoPBQAA
+/wXDBQYKpAkFCg8FAAD/BcMFBwqiCQYKDwUAAP8FxAUHCqAJBgoQBQAA/wXE
+BQsKmAkKChAFAAD/BcUFqwoRBQAA/wXGBakKEgUAAP8FxwWnChMFAAD/BcsF
+nwoXBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUA
+AP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8F
+ggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/
+Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIF
+AAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/
+BYIFAAD/Bf8FggUAAP8F/wWCBQAA/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAA
+/wX/BYIFAAD/Bf8FggUAAP8F/wWCBQAB
+====
diff --git a/keytab-lilo.pl b/keytab-lilo.pl
new file mode 100755 (executable)
index 0000000..1312194
--- /dev/null
@@ -0,0 +1,91 @@
+#!/usr/bin/perl
+$DEFAULT_MAP = "us";
+$DEFAULT_EXT = ".kmap";
+
+sub usage
+{
+    print STDERR
+      "usage: $0 [ -p old_code=new_code ] ...\n".
+      (" "x(8+length $0))."[path]default_layout[.map] ] ".
+      "[path]kbd_layout[.map]\n";
+    exit 1;
+}
+
+
+while ($ARGV[0] eq "-p") {
+    shift(@ARGV);
+    &usage unless $ARGV[0] =~ /=/;
+    $table[eval($`)] = eval($');
+    shift(@ARGV);
+}
+&usage unless defined $ARGV[0];
+load_map("def",defined $ARGV[1] ? $ARGV[0] : undef);
+load_map("kbd",defined $ARGV[1] ? $ARGV[1] : $ARGV[0]);
+&build_table("plain","shift","ctrl","altgr","shift_ctrl",
+  "altgr_ctrl","alt","shift_alt","ctrl_alt");
+for ($i = 0; $i < 256; $i++) {
+    printf("%c",$table[$i] ? $table[$i] : $i) || die "print: $!";
+}
+close STDOUT || die "close: $!";
+
+
+sub load_map
+{
+    local ($pfx,$map) = @_;
+    local ($empty,$current);
+
+    $map = $DEFAULT_MAP unless defined $map;
+    $map .= $DEFAULT_EXT unless $map =~ m|/[^/]+\.[^/]+$|;
+    if (!open(FILE,"loadkeys -m $map |")) {
+       print STDERR "loadkeys -m $map: $!\n";
+       exit 1;
+    }
+    undef $current;
+    $empty = 1;
+    while (<FILE>) {
+       chop;
+       if (/^(static\s+)?u_short\s+(\S+)_map\[\S*\]\s+=\s+{\s*$/) {
+           die "active at beginning of map" if defined $current;
+           $current = $pfx.":".$2;
+           next;
+       }
+       undef $current if /^};\s*$/;
+       next unless defined $current;
+       s/\s//g;
+       $map{$current} .= $_;
+       $empty = 0;
+    }
+    close FILE;
+    return unless $empty;
+    print STDERR "Keymap is empty\n";
+    exit 1;
+}
+
+
+sub build_table
+{
+    local (@maps) = @_;
+    local (@tmp);
+
+    $set = 0;
+    for $map (@maps) {
+       $code = $set;
+       for (split(",",$map{"def:".$map})) {
+           die "bad map entry $_ (def, map $map)" unless /^0x\S\S(\S\S)$/;
+           $tmp[$code] = hex $1 unless $tmp[$code];
+           $code++;
+       }
+       $set += 256;
+    }
+    $set = 0;
+    for $map (@maps) {
+       $code = $set;
+       for (split(",",$map{"kbd:".$map})) {
+           die "bad map entry $_ (kbd, map $map)" unless /^0x\S\S(\S\S)$/;
+           $table[$tmp[$code]] = hex $1 unless $table[$tmp[$code]];
+           $code++;
+       }
+       $set += 256;
+    }
+    $table[0] = 0;
+}
diff --git a/lilo.lsm b/lilo.lsm
new file mode 100644 (file)
index 0000000..fa399f5
--- /dev/null
+++ b/lilo.lsm
@@ -0,0 +1,20 @@
+Begin4
+Title:                 LILO
+Version:               23.1
+Entered-date:  2010-11-04
+Description:   Generic boot loader for Linux. Distribution 
+               includes full source, documentation and support files.  
+Keywords:              Linux, boot loader, LILO
+Author:                        Joachim Wiedorn
+Maintained-by: Joachim Wiedorn <ad_debian@joonet.de>
+Primary-site:  http://lilo.alioth.debian.org/
+Original-site:  http://lilo.alioth.debian.org/
+Alternate-site:        http://alioth.debian.org/projects/lilo/  (developer's site)
+Files:                 561kB  lilo-23.1.tar.gz
+Platforms:             Linux (>= 2.4.0), 
+               gcc (>= 3.3.5), as86 (>= 0.16.14) needed to compile.
+               bcc (0.16.14) needed to compile diagnostic disk 2 & DOS *.com.
+               LaTeX and (optionally) Perl and Transfig needed to print the
+               documentation.
+Copying-policy:        BSD-License
+End
diff --git a/make.vars b/make.vars
new file mode 100644 (file)
index 0000000..afa1656
--- /dev/null
+++ b/make.vars
@@ -0,0 +1,101 @@
+### Configuration variables for makefiles ###
+
+# NOTE: These variables can also be stored in a file /etc/lilo.defines, e.g.
+# -DIGNORECASE -DONE_SHOT
+#
+# NOTE: If the file /etc/lilo.defines exists, variables configured in this
+# Makefile are ignored
+#
+#   ATARAID     Detect 'dmraid' drivers (linux/drivers/raid/dm.c).
+#   AUTOAUTO    Enable automatic generation of change rules for MS partitions;
+#               issue warning if "CHANGE AUTOMATIC" is assumed
+# * BDATA       Enable real mode gathering of system information for '-T'
+#   BEEP        Beep after displaying "LILO".
+#   BOOT_FILE   Append "BOOT_FILE=<path>" to the kernel command line.
+#   BUG_SI_EBDA=n  Compensate for BIOS's (notably early Silicon Image S-ATA)
+#               that use the EBDA, but don't properly allocate the space.
+#               (n=1..64) specifies the extra EBDA in kilobytes (default 20).
+#   COHERENT    Make boot loaders (chain.b & mbr.b) compatible with Coherent
+#               by writing the boot device code to the memory copy of the PT
+# * DEVMAPPER   Device Mapper (aka LVM2) support (2.6 kernels only)
+# * DSECS=n     Set the number of Descriptor Sectors (n=1..12).  Each sector
+#               of the descriptor table holds 9..10 descriptors.
+# * EVMS        Enables support for booting from EVMS volumes. Requires a
+#               2.4 or 2.6 kernel patched to EVMS version 1.1.0 or later.
+#   HP_TTRC     Insert 150ms delay for HP TTRC card.  Affects 'second.S'
+# * IGNORECASE  Image selection is case-insensitive. Passwords are still
+#               case-sensitive.
+#   INITRDLOW   Always load initial ramdisk images below address 15M,
+#               ignoring any 'large-memory' option in the config file.
+# * LVM         Enables support for booting from LVM partitions. Requires a
+#               2.4 kernel (>= 2.4.7) or a 2.6 kernel.
+# * MDPRAID     Enable automatic marking of volumes of full volume raid
+#               as 'inaccessible.  Add "noraid" keyword to suppress.
+#   NO1STDIAG   Don't show diagnostic on read errors in the first stage
+#               boot. (not recommended)
+#   NODRAIN     Don't drain keyboard buffer after booting.
+#   NOINSTDEF   Don't install a new boot sector if INSTALL is not specified.
+# * NOKEYBOARD  Enable the 'nokbdefault' keyword, and test for booting on
+#               a system without a keyboard; alters default descriptor
+#               to be booted.  Enable the 'nokbdisable' keyword also.
+#   NOSERIAL    Don't assemble serial line support in the boot loader.
+#   NOVGA       Don't write to Monochrome or VGA displays.
+#   OLD_DIRSTR  Use old locations of config and boot files: (/etc/lilo)
+# * ONE_SHOT    Disable the command-line and password timeout if any key is
+#               hit at the boot prompt.
+# * PASS160     Use 160-bit password hash (Secure Hash Standard, see
+#               FIPS PUB 180-1) instead of 64-bit CRC-32 hash
+#   READAHEAD   Enable read-ahead on EDD disks which support the function.
+#               Note:  no BIOS has yet been seen which supports this
+#               EDD revision 1.1 function.
+#   READONLY    Don't write to disk while booting, e.g. don't overwrite the
+#               default command line in the map file after reading it.
+# * REISERFS    Compile support for parts of LILO on ReiserFS.
+#               Requires header files for kernel 2.4.0test8 or later.
+# * REWRITE_TABLE Enable rewriting the partition table at boot time.
+# * SOLO_CHAIN  Assemble all chain-loader functions into 'chain.b', 
+#               eliminating the need for 'os2_d.b'.
+#   SUSPEND=    Modify 'vmdefault' action if this partition type on C: drive
+#               is marked active; (Dell suspend partition is -DSUSPEND=0x84).
+#   USE_TMPDIR  Create temporary devices in $TMPDIR if set
+# * VERSION     Prints version string at LILO boot prompt.
+# * VIRTUAL     Enable 'vmdefault', 'vmdisable', 'vmwarn' keywords; feature
+#               requested by VMware users (new, experimental)
+#   XL_SECS=n   Support for extra large (non-standard) floppies.
+
+CONFIG=-DBDATA -DDSECS=3 -DEVMS -DIGNORECASE -DLVM -DNOKEYBOARD -DONE_SHOT \
+    -DPASS160 -DREISERFS -DREWRITE_TABLE -DSOLO_CHAIN -DVERSION -DVIRTUAL \
+    -DMDPRAID -DDEVMAPPER
+   
+# set the following if you wish LILO.COM to be installed
+DOS_DIR=/dosC/boot
+
+# select place for man pages
+MAN_DIR=/usr/share/man
+
+# set the compiler optimization level
+OPT=-Os
+
+### End of configuration variables for makefiles ###
+
+
+#
+#  Do not modify anything below this point
+#
+
+SBIN_DIR=/sbin
+CFG_DIR=/etc
+BOOT_DIR=/boot
+USRSBIN_DIR=/usr/sbin
+BUILTIN=1
+
+PCONFIG=$(KVER) $(HDM) $(LILO) `( if [ -r $$DESTDIR/etc/lilo.defines ]; then \
+  cat $$DESTDIR/etc/lilo.defines; else echo $(CONFIG); fi ) | \
+  sed 's/-D/-DLCF_/g'`
+LILO=-DLILO=0xbb920890
+KVER=`if [ -f /usr/include/linux/version.h ]; then echo -DHAS_VERSION_H; fi`
+HDM=`if [ -f /usr/include/libdevmapper.h ]; then echo -DHAS_LIBDEVMAPPER_H; fi`
+DEVMAPPER=`if [ -f /usr/include/libdevmapper.h ]; then echo "-ldevmapper"; fi`
+
+TMP=_TmP_
+
diff --git a/man/Makefile b/man/Makefile
new file mode 100644 (file)
index 0000000..05ae551
--- /dev/null
@@ -0,0 +1,25 @@
+# -*- makefile -*-
+
+# adding variables
+include ../make.vars
+
+all:
+
+install:
+       mkdir -p $$DESTDIR$(MAN_DIR)/man5
+       mkdir -p $$DESTDIR$(MAN_DIR)/man8
+
+       install -m 0644  lilo.8  $$DESTDIR$(MAN_DIR)/man8
+       install -m 0644  mkrescue.8  $$DESTDIR$(MAN_DIR)/man8
+       install -m 0644  lilo.conf.5  $$DESTDIR$(MAN_DIR)/man5
+       install -m 0644  keytab-lilo.8  $$DESTDIR$(MAN_DIR)/man8
+
+clean:
+
+distclean:
+
+uninstall:
+       rm -f $$DESTDIR$(MAN_DIR)/man8/lilo.8
+       rm -f $$DESTDIR$(MAN_DIR)/man8/mkrescue.8
+       rm -f $$DESTDIR$(MAN_DIR)/man5/lilo.conf.5
+       rm -f $$DESTDIR$(MAN_DIR)/man8/keytab-lilo.8
diff --git a/man/keytab-lilo.8 b/man/keytab-lilo.8
new file mode 100644 (file)
index 0000000..d5f4e90
--- /dev/null
@@ -0,0 +1,102 @@
+.\" '\" t
+.\" This page is based on the lilo docs/source, which carry the following
+.\" COPYING condition:
+.\" 
+.\" LILO program code, documentation and auxiliary programs are
+.\" Copyright 1992-1994 Werner Almesberger.
+.\" All rights reserved.
+.\" 
+.\" Redistribution and use in source and binary forms of parts of or the
+.\" whole original or derived work are permitted provided that the
+.\" original work is properly attributed to the author. The name of the
+.\" author may not be used to endorse or promote products derived from
+.\" this software without specific prior written permission. This work
+.\" is provided "as is" and without any express or implied warranties.
+.\" 
+.\" Original version of this manpage: 
+.\" Peter Maydell (pmaydell@chiark.greenend.org.uk), 03/1998
+.\" 
+.TH "KEYTAB-LILO.PL" "8" "April 1998" "" ""
+.SH "NAME"
+keytab\-lilo \- compile keytables files for use with LILO
+.SH "SYNOPSIS"
+.B /usr/sbin/keytab\-lilo
+.RB [ \-p
+.I R old_code = new_code ]
+.RB ...
+.RI [ default_layout ] " kbd_layout"
+.SH "DESCRIPTION"
+.LP 
+.B keytab\-lilo
+is a program which compiles keytable definitions (in the format
+specified in 
+.BR keytables(5) ) 
+into a format which can be used by 
+.B lilo(8)
+to set the keyboard type when booting
+[using the 
+.B keytable
+parameter in
+.BR /etc/lilo.conf ].
+
+.I kbd_layout
+should be the name of a map file which specifies the desired 
+keyboard layout. This file may be a 
+.B gzip(1) 
+compressed map. If no file extension is given,
+.B .map.gz
+is assumed. If the full pathname is not specified,
+.B /usr/share/keymaps/
+is assumed.
+
+Since 
+.B lilo 
+essentially needs to know the differences between
+the BIOS keyboard mapping and the one you require, the
+.I default_layout
+file should contain a 
+.B keytables(5) 
+file for the BIOS default mapping. If no 
+.I default_layout
+file is specified,
+.B us.map.gz
+is used.
+
+.B keytab\-lilo
+writes the output translation table as a binary string to standard
+output, so you should redirect it to a suitable file. 
+.B lilo
+has no particular restrictions on the name of keyboard translation
+files, but the suggested naming convention and location is
+.BI /boot/ mapping .ktl
+(where
+.B .ktl
+stands for "Keyboard Table for Lilo").
+.SH "OPTIONS"
+.TP 
+.B \-p
+.I R old_code = new_code
+.br 
+Specifies corrections ("patches") to the mapping obtained from the 
+translation table files. E.g. if pressing the upper case "A" should 
+yield an at sign, \-p 65=64 would be used. The  \-p  option can be 
+repeated any number of times. The codes can also be given as 
+hexadecimal or as octal numbers if they are prefixed with 0x or 0, 
+respectively. 
+
+.SH "EXAMPLES"
+.TP 
+.B keytab\-lilo dvorak >/boot/dvorak.ktl
+
+This is the most common form of invocation; it simply compiles the
+given map file (in this case dvorak) and puts the result in
+.BR /boot/dvorak.ktl .
+
+.SH "AUTHOR"
+Werner Almesberger (almesber@bernina.ethz.ch).
+.br 
+Peter Maydell (pmaydell@chiark.greenend.org.uk) wrote this manual page.
+.SH "SEE ALSO"
+.BR lilo (8),
+.BR keytables (5),
+.BR gzip (1)
diff --git a/man/lilo.8 b/man/lilo.8
new file mode 100644 (file)
index 0000000..9309925
--- /dev/null
@@ -0,0 +1,496 @@
+'\" t
+.\" @(#)lilo.8 1.0 950728 aeb
+.\" This page is based on the lilo docs, which carry the following
+.\" COPYING condition:
+.\"
+.\" LILO program code, documentation and auxiliary programs are
+.\" Copyright 1992-1998 Werner Almesberger.
+.\" Extensions to LILO, documentation and auxiliary programs are
+.\" Copyright 1999-2005 John Coffman.
+.\" All rights reserved by the respective copyright holders.
+.\" 
+.\" Redistribution and use is subject to the terms set forth in
+.\" the file COPYING in the source directory.
+.\"
+.\" Original version, Andries Brouwer (aeb@cwi.nl), 950728
+.\" Added t directive, as Daniel Quinlan asked, 950824
+.\" Added L switch, John Coffman, 991118
+.\" Added T switch, John Coffman, 001001
+.\" Added p switch, John Coffman, 010402
+.\" Added x switch, John Coffman, 010409
+.\" Added A switch, John Coffman, 010417
+.\" Added M switch, John Coffman, 010417
+.\" Added g switch, John Coffman, 010526
+.\" Added z switch, John Coffman, 010829
+.\" Added E switch, John Coffman, 020409
+.\" Added B,F & X switches, John Coffman, 020418
+.\" Added "k" option to I switch, John Coffman, 020609
+.\" Added Z switch, John Coffman, 030314
+.\" Added I switch options "D" and "a", John Coffman, 030513
+.\" Added I switch option "R", John Coffman, 041116
+.\" Added H switch, John Coffman, 050927
+.\"
+.TH LILO 8 "07 Oct 2005"
+.SH NAME
+lilo \- install boot loader
+.SH SYNOPSIS
+Main function:
+.LP
+.B " /sbin/lilo"
+\- install boot loader
+.LP
+Auxiliary uses:
+.LP
+.B " /sbin/lilo -A"
+\- activate/show active partition
+.br
+.B " /sbin/lilo -E"
+\- edit header or update a bitmap file
+.br
+.B " /sbin/lilo -I"
+\- inquire path name of current kernel
+.br
+.B " /sbin/lilo -M "
+\- write a Master Boot Loader on a device
+.br
+.B " /sbin/lilo -q"
+\- query map
+.br
+.B " /sbin/lilo -R"
+\- set default command line for next reboot
+.br
+.B " /sbin/lilo -T"
+\- tell more about specified topic
+.br
+.B " /sbin/lilo {-u|-U}"
+\- uninstall LILO boot loader
+.SH DESCRIPTION
+.LP
+.B lilo
+installs a boot loader that will be activated the next time you boot your
+system. The default configuration file
+.I "/etc/lilo.conf"
+(see 'man lilo.conf') will contain most options, but many, including
+those which override the
+configuration file, may be specified on the command line.
+.LP
+.TP
+.BI "\-\^A " "master-device [ N ]"
+Used with a single argument, inquire of active partition on device
+.IR master-device ;
+e.g., \fI/dev/hda\fP.  With N==0, deactivate all partitions on the device.  With
+N in the range [1..n], activate the specified partition and deactivate all
+others.  Normally, only primary partitions [1..4] may be activated, but if
+the Extended Master Boot Loader is present on the Master Boot Record
+of the device
+(see the \fI-M\fP option), any partition may be made active.  Whether the
+actual OS in the partition will boot from an extended partition depends on
+the characteristics of the OS.  LILO boot records for Linux
+may be booted from an extended partition.
+.TP
+.BI "\-\^b " bootdev
+Specify the boot device; i.e., where the boot loader will be installed.
+"\-b /dev/hda" specifies the Master Boot Record; "\-b /dev/sdb5" specifies
+the first extended partition on the second SCSI disk.
+.TP
+.BI "\-\^B " bitmap-file
+Specify a bitmap file for the boot-time graphics screen, preferably one
+already pre-processed with the 'lilo \-E' command.
+.TP
+.B "\-\^c"
+Enable map compaction. This will merge read requests from adjacent
+sectors. Speeds up the booting (especially from floppy).
+.TP
+.BI "\-\^C " config-file
+.B lilo
+Specify an alternate pathname for the configuration file.
+This option overrides the use of the default configuration file,
+.IR "/etc/lilo.conf" .
+.TP
+.BI "\-\^d " delay
+Specifies the delay time in tenths of a second (20 = 2 sec) before
+automatically booting the first image.  Gives you time to interrupt the
+automatic boot process with Shift, Alt, Ctrl, ScrollLock, or CapsLock.  If
+interrupted, the `boot:' prompt is displayed.  This switch is overridden by
+the appearance of
+.I prompt
+in the configuration file.
+.TP
+.BI "\-\^D " label
+Use the kernel with the given label, instead of the first one
+in the list, as the default kernel to boot.
+.TP
+.BI "\-\^E " filename.ext
+If \fB.ext\fP is \fB.bmp\fP, then take the file to be a bitmap graphic file
+for use in the "bitmap=" configuration file directive.  Enter an interactive
+editor to create or update the color/placement information in the
+bitmap file LILO header.  (see 'bmp-colors', 'bmp-table', and 'bmp-timer'
+on the man page for 'lilo.conf(5)'.)
+.sp
+If \fB.ext\fP is \fB.dat\fP, then take the file to be a configuration file which
+specifies bitmap graphic parameters, which are transferred into the LILO
+header in the bitmap file of the same name.
+.sp
+When a \fB.bmp\fP file is modified using a graphics editor (e.g., GIMP), the
+LILO header will be lost.  It can be restored using the \fB.dat\fP file,
+which is used as a text-based backup for the LILO header information.
+.TP
+.BI "\-\^f " disk-tab
+Specify disk geometry parameter file. (The default is
+.IR /etc/disktab .)
+.TP
+.BI "\-\^F"
+Override boot sector check for filesystems (e.g., swap, XFS, ...) which might be
+destroyed by the installation of the LILO boot sector on the first sector of
+the partition.  These filesystems use the first sector as a superblock.
+
+Compare with "\-P ignore", which bypasses certain partition table checks.
+.TP
+.BI "\-\^g"
+Generate cylinder/head/sector (geometric) disk addresses.  Limited to
+cylinders up to 1023.  Forces compatibility with older versions of LILO.
+.TP
+.BI "\-\^H"
+Override fatal halt when a RAID array does not have all disks active.
+.TP
+.BI "\-\^i " boot-loader
+Specify a file to be used as the new boot loader. (The default is
+.IR /boot/boot.b .)
+.TP
+.BI "\-I " "label [D|a|i|k|r|R]"
+.B label
+is taken to be the name of an image specified in the configuration file.
+This command will print the path name of the corresponding kernel file, keytable
+file, initial ramdisk file, root specification, or "append="
+string ("i", "k", "r", "R", or "a" option). 
+The "D" option ignores the
+.B label
+parameter, and prints the default "image=" label, or first "image=" label
+if no default
+.BI image
+is specified.
+.TP
+.BI "\-\^l"
+Generate 24-bit linear sector addresses instead of cylinder/head/sector
+addresses.
+.TP
+.BI "\-\^L"
+Generate 32-bit Logical Block Addresses instead of cylinder/head/sector
+addresses, allowing
+access to all partitions on disks with more than 1024 cylinders.
+.TP
+.BI "\-\^m " map-file
+Use specified map file instead of the default.
+.TP
+.BI "\-\^M " "master-device " "[mbr|ext]"
+Install a Master Boot Record on the device specified as
+.IR master-device ,
+selecting the Standard or Extended Master Boot Loader per the option.
+The primary partition table on
+.I master-device
+is undisturbed.  If no valid Volume-ID (serial number)
+is present, then generate one
+and write it to the MBR.  If \fBmbr\fP is specified, the Standard Master
+Boot Loader
+will search partitions 1-4 for an active flag, and boot the flagged
+partition.  Only one active flag is allowed.  If \fBext\fP is specified, the
+search for an active partition will include extended partitions as well. 
+The presence of the Extended Master Boot Loader on the
+Master Boot Record (MBR = sector 0) of a disk
+affects the operation of the \fI-A\fP option.
+.TP
+.BI "\-\^p"
+Require interactive entry of all passwords specified as
+.B """""" 
+in the configuration file.
+.TP
+.BI "\-\^P " "{fix|ignore|\<global-option\>}"
+Fix or ignore `corrupt' partition tables, i.e., partition tables
+with linear and cylinder/head/sector addresses that do not correspond.
+Always try
+.I -P ignore
+first, as
+.I -P fix
+will re-write the partition table, possibly destroying all partitions
+on the disk.
+
+.I -P ignore
+is also used to bypass the partition table check for partition types within
+the partition table which
+might not allow the installation of a LILO boot sector.  Compare with the
+"\-F" flag, which overrides the check of the actual boot sector.
+
+.I "-P <global-option>"
+allows the passing of any global option which may appear in the global
+section (top) of the configuration file (/etc/lilo.conf).  For instance,
+.I -P nowarn
+will pass the "nowarn" option, just as though "nowarn" appeared in the
+configuration file (same as the "\-w" switch).  Similarly,
+.I -P timeout=50
+will add or override the "timeout=" line in the configuration file.  Note
+that the general
+.I -P
+switch actually duplicates a number of command line option switches. 
+However, it is not strictly the same as some switches whick cause an
+override of other options; e.g., "\-g" (\-P geometric), "\-L" (\-P lba32).
+.TP
+.B \-\^q
+List the currently mapped files.
+.B lilo
+maintains a file, by default
+.IR "/boot/map" ,
+containing the name and location of the kernel(s) to boot.
+This option will list the names therein.  Use with \fB-v\fP for
+more detailed information about the installed boot loader.
+.TP
+.BI "\-\^r " root-directory
+Before doing anything else, do a \fIchroot\fP to the indicated
+directory. The new root directory must contain a
+.I /dev
+directory, and may need a
+.I /boot
+directory. It may also need an
+.IR /etc/lilo.conf " file."
+.TP
+.BI "\-\^R " "command line"
+This option sets the default command for the boot loader the next
+time it executes. The boot loader will then erase this line: this
+is a once-only command. It is typically used in reboot scripts,
+just before calling `shutdown \-r'.  Used without any arguments, it will
+cancel a \fIlock\fP-ed or \fIfallback\fP command line.
+.TP
+.BI "\-\^s " save-file
+When
+.B lilo
+writes a new boot sector, it preserves the former contents of the sector
+in a file, named by default \fI/boot/boot.NNNN\fP,
+where NNNN is the hexadecimal representation of the major and minor
+device numbers of the drive/partition. This option specifies the backup
+save file in one of three ways: a save directory (default is '/boot') using
+the default filename 'boot.NNNN' in the specified directory; a pathname template
+to which '.NNNN' is appended (default would be '/boot/boot');
+or the full pathname of the file, which must include the correct '.NNNN'
+suffix. When used with the
+\fB-u\fP option, the full file pathname must be specified.
+.TP
+.BI "\-\^S " save-file
+Normally,
+.B lilo
+will not overwrite an existing boot sector save file. This options says
+that overwriting is to be forced. As with \fB-s\fP, the specification may be of a
+save directory, pathname template, or full pathname (which includes the '.NNNN'
+suffix.)
+.TP
+.BI "\-\^t "
+Test only. Do not really write a new boot sector or map file.
+Use together with \fB-v\fP to find out what
+.B lilo
+is about to do.
+.TP
+.BI "\-\^T " option
+Print out system information, some of it extracted from the system
+bios.  This is more convenient than booting the LILO diagnostic
+floppy on problem systems.
+.I option
+may be any one of the following:
+.IP
+.nf
+   help  - print a list of available diagnostics
+   ChRul - list the partition types subject to
+           Change-Rules
+   EBDA  - list Extended BIOS Data Area information
+   geom=<drive> list drive geometry for bios drive;
+           e.g., geom=0x80
+   geom  - list drive geometry for all drives
+   table=<drive> list the primary partition table;
+           e.g., table=/dev/sda
+   video - list graphic modes available to boot
+           loader
+.fi
+.TP
+.BI "\-\^u " [device-name]
+Uninstall \fIlilo\fP by copying the saved boot sector back.
+The '\-s' and '\-C' switches may be used with this option.
+The \fIdevice-name\fP is optional.  A time-stamp is checked.
+.TP
+.BI "\-\^U " [device-name]
+Idem, but do not check the time-stamp.
+.TP
+.B "\-\^v"
+Increase verbosity. Giving one to five \fB-v\fP options
+will make lilo more verbose, or use, \fB-v\fP \fIn\fP (n=1..5) to
+set verbosity level '\fIn\fP'.
+.TP
+.B "\-\^V"
+Print version number.
+.TP
+.B "\-\^w"
+Used as \fB-w\fP or \fB-w-\fP, suppress warning messages.
+Used as \fB-w+\fP, override \fInowarn\fP in
+the configuration file, and show warning messages.
+.TP
+.BI "\-\^x " option
+For RAID installations only.  The option may be any of the keywords
+.IR none ,
+.IR auto ,
+.IR mbr ,
+.IR mbr-only ,
+or a comma separated list of additional boot devices (no spaces allowed in
+the list).
+.TP
+.BI "\-\^X"
+Reserved for LILO internal use.  May produce different
+output for different LILO versions. The line beginning "CFLAGS="
+will contain the compiler options used to generate this version of LILO.
+.TP
+.B "\-\^z"
+When used with the `\-M' switch, clears the Volume-ID.  Usually used
+in the following sequence to generate a new Volume-ID:
+.nf
+     lilo \-z \-M /dev/hda
+     lilo \-M /dev/hda
+.fi
+.br
+.TP
+.BI "\-\^Z " option
+Tells the boot installer whether special precautions need to be taken
+because the BIOS fails to pass the correct device code in DL (\-Z0). Or may
+specify that the BIOS always gets DL right (\-Z1). Corresponds to, and
+overrides, the configuration file option 'bios-passes-dl='.
+.LP
+The above command line options correspond to the key words
+in the config file indicated below.
+.IP
+.TS
+l l.
+\-b bootdev    boot=bootdev
+\-B file.bmp   bitmap=file.bmp
+\-c    compact
+\-d dsec       delay=dsec
+\-D label      default=label
+\-i boot-loader        install=boot-loader
+\-f file       disktab=file
+\-g    geometric
+\-l    linear
+\-L    lba32
+\-m mapfile    map=mapfile
+\-P fix        fix-table
+\-P ignore     ignore-table
+\-s file       backup=file
+\-S file       force-backup=file
+\-v [N]        verbose=N
+\-w    nowarn
+\-x option     raid-extra-boot=option
+\-Z option     bios-passes-dl=option
+.TE
+.SH "BOOT OPTIONS"
+The options described here may be specified at boot time on
+the command line when a
+kernel image is booted.  These options are processed by LILO, and are
+removed from the command line before it is passed to the kernel,
+unless otherwise noted.
+.LP
+.TP
+.BI lock
+Locks the command line, as though 'lock' had been specified in 'lilo.conf.'
+.TP
+.BI "mem=###[,K,M,G]"
+Specifies the maximum memory in the system in bytes, kilobytes, megabytes,
+or gigabytes.
+This option is not removed from the command line, and is always passed to
+the kernel.
+.TP
+.BI nobd
+Suppresses the BIOS data check.  This option is reserved for use with
+non-IBM-compliant BIOS's which hang with the lines:
+.sp
+.nf
+     Loading...............
+     BIOS data check 
+.fi
+.TP
+.BI "vga=[ASK,EXT,EXTENDED,NORMAL,###,0x###]"
+Allows overriding the default video mode upon kernel startup.
+.br
+.SH BOOT ERRORS
+The boot process takes place in two stages.  The first stage loader is a
+single sector, and is loaded by the BIOS or by the loader in the MBR.  It
+loads the multi-sector second stage loader, but is very space limited.  When
+the first stage loader gets control, it types the letter "L"; when it is
+ready to transfer control to the second stage loader it types the letter
+"I".  If any error occurs, like a disk read error, it will put out a
+hexadecimal error code, and then it will re-try the operation.  All hex
+error codes are BIOS return values, except for the lilo-generated 40, 99 and 9A.
+A partial list of error codes follows:
+.br
+.IP
+.TS
+l l.
+00  no error
+01  invalid disk command
+02  address mark not found
+03  disk write-protected
+04  sector not found
+06  floppy disk removed
+08  DMA overrun
+0A  bad sector flag
+0B  bad track flag
+20  controller failure
+40  seek failure (BIOS)
+40  cylinder>1023 (LILO)
+99  invalid second stage index sector (LILO)
+9A  no second stage loader signature (LILO)
+AA  drive not ready
+FF  sense operation failed
+.TE
+.br
+.LP
+Error code 40 is generated by the BIOS, or by LILO during the conversion of
+a linear (24-bit) disk address to a geometric (C:H:S) address.  On older
+systems which do not support lba32 (32-bit) addressing, this error may also
+be generated.  Errors 99 and 9A usually mean the map file (\-m or map=) is
+not readable, likely because LILO was not re-run after some system change,
+or there is a geometry mis-match between what LILO used (lilo \-v3 to
+display) and what is actually being used by the BIOS (one of the lilo
+diagnostic disks, available in the source distribution, may be needed to
+diagnose this problem).
+
+When the second stage loader has received control from the first stage, it
+prints the letter "L", and when it has initialized itself, including
+verifying the "Descriptor Table" \- the list of kernels/others to boot \- it
+will print the letter "O", to form the full word "LILO", in uppercase.
+
+All second stage loader error messages are English text, and try to
+pinpoint, more or less successfully, the point of failure.
+.br
+.SH INCOMPATIBILITIES
+.B lilo
+is known to have problems with the
+.I reiserfs
+introduced with the 2.2.x kernels, unless the file system is
+mounted with the 'notail' option.  This incompatibility has been
+resolved with reiserfs 3.6.18 and lilo 21.6.
+.I reiser4
+introduced with the 2.5.x kernels requires lilo 22.5.2 or later.
+.sp
+Beginning with version 22.0, RAID installations write the boot record to
+the RAID partition. Conditional writing of MBRs may occur to aid in making
+the RAID set bootable in a recovery situation, but all default actions may
+be overridden. Action similar to previous versions is
+achieved using the `\-x mbr-only' switch.
+.SH BUGS
+Configuration file options `backup' and `force-backup'
+should specify a backup directory or backup file pathname template on
+all RAID installations. Use of an explicit filename may not allow multiple
+backup files to be created correctly. It is best to use the default mechanism,
+as it works correctly in all cases.
+.SH "SEE ALSO"
+fdisk(8), lilo.conf(5), mkrescue(8), mkinitrd(8).
+.sp
+The lilo distribution comes with very extensive TeX documentation through
+Version 21.  Text file README's in the source directory provide updates on
+more recent topics.
+.SH "AUTHORS"
+Werner Almesberger <almesber@lrc.epfl.ch> (versions 0 to 21)
+.br
+John Coffman <johninsd@san.rr.com> (21.2 to present date)
diff --git a/man/lilo.conf.5 b/man/lilo.conf.5
new file mode 100644 (file)
index 0000000..a0f5da0
--- /dev/null
@@ -0,0 +1,1066 @@
+'\" t
+.\" @(#)lilo.conf.5 1.0 950728 aeb
+.\" This page is based on the lilo docs, which carry the following
+.\" COPYING condition:
+.\"
+.\" LILO program code, documentation and auxiliary programs are
+.\" Copyright 1992-1998 Werner Almesberger.
+.\" Extensions to LILO, documentation and auxiliary programs are
+.\" Copyright 1999-2005 John Coffman.
+.\" All rights reserved by the respective copyright holders.
+.\" 
+.\" Redistribution and use in source and binary forms of parts of or the
+.\" whole original or derived work are permitted provided that the
+.\" original work is properly attributed to the author. The name of the
+.\" author may not be used to endorse or promote products derived from
+.\" this software without specific prior written permission. This work
+.\" is provided "as is" and without any express or implied warranties.
+.\"
+.TH LILO.CONF 5 "July 2010"
+.SH NAME
+lilo.conf \- configuration file for lilo
+.SH DESCRIPTION
+.LP
+This file, by default
+.IR /etc/lilo.conf ,
+is read by the boot loader installer 'lilo' (see lilo(8)).
+.LP
+It might look as follows:
+.IP
+.nf
+# lilo.conf
+#
+#  global options:
+boot=/dev/hda
+prompt
+timeout=150
+lba32
+compact
+vga=normal
+root=/dev/hda1
+read-only
+menu-title=" John's Computer "
+#
+#  bootable kernel images:
+image=/boot/zImage-1.5.99
+     label=try
+image=/boot/zImage-1.0.9
+     label=1.0.9
+image=/tamu/vmlinuz
+     label=tamu
+     initrd=initramdisk.img
+     root=/dev/hdb2
+     vga=ask
+#
+#  other operating systems:
+other=/dev/hda3
+     label=dos
+     boot-as=0x80    # must be C:
+other=/dev/hdb1
+     label=Win98
+     boot-as=0x80    # must be C:
+other=/dev/hdb5
+     label=os2
+     loader=os2_d
+     table=E:   # os2 sees as E:
+.fi
+.LP
+This configuration file specifies that lilo uses the Master
+Boot Record on /dev/hda. (For a discussion of the various ways
+to use lilo, and the interaction with other operating systems,
+see user.tex from the lilo documentation.)
+.LP
+When booting, the boot loader will issue its 
+.I "boot:"
+prompt and wait for you to enter the label of the kernel (and any options)
+which you wish to boot. At any time you may hit [Tab] to see
+a list of kernel/other labels.
+Alternately, if the \fBmenu\fP boot loader is installed,
+a menu of boot options will be presented for your selection.
+The title of this menu is overridden with the menu
+title specification in this configuration file.
+If you enter nothing,
+then the default kernel image, the first mentioned, (/boot/zImage-1.5.99)
+will be booted after a timeout of 15 seconds (150 deciseconds).
+There may be at least 16 images mentioned in lilo.conf. (The exact number depends
+upon compilation options.)
+.LP
+As can be seen above, a configuration file starts with a number
+of global options (the top 9 lines in the example),
+followed by descriptions of the options for the various images.
+An option in an image description will override a global option.
+.LP
+Comment lines may appear anywhere, and begin with the "#" character.
+
+.SH "GLOBAL OPTIONS"
+There are many possible keywords. The description below is
+almost literally from user.tex (just slightly abbreviated).
+.TP
+.BI "backup=" <backup-file>
+Specifies the location where a copy of any modified boot sector will be
+saved in a file. 'backup=' may specify this location in one of three ways:
+a directory where the default backup file 'boot.NNNN' will be created;
+a file pathname template to which the '.NNNN' suffix will be added; or
+the full file pathname, which must include the correct '.NNNN' suffix.
+All RAID installations should use only the first two alternatives, as
+multiple backups may be created.  The '.NNNN' suffix is the hexadecimal
+representation of the major and minor device numbers of the device or
+partition. If this option is not specified, the default name of boot sector
+backups is '/boot/boot.NNNN'. If a backup already exists, it will be
+preserved, rather than overwritten.  C.f., \fBforce-backup=\fP below.
+.TP
+.BI "bios-passes-dl=" <option>
+The option is indicated as \fIyes\fP, \fIno\fP, or \fIunknown\fP.  If not
+specified, a value of "unknown" is assumed, unless additional information
+is available to the boot installer. When "no" is specified, it indicates
+that the BIOS is known not to pass the current boot device code to the boot
+loader in the DL register.  Its only function at this point is experimental,
+as certain RAID installations may benefit from knowing that the
+BIOS is 100% reliable.  Its use should be considered experimental.
+.sp
+N.B.:  This option may not be retained in releases beyond 22.5.1, and
+may be specified on the command line with the '\-Z' switch:  yes=1, no=0.
+.TP
+.BI "bitmap=" <bitmap-file>
+Specifies use of a 640x480x16 (VGA BIOS) or 640x480x256 (VGA/VESA BIOS)
+bitmap file as the background on which a boot
+menu is displayed.  May not be used if 'message=' is specified.
+Use of this option will select a bitmap-capable boot
+loader, unless overridden with "install=" (see below).
+.sp
+When a bitmap file is specified as a background screen during the boot
+process, the color selection and layout of the text which overlays the
+graphic image must be specified in one of two ways.  One way, is to use
+a bitmap image (*.bmp) file which has had a header written by the
+.BI "lilo -E"
+command.  If this command is used, then all of the
+information specified by the 'bmp-colors', 'bmp-table', and 'bmp-timer'
+options is stored in a special LILO header within the bitmap file.
+Without this header, the 'bmp-' option values should be
+specified in the configuration file; if not, default values are used.
+Any use of the 'bmp-' options
+within the configuration file overrides the values stored in the
+bitmap file header.
+.TP
+.BI "bmp-colors=" <fg>,<bg>,<sh>,<hfg>,<hbg>,<hsh>
+Specifies the decimal values of the colors to be used for the menu display
+on a 'bitmap=' background.  The list consists of 6 entries, 3 for normal
+text followed by 3 for highlighted text.  The order of each triple is:
+foreground color, background color, shadow color.  If background color is
+not specified, "transparent" is assumed.  If shadow color is not specified,
+then "none" is assumed.  The list entries are separated by commas, with no
+spaces.
+.TP
+.BI "bmp-retain"
+Option applies to all 'image=' and 'other=' sections.
+(See COMMON OPTIONS, below.)
+.TP
+.BI "bmp-table=" <x>,<y>,<ncol>,<nrow>,<xsep>,<spill>
+Specifies the location and layout of the menu table.  <x>,<y> specify the
+starting x- and y-position of the upper left corner of the table in
+character coordinates: x in [1..80], y in [1..30]. <ncol> is the number of
+columns in the menu (1..5); and <nrow> is the number of rows (entries)
+in each column.
+If more than one column is specified, then <xsep> is the number of character
+columns between the leftmost characters in each column: (18..40), and
+<spill> is the number of entries in one column which must be filled before
+entries spill into the next column. <spill> must be .le. <nrow>. If pixel
+addressing is used, instead of character addressing, then any of <x>, <y>,
+or <xsep> may be specified with a 'p' suffix on the decimal value.
+.TP
+.BI "bmp-timer=" <x>,<y>,<fg>,<bg>,<sh>
+Optional specification of the 'timeout='
+countdown timer.  <x>,<y> 
+specifies the character (or pixel) coordinate of the location of the timer
+the same as 'bmp-table='
+above; and the color triple specifies the character color attributes
+the same as 'bmp-colors=' above, with the exception that the background color
+.I must
+be specified.  If used to override the timer specification in a bitmap file,
+then the form 'bmp-timer = none' is acceptable.  This will disable the timer
+display entirely.
+.TP
+.BI "boot=" <boot-device>
+Sets the name of the device (e.g. a hard disk partition) that contains
+the boot sector. If this keyword is omitted, the boot sector is read
+from (and possibly written to) the device that is currently mounted as root.
+.sp
+A raid installation is initiated by specifying a RAID1 device as the boot
+device; e.g., "boot=/dev/md0".  Note that LILO version 22.0 and later
+operate differently from earlier versions with respect to the actual
+location of the boot records.
+.sp
+On newer systems you need an unique ID for the boot device. If the boot
+sector should write to a partition you can use its UUID in the same manner
+is for the root options.
+.sp
+If your boot device is a hard disk you need a special ID, which is supported
+by udev. You find the right ID in the directory /dev/disks/by-id, i. e.:
+.IP
+.nf
+    boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999
+.fi
+.TP
+.BI "change-rules"
+Defines boot-time changes to partition type numbers (`hiding').
+.IP
+.nf
+change-rules
+   reset
+   type=DOS12
+      normal=1
+      hidden=0x11
+   type=DOS16_small
+      normal=4
+      hidden=0x14
+   type=DOS16_big
+      normal=0x06
+      hidden=0x16
+.fi
+.IP
+The above excerpt from a configuration file specifies that all default
+.I change-rules
+are removed ("reset"), and the change-rules for three partition types
+are specified.  Without the \fIreset\fP, the three types specified would
+have been added to the existing default change-rules.  Normally, the default
+rules are sufficient.  The strings which define the partition types
+are used in a
+.I change
+section (see below), with the suffixes "_normal" or "_hidden" appended.
+See section "Partition type change rules" of user.tex for more details.
+.TP
+.BI "compact"
+Tries to merge read requests for adjacent sectors into a single 
+read request. This drastically reduces load time and keeps the map file
+smaller. Using `compact' is especially recommended when booting
+using a map file on a floppy disk. 
+.TP
+.BI "default=" <name>
+Uses the specified image as the default boot image. If `default' is omitted,
+the image appearing first in the configuration file is used. See also,
+.I vmdefault
+below.
+.TP
+.BI "delay=" <tsecs>
+Specifies the number of tenths of a second the boot loader should 
+wait before automatically booting a locked command line,
+a command line pre-stored by
+"lilo \-R", or the default `image=' or `other='.
+When `delay' is non-zero, the boot loader will wait for an interrupt for the 
+specified interval. If an interrupt is received, or
+is already waiting, the \fBboot:\fP
+prompt will be be issued, and no automatic boot will take place. The setting
+of CAPS LOCK or SCROLL LOCK, or any of the
+keys ALT, CTRL, or SHIFT, when held down, are taken as interrupts.
+
+This action is modified by specifying `prompt' (see below).
+.TP
+.BI "disk=" <device-name>
+Defines non-standard parameters for the specified disk.
+See section "Disk geometry" of user.tex for details.
+For versions of LILO prior to 22.5, the `bios=' parameter
+is quite useful for specifying how the BIOS has assigned
+device codes to your disks.
+For example,
+.sp
+.nf
+       disk=/dev/sda
+            bios=0x80
+       disk=/dev/hda
+            bios=0x81
+       disk=/dev/sdb
+            inaccessible
+.fi
+.sp
+would say that your SCSI disk is the first BIOS disk (0x80),
+that your (primary master) IDE disk is the second BIOS disk (0x81),
+and that your second SCSI disk (perhaps a USB device) receives no
+device code, and is therefore inaccessible at boot time.
+.sp
+NOTE: Use of the 'bios=' option is largely obsolete beginning
+with LILO version 22.5, as the boot loader now identifies disks
+by 32-bit Volume-ID, and defers BIOS device code determination
+until boot time.
+.sp
+Other options include the specification of disk geometry; e.g.,
+.sp
+.nf
+       disk=/dev/fd0
+            sectors=18
+            heads=2
+            cylinders=80
+.fi
+.sp
+probably only useful for floppy disks and loopback devices,
+since for hard disks the
+.BI lba32
+disk addressing option (LILO 21.2) ignores disk geometry.
+.sp
+(22.5.8) Developers who have implemented a disk driver for a new block storage
+device will have to indicate to LILO the maximum number of partitions
+on the device.  This is in addition to making all of the necessary
+entries for the device in the "/dev" directory (with 'mknod').  The
+maximum number of partitions must be one of 63 (like an IDE disk), 31 (uncommon), 15
+(like SCSI disks -- most common value), or 7 (like one array controller).
+An example specification would be:
+.sp
+.nf
+     disk=/dev/userd0
+          max-partitions=15
+.fi
+.sp
+In cases where there is no
+kernel partition information available, such as on loopback devices,
+the 'disk=' specification may include paritition start information;
+viz.,
+.sp
+.nf
+       disk=/dev/loop0
+            bios=0x80                  # use this BIOS code
+            max-partitions=7           # declare partitionable
+            paritition=/dev/loop1
+                 start=63              # offset from sector 0
+            paritition=/dev/loop2
+                 start=102400          # offset from sector 0
+.fi
+.sp
+.TP
+.BI "disktab=" <disktab-file>
+Specifies the name of the disk parameter table.
+The map installer looks for
+.I /etc/disktab
+if `disktab' is omitted. The use of disktabs is discouraged.
+.TP
+.BI "el-torito-bootable-CD"
+Flag second stage loader to terminate disk emulation when booting
+from an El Torito Bootable CD. This option is used by the
+\fBmkrescue\fP utility when the "\-\-iso" switch is specified.
+.TP
+.BI "fix-table"
+This allows lilo to adjust 3D addresses in partition tables. Each 
+partition entry contains a 3D (cylinder/head/sector) and a linear 
+address of the first and the last sector of the partition. If a 
+partition is not track-aligned and if certain other operating systems 
+(e.g. PC/MS-DOS or OS/2) are using the same disk, they may change the 
+3D address. lilo can store its boot sector only on partitions where 
+both address types correspond. lilo re-adjusts incorrect 3D start 
+addresses if `fix-table' is set.
+
+WARNING: This does not guarantee that other operating systems may 
+not attempt to reset the address later. It is also possible that this 
+change has other, unexpected side-effects. The correct fix is to 
+re-partition the drive with a program that does align partitions to 
+tracks. Also, with some disks (e.g. some large EIDE disks with address 
+translation enabled), under some circumstances, it may even be 
+unavoidable to have conflicting partition table entries.
+.TP
+.BI "force-backup=" <backup-file>
+Operation is identical to \fBbackup=\fP above, except an existing backup
+file is unconditionally overwritten if it exists.
+.TP
+.BI "geometric"
+Force disk addressing which is compatible with older versions of LILO. 
+Geometric addressing uses cylinder/head/sector addresses, and is limited to
+disk cylinders up to 1023.  If inaccessible cylinders are referenced,
+diagnostics will be issued at boot-install time, rather than boot-time. 
+With a newer BIOS, use of 'lba32' is recommended.
+.TP
+.BI "ignore-table"
+tells lilo to ignore corrupt partition tables. 
+.TP
+.BI "install=" <user-interface>
+Selects the user interface which will be seen at boot time.  One of the
+following three options may be specified:  \fBtext\fP, \fBmenu\fP, or
+\fBbmp\fP. The traditional LILO interface is `text'; but `menu' is now the
+default, unless the configuration file contains the `bitmap='
+specification.  The \fItext\fP interface is strictly a command-line
+interface as though the console were a dumb terminal.  The \fImenu\fP
+interface is a text-based screen of the boot choices, with the option to
+enter additional command line parameters.  And the \fIbmp\fP interface is a
+menu presented against a graphic screen, specified as a 640x480 BitMaP file
+of 16 or 256 colors.  (See the 'lilo \-E' switch for editing options).
+.sp
+(Prior to LILO version 22.3, `install=' specified the user interface as
+a file in the `/boot' directory.)
+.TP
+.BI "large-memory"
+Normally any initial ramdisk (initrd) loaded with a kernel is loaded as
+high in memory as possible, but never above 15Mb.  This is due to a BIOS
+limitation on older systems.  On newer systems, this option enables using
+memory above 15Mb (up to a kernel imposed limit, around 768Mb) for
+passing the initrd to the kernel.  The presence of this option merely
+indicates that your system does not have the old BIOS limitation.
+
+This switch (or its absence) is not passed to the kernel, and does not
+in any way affect the
+amount of physical memory which it will use.  (See the
+kernel documentation for the kernel command line parameter
+"mem=" for limiting the memory used by the kernel.)
+.TP
+.BI "lba32"
+Generate 32-bit Logical Block Addresses instead of cylinder/head/sector 
+addresses. If the BIOS supports packet addressing, then packet calls will be
+used to access the disk. This allows booting from any partition on disks
+with more than 1024 cylinders.
+If the BIOS does not support packet addressing, then 'lba32' addresses are
+translated to cylinder/head/sector ('geometric'), just as for 'linear'.
+All floppy disk
+references are retained in C:H:S form.  Use of 'lba32' is recommended on
+all post-1998 systems.  Beginning with LILO version 22, 'lba32' is the
+default disk addressing scheme.
+.TP
+.BI "linear"
+Generate 24-bit linear sector addresses instead of cylinder/head/sector 
+(geometric) addresses. Linear addresses are translated at run time to
+geometric addresses, and are limited to cylinders <= 1023. When using
+`linear' with large disks,
+.I /sbin/lilo
+may generate references to inaccessible disk cylinders. 'lba32' avoids
+many of these pitfalls with its use of packet addressing, but requires a
+recent BIOS (post-1998).  The 'linear' option is considered obsolete,
+and its use is strongly discouraged.
+.TP
+.BI "lock"
+Enables automatic recording of boot command lines as the defaults 
+for the following boots. This way, lilo "locks" on a choice until it is 
+manually overridden.
+.TP
+.BI "mandatory"
+The per-image password option `mandatory' (see below) applies to all images.
+.TP
+.BI "map=" <map-file>
+Specifies the location of the map file. If `map' is omitted, the file
+.I /boot/map
+is used.
+
+On machines with a pre-1998 BIOS, the EDD bios extensions which are required
+to support "lba32" disk sector addressing may not be present. In this case,
+the boot-loader will fall back automatically to "geometric" addressing; this
+fall back situation, or the specific use of "geometric" or "linear"
+addressing, will require the map file to be located within the first 1024
+cylinders of the disk drive. This BIOS limitation is not present on
+post-1998 systems, most of which support the newer EDD disk BIOS calls.
+.TP
+.BI "menu-title=" <title-string>
+Specifies the title line (up to 37 characters) for the boot menu. This
+title replaces the default "LILO Boot Menu" title string. If
+.I menu
+is not installed as the boot loader (see
+.I "install="
+option), then this line has no effect.
+.TP
+.BI "menu-scheme=" <color-scheme>
+The default color scheme of the boot menu may be overridden on VGA displays
+using this option. (The color scheme of MDA displays is fixed.)
+The general
+.I color-scheme
+string is of the form:
+.sp
+.nf
+     <text>:<highlight>:<border>:<title>
+.fi
+.sp
+where each entry is two characters which specify a
+foreground color and a background color. Only the first entry is
+required. The default highlight is the reverse of the text color; and the
+default border and title colors are the text color.
+Colors are specified using the characters \fBkbgcrmyw\fP, for blac\fBK\fP,
+\fBB\fPlue, \fBG\fPreen, \fBC\fPyan, \fBR\fPed,
+\fBM\fPagenta, \fBY\fPellow, and \fBW\fPhite: upper case for
+intense (fg only), lower case for dim.
+Legal color-scheme strings would be
+.sp
+.nf
+    menu-scheme=Wm     intense white on magenta
+    menu-scheme=wr:bw:wr:Yr    the LILO default
+    menu-scheme=Yk:kw    bright yellow on black
+.fi
+.sp
+If
+.I "menu"
+is not installed as the boot loader, then this line has no effect.
+.TP
+.BI "message=" <message-file>
+specifies a file containing a message that is displayed before
+the boot prompt. No message is displayed while waiting 
+for a shifting key after printing "LILO ". In the message, the FF
+character ([Ctrl L]) clears the local screen. This is undesirable when
+the \fImenu\fP boot loader is installed. 
+The size of the message 
+file is limited to 65535 bytes. The map file has to be rebuilt if the 
+message file is changed or moved.  'message=' and 'bitmap=' are mutually
+exclusive.
+.TP
+.BI "nodevcache"
+(22.8)
+Disables pre-loading of the internal device cache. May be needed for
+Linux distributions which use non-standard device naming conventions;
+e.g., when the first IDE disk is not `/dev/hda'.
+.TP
+.BI "nokbdefault=" <name>
+(22.7.2)
+The named descriptor is taken to be the default boot image 
+if no IBM-PC keyboard is 
+present. If no serial interface ("serial=") is in use, then any "prompt"
+keyword and "timeout" value are bypassed, and default booting occurs as
+specified by "delay=".
+The keyboard detection codes cannot detect the presence or absence of
+a newer USB keyboard.
+.TP
+.BI "noraid"
+Disables the automatic marking of disk volumes which are components of
+RAID arrays as \fBinaccessible\fP.  This allows the user to edit the \fBdisk=\fP
+/ \fBinaccessible\fP declarations into the configuration file himself.  Without
+such declarations, duplicate Volume IDs will be overwritten, leading to
+confusing situations at boot-time, and possible failure to boot.  The use
+of this keyword is generally not necessary.
+.TP
+.BI "nowarn"
+Disables warnings about possible future dangers.
+.TP
+.BI "optional"
+The per-image option `optional' (see below) applies to all images.
+.TP
+.BI "password=" <password>
+The per-image option `password=...' (see below) applies to all images. This
+option may prevent unattended booting, if the default image is `password='
+protected at the default level `mandatory', which is a level higher than
+`restricted'.
+.TP
+.BI "prompt"
+Automatic booting (see `delay' above) will not take place unless a locked or
+pre-stored ("lilo \-R") command line is present. Instead, the boot
+loader will issue the 
+.I boot:
+prompt and wait for user input before proceeding (see
+.I timeout
+below).
+Unattended default image reboots are impossible if `prompt' is set
+and `timeout' is not, or the default image is password protected at a higher
+level than `restricted'.
+.TP
+.BI "raid-extra-boot=" <option>
+This option only has meaning for RAID1 installations.
+The <option> may be specified as \fInone\fP, \fIauto\fP, \fImbr\fP,
+\fImbr-only\fP,
+or a comma-separated list of devices; e.g., "/dev/hda,/dev/hdc6".  Starting
+with LILO version 22.0, the boot record is normally written to the first
+sector of the RAID1 partition.  On PARALLEL raid sets, no other boot records
+are needed.  The
+default action is \fIauto\fP, meaning, automatically generate auxiliary boot
+records as needed on SKEWED raid sets.  \fInone\fP means
+suppress generation of all auxiliary boot records.
+\fImbr-only\fP suppresses generation of a boot record on the raid device,
+and forces compatibility with versions of LILO earlier than version 22.0
+by writing boot records to all Master Boot Records (MBRs) of all disks which
+have partitions in the raid set. \fImbr\fP is like \fImbr-only\fP except the
+boot record on the RAID partition is not suppressed.
+Use of an explicit list of devices, forces writing of auxiliary boot records
+only on those devices enumerated, in addition to the boot record on the RAID1
+device. Since the version 22 RAID1 codes will never automatically write a boot
+record on the MBR of device 0x80, if such a boot record is desired, this is
+one way to have it written. Use of \fImbr\fP is the other way to force
+writing to the MBR of device 0x80.
+.TP
+.BI "restricted"
+The per-image password option `restricted' (see below) applies to all images.
+.TP
+.BI "serial=" <parameters>
+enables control from a serial line. The specified serial port is
+initialized and the boot loader is accepting input from it and from 
+the PC's keyboard. Sending a break on the serial line corresponds to 
+pressing a shift key on the console in order to get the boot loader's
+attention. 
+All boot images should be password-protected if the serial access is 
+less secure than access to the console, e.g. if the line is connected 
+to a modem. The parameter string has the following syntax:
+.sp
+.nf
+    <port>[,<bps>[<parity>[<bits>]]]
+.fi
+.sp
+<port>:  the number of the serial port, zero-based. 0 corresponds to
+COM1 alias /dev/ttyS0, etc. All four ports can be used (if present).
+.sp
+<bps>:  the baud rate of the serial port. The following baud rates are 
+supported: 110, 150, 300, 600, 1200, 2400(default), 4800, 9600, plus the 
+extended rates 19200, 38400, and 57600(56000).  115200 is allowed, but may
+not work with all COMx port hardware.
+.sp
+<parity>:  the parity used on the serial line. The boot loader ignores input 
+parity and strips the 8th bit. The following (upper or lower case) 
+characters are used to describe the parity:  "n" for no parity, "e" 
+for even parity and "o" for odd parity.
+.sp
+<bits>:  the number of bits in a character. Only 7 and 8 bits are 
+supported. Default is 8 if parity is "none", 7 if parity is "even" 
+or "odd". 
+.sp
+If `serial' is set, the value of `delay' is automatically raised to 20.
+.sp
+Example: "serial=0,2400n8" initializes COM1 with the default parameters.
+.TP
+.BI "single-key"
+This option specifies that boot images or 'other's are to be selected and
+launched with a single keystroke.  Selection is based upon the first
+character of each name, which must be unique.  This option should not be
+used with the menu or bitmap user interface ("install=").
+.TP
+.BI "static-BIOS-codes"
+Causes the operation of the boot installer and boot loader to bypass the
+use of Volume-ID information, and to revert to a mode of operation of
+versions of LILO from 22.4 backward.  With Volume-ID booting (22.5 and later),
+the BIOS codes
+of disks are determined at boot time, not install time; hence they may
+be switched around, either by adding or removing disk(s) from the hardware
+configuration, or by using a BIOS menu to select the boot device.
+.sp
+With the use of
+this option, BIOS codes of disks MUST be correctly specified at install
+time; either guessed correctly by LILO (which often fails on
+mixed IDE/SCSI systems), or explicitly specified with 'disk=/dev/XXX
+bios=0xYY' statements.  The use of this option precludes
+any activity which may switch around the BIOS codes assigned to particular
+disk devices, as noted above.
+.sp
+In general, this option should
+never be used, except as a bug workaround.
+.TP
+.BI "suppress-boot-time-BIOS-data"
+This global option suppresses the boot-time real mode collection of BIOS data
+on systems which hang on certain BIOS calls.  It is equivalent to using the
+boot-time switch 'nobd'.
+.sp
+This option defeats the disk volume recognition and BIOS device code
+detection features of LILO on systems with more than one disk. Thus the use
+of this option will produce a strong cautionary message,
+which cannot be suppressed.
+.TP
+.BI "timeout=" <tsecs>
+sets a timeout (in tenths of a second) for keyboard input at the 
+.I boot:
+prompt.  "timeout" only has meaning if "prompt" is mentioned.
+If no key is pressed for the specified time, the default image is 
+automatically booted. The default timeout is infinite.
+.TP
+.BI "unattended"
+(22.6) Alters the operation of the "timeout" parameter in a manner which
+is useful on
+noisy serial lines.  Each typed (or noise) character restarts the "timeout"
+timer and a timeout will always boot the default descriptor, even if noise
+characters have appeared on the input line.
+.TP
+.BI "verbose=" <number>
+Turns on lots of progress reporting. Higher numbers give more verbose
+output. If  \-v  is additionally specified on the lilo command line,
+the level is increased accordingly. The maximum verbosity level is 5.
+.TP
+.BI "vmdefault=" <name>
+The named boot image is used as the default boot if booting in "virtual"
+mode with a virtual monitor, such as VMware(tm).  Thus a real mode boot and
+a virtual mode boot can be made to have different default boot images.
+.br
+
+.LP
+Additionally, the kernel configuration parameters
+.BR append ", " ramdisk ", " read-only ", " read-write ", " root
+and
+.B vga
+can be set in the global options section. They are used as defaults
+if they aren't specified in the configuration sections of the
+respective kernel images.
+
+.SH "PER-IMAGE SECTION"
+A per-image section starts with either a line
+.sp
+.nf
+    \fBimage=\fP\fI<pathname>\fP
+.fi
+.sp
+to indicate a file or device containing the boot image of a Linux
+kernel, or a line
+.sp
+.nf
+    \fBother=\fP\fI<device>\fP
+.fi
+.sp
+to indicate an arbitrary system to boot.
+.LP
+
+In the former case, if an \fBimage\fP line specifies booting
+from a device, then one has to indicate the range of sectors to be mapped
+using
+.sp
+.nf
+    \fBrange=\fP\fI<start>-<end>\fP
+    \fBrange=\fP\fI<start>+<nsec>\fP
+    \fBrange=\fP\fI<sector>\fP
+.fi
+.LP
+In the third case, 'nsec=1' is assumed.
+
+.SH "KERNEL OPTIONS (image=)"
+If the booted image is a Linux kernel, then one may pass
+command line parameters to this kernel.
+.TP
+.BI "addappend=" <string>
+(22.6) The kernel parameters from the specified string, are concatenated to the
+parameter(s) from an
+.B "append="
+specification (see below).
+The string must be enclosed within double quotes.  Usually, the previous
+.B "append="
+will specify parameters common to all kernels by appearing in the top,
+or global, section of the configuration file and
+.B "addappend="
+will be used to add local parameter(s) to an individual image.
+Addappend= may be used only once per "image=" section.
+.TP
+.BI "append=" <string>
+Appends the options specified to the parameter line passed to the kernel.
+This is typically used to specify hardware parameters that can't be
+entirely auto-detected or for which probing may be dangerous. Multiple
+kernel parameters are separated by a blank space, and the string must be
+enclosed in double quotes.  A local append= appearing withing an image=
+section overrides any
+global append= appearing in the top section of the configuration file.
+Append= may be used only once per "image="
+section. To concatenate parameter strings, use "addappend=". Example:
+.sp
+.nf
+     append="mem=96M hd=576,64,32 console=ttyS1,9600"
+.fi
+.sp
+.TP
+.BI "initrd=" <name>
+Specifies the initial ramdisk image to be loaded with the kernel.  The
+image will contain modules needed at boot time, such as network and scsi
+drivers. See man pages for \fImkinitrd(8)\fP.
+.TP
+.BI "literal=" <string>
+Like `append', but removes all other options (e.g. setting of the root
+device). 'literal' overrides all 'append' and 'addappend' options.
+Because vital options can be removed unintentionally with `literal',
+this option cannot be set in the global options section.
+.TP
+.BI "ramdisk=" <size>
+This specifies the size (e.g., "4096k") of the optional RAM disk. A value of 
+zero indicates that no RAM disk should be created. If this variable is 
+omitted, the RAM disk size configured into the boot image is used.
+.TP
+.BI "read-only"
+This specifies that the root file system should be mounted read-only.
+It may be specified as a global option.
+Typically, the system startup procedure re-mounts the root 
+file system read-write later (e.g. after fsck'ing it).
+.TP
+.BI "read-write"
+This specifies that the root file system should be mounted read-write.
+It may be specified as a global option.
+.TP
+.BI "root=" <root-device>
+This specifies the device that should be mounted as root. 
+It may be specified as a global option.
+If the special name
+.B current
+is used, the root device is set to the device on which the root file
+system is currently mounted. If the root has been changed with  \-r ,
+the respective device is used. If the variable `root' is omitted,
+the root device setting contained in the kernel image is used.
+(And that is set at compile time using the ROOT_DEV variable in
+the kernel Makefile, and can later be changed with the rdev(8) program.)
+.sp
+The root filesystem may also be specified by a
+.B LABEL=
+or
+.B UUID=
+directive, as in '/etc/fstab'.  In this case, the argument to
+.I root=
+must be enclosed in quotation marks, to avoid a syntax error on the second
+equal sign, e.g.:
+.sp
+.nf
+     root="LABEL=MyDisk"
+     root="UUID=5472fd8e-9089-4256-bcaa-ceab4f01a439"
+.fi
+.sp
+Note:  The command line
+.I root=
+parameter passed to the kernel will be: 'root=LABEL=MyDisk'; i.e., without
+the quotation marks. If the
+.I root=
+parameter is passed from the boot time
+.B boot:
+prompt, no quotes are used.  The quotes are only there to satisfy the
+requirements of the boot-installer parser, which treats an equal sign as
+an operator.  The kernel command line parser is very much simpler, and
+must not see any quotation marks.  Simply stated, only use the quotation
+marks within
+.IR /etc/lilo.conf .
+.TP
+.BI "vga=" <mode>
+This specifies the VGA text mode that should be selected when 
+booting.
+It may be specified as a global option.
+The following values are recognized (case is ignored): 
+.sp
+.BR normal :
+select normal 80x25 text mode. 
+.sp
+.BR extended " (or " ext ):
+select 80x50 text mode.
+.sp
+.BR ask :
+stop and ask for user input (at boot time).
+.sp
+<number>: use the corresponding text mode. A list of available modes 
+can be obtained by booting with
+.I vga=ask
+and pressing [Enter]. 
+.sp
+If this variable is omitted, the VGA mode setting contained in the 
+kernel image is used. (And that is set at compile time using the
+SVGA_MODE variable in the kernel Makefile, and can later be changed with
+the rdev(8) program.)
+
+.SH "ALTERNATE SYSTEM (other=)"
+.LP
+Used to load systems other than Linux. The `other = <device>' specifies
+the boot sector of an alternate system contained on a device or disk
+partition; e.g., DOS on, say, `/dev/hda2', or a floppy on `/dev/fd0'.
+In the case of booting another system there are these options:
+.TP
+.BI "loader=" <chain-loader>
+This specifies the chain loader that should be used.  It may also be
+specified as a global option.
+By default
+.I chain
+is used.  This chain loader passes partition and drive information in the
+boot sector it loads only to DOS on FAT12 or FAT16, Windows on FAT16 or
+FAT32, or OS/2 on FAT16 or HPFS.
+The alternate chain loader,
+.I os2_d
+passes partition and drive information unconditionally, and uses a format
+suitable for OS/2 and DOS (see 
+.I table=<letter>
+below).
+.TP
+.BI "table=" <device>
+This specifies the device that contains the partition table. 
+The boot loader will pass default partition information to the booted
+operating system if this variable is omitted. (Some operating systems
+have other means to determine from which partition they have been booted.
+E.g., MS-DOS usually stores the geometry of the boot disk or partition
+in its boot sector.)
+Note that /sbin/lilo must be re-run if a partition table mapped referenced
+with `table' is modified.
+.TP
+.BI "table=" <drive-letter>
+This is a special case for the
+.I os2_d
+chain loader.  It specifies the DOS drive letter for the partition
+that will be booted.  This is
+.I mandatory
+when booting OS/2 installed on
+an extended partition.  The drive letter may be specified with or without a
+trailing colon.
+.TP
+.BI "change"
+This keyword starts a section which describes how primary partition IDs are
+changed, and how primary partitions are activated and deactivated.  If
+.B change
+is omitted, change rules are generated as though the 
+.I "automatic"
+keyword were specified.  The keyword
+.B change
+alone, without any rules following, will suppress automatic change-rules.
+For example,
+.IP
+.nf
+   other=/dev/hda2
+      label=dos
+      table=/dev/hda
+      change
+        automatic
+        partition=/dev/hda1
+           set=DOS12_hidden
+           deactivate
+        partition=/dev/hda2
+           set=DOS16_big_normal
+           activate
+.fi
+.IP
+specifies that when primary partition /dev/hda2 is booted, automatic
+change-rules will be in effect; plus, partition 1, a DOS12 partition, will
+be set hidden, and deactivated.  In addition, partition 2, will be set
+normal, and activated.  Activation sets the boot-flag in the partition
+table.  The 
+.I automatic
+keyword may conflict with default change rules, so the
+.I set=
+lines above may be redundant.
+.TP
+.BI "boot-as=" "<bios>"
+This option (LILO version 22.5.1) indicates the BIOS device code which must
+be assigned to the specified drive in order for the "other=" operating
+system to boot.  If the chain loader detects that another BIOS device code
+is assigned to this disk, then it will dynamically swap the assigned device
+code with the specified device code.
+.sp
+This option is easier to specify than "map-drive=" and more general than
+"master-boot" in that any device code may be specified.  Unlike
+"map-drive=", the determination whether to swap device codes is made at boot
+time, not install time.  This is advantageous on systems where the BIOS
+presents a boot menu of devices, and will map disks to devices in different
+ways, depending upon the BIOS boot selection.
+.sp
+This option may be specified as a global option, in which case it applies to
+all "other=" sections unless overridden with a specific "master-boot" option.
+If one of "boot-as=" or "master-boot" is specified as a global option, it is
+better to specify "master-boot" as the global option, as it will not
+interfere with floppy disk BIOS device codes; "boot-as=" is then used as a
+local option to override "master-boot" as necessary.
+.TP
+.BI "master-boot"
+This flag (LILO version 22.5) indicates a DOS/Windows/OS2 or other
+system which will only boot from BIOS device 0x80, the "C:" drive, or BIOS
+device 0, the A: drive. When this
+flag is specified, if this drive is not assigned device code 0x80 or 0 by the
+BIOS, then the chain loader will dynamically swap the device code actually
+assigned with device code 0x80 or 0 to make this drive appear
+to be the first hard or floppy drive, "C:" or "A:".
+.sp
+This flag is easier to use than "map-drive=" (see below), and is preferred,
+if simple forcing of device code 0x80 is all that is required. It is also
+more general, in that the necessity to swap BIOS device codes is determined
+dynamically at boot-time, not at boot install-time, as with "map-drive=". 
+It is slightly more powerful than "boot-as=", in that the device code which
+is assigned, 0 or 0x80, is determined dynamically.
+.sp
+This option may be specified as a global option, in which case it applies to
+all "other=" sections unless overridden with a specific "boot-as=" option.
+.TP
+.BI "map-drive=" <num>
+Maps BIOS calls for the specified drive to the device code specified on the
+next line as \fBto=\fP<num>.  This mapping is useful for booting operating
+systems, such as DOS, from the second hard drive.  The following, swaps the
+C: and D: drives,
+.sp
+.nf
+   map-drive=0x80
+      to=0x81
+   map-drive=0x81
+      to=0x80
+.fi
+.sp
+This option is largely
+rendered obsolete by "boot-as=", introduced with LILO version 22.5.
+.TP
+.BI "unsafe"
+Do not access the boot sector at map creation time. This disables 
+some sanity checks, including a partition table check. If the boot 
+sector is on a fixed-format floppy disk device, using UNSAFE avoids the 
+need to put a readable disk into the drive when running the map 
+installer. If the boot sector is on a hard drive, the BIOS device code
+of the drive will have to be specified explicitly with "disk=/dev/XXXX
+bios=0x8X inaccessible" in the configuration file.
+`unsafe' and `table' (explicit or implicit) are mutually incompatible. 
+
+.SH "COMMON DESCRIPTOR OPTIONS (image= & other=)"
+.LP
+In both the
+.BR image= " and " other=
+cases, the following options apply.
+.TP
+.BI "bypass"
+No password is required to boot this image. Used to indicate that the global
+password does not apply to this `image=' or `other='.  See 'password=' below.
+.TP
+.BI "label=" <name>
+The boot loader uses the main file name (without its path)
+of each image specification to identify that image.
+A different name can be used by setting the variable `label'.
+.TP
+.BI "alias=" <name>
+A second name for the same entry can be used by specifying an alias.
+.TP
+.BI "bmp-retain"
+The bitmap graphic (install=bmp) is retained when control is passed to the
+loaded kernel image, or other= bootloader; i.e., the screen is not
+blanked to alphanumeric mode before starting the kernel.  This feature is
+considered EXPERIMENTAL, for those users working with startup splash
+screens.
+.TP
+.BI "fallback=" <command-line>
+Specifies a string that is stored as the default 
+command line if the current image is booted. This is useful when 
+experimenting with kernels which may crash before allowing interaction 
+with the system. If using the
+.BI fallback
+option, the next reboot (e.g. 
+triggered by a manual reset or by a watchdog timer) will load a 
+different (supposedly stable) kernel. The command line stored by the fallback 
+mechanism is cleared by removing or changing the default command line 
+with the
+.IR "-R"
+option, which should be a part of the boot startup scripts.
+.TP
+.BI "lock"
+(See above.)
+.TP
+.BI "optional"
+Omit the image if it is not available at map creation time.
+It may be specified as a global option.
+This is useful to specify test kernels that are not always present.
+.TP
+.BI "password=" <password>
+Protect the `image=' or `other=' with a password (or passphrase).
+It may be specified as a global option.
+The interpretation of the `password=' setting is modified by the words
+`mandatory', `restricted', and `bypass' (see below).
+.br
+The password may be specified in the config-file (less secure) or entered
+at the time the boot loader is installed. To request interactive entry of
+the password, it should be specified: \fBpassword=""\fP.
+Passwords entered interactively are not required to be entered again if the
+boot installer is re-run. They are cached, in hashed form, in a companion
+file to the config-file, default name: \fB/etc/lilo.conf.crc\fP. If the 
+config-file is updated, a warning message
+will be issued telling you to re-run \fIlilo \-p\fP to force re-creation of the
+password cache file.
+.TP
+.BI "mandatory"
+A password is required to boot this image. This is the default. May be used
+on a single `image=' or `other=' to override a different global setting.
+.TP
+.BI "nokbdisable"
+(22.7.2)
+The specified descriptor is not bootable if the IBM-PC keyboard is not present.
+This option is really only useful if the "serial=" boot terminal is in use.
+With no keyboard (and no serial terminal) attached, selecting a boot descriptor 
+other than the default is impossible.
+See
+.I nokbdefault
+above.
+.TP
+.BI "restricted"
+A password is only required to boot the image if kernel parameters
+are specified on the command line (e.g. 'single').  May be used
+on a single `image=' or `other=' to override a different global setting.
+.TP
+.BI "vmwarn"
+If booting under a virtual monitor such as VMware(tm), the image with this
+label will cause a cautionary warning to be issued at boot time, and user
+intervention will be required to continue or to abort the boot process.
+.TP
+.BI "vmdisable"
+If booting under a virtual monitor, the image with this label will not be
+displayed as a boot option.  The image is only bootable in real mode.  See
+.I vmdefault
+above.
+
+.LP
+
+.SH "SEE ALSO"
+lilo(8), mkinitrd(8), mknod(1), mkrescue(8), rdev(8).
+
diff --git a/man/mkrescue.8 b/man/mkrescue.8
new file mode 100644 (file)
index 0000000..8e36327
--- /dev/null
@@ -0,0 +1,131 @@
+'\" t
+.\" @(#)mkrescue.8 1.0 20011031 jrc
+.\" This page is part of the LILO package, which is released by
+.\" the author(s) under a BSD license.  See the file COPYING
+.\" in the LILO source directory for the License and Disclaimer.
+.\"
+.\" Original version, John Coffman 2001-10-31
+.\" Updated to version 2.0 & lilo 22.5.4, John Coffman 2003-05-24
+.\"
+.\" Updated to version 3.0 & lilo 22.6.1, John Coffman 2004-11-16
+.\"
+.TH MKRESCUE 8 "16 Nov 2004"
+.SH NAME
+mkrescue \- make rescue floppy
+.SH SYNOPSIS
+.LP
+.B "/usr/sbin/mkrescue"
+\- make a bootable rescue floppy or CD using the default kernel specified
+in \fIlilo.conf\fP.
+.SH DESCRIPTION
+.LP
+.B mkrescue
+takes its specification for the kernel from the default image specified in
+\fB/etc/lilo.conf\fP.  If the actual default is an \fIother=\fP specification,
+then use the first \fIimage=\fP specification.
+Any associated initial ramdisk (initrd=), and \fIappend=\fP
+options will also be used.  The root directory will be taken to be the
+\fIcurrent\fP root.  A bootable floppy or CD-image will be created using LILO version
+22.5.5 or later.
+.B mkrescue
+normally requires no options, unless a CD-image is desired (\fI--iso\fP).
+.SH OPTIONS
+.LP
+.TP
+.BI "--append <string>"
+Override any \fIappend=\fP options taken from the default image.  If there is
+any doubt about whether the \fIlilo.conf\fP options are correct, then specify
+no kernel parameters with:  \fB--append ""\fP, the null string.
+.TP
+.BI "--debug"
+Provide verbose output of the operation of "mkrescue", pausing to allow
+the setting of internal operating parameters to be viewed.  "<CR>" must
+be hit to proceed from these pauses.
+.TP
+.BI "--device <device>"
+Make the floppy on a device other than /dev/fd0.  The floppy disk will
+always be made to boot on BIOS device code 0x00 (A: drive), without
+regard to the drive on which it is created.
+.TP
+.BI "--fast"
+Use a faster method of creating the boot floppy.  This involves first
+creating a file of "\-\-size" 1k blocks (default is 1440)
+mounted using a loopback device, creating the bootable floppy,
+then copying the entire file to the disk.
+.TP
+.BI "--fs [ ext2 | msdos | minix ]"
+Specify the type of filesystem to create on the drive.
+.B ext2
+is the default, but "msdos" and "minix" allow slightly more disk sectors
+for really big kernels.
+.TP
+.BI "--help"
+Print a short usage synopsis, including a list of command options.
+.TP
+.BI "--image <label>"
+Specifies the label or alias of the particular image from which the
+append, initial ramdisk, root, keytable, and kernel information is to be 
+taken.
+.TP
+.BI "--initrd <filepath>" "  and  " "--kernel <filepath>"
+These options, which must be used together, allow specification of an
+arbitrary kernel file and initial ramdisk file to be used on the created
+boot floppy.  Be sure you know what you are doing before you use these
+options.  If no initial ramdisk is needed with a particular kernel, then you
+MUST specify \fB--initrd ""\fP, meaning a null pathname.
+.TP
+.BI "--install [ text | menu ]"
+Allows overriding the default human interface used with the rescue
+bootloader (configuration file "install=" option). "text" is the
+default on 1.2MB and 1.44MB floppy disks, and "menu" is the default on
+2.88MB floppies and HD emulation on CD-R media.
+.TP
+.BI "--iso"
+Create an ISO-9660 bootable CD image (El Torito Format) suitable for burning
+to a CD-R or CD-RW.  The \fB--device\fP specification defaults to the
+filename \fB"rescue.iso"\fP, and the \fB--size\fP defaults to 2880.  A utility
+such as \fIcdrecord\fP may be used to burn the ISO file to a recordable CD
+medium.  With this ISO option, the
+.B "--size HD"
+option is allowed.
+.TP
+.BI "--nocompact"
+For faster kernel loading from a floppy, LILO map compaction is normally
+enabled. This option will disable map compaction by omitting the
+lilo "\-c" switch.
+.TP
+.BI "--noformat"
+Suppresses creation of a new filesystem on the boot floppy. This option may
+be used
+.B only
+when you know that the floppy you will be writing upon is formatted with the
+same filesystem as specified by "\-\-fs XXX" (default is ext2).
+.TP
+.BI "--root <device>"
+Specify the root filesystem for the kernel on the boot floppy. The currently
+mounted root is taken as the default specification.
+.TP
+.BI "--size [ 1440 | 1200 | 2880 | HD ]"
+The default floppy disk size is \fI1440\fP, meaning a 1.44MB floppy. When \fI--iso\fP 
+is specified, the default size is \fI2880\fP.  Allowed
+specifications are 1200, 1440, or 2880, meaning a 1.2MB, 1.44MB or 2.88MB
+floppy, respectively.  No other floppy disk sizes are supported.
+.sp
+The
+.I HD
+specification, meaning "hard disk", may only be used with the
+.B "--iso"
+option, to indicate a 16MB hard disk is to be generated for emulation.  This
+allows for very large kernel / initial ramdisk combinations on CD-R.  The
+hard disk image is created using loopback devices
+"/dev/loop0" and "/dev/loop1", which
+must be free to utilize this size option.
+.TP
+.BI "--version"
+Print the version number of \fImkrescue\fP, then terminate.
+.TE
+.SH "SEE ALSO"
+lilo(8), lilo.conf(5), mkfs(8), dd(1), mount(8), mkinitrd(8), mkisofs(8),
+cdrecord(1).
+.SH "AUTHOR"
+John Coffman <johninsd@san.rr.com> (3.0)
diff --git a/mkrescue b/mkrescue
new file mode 100755 (executable)
index 0000000..39b13be
--- /dev/null
+++ b/mkrescue
@@ -0,0 +1,705 @@
+#!/bin/bash
+#
+# mkrescue
+#
+#      30-Oct-2001     original version 1.0
+#
+# Revision history:
+#      09-Apr-2002     John Coffman    modify for lilo 22.3   1.1
+#      09-Jun-2002     John Coffman    get keyboard translation table 1.2
+#                                      (suggested by Qing Liu)
+#      07-May-2003     John Coffman    add nowarn for lilo 22.5.2  1.3
+#      13-May-2003     John Coffman    use default image, add append=  1.4
+#      24-May-2003     John Coffman    specify ext2 params for xtra space
+#      26-May-2003     John Coffman    el-torito-bootable-CD   2.1
+#      30-May-2003        "            add lilo version check  2.1
+#      07-Jul-2003        "            determine loopback dynamically 2.3
+#      29-Aug-2004        "            allow --root LABEL=lblname  2.4
+#      01-Sep-2004        "            fix check for LILO version  2.4
+#      03-Oct-2004        "            get root= from /etc/fstab   2.5
+#      15-Nov-2004        "            support --iso --size HD     3.0
+#      18-Aug-2005        "            applied temp-file security patch 3.1
+#      25-Sep-2005        "            log config file on --debug  3.2
+#      04-Oct-2005        "            new 'master' determination  3.2
+#      07-Oct-2005        "            add -v0 -w to usages of -I  3.2
+#
+
+debug=false
+#debug=true
+
+# set the version number on this command
+version=3.2
+
+# set the version of LILO required to run
+major=22
+minor=6
+revision=1
+
+log=$(pwd)/mkrescue.log
+clog=$(pwd)/mkrescue.conf.log
+
+
+usage () {
+    cat <<EOF
+
+usage: `basename $0` [--help]
+       `basename $0` [--version]
+       `basename $0` [--device <device>] [--fast] [--fs ext2|msdos|minix]
+           [--image <label>] [--install text|menu] [--keymap <keymap.ktl>] 
+           [--initrd <file> --kernel <file>] [--append <string>]
+           [--root <device>] [--nocompact] [--noformat]
+           [--iso] [--size 1440|1200|2880|HD]
+
+  --device  is the floppy drive; e.g.,  /dev/fd0
+  --fast  specifies creation using a loopback device, which may be faster
+  --fs  is the filesystem to make on the device; e.g.,  ext2
+  --help  prints this helpfile
+  --iso  create a bootable ISO image to burn to a CD-R or CD-RW
+  --keymap  is the keyboard translation table; default to same as lilo.conf
+  --noformat  bypasses creation of a new filesystem on device
+  --nocompact  omits lilo map file compaction
+  --size  is assumed to be 1440 (1.44M), unless 1200 or 2880 is specified
+       HD may be specified for ISO images
+  --image  specifies the label of the kernel/initrd if not the default
+  --install  text is the default for floppies, menu for ISO images
+  --initrd and --kernel  are the initial ramdisk & kernel files
+  --append  is a string used to specify kernel options
+  --root  is the root filesystem for the boot floppy; e.g., current
+  --version  prints the version number of `basename $0`
+
+Used without any arguments, `basename $0` will use the default kernel in
+/etc/lilo.conf, the companion initrd (if any), and the specified root
+filesystem to make a bootable rescue floppy.
+
+EOF
+#
+# --install & --debug are undocumented above
+#
+#
+    exit $1
+}
+
+if [ $debug != false ]; then
+       lilo=$(pwd)/lilo
+       config=$(pwd)/lilo.conf
+else
+       lilo=/sbin/lilo
+       config=/etc/lilo.conf
+fi
+
+if [ ! -r "$config" ] ; then
+       echo "$0: Cannot read the configuration file $config (are you root?)"
+       exit 1
+fi
+
+
+compact=-c
+device=/dev/fd0
+fs=ext2
+tmpbase=${TMPDIR:-/tmp}/mkrescue_$$
+mount=`mktemp -d -t mkrescue-flp.XXXXXX` || { echo "$0: Cannot create temporary directory" >&2; exit 1; }
+mfile=`mktemp -t mkrescue-emu.XXXXXX` || { echo "$0: Cannot create temporary file" >&2; exit 1;  }
+mtemp=`mktemp -t mkrescue-tmp.XXXXXX` || { echo "$0: Cannot create temporary file" >&2; exit 1;  }
+trap " [ \"$debug\" != true ] && rm -f \"$mtemp\" ;  /bin/rm -rf -- \"$mount\" \"$mfile\" " 0 1 2 3 13 15
+loopback=loop0
+looppart=loop1
+install=text
+isoimage=no
+format=yes
+image=
+root=
+bios=0x00
+fast=slow
+size=0
+heads=2
+sectors=18
+cylinders=80
+hdsize=16384
+bootcmd=
+append=
+initrd=
+boot=/boot
+diag=no
+master=
+
+VERSION=$($lilo -V | awk '{print $3}' | sed -e "s/[^a-zA-Z0-9.]//g")
+
+NVERSION=$(echo $VERSION | sed "s/\\./ /g")
+
+DASH=$(echo $VERSION | sed "/-/s/.*-//" )
+if [ "$DASH" = "$VERSION" ]; then
+       DASH=0
+else
+       NVERSION=$(echo $NVERSION | sed "s/-.*//")
+fi
+MAJOR=$(echo $NVERSION | sed "s/ .*//")
+MINOR=$(echo $NVERSION | sed -e "s/$MAJOR //" -e "s/ .*//" )
+if [ "$MINOR" = "$NVERSION" ]; then
+       MINOR=0
+fi
+REVISION=$(echo $NVERSION | sed "s/$MAJOR $MINOR //")
+if [ "$REVISION" = "$NVERSION" ]; then
+       REVISION=0
+fi
+REVISION=$(echo $REVISION | sed "s/ .*//")
+if [ "$MINOR" -gt 49 ]; then MINOR=$(expr $MINOR % 10); fi
+
+if [ $debug = true ]; then
+echo ""
+echo VERSION $VERSION
+echo ""
+echo MAJOR $MAJOR
+echo MINOR $MINOR
+echo REVISION $REVISION
+echo DASH $DASH
+echo ""
+fi
+
+#if [ "$MAJOR" -lt "$major" \
+#      -o "$MINOR" -lt "$minor" \
+#              -o $REVISION -lt "$revision" ]
+skip=false
+if [ "$REVISION" -lt "$revision" ]
+then
+skip=true
+#echo $REVISION lt $revision
+fi
+if [ "$MINOR" -gt "$minor" ]
+then
+skip=false
+#echo $MINOR gt $minor
+fi
+if [ "$MAJOR" -gt "$major" ]
+then
+skip=false
+#echo $MAJOR gt $major
+fi
+if [ "$skip" = "true" ]
+then
+    echo `basename $0` version $version
+    echo "LILO version $major.$minor.$revision (or newer) is required."
+    exit 0
+fi
+
+umount $mount 2>/dev/null
+rm -rf $mount/*
+> $mfile
+
+mkdir $tmpbase || {
+    echo "Could not create temporary directory."
+    exit 1
+}
+
+master=`mount | grep " / " | cut -d " " -f 1`
+master=`echo $master | sed "s/part[0-9]*$/disc/"`
+master=`echo $master | sed "s/[0-9]*$//"`
+if [ ! -b $master ]; then master=`echo $master | sed "s/p$//"`; fi
+if [ ! -b $master ]; then master=""  ; fi
+
+
+while [ $# -gt 0 ]; do
+    case $1 in
+       --append)
+           shift
+           append=$1
+           ;;
+       --debug)
+           debug=true
+           ;;
+       --device)
+           shift
+           device=$1
+           ;;
+       --fast)
+           fast=fast
+           ;;
+       --fs)
+           shift
+           fs=$1
+           ;;
+       -h)
+           usage 0
+           ;;
+       --help)
+           usage 0
+           ;;
+       --image)
+           shift
+           image=$1
+           ;;
+       --initrd)
+           shift
+           initrd=$1
+           ;;
+       --install)
+           shift
+           install=$1
+           ;;
+       --iso)
+           isoimage=yes
+           ;;
+       --kernel)
+           shift
+           kernel=$1
+           ;;
+       --keymap)
+           shift
+           keymap=$1
+           ;;
+       --nocompact)
+           compact=
+           ;;
+       --noformat)
+           format=no
+           ;;
+       --root)
+           shift
+           root=$1
+           ;;
+       --size)
+           shift
+           size=$1
+           ;;
+       --version)
+           echo `basename $0` version $version
+           exit 0
+           ;;
+       *)
+           echo "unrecognized argument: " $1
+           usage 1
+           ;;
+    esac
+
+    shift
+done
+
+if [ -z "$image" ]; then
+#      image=`cat /proc/cmdline | sed "s/.*BOOT_IMAGE=//" | sed "s/ .*//"`
+       image=`$lilo -C $config -v0 -w -I " " D`
+fi
+
+if [ -z $kernel ]; then
+       kernel=`$lilo -C $config -v0 -w -I "$image" i`
+       if [ "$kernel" = "" ]; then exit 1;
+       elif [ $debug = "true" ]; then echo kernel = "$kernel";
+       fi
+fi
+
+if [ -z $root ]; then
+       root=`$lilo -C $config -v0 -w -I "$image" R`
+       if [ "$root" = "No root specified" ]; then
+               root=`grep </etc/fstab -v "^[ \t]*#" |
+                       grep "[[:space:]]/[[:space:]]" | \
+                               sed -e "s/^[ \t]*//" -e "s/[ \t].*//"`
+               if [ -z $root ]; then
+                       root=`mount | grep " on / type" | sed "s/ .*//"`
+               fi
+               if [ -z $root ]; then
+                       echo "Cannot find mounted root partition"
+                       echo "Using current root"
+                       root=current
+               fi
+       fi
+       if [ $debug = true ]; then echo root = "$root";
+       fi
+fi
+
+if [ -z $initrd ]; then
+       initrd=`$lilo -C $config -v0 -w -I "$image" r`
+       if [ "$initrd" = "" ]; then exit 1;
+       elif [ $debug = "true" ]; then echo initrd = "$initrd";
+       fi
+fi
+if [ "$initrd" = "No initial ramdisk specified" ]; then initrd= ; fi
+
+if [ -z $append ]; then
+       append=`$lilo -C $config -v0 -w -I "$image" a`
+       if [ "$append" = "" ]; then exit 1;
+       elif [ $debug = "true" ]; then echo append = \"$append\";
+       fi
+fi
+if [ "$append" = "No append= was specified" ]; then append= ; fi
+
+if [ -z $keymap ]; then
+       keymap=`$lilo -C $config -v0 -w -I "$image" k`
+       if [ "$keymap" = "" ]; then exit 1;
+       elif [ $debug = "true" ]; then echo keymap = "$keymap";
+       fi
+fi
+
+if [ $isoimage = yes ]; then
+    fast=fast
+    if [ $size = 0 ]; then
+       size=$hdsize
+    elif [ $size = HD -o $size = hd ]; then
+       size=$hdsize
+    fi
+    if [ $device = "/dev/fd0" ]; then
+       device=rescue.iso
+    fi
+else
+       umount $device 2>/dev/null 1>/dev/null
+fi
+
+if [ $size = 0 ]; then
+    size=1440
+fi
+
+if [ $size = 1200 ]; then
+    sectors=15
+elif [ $size = 1440 ]; then
+    sectors=18
+elif [ $size = 2880 ]; then
+    sectors=36
+    install=menu
+    if [ -f $boot/diag1.img -a -f $boot/diag2.img ]; then
+       diag=yes
+    fi
+elif [ $size = $hdsize ]; then
+    sectors=32
+    heads=8
+    cylinders=$(($size/$sectors/$heads*2))
+    if [ $size != $(($sectors*$heads*$cylinders/2)) ]; then
+       echo Internal error in HDsize
+       exit 1
+    fi
+    install=menu
+    if [ -f $boot/diag1.img -a -f $boot/diag2.img ]; then
+       diag=yes
+    fi
+elif [ $size = HD -o $size = hd ]; then
+    echo "--size $size  may only be used with the  --iso  option."
+    exit 1
+else
+    echo "--size must be 1200 or 1440; --size 1440 assumed."
+    sectors=18
+    size=1440
+fi
+
+if [ $fs != msdos -a $fs != ext2 -a $fs != minix ]; then
+    echo "illegal option:  --fs" $fs
+    echo "   must be either  msdos  or  ext2  or  minix"
+    exit 1
+fi
+
+if [ $fs = msdos ]; then
+       mountconfig=$mount/lilo.cnf
+else
+       mountconfig=$mount/lilo.conf
+fi
+
+if [ $debug = "true" ]; then
+       umount $mfile
+
+       echo ""
+
+       echo lilo = $lilo
+       echo device = $device
+       echo image = $image
+       echo kernel = $kernel
+       echo initrd = $initrd
+       echo append = \"$append\"
+       echo install = $install
+       echo format = $format
+       echo fs = $fs
+       echo size = $size
+       echo root = $root
+       echo compact = $compact
+       echo keymap = $keymap
+       echo isoimage = $isoimage
+       echo master = $master
+       echo ""
+       echo pause after parameter display
+       read aline
+fi
+
+if [ ! -f $kernel ]; then
+       echo "Kernel file " $kernel " does not exist"
+       exit 1
+fi
+
+if [ ! -z $initrd ]; then
+       if [ ! -f $initrd ]; then
+               echo "Initial ramdisk file " $initrd " does not exist"
+               exit 1
+       fi
+fi
+
+if [ $isoimage != yes ]; then
+       # Calculate size
+        if [ -x /usr/bin/du ]; then
+                totalsize=`/usr/bin/du -Dc $kernel $initrd $keymap |tail -1 | awk '{ print $1 }'`
+                if [ "$totalsize" -gt "$size" ] ; then
+                        echo "Sorry, the ramdisk, kernel and keymap don't fit in the floppy disk."
+                        exit 1
+                fi
+        fi
+       echo ""
+       echo "Insert a blank floppy into $device"
+       echo "All information on this floppy will be destroyed"
+       echo "Press [Enter] to proceed, ^C to abort"
+       read aline
+fi
+
+if [ "$fast" = fast ]; then
+
+       dd bs=1024 count=$size of=$mfile if=/dev/zero
+       bsize=$size
+       mpart=$mfile
+       if [ $size = $hdsize ]; then
+           bios=0x80
+           bsize=$(($size-$sectors))
+           cat > $mtemp <<EOF
+n
+p
+1
+
+
+a
+1
+w
+EOF
+           echo Partitioning HD "file   (this will take a minute)"
+           fdisk -b 512 -S $sectors -H $heads -C $cylinders \
+               $mfile < $mtemp > /dev/null 2> /dev/null
+           rm -f $mtemp
+           echo bsize = $bsize
+#read aline
+           losetup -d /dev/$loopback 2>/dev/null
+            losetup -d /dev/$looppart 2>/dev/null
+            losetup /dev/$loopback $mfile
+           losetup -o $(($sectors*512)) /dev/$looppart $mfile
+           mpart=/dev/$looppart
+       fi
+       echo Making filesystem
+       if [ "$fs" = ext2 ]; then
+               echo y | mkfs.$fs -N 24 -b 1024 $mpart $bsize
+       else
+               echo y | mkfs.$fs $mpart
+       fi
+       echo Mounting filesystem
+#read aline
+       if [ $size != $hdsize ]; then
+           mount -t $fs -o rw,loop $mfile $mount
+           loopback=`mount | grep $mfile | sed -e "sX.*loop=/dev/XX" -e "s/).*//"`
+       else
+           mount -t $fs -o rw $mpart $mount
+       fi
+       if [ $debug = true ]; then
+               mount
+       fi
+       disk="/dev/$loopback"
+       if [ $debug = true ]; then
+               echo "disk=$disk"
+       fi
+
+else
+
+       if [ "$format" = "yes" ]; then
+               echo Formatting $device with $fs filesystem...
+               dd of=$device if=/dev/zero bs=512 count=1
+               if [ "$fs" = ext2 ]; then
+                       mkfs -t $fs -N 24 -b 1024 $device 1>/dev/null 2>/dev/null
+               else
+                       mkfs -t $fs $device 1>/dev/null 2>/dev/null
+               fi
+               echo done.
+               echo ""
+       fi
+
+       rm -rf $mount/*
+       mount -t $fs -o rw $device $mount
+
+       rm -rf $mount/*
+       disk=$device
+
+fi
+
+cat > $mountconfig <<EOF
+#  Begin mkrescue $version configuration file
+install=$install
+boot=$device
+map=map
+backup=/dev/null
+message=message
+prompt
+timeout=150
+nowarn
+geometric
+disk=$disk bios=$bios
+  sectors=$sectors heads=$heads cylinders=$cylinders
+EOF
+if [ $size = $hdsize ]; then
+       echo "  max-partitions=7" >>$mountconfig
+       echo "  partition=/dev/$looppart  start=$sectors" >>$mountconfig
+       echo static-bios-codes >>$mountconfig
+       bios=0x81
+else
+       bios=0x80
+fi
+
+if [ "$master" != "" -a $isoimage = yes ]; then
+       echo "disk=$master" >>$mountconfig
+       echo "  bios=$bios" >>$mountconfig
+elif [ "$master" != "" -a $debug = true ]; then
+       echo "disk=$master" >>$mountconfig
+       echo "  bios=$bios" >>$mountconfig
+fi
+
+if [ $keymap != us.ktl ]; then 
+       echo "keytable=lang.ktl" >>$mountconfig
+fi
+
+if [ $isoimage = yes ]; then 
+       echo "el-torito-bootable-CD" >>$mountconfig
+fi
+
+echo " " >>$mountconfig
+echo "image=linux" >>$mountconfig
+
+if [ ! -z $initrd ]; then
+       echo "  initrd=initrd" >>$mountconfig
+fi
+
+if [ ! -z "$append" ]; then
+       echo "  append=\"$append\"" >>$mountconfig
+fi
+
+cat >> $mountconfig <<EOF
+  root="$root"
+  read-only
+EOF
+
+if [ "$master" != "" -a $isoimage = yes ]; then
+cat >> $mountconfig <<EOF
+other=$master
+  unsafe
+  label=hard_disk
+EOF
+fi
+
+if [ "$diag" = yes ]; then
+cp -pv $boot/diag1.img $mount
+cp -pv $boot/diag2.img $mount
+cat >> $mountconfig <<EOF
+image=diag1.img
+  label=diagnostic_1
+image=diag2.img
+  label=diagnostic_2
+EOF
+fi
+echo >>$mountconfig "#  End of mkrescue-generated configuration file"
+
+if [ $isoimage = yes ]; then
+       comment="El-Torito bootable-CD will boot at end of timeout"
+else
+       comment="floppy will boot in 15 seconds"
+fi
+
+rm -rf $mount/lost+found
+cat > $mount/message <<EOF
+
+MKRESCUE version $version $comment
+Use  "boot: linux <options>"  to enter kernel options
+The root device is currently configured as  root="$root"
+
+EOF
+echo `uname --sysname` `uname --release` > $mount/$(uname --release)
+
+sync
+
+if [ $debug = true ]; then
+       echo root=\"$root\"
+       echo ""
+       echo "pause after writing lilo.conf & message ..."
+       read aline
+fi
+
+echo "Copying files..."
+if [ $keymap != us.ktl ]; then 
+       cp -pv $keymap $mount/lang.ktl
+fi
+
+if [ ! -z $initrd ]; then
+       cp -pv $initrd $mount/initrd
+fi
+
+cp -pv $kernel $mount/linux
+sync
+
+echo "done."
+echo ""
+
+
+
+pushd $mount >/dev/null 2>/dev/null
+if [ "$fast" = fast ]; then
+       bootcmd="-b /dev/$loopback"
+fi
+
+echo Running $lilo ...
+if [ $debug = true ]; then
+
+cp -pvf $mountconfig $clog
+if [ -z $log ]; then
+ echo  $lilo -w+ -C $mountconfig $compact $bootcmd -v5
+       $lilo -w+ -C $mountconfig $compact $bootcmd -v5 || fast=error
+else
+ echo  $lilo -w+ -C $mountconfig $compact $bootcmd -v5 ">$log"
+       $lilo -w+ -C $mountconfig $compact $bootcmd -v5 >$log || fast=error
+fi
+
+else
+       $lilo -C $mountconfig $compact $bootcmd || fast=error
+fi
+popd >/dev/null 2>/dev/null
+if [ "$fast" = error ]; then
+       echo -n `$lilo -V`
+       echo " failure."
+else
+       echo done.
+fi
+echo ""
+
+umount $mount
+
+if [ $fast = error ]; then
+       exit 1
+fi
+
+if [ $isoimage = yes ]; then
+       echo MKISOFS
+       out=$device
+       opt=
+       if [ $size = $hdsize ]; then
+           losetup -d /dev/$looppart
+           losetup -d /dev/$loopback
+           opt=-hard-disk-boot
+       fi
+       mv $mfile $mount/boot.bin
+       mkisofs $opt -J -R -T \
+               -V LILO_BOOT -A "Linux Boot CD created by LILO mkrescue" \
+               -b boot.bin -c boot.cat -o $out $mount
+       cat <<EOF
+
+END MKISOFS:  output is in  '$device'
+
+
+The bootable CD can be burned with the 'cdrecord' utility
+using a command of the form:
+
+       cdrecord [<options>] [dev=<device>] $device
+
+EOF
+elif [ "$fast" = fast ]; then
+       if [ $debug = true ]; then
+               echo Pause before transfering to $device
+               read aline
+       fi
+       dd if=$mfile of=$device bs=1024
+fi
+
+echo "All done."
+echo ""
+exit 0
+
diff --git a/readme/INCOMPAT b/readme/INCOMPAT
new file mode 100644 (file)
index 0000000..b10812b
--- /dev/null
@@ -0,0 +1,546 @@
+Incompatibilities between LILO >= 22 and earlier versions
+=========================================================
+
+Boot loaders
+------------
+
+Starting with version 22, a third boot loader, '/boot/boot-bmp.b' is now
+available.  This loader supports booting from a bitmapped screen, defined in
+a bitmap file referenced from the config file.  This boot loader requires a
+VGA adapter which supports video mode 0x12: 16-color, 640x480 pixels.  It
+will fall back to the teletype-text interface if such an adapter is not
+present.
+
+Chain loaders
+-------------
+
+The chain loader for loading OS/2 from other than the C: drive, 'os2_d.b',
+is now obsolete.  All of the functionality is combined into 'chain.b'.
+
+Disk addressing
+---------------
+
+A Makefile option in version 22, LBA32, makes 32-bit sector addressing the
+default, instead of geometric addressing.  Thus, the 1024 cylinder limit on
+large disks will be avoided on virtually all newer (post 1998) systems. 
+With the fallback to geometric addressing as before, compatibility with
+older systems is extremely likely.  If geometric addressing must be forced
+on older system, there is now the 'geometric' command and '-g' switch.  Not
+all versions of LILO will be compiled with the LBA32 switch to enable this
+feature.
+
+RAID installation
+-----------------
+
+Installation on RAID1 partitions is completely re-written.  Consult the
+tutorial "README.raid1" for details.  The boot loaders are no longer written
+unconditionally to the MBRs of the disks containing the raid set partitions,
+but preferably to the raid partition itself.  Auxiliary records may be
+written to MBRs, but this writing may be controlled with 'raid-extra-boot='.
+A mode of operation compatible with previous versions is available.
+
+
+Incompatibilities between LILO >= 21 and earlier versions
+=========================================================
+
+Serial lines
+------------
+
+Since version 21.7, all IBM standard bit rates from 110 to 9600 are
+supported, as well as extended rates of 19200, 38400, 57600, & 115200.
+
+Boot loaders
+------------
+
+Starting with version 21.5, the default boot loader is '/boot/boot-menu.b',
+referenced as '/boot/boot.b' through a symbolic link.  This boot loader
+allows booting from a text-based menu using the keyboard arrow keys to make
+the kernel/other selection.  For strict compatibility with earlier
+teletype-text based boot loaders, '/boot/boot-text.b' is still available,
+although probably unneeded.
+
+Change Rules
+------------
+
+A more complete set of default partition change-rules is available starting 
+with version 21.6 and later.
+
+A Makefile option allows the automatic insertion of the "CHANGE AUTOMATIC"
+command into the config file.  A comment is now issued when this is done,
+and it is possible to see the partition change rules in force by using a
+verbosity level of 3:  -v3 or verbose=3.  Not all versions of LILO will be
+compiled with the AUTOAUTO switch to enable this feature.
+
+Disk addressing
+---------------
+
+32-bit 0-based sector addressing has been available since version 21.2,
+enabled by the 'lba32' (-L) option.  If the BIOS does not support the EDD
+packet calls on int 0x13 to use this feature, then the boot loader will fall
+back to geometric (Cylinder:Head:Sector) addressing by using int 0x13, fn 8,
+to obtain the disk geometry.  
+
+
+Incompatibilities between LILO >= 20 and earlier versions
+=========================================================
+
+Special chain loaders
+---------------------
+
+The functionality of the chain loaders any_b.b and any_d.b has been
+generalized and integrated into chain.b. any_b.b and any_d.b are
+therefore no longer supported. Their behaviour can be emulated as
+follows:
+
+   other = foo
+     loader = /boot/any_b.b
+
+becomes
+
+   other = foo
+     map-drive = 0
+       to = 1
+     map-drive = 1
+       to = 0
+
+and
+
+   other = foo
+     loader = /boot/any_d.b
+
+becomes
+
+   other = foo
+     map-drive = 0x80
+       to = 0x81
+     map-drive = 0x81
+       to = 0x80
+
+The use of os2_d.b changes as follows:
+
+   other = foo
+     loader = /boot/os2_d.b
+
+becomes
+
+   other = foo
+     loader = /boot/os2_d.b
+     map-drive = 0x80
+       to = 0x81
+     map-drive = 0x81
+       to = 0x80
+
+
+Removal of less common baud rates
+---------------------------------
+
+The baud rates 150 bps and 600 bps are no longer available with the SERIAL
+option.
+
+
+Incompatibilities between LILO >= 18 and earlier versions
+=========================================================
+
+Partition type check
+--------------------
+
+Starting with version 18, LILO checks the type of the partition where it
+stores its boot sector. LILO installation may therefore fail on systems
+where the LILO boot sector resides on a seemingly unsuitable partition.
+This problem can be solved by either changing the partition type of by
+using the IGNORE-TABLE configuration option.
+
+
+disktab
+-------
+
+Is no longer documented and support for it will be removed in a future
+version of LILO. See section "Disk geometry" in the accompanying
+documentation for the right way to configure unusual disk geometry.
+
+
+Booting kernel images from a device
+-----------------------------------
+
+An essentially useless feature of LILO is to be able to boot a kernel
+from a device without file system, e.g.
+
+  image = /dev/fd0
+    range = 1+512
+
+Support for this will be removed in a future version of LILO. Also, new
+functions such as kernels > 512kB are not supported for kernels booted
+from a device.
+
+Note that booting of non-Linux systems (other = /dev/...) will in no
+way be affected by this feature removal.
+
+
+REWRITE-TABLE
+-------------
+
+The REWRITE-TABLE configuration option and the compile-time options
+REWRITE_TABLE, FIX_TYPE, and HIDE_DOS are not available in the current
+version of LILO, because deficiencies were found in the implementation
+in version 17 (e.g. attempts to alter the partition table of the second
+disk resulted in a modification of the partition table of the first
+disk, using the parameters of the second disk), and there was not
+enough time to complete an improved version.
+
+Future versions will use a radically different internal mechanism, but
+no configuration change should be required in most cases. Users who
+depend on REWRITE-TABLE to be available should continue to use their
+current version of LILO and wait for a later version before upgrading.
+
+
+Incompatibilities between LILO >= 17 and earlier versions
+=========================================================
+
+Documentation change
+--------------------
+
+The last traces of "old-style" configuration have been removed.
+
+
+Incompatibilities between LILO >= 0.16 and earlier versions
+===========================================================
+
+Sanity checks
+-------------
+
+When booting an operating system from any device than the first hard or floppy
+disk, specifying the chain loader is now mandatory.
+
+
+Incompatibilities between LILO >= 0.14 and earlier versions
+===========================================================
+
+mkbindist
+---------
+
+... is gone. I don't think anybody used it and I got tired of updating it.
+
+
+Variable-size setup
+-------------------
+
+Kernels >= 1.1.43 support setup segments of variable size. LILO 0.15 is able
+to detect this and act accordingly. However, older kernels could possibly
+contain other information at that place. This can be discovered by running
+the following command:
+
+# /sbin/lilo -t -v -v | grep Setup
+
+If very unusual numbers (e.g. below four or significantly bigger than five)
+are shown, you may have such a kernel.
+
+LILO has to be compiled without the VARSETUP option in such cases. Note that
+later kernels may no longer support running LILO without VARSETUP.
+
+
+Incompatibilities between LILO >= 0.13 and earlier versions
+===========================================================
+
+Possible conflict with /etc/disktab from Shoelace
+-------------------------------------------------
+
+When using the new path names, installation of LILO may fail with
+    Invalid line in /etc/disktab:
+    "w0|wini|Generic hard disk:\"
+if you have an old /etc/disktab file from Shoelace (a different boot loader
+that is quite obsolete nowadays). Remove or rename that file before running
+/sbin/lilo (or QuickInst).
+
+Note: you may have an /etc/disktab file even if you've never used Shoelace,
+because even current versions of SLS still install that file.
+
+
+Removal of support for unstripped kernels
+-----------------------------------------
+
+(Compound) unstripped kernels are no longer supported by LILO, because
+current kernels are expected to be compressed. This change also obsoletes
+/etc/lilo/install (see below).
+
+A new concept to support compressed kernels carrying symbol information may
+be devised later.
+
+
+Removal of /etc/lilo/install
+----------------------------
+
+Early versions of LILO expected to find all parameters on the command line.
+In order to simplify repeated re-installations of LILO, the invocation of
+LILO with all its parameters was stored in /etc/lilo/install.
+
+Because this was messy and introduced syntactical limitations,
+/etc/lilo/config was introduced after a while and support for command-line
+options was drastically reduced later. /etc/lilo/install now typically just
+invoked /etc/lilo/lilo with no options or with -C /etc/lilo/config, which
+became the default. Only when using compound unstripped kernels, one had to
+put additional instructions to build the kernel file into /etc/lilo/install.
+
+Now, that unstripped kernels are gone too (see above), /etc/lilo/install is
+superfluous. Because the kernel Makefile still invokes LILO by calling
+/etc/lilo/install, /etc/lilo/install should be a symbolic link to /sbin/lilo
+or /etc/lilo/lilo until everybody has switched to the new directory
+structure.
+
+
+Directory hierarchy change
+--------------------------
+
+A new Linux directory structure is in the process of being standardized.
+Most distributions will support the new structure. In order to install LILO
+with the new structure, you have to use the .new versions of QuickInst and
+Makefile. Otherwise, you have to use the .old versions.
+
+The locations of the following files change:
+
+  Old location                 New location
+  ------------------------     -----------------
+  /etc/lilo/config.defines     /etc/lilo.defines
+  /etc/lilo/config             /etc/lilo.conf
+  /etc/lilo/disktab            /etc/disktab
+  /etc/lilo/lilo               /sbin/lilo
+  /etc/lilo/boot.NNNN          /boot/boot.NNNN
+  /etc/lilo/part.NNNN          /boot/part.NNNN
+  /etc/lilo/map                        /boot/map
+  /etc/lilo/*.b                        /boot/*.b
+
+/etc/lilo/install should be a symbolic link to /sbin/lilo for backwards
+compatibility. If you already have a (very old) /etc/disktab file from
+Shoelace, you have to delete or replace it. (Note: SLS 1.03 still installs
+that file, so you might have it even if you've never heard of Shoelace.)
+
+The current documentation still uses the old paths.
+
+
+Temporary unavailability of RAM disk size override
+--------------------------------------------------
+
+The RAM disk size override option (RAMDISK) has no effect when using
+0.99pl13 or older kernels, because no corresponding parameter line item
+exists. Support for it may be available in 0.99pl14 or later kernels.
+
+
+Incompatibilities between LILO >= 0.12 and earlier versions
+===========================================================
+
+The first stage boot loader now displays diagnostic codes if loading
+the second stage loader fails. This may create irritating messages
+like L06ILO on systems, where the first read access on a disk after
+booting usually fails. These diagnostics can be disabled by setting
+the compile-time option NO1STDIAG.
+
+
+Incompatibilities between LILO >= 0.11 and earlier versions
+===========================================================
+
+The configuration variable INSTALL is no longer required. If absent, a
+default of /etc/lilo/boot.b is used. This means that it is no longer
+possible to avoid installing a new boot sector when updating the map
+file. The old behaviour can be restored by setting the compile-time
+option NOINSTDEF.
+
+
+Incompatibilities between LILO >= 0.10 and earlier versions
+===========================================================
+
+Version 0.10 of LILO is intentionally incompatible in many ways with
+earlier versions. However, in most cases, there is an easy migration
+path.
+
+LILO 0.10 may not work with versions of the following programs older
+than specified:
+
+  Kernel                               0.99pl8
+  Peter Orbaek's poeigl                        1.13a
+  Miquel van Smoorenburg's SysV-init   2.1
+  Mike Jagdis' bootsys                 version 3 (?)
+
+
+Documentation cleaning and splitting
+------------------------------------
+
+Because the documentation was slowly becoming a multiple-choice test,
+all references to old versions of kernels and other programs have been
+removed. All traces of removed features have vanished too.
+
+The single file "doc.tex" is now split in two parts: the user's guide
+"user.tex" and the technical overview "tech.tex". Reading the
+technical overview is not necessary in order to install LILO.
+
+
+Old-style configuration has been removed
+----------------------------------------
+
+Old-style configuration (e.g. /etc/lilo/lilo /vmlinux,/dev/hda1) is no
+longer supported. New-style configuration uses a configuration file in
+a far better readable format (/etc/lilo/config). There is also space
+for future extensions.
+
+If you're still using old-style configuration, you have to switch to
+new-style configuration before installing LILO 0.10.
+
+For all versions of LILO since 0.7, an automated migration facility is
+provided. See section "Migration" in the documentation of that version
+of LILO. In short, you have to run the following commands _before_
+upgrading to LILO 0.10:
+
+# /etc/lilo/install -D >/etc/lilo/config
+# mv install.new /etc/lilo/install
+
+If you're using an older version of LILO than 0.7 or if you're not
+using /etc/lilo/install, you should either manually create a
+configuration file or use QuickInst to re-install from scratch.
+
+
+No support for dumps
+--------------------
+
+Because LILO 0.10 doesn't understand old-style configuration, the dump
+option (-D) is no longer supported. Therefore, if you need to migrate
+from old-style configuration, you have to use the installed version of
+LILO to do that.
+
+
+No support for not-compound unstripped kernels
+----------------------------------------------
+
+Since LILO 0.9, compound unstripped kernels are supported. They are
+easier to handle and provide the same functionality as not-compound
+unstripped kernels. Note: all this has _nothing_ to do with compressed
+(zipped) kernels. They work fine with all versions of LILO.
+
+
+Suggesting using a link for /etc/lilo/install
+---------------------------------------------
+
+Because not-compound unstripped kernels, which were needing some
+support code in /etc/lilo/install, have been removed, and because the
+-C option is no longer necessary to distinguish between old-style and
+new-style configuration, /etc/lilo/install is unnecessary in most
+cases.
+
+In order to preserve compatibility with older installations and with
+installations that use code for special actions in /etc/lilo/install,
+a symbolic link should be created from /etc/lilo/install to lilo.
+
+
+Removed configuration option NOAUTO
+-----------------------------------
+
+The compile-time configuration option NOAUTO has been removed. This
+means that you have to upgrade to poeigl ?.??? (or later) if you're
+using simpleinit from an earlier version of poeigl. If the option
+NOAUTO is still present, it is ignored.
+
+
+Incompatibilities between LILO >= 0.9 and earlier versions
+==========================================================
+
+Case-insensitive name matching
+------------------------------
+
+By default, LILO is now configured to ignore case when matching image
+names. This can cause problems if labels are being used that differ
+only in case. (Detected at map creation time.) Either change the
+label names or remove -DIGNORECASE from the configuration section of
+the Makefile.
+
+
+New keyword "auto" passed to init
+---------------------------------
+
+If the system boots without manual intervention, the word "auto" is
+passed on the command line to the kernel, which in turn passes it to
+init. Some init programs don't recognize that word and issue an error
+message or fail to process other command-line options (e.g. some
+versions of poeigl init expects "single" to be the only word on the
+command line). The old behaviour can be obtained by setting the build-
+time configuration variable NOAUTO in the configuration section of the
+Makefile.
+
+
+-r implied if environment variable ROOT is set
+----------------------------------------------
+
+The map installer acts as if the option -r was on the command line if
+the environment variable ROOT is set. If you are using ROOT for other
+purposes than indicating the path of the actual root of the file
+system (i.e. it should be set to "/" during normal system operation),
+you have to pass the option  -r /  to the map installer. Typically,
+ROOT is not used for anything but LILO (or possibly programs that are
+aware of how LILO uses it), so this should be no problem.
+
+
+Incompatibilities between LILO >= 0.7 and earlier versions
+==========================================================
+
+There are a number of incompatibilities between LILO 0.7 (or newer)
+and earlier versions that cause working /etc/lilo/install scripts to
+fail or that change earlier behaviour without warning.
+
+
+Root device presetting
+----------------------
+
+The way how the root device is preset differs from LILO >= 0.7 and
+earlier versions if using /etc/lilo/config. If the boot images are
+listed on the command line, LILO >= 0.7 emulates the old behaviour.
+
+Old behaviour:
+  - if the root device was specified after the image descriptor
+    (e.g. foo=/bar,/dev/hda1), that device was used.
+  - if a root device was set in the boot image and no device was
+    specified at the command line, the setting from the boot
+    image was used. Later changes of the settings (e.g. with rdev
+    aka setroot) had no effect.
+  - if no root device was set in the boot image, LILO used the
+    current root partition instead. Again, changing the setting
+    later had no effect.
+
+New behaviour:
+  - if the ROOT variable is set, that value is used and the
+    setting in the boot image is ignored.
+  - otherwise, the value found in the boot image at boot time is
+    used. This means that changing the root device setting after
+    map creation has the desired effect.
+
+
+Swap device settings
+--------------------
+
+Presetting the swap device (e.g. /linux,/dev/root,/dev/swap) is no
+longer supported. Linus has already stopped providing that feature
+in recent kernels.
+
+Kernels that expect swap device settings in the boot sector may no
+longer work. I'm not sure when presettable swap devices were removed,
+but generally 0.96 and early 0.97 kernels may be considered
+incompatible.
+
+The memory location where the swap device preset value used to be
+stored has been occupied by the VGA mode value in 0.98pl6 and
+possibly also in SLS versions of 0.98pl5.
+
+Workaround: Create a /etc/lilo/config file and set the VGA variable
+           to zero to disable using a swap device at boot time.
+
+
+BIOS code overrides
+-------------------
+
+Appending BIOS codes to file names (e.g. /foo/bar:0x80) is no longer
+supported. /etc/lilo/disktab can be used for most purposes where
+BIOS code overrides might have been useful.
+
+
+Command-line arguments of the map installer
+-------------------------------------------
+
+Older versions of the map installer accepted multiple ocurrences of
+the same flag. LILO 0.7 and later versions are only guaranteed to
+accept repetition of -v. However, variables set in /etc/lilo/config
+can be overridden on the command line in LILO 0.8.
diff --git a/readme/README b/readme/README
new file mode 100644 (file)
index 0000000..aee428c
--- /dev/null
@@ -0,0 +1,2944 @@
+LILO - Generic Boot Loader for Linux ("LInux LOader") by Werner Almesberger
+===========================================================================
+
+   NOTE:  This document is no longer maintained.  However, it is
+   still current.  Changes to LILO for versions 21.2 and later are
+   documented in detail in the 'man' pages for 'lilo' and 'lilo.conf'.
+   Refer to them first, then to this document.
+
+  
+Version 21-4 (release) -- John Coffman <johninsd@san.rr.com>
+
+Minor changes suggested by Werner to show that this release is derived
+from the source code to his version 21.  Added VERSION_MAJOR and 
+VERSION_MINOR to replace VERSION.  The file VERSION is replaced by 
+'version.h'.
+
+The first and second stage loaders have been modified so that ONLY
+'lba32' will use EDD packet calls.  'linear' will now always ask the
+BIOS for the disk geometry, and then use C:H:S addressing.
+
+
+Version 21-2  -- John Coffman <johninsd@san.rr.com>
+
+This version was created to allow booting on disks larger than 8.4Gb using
+the Enhanced BIOS call (int 0x13, AH=0x42) and the packet-call interface.
+These calls are supported on post-1998 systems, and through software BIOS
+extensions such as EZ-DRIVE(tm).  
+
+My primary objective in making these changes to LILO, is not to break any-
+thing.  Hence, the 32-bit direct addressing of sectors is supported by a
+new keyword in the 'lilo.conf' file:  "lba32".  This keyword is mutually
+exclusive with the keyword "linear".  On the command line, these options
+are invoked with the new "-L" switch, or the old "-l" switch, respectively.
+
+Apologies to Werner Almesberger for not communicating these changes/addi-
+tions to him directly; but I have not been able to contact him by e-mail
+at the address he provided in the latest 'lilo.lsm' file.  I do not want
+versions of LILO to get out-of-step.
+
+Disk sector addresses are conveyed from the Map Installer (lilo executable)
+to the boot loaders, first- and second-stages through a 5 byte structure:
+
+     sector    [1..63] plus 2 high bits of Cylinder
+     cylinder  [0..1023] low eight bits in this byte
+     device    [0..3] for floppies, [0x80..0x8F] for hard disks
+     head      [0..254] no, the max is 254, not 255
+     count     [1...] number of sectors to transfer
+     
+The first two bytes are normally loaded into the CX register, the second 
+two
+bytes into the DX register, and the last byte into the AL register.  This 
+is
+the call used for the C:H:S addressing scheme of the original IBM-PC BIOS.
+LILO checks that the 64Kb DMA boundary is never crossed by a call, and that
+the count never exceeds the sector count of one track on the disk.
+
+When 'linear' is specified, a 24-bit, 0 based addressing scheme is 
+employed.
+The low 8 bits are in 'sector'; the middle 8 bits in 'cylinder'; and the 
+high
+8 bits are in 'head'.  To flag this as a 'linear' address, the 'device' 
+byte
+has bit 6 set (mask 0x40 or'ed in).  The count field is a maximum of 128,
+since anything greater would cross a 64Kb DMA boundary.  It is up to the 
+loader code (second stage only), to check that no track boundary is 
+crossed.
+
+The situation is more complicated with 'lba32' addressing.  It is flagged 
+with
+bit 5 of the 'device' byte being set (mask 0x20 or'ed in).  The 32-bit 
+address
+is spread over the 'sector', 'cylinder', 'head', and 'count' fields, from 
+low
+byte to high byte, respectively.  Whenever this full 32-bit address is
+specified explicitly, the actual sector count to transfer is implied to be
+one (1), and this fact is flagged in the 'device' byte by setting bit 5
+(mask 0x10 or'ed in).  When a multi-sector transfer is called for, the high
+8-bits of the address are NOT specified explicitly, but are assumed to be
+the same as the previous transfer, the 'count' of sectors to transfer will
+be in the range [2..127], and bit 5 (mask 0x10) of the 'device' byte will 
+be
+clear.
+
+The first-stage loader uses single sector transfers only, so it uses a
+simplified disk read routine, always assumes a sector transfer count of 1,
+and always assumes that the full 32-bit address of the sector is specified
+when 'lba32' mode is detected in the 'device' byte.  However, the second-
+stage loader is capable of multi-sector transfers when map-compaction has
+been used (-c switch, or 'compact' global option), so it uses the fully
+capable read routine to load the -initrd- image, and the -kernel- image.
+
+Both 'linear' and 'lba32' will use the Enhanced BIOS packet calls, if they
+are available.  Otherwise, the disk address is converted to C:H:S, using 
+the
+disk geometry returned by (int 0x13, AH=8).  If cylinder overflow occurs --
+i.e., cylinder > 1023, then error code '9f' is issued.
+
+The BIOS calls used to implement large disk booting conform to the Enhanced
+Disk Drive Specification, version 3.0, rev 0.8, dated March 12, 1998.  This
+document is available on-line from Phoenix Technologies Ltd., at:
+   
+   http://www.phoenix.com/products/specs.html
+
+Known bugs:
+   The chain loader, 'os2_d.b', still will not boot OS2 4.0 from a 
+secondary
+   partition on my "D:" drive.  Boot Manager can, and I am still working on
+   the problem.
+----------------------------------------------------------------------------
+
+
+Version 21
+
+Important: The file INCOMPAT contains vital (in)compatibility information
+           for this release of LILO. Read it before proceeding.
+
+Installing boot loaders is inherently dangerous. Be sure to have some means
+to boot your system from a different media if you install LILO on your hard
+disk.
+
+
+There is also a LaTeX version of this document in the "doc" directory.
+It is much nicer to read than pure ASCII.
+
+
+Installation
+------------
+
+Please read the file INCOMPAT for compatibility notes.
+
+The installation procedure is described in the section "Normal first-time
+installation". Please read "Booting basics" for the whole story.
+
+*** QUICK INSTALLATION ***
+
+    If you want to install LILO on your hard disk and if you don't want
+    to use all its features, you can use the quick installation script.
+    Read QuickInst for details.
+
+
+ LILO is a versatile boot loader for Linux. It does not depend on a 
+specific file system, can boot Linux kernel images from floppy disks and 
+from hard disks and can even act as a "boot manager" for other operating 
+systems.*
+
+  *  PC/MS-DOS, DR DOS, OS/2, Windows 95, Windows NT, 386BSD, SCO UNIX, 
+    Unixware, ...
+
+One of up to sixteen different images can be selected at boot time. Various 
+parameters, such as the root device, can be set independently for each 
+kernel. LILO can even be used as the master boot record.
+
+This document introduces the basics of disk organization and booting, 
+continues with an overview of common boot techniques and finally describes 
+installation and use of LILO in greater detail. The troubleshooting section 
+at the end describes diagnostic messages and contains suggestions for most 
+problems that have been observed in the past.
+
+Please read at least the sections about installation and configuration if 
+you're already using an older version of LILO. This distribution is 
+accompanied by a file named INCOMPAT that describes further 
+incompatibilities to older versions.
+
+For the impatient: there is a quick-installation script to create a simple 
+but quite usable installation. See section "Quick installation" for 
+details.
+
+But wait ... here are a few easy rules that will help you to avoid most 
+problems people experience with LILO:
+
+  - _Don't panic._ If something doesn't work, try to find out what is 
+    wrong, try to verify your assumption and only then attempt to fix it. 
+  - Read the documentation. Especially if what the system does doesn't 
+    correspond to what you think it should do. 
+  - Make sure you have an emergency boot disk, that you know how to use it, 
+    and that it is always kept up to date. 
+  - Run /sbin/lilo _whenever_ the kernel or any part of LILO, including its 
+    configuration file, has changed. When in doubt, run it. You can't run 
+    /sbin/lilo too many times. 
+  - If performing a destructive upgrade and/or erasing your Linux 
+    partitions, de-install LILO _before_ that if using it as the MBR. 
+  - Don't trust setup scripts. Always verify the /etc/lilo.conf they create 
+    before booting. 
+  - If using a big disk, be prepared for inconveniences: you may have to 
+    use the LINEAR option. 
+
+
+System overview
+---------------
+
+LILO is a collection of several programs and other files:
+
+  The map installer  is the program you run under Linux to put all files 
+    belonging to LILO at the appropriate places and to record information 
+    about the location of data needed at boot time. This program normally 
+    resides in /sbin/lilo. It has to be run to refresh that information 
+    whenever any part of the system that LILO knows about changes, e.g. 
+    after installing a new kernel. 
+  Various files  contain data LILO needs at boot time, e.g. the boot 
+    loader. Those files normally reside in /boot. The most important files 
+    are the boot loader (see below) and the map file (/boot/map), where the 
+    map installer records the location of the kernel(s).* Another important 
+    file is the configuration file, which is normally called /etc/lilo.conf 
+  The boot loader  is the part of LILO that is loaded by the BIOS and that 
+    loads kernels or the boot sectors of other operating systems. It also 
+    provides a simple command-line interface to interactively select the 
+    item to boot and to add boot options. 
+
+  *  LILO does not know how to read a file system. Instead, the map 
+    installer asks the kernel for the physical location of files (e.g. the 
+    kernel image(s)) and records that information. This allows LILO to work 
+    with most file systems that are supported by Linux.
+
+LILO primarily accesses the following parts of the system:
+
+  The root file system partition  is important for two reasons: first, LILO 
+    sometimes has to tell the kernel where to look for it. Second, it is 
+    frequently a convenient place for many other items LILO uses, such as 
+    the boot sector, the /boot directory, and the kernels. 
+  The boot sector  contains the first part of LILO's boot loader. It loads 
+    the much larger second-stage loader. Both loaders are typically stored 
+    in the file /boot/boot.b 
+  The kernel  is loaded and started by the boot loader. Kernels typically 
+    reside in the root directory or in /boot. 
+
+Note that many of the files LILO needs at boot time have to be accessible 
+with the BIOS. This creates certain restrictions, see section "BIOS 
+restrictions".
+
+
+Introduction
+============
+
+The following sections describe how PCs boot in general and what has to be 
+known when booting Linux and using LILO in particular.
+
+
+Disk organization
+-----------------
+
+When designing a boot concept, it is important to understand some of the 
+subtleties of how PCs typically organize disks. The most simple case are 
+floppy disks. They consist of a boot sector, some administrative data (FAT 
+or super block, etc.) and the data area. Because that administrative data 
+is irrelevant as far as booting is concerned, it is regarded as part of the 
+data area for simplicity.
+
+            +---------------------------+
+            |Boot sector|               |
+            |-----------+               |
+            |                           |
+            |         Data area         |
+            |                           |
+            |                           |
+            +---------------------------+
+
+The entire disk appears as one device (e.g. /dev/fd0) on Linux.
+
+The MS-DOS boot sector has the following structure:
+
+                    +------------------------+
+              0x000 |Jump to the program code|
+                    |------------------------|
+              0x003 |                        |
+                    |    Disk parameters     |
+                    |                        |
+                    |------------------------|
+        0x02C/0x03E |                        |
+                    |      Program code      |
+                    |                        |
+                    |                        |
+                    |------------------------|
+              0x1FE | Magic number (0xAA55)  |
+                    +------------------------+
+
+LILO uses a similar boot sector, but it does not contain the disk 
+parameters part. This is no problem for Minix, Ext2 or similar file 
+systems, because they don't look at the boot sector, but putting a LILO 
+boot sector on an MS-DOS file system would make it inaccessible for MS-DOS.
+
+Hard disks are organized in a more complex way than floppy disks. They 
+contain several data areas called partitions. Up to four so-called primary 
+partitions can exist on an MS-DOS hard disk. If more partitions are needed, 
+one primary partition is used as an extended partition that contains 
+several logical partitions.
+
+The first sector of each hard disk contains a partition table, and an 
+extended partition and _each_ logical partition contains a partition table 
+too.
+
+        +--------------------------------------------+
+        | Partition table                  /dev/hda  |
+        | +------------------------------------------|
+        | | Partition 1                    /dev/hda1 |
+        | |                                          |
+        | |------------------------------------------|
+        | | Partition 2                    /dev/hda2 |
+        | |                                          |
+        +--------------------------------------------+
+
+The entire disk can be accessed as /dev/hda, /dev/hdb, /dev/sda, etc. The 
+primary partitions are /dev/hda1 ... /dev/hda4.
+
+        +--------------------------------------------+
+        | Partition table                  /dev/hda  |
+        | +------------------------------------------|
+        | | Partition 1                    /dev/hda1 |
+        | |                                          |
+        | |------------------------------------------|
+        | | Partition 2                    /dev/hda2 |
+        | |                                          |
+        | |------------------------------------------|
+        | | Extended partition             /dev/hda3 |
+        | | +----------------------------------------|
+        | | | Extended partition table               |
+        | | |----------------------------------------|
+        | | | Partition 3                  /dev/hda5 |
+        | | |                                        |
+        | | |----------------------------------------|
+        | | | Extended partition table               |
+        | | |----------------------------------------|
+        | | | Partition 4                  /dev/hda6 |
+        | | |                                        |
+        +--------------------------------------------+
+
+This hard disk has two primary partitions and an extended partition that 
+contains two logical partitions. They are accessed as /dev/hda5 ...
+
+Note that the partition tables of logical partitions are not accessible as 
+the first blocks of some devices, while the main partition table, all boot 
+sectors and the partition tables of extended partitions are.
+
+Partition tables are stored in partition boot sectors. Normally, only the 
+partition boot sector of the entire disk is used as a boot sector. It is 
+also frequently called the master boot record (MBR). Its structure is as 
+follows:
+
+                    +------------------------+
+              0x000 |                        |
+                    |      Program code      |
+                    |                        |
+                    |                        |
+                    |------------------------|
+              0x1BE |    Partition table     |
+                    |                        |
+                    |------------------------|
+              0x1FE | Magic number (0xAA55)  |
+                    +------------------------+
+
+The LILO boot sector is designed to be usable as a partition boot sector. 
+(I.e. there is room for the partition table.) Therefore, the LILO boot 
+sector can be stored at the following locations:
+
+  - boot sector of a Linux floppy disk. (/dev/fd0, ...) 
+  - MBR of the first hard disk. (/dev/hda, /dev/sda, ...) 
+  - boot sector of a primary Linux file system partition on the first hard 
+    disk. (/dev/hda1, ...) 
+  - partition boot sector of an extended partition on the first hard disk. 
+    (/dev/hda1, ...)* 
+
+  *  Most FDISK-type programs don't believe in booting from an extended 
+    partition and refuse to activate it. LILO is accompanied by a simple 
+    program (activate) that doesn't have this restriction. Linux fdisk also 
+    supports activating extended partitions.
+
+It _can't_ be stored at any of the following locations:
+
+  - boot sector of a non-Linux floppy disk or primary partition. 
+  - a Linux swap partition. 
+  - boot sector of a logical partition in an extended partition.* 
+  - on the second hard disk. (Unless for backup installations, if the 
+    current first disk will be removed or disabled, or if some other boot 
+    loader is used, that is capable of loading boot sectors from other 
+    drives.) 
+
+  *  LILO can be forced to put the boot sector on such a partition by using 
+    the  -b  option or the BOOT variable. However, only few programs that 
+    operate as master boot records support booting from a logical 
+    partition.
+
+Although LILO tries to detect attempts to put its boot sector at an invalid 
+location, you should not rely on that.
+
+
+Booting basics
+--------------
+
+When booting from a floppy disk, the first sector of the disk, the 
+so-called boot sector, is loaded. That boot sector contains a small program 
+that loads the respective operating system. MS-DOS boot sectors also 
+contain a data area, where disk and file system parameters (cluster size, 
+number of sectors, number of heads, etc.) are stored.
+
+When booting from a hard disk, the very first sector of that disk, the 
+so-called master boot record (MBR) is loaded. This sector contains a loader 
+program and the partition table of the disk. The loader program usually 
+loads the boot sector, as if the system was booting from a floppy.
+
+Note that there is no functional difference between the MBR and the boot 
+sector other than that the MBR contains the partition information but 
+doesn't contain any file system-specific information (e.g. MS-DOS disk 
+parameters).
+
+The first 446 (0x1BE) bytes of the MBR are used by the loader program. They 
+are followed by the partition table, with a length of 64 (0x40) bytes. The 
+last two bytes contain a magic number that is sometimes used to verify that 
+a given sector really is a boot sector.
+
+There is a large number of possible boot configurations. The most common 
+ones are described in the following sections.
+
+
+MS-DOS alone
+- - - - - -
+
+        +-------------------------------------------------------+
+        | Master Boot Record    Boot sector    Operating system |
+        |-------------------------------------------------------|
+        | DOS-MBR ------------> MS-DOS ------> COMMAND.COM      |
+        +-------------------------------------------------------+
+
+This is what usually happens when MS-DOS boots from a hard disk: the 
+DOS-MBR determines the active partition and loads the MS-DOS boot sector. 
+This boot sector loads MS-DOS and finally passes control to COMMAND.COM. 
+(This is greatly simplified.)
+
+
+LOADLIN
+- - - -
+
+    +------------------------------------------------------------+
+    | Master Boot Record    Boot sector    Operating system      |
+    |------------------------------------------------------------|
+    | DOS-MBR ------------> MS-DOS ------> COMMAND.COM           |
+    |                                 ---> LOADLIN ------> Linux |
+    +------------------------------------------------------------+
+
+A typical LOADLIN setup: everything happens like when booting MS-DOS, but 
+in CONFIG.SYS or AUTOEXEC.BAT, LOADLIN is invoked. Typically, a program 
+like BOOT.SYS is used to choose among configuration sections in CONFIG.SYS 
+and AUTOEXEC.BAT. This approach has the pleasant property that no boot 
+sectors have to be altered.
+
+Please refer to the documentation accompanying the LOADLIN package for 
+installation instructions and further details.
+
+
+LILO started by DOS-MBR
+- - - - - - - - - - - -
+
+        +-------------------------------------------------------+
+        | Master Boot Record    Boot sector    Operating system |
+        |-------------------------------------------------------|
+        | DOS-MBR ------------> LILO --------> Linux            |
+        |                  ---> other OS                        |
+        +-------------------------------------------------------+
+
+This is a "safe" LILO setup: LILO is booted by the DOS-MBR. No other boot 
+sectors have to be touched. If the other OS (or one of them, if there are 
+several other operating systems being used) should be booted without using 
+LILO, the other partition has to be marked "active" with fdisk or activate.
+
+Installation: 
+
+  - install LILO with its boot sector on the Linux partition. 
+  - use fdisk or activate to make that partition active. 
+  - reboot. 
+
+Deinstallation: 
+
+  - make a different partition active. 
+  - install whatever should replace LILO and/or Linux. 
+
+
+Several alternate branches
+- - - - - - - - - - - - -
+
+    +------------------------------------------------------------+
+    | Master Boot Record    Boot sector    Operating system      |
+    |------------------------------------------------------------|
+    | DOS-MBR ------------> MS-DOS ------> COMMAND.COM           |
+    |                                 ---> LOADLIN ------> Linux |
+    |                  ---> LILO --------> Linux                 |
+    |                                 ---> MS-DOS --- ...        |
+    +------------------------------------------------------------+
+
+An extended form of the above setup: the MBR is not changed and both 
+branches can either boot Linux or MS-DOS. (LILO could also boot other 
+operating systems.)
+
+
+LILO started by BOOTACTV*
+- - - - - - - - - - - - -
+
+  *  Other, possibly better known boot switchers, e.g. OS/2 BootManager 
+    operate in a similar way. The installation procedures typically vary.
+
+        +-------------------------------------------------------+
+        | Master Boot Record    Boot sector    Operating system |
+        |-------------------------------------------------------|
+        | BOOTACTV -----------> LILO --------> Linux            |
+        |                  ---> other OS                        |
+        +-------------------------------------------------------+
+
+Here, the MBR is replaced by BOOTACTV (or any other interactive boot 
+partition selector) and the choice between Linux and the other operating 
+system(s) can be made at boot time. This approach should be used if LILO 
+fails to boot the other operating system(s).*
+
+  *  And the author would like to be notified if booting the other 
+    operating system(s) doesn't work with LILO, but if it works with an 
+    other boot partition selector.
+
+Installation: 
+
+  - boot Linux. 
+  - make a backup copy of your MBR on a floppy disk, e.g.
+     dd if=/dev/hda of=/fd/MBR bs=512 count=1 
+  - install LILO with the boot sector on the Linux partition. 
+  - install BOOTACTV as the MBR, e.g.
+     dd if=bootactv.bin of=/dev/hda bs=446 count=1 
+  - reboot. 
+
+Deinstallation: 
+
+  - boot Linux. 
+  - restore the old MBR, e.g.
+     dd if=/MBR of=/dev/hda bs=446 count=1
+     or FDISK /MBR under MS-DOS. 
+
+If replacing the MBR appears undesirable and if a second Linux partition 
+exists (e.g. /usr, _not_ a swap partition), BOOTACTV can be merged with the 
+partition table and stored as the "boot sector" of that partition. Then, 
+the partition can be marked active to be booted by the DOS-MBR.
+
+Example:
+
+# dd if=/dev/hda of=/dev/hda3 bs=512 count=1
+# dd if=bootactv.bin of=/dev/hda3 bs=446 count=1
+
+_WARNING:_ Whenever the disk is re-partitioned, the merged boot sector on 
+that "spare" Linux partition has to be updated too.
+
+
+LILO alone
+- - - - -
+
+            +----------------------------------------+
+            | Master Boot Record    Operating system |
+            |----------------------------------------|
+            | LILO ---------------> Linux            |
+            |                  ---> other OS         |
+            +----------------------------------------+
+
+LILO can also take over the entire boot procedure. If installed as the MBR, 
+LILO is responsible for either booting Linux or any other OS. This approach 
+has the disadvantage, that the old MBR is overwritten and has to be 
+restored (either from a backup copy, with FDISK /MBR on recent versions of 
+MS-DOS or by overwriting it with something like BOOTACTV) if Linux should 
+ever be removed from the system.
+
+You should verify that LILO is able to boot your other operating system(s) 
+before relying on this method.
+
+Installation: 
+
+  - boot Linux. 
+  - make a backup copy of your MBR on a floppy disk, e.g.
+     dd if=/dev/hda of=/fd/MBR bs=512 count=1 
+  - install LILO with its boot sector as the MBR. 
+  - reboot. 
+
+Deinstallation: 
+
+  - boot Linux. 
+  - restore the old MBR, e.g.
+     dd if=/fd/MBR of=/dev/hda bs=446 count=1 
+
+If you've installed LILO as the master boot record, you have to explicitly 
+specify the boot sector (configuration variable BOOT=...) when updating the 
+map. Otherwise, it will try to use the boot sector of your current root 
+partition, which will usually work, but it will probably leave your system 
+unbootable.
+
+
+Names
+- - -
+
+The following names have been used to describe boot sectors or parts of 
+operating systems:
+
+  "DOS-MBR"  is the original MS-DOS MBR. It scans the partition table for a 
+    partition that is marked "active" and loads the boot sector of that 
+    partition. Programs like MS-DOS' FDISK, Linux fdisk or activate 
+    (accompanies LILO) can change the active marker in the partition table. 
+  "MS-DOS"  denotes the MS-DOS boot sector that loads the other parts of 
+    the system (IO.SYS, etc.). 
+  "COMMAND.COM"  is the standard command interpreter of MS-DOS. 
+  "LOADLIN"  is a program that loads a Linux kernel image from an MS-DOS 
+    partition into memory and executes it. It is usually invoked from 
+    CONFIG.SYS and is used in combination with a CONFIG.SYS configuration 
+    switcher, like BOOT.SYS.* 
+  "LILO"  can either load a Linux kernel or the boot sector of any other 
+    operating system. It has a first stage boot sector that loads the 
+    remaining parts of LILO from various locations.** 
+  "BOOTACTV"  permits interactive selection of the partition from which the 
+    boot sector should be read. If no key is pressed within a given 
+    interval, the partition marked active is booted. BOOTACTV is included 
+    in the pfdisk package. There are also several similar programs, like 
+    PBOOT and OS-BS.*** 
+
+  *  LOADLIN is available for anonymous FTP from
+     ftp://tsx-11.mit.edu/pub/linux/dos_utils/lodlin<n>.tar.gz
+     ftp://sunsite.unc.edu/pub/Linux/system/boot/dualboot/lodlin<n>.tgz
+     BOOT.SYS is available for anonymous FTP from
+     ftp://ftp.funet.fi/pub/Linux/tools/boot142.zip
+
+  **  LILO can be found in
+     ftp://tsx-11.mit.edu/pub/linux/packages/lilo/lilo-<n>.tar.gz
+     ftp://sunsite.unc.edu/pub/Linux/system/boot/lilo/lilo-<n>.tar.gz
+     ftp://lrcftp.epfl.ch/pub/linux/local/lilo/lilo-<n>.tar.gz
+
+  ***  pfdisk is available for anonymous FTP from
+     ftp://sunsite.unc.edu/pub/Linux/utils/disk-management/pfdisk.tar.Z or
+     ftp://ftp.funet.fi/pub/Linux/tools/pfdisk.tar.Z
+     PBOOT can be found in
+     ftp://ftp.funet.fi/pub/Linux/tools/pboot.zip
+
+
+Choosing the "right" boot concept
+-----------------------------------
+
+Although LILO can be installed in many different ways, the choice is 
+usually limited by the present setup and therefore, typically only a small 
+number of configurations which fit naturally into an existing system 
+remains. The following sections describe various possible cases. See also 
+section "BIOS restrictions".
+
+The configuration file /etc/lilo.conf for the examples could look like 
+this:
+
+boot = /dev/hda2
+compact
+image = /vmlinuz
+image = /vmlinuz.old
+other = /dev/hda1
+  table = /dev/hda
+  label = msdos
+
+It installs a Linux kernel image (/vmlinuz), an alternate Linux kernel 
+image (/vmlinuz.old) and a chain loader to boot MS-DOS from /dev/hda1. The 
+option COMPACT on the second line instructs the map installer to optimize 
+loading.
+
+In all examples, the names of the IDE-type hard disk devices (/dev/hda...) 
+are used. Everything applies to other disk types (e.g. SCSI disks; 
+/dev/sda...) too.
+
+
+BIOS restrictions
+- - - - - - - - -
+
+Nowadays, an increasing number of systems is equipped with comparably large 
+disks or even with multiple disks. At the time the disk interface of the 
+standard PC BIOS has been designed (about 16 years ago), such 
+configurations were apparently considered to be too unlikely to be worth 
+supporting.
+
+The most common BIOS restrictions that affect LILO are the limitation to 
+two hard disks and the inability to access more than 1024 cylinders per 
+disk. LILO can detect both conditions, but in order to work around the 
+underlying problems, manual intervention is necessary.
+
+The drive limit does not exist in every BIOS. Some modern motherboards and 
+disk controllers are equipped with a BIOS that supports more (typically 
+four) disk drives. When attempting to access the third, fourth, etc. drive, 
+LILO prints a warning message but continues. Unless the BIOS really 
+supports more than two drives, the system will _not_ be able to boot in 
+that case.*
+
+  *  However, if only "unimportant" parts of the system are located on the 
+    "high" drives, some functionality may be available.
+
+The cylinder limit is a very common problem with IDE disks. There, the 
+number of cylinders may already exceed 1024 if the drive has a capacity of 
+more than 504 MB. Many SCSI driver BIOSes present the disk geometry in a 
+way that makes the limit occur near 1 GB. Modern disk controllers may even 
+push the limit up to about 8 GB. All cylinders beyond the 1024th are 
+inaccessible for the BIOS. LILO detects this problem and aborts the 
+installation (unless the LINEAR option is used, see section "Global 
+options").
+
+Note that large partitions that only partially extend into the "forbidden 
+zone" are still in jeopardy even if they appear to work at first, because 
+the file system does not know about the restrictions and may allocate disk 
+space from the area beyond the 1024th cylinder when installing new kernels. 
+LILO therefore prints a warning message but continues as long as no 
+imminent danger exists.
+
+There are four approaches of how such problems can be solved: 
+
+  - use of a different partition which is on an accessible disk and which 
+    does not exceed the 1024 cylinder limit. If there is only a DOS 
+    partition which fulfills all the criteria, that partition can be used 
+    to store the relevant files. (See section "/boot on a DOS partition".) 
+  - rearranging partitions and disks. This is typically a destructive 
+    operation, so extra care should be taken to make good backups. 
+  - if the system is running DOS or Windows 95, LOADLIN can be used instead 
+    of LILO. 
+  - if all else fails, installation of a more capable BIOS, a different 
+    controller or a different disk configuration. 
+
+LILO depends on the BIOS to load the following items: 
+
+  - /boot/boot.b 
+  - /boot/map (created when running /sbin/lilo) 
+  - all kernels 
+  - the boot sectors of all other operating systems it boots 
+  - the startup message, if one has been defined 
+
+Normally, this implies that the Linux root file system should be in the 
+"safe" area. However, it is already sufficient to put all kernels into 
+/boot and to either mount a "good" partition on /boot or to let /boot be a 
+symbolic link pointing to or into such a partition.
+
+See also /usr/src/linux/Documentation/ide.txt (or 
+/usr/src/linux/drivers/block/README.ide in older kernels) for a detailed 
+description of problems with large disks.
+
+
+One disk, Linux on a primary partition
+- - - - - - - - - - - - - - - - - - -
+
+If at least one primary partition of the first hard disk is used as a Linux 
+file system (/, /usr, etc. but _not_ as a swap partition), the LILO boot 
+sector should be stored on that partition and it should be booted by the 
+original master boot record or by a program like BOOTACTV.
+
+            +--------------------------+
+            | MBR            /dev/hda  |
+            | +------------------------|
+            | | MS-DOS       /dev/hda1 |
+            | |------------------------|
+        --> | | Linux /      /dev/hda2 |
+            +--------------------------+
+
+In this example, the BOOT variable could be omitted, because the boot 
+sector is on the root partition.
+
+
+One disk, Linux on a logical partition
+- - - - - - - - - - - - - - - - - - -
+
+If no primary partition is available for Linux, but at least one logical 
+partition of an extended partition on the first hard disk contains a Linux 
+file system, the LILO boot sector should be stored in the partition sector 
+of the extended partition and it should be booted by the original master 
+boot record or by a program like BOOTACTV.
+
+            +--------------------------+
+            | MBR            /dev/hda  |
+            | +------------------------|
+            | | MS-DOS       /dev/hda1 |
+            | |------------------------|
+        --> | | Extended     /dev/hda2 |
+            | | +----------------------|
+            | | | Linux      /dev/hda5 |
+            | | |----------------------|
+            | | | ...        /dev/hda6 |
+            +--------------------------+
+
+Because many disk partitioning programs refuse to make an extended 
+partition (in our example /dev/hda2) active, you might have to use 
+activate, which comes with the LILO distribution.
+
+OS/2 BootManager should be able to boot LILO boot sectors from logical 
+partitions. The installation on the extended partition itself is not 
+necessary in this case.
+
+
+Two disks, Linux (at least partially) on the first disk
+- - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+This case is equivalent to the configurations where only one disk is in the 
+system. The Linux boot sector resides on the first hard disk and the second 
+disk is used later in the boot process.
+
+Only the location of the boot sector matters - everything else 
+(/boot/boot.b, /boot/map, the root file system, a swap partition, other 
+Linux file systems, etc.) can be located anywhere on the second disk, 
+provided that the constraints described in section "BIOS restrictions" are 
+met.
+
+
+Two disks, Linux on second disk, first disk has an extended partition
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+If there is no Linux partition on the first disk, but there is an extended 
+partition, the LILO boot sector can be stored in the partition sector of 
+the extended partition and it should be booted by the original master boot 
+record or by a program like BOOTACTV.
+
+                 FIRST DISK                     SECOND DISK
+        +--------------------------+    +--------------------------+
+        | MBR            /dev/hda  |    | MBR            /dev/hdb  |
+        | +------------------------|    | +------------------------|
+        | | MS-DOS       /dev/hda1 |    | | Linux        /dev/hdb1 |
+        | |------------------------|    | |------------------------|
+    --> | | Extended     /dev/hda2 |    | | ...          /dev/hdb2 |
+        | | +----------------------|    | |                        |
+        | | | ...        /dev/hda5 |    | |                        |
+        | | |----------------------|    | |                        |
+        | | | ...        /dev/hda6 |    | |                        |
+        +--------------------------+    +--------------------------+
+
+The program activate, that accompanies LILO, may have to be used to set the 
+active marker on an extended partition, because MS-DOS' FDISK and some 
+older version of Linux fdisk refuse to do that. (Which is generally a good 
+idea.)
+
+
+Two disks, Linux on second disk, first disk has no extended partition
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+If there is neither a Linux partition nor an extended partition on the 
+first disk, then there's only one place left, where a LILO boot sector 
+could be stored: the master boot record.
+
+In this configuration, LILO is responsible for booting all other operating 
+systems too.
+
+                 FIRST DISK                     SECOND DISK
+        +--------------------------+    +--------------------------+
+    --> | MBR            /dev/hda  |    | MBR            /dev/hdb  |
+        | +------------------------|    | +------------------------|
+        | | MS-DOS       /dev/hda1 |    | | Linux        /dev/hdb1 |
+        | |------------------------|    | |------------------------|
+        | | ...          /dev/hda2 |    | | ...          /dev/hdb2 |
+        +--------------------------+    +--------------------------+
+
+You should back up your old MBR before installing LILO and verify that LILO 
+is able to boot your other operating system(s) before relying on this 
+approach.
+
+The line boot = /dev/hda2 in /etc/lilo.conf would have to be changed to 
+boot = /dev/hda in this example.
+
+
+More than two disks
+- - - - - - - - - -
+
+On systems with more than two disks, typically only the first two can be 
+accessed. The configuration choices are therefore the same as with two 
+disks.
+
+When attempting to access one of the extra disks, LILO displays a warning 
+message ( Warning: BIOS drive 0x<number> may not be accessible ) but does 
+not abort. This is done in order to allow the lucky few whose BIOS (or 
+controller-BIOS) does support more than two drives to make use of this 
+feature. By all others, this warning should be considered a fatal error.
+
+Note that the two disks restriction is only imposed by the BIOS. Linux 
+normally has no problems using all disks once it is booted.
+
+
+/boot on a DOS partition
+- - - - - - - - - - - -
+
+Recent kernels support all the functions LILO needs to map files also on 
+MS-DOS (or UMSDOS) file systems. Since DOS partitions tend to occupy 
+exactly the places where BIOS restrictions (see section "BIOS 
+restrictions") are invisible, they're an ideal location for /boot if the 
+native Linux file systems can't be used because of BIOS problems.
+
+In order to accomplish this, the DOS partition is mounted read-write, a 
+directory (e.g. /dos/linux) is created, all files from /boot are moved to 
+that directory, /boot is replaced by a symbolic link to it, the kernels are 
+also moved to the new directory, their new location is recorded in 
+/etc/lilo.conf, and finally /sbin/lilo is run.
+
+From then on, new kernels must always be copied into that directory on the 
+DOS partition before running /sbin/lilo, e.g. when recompiling a kernel, 
+the standard procedure changes from
+
+# make zlilo
+
+to
+
+# make zImage
+# mv /dos/linux/vmlinuz /dos/linux/vmlinuz.old
+# mv arch/i386/boot/zImage /dos/linux/vmlinuz
+# /sbin/lilo
+
+_WARNING:_ De-fragmenting such a DOS partition is likely to make Linux or 
+even the whole system unbootable. Therefore, the DOS partition should 
+either not be de-fragmented, or a Linux boot disk should be prepared (and 
+tested) to bring up Linux and to run /sbin/lilo after the 
+de-fragmentation.*
+
+  *  Setting the "system" attribute from DOS on the critical files (e.g. 
+    everything in C:\LINUX) may help to protect them from being rearranged. 
+    However, the boot floppy should still be ready, just in case.
+
+
+The boot prompt
+===============
+
+Immediately after it's loaded, LILO checks whether one of the following is 
+happening:
+
+  - any of the [Shift], [Control] or [Alt] keys is pressed. 
+  - [CapsLock] or [ScrollLock] is set. 
+
+If this is the case, LILO displays the boot: prompt and waits for the name 
+of a boot image (i.e. Linux kernel or other operating system). Otherwise, 
+it boots the default boot image* or - if a delay has been specified - waits 
+for one of the listed activities until that amount of time has passed.
+
+  *  The default boot image is either the first boot image, the image 
+    specified with the DEFAULT variable, or the image that has been 
+    selected at the boot prompt.
+
+At the boot prompt, the name of the image to boot can be entered. Typing 
+errors can be corrected with [BackSpace], [Delete], [Ctrl U] and [Ctrl X]. 
+A list of known images can be obtained by pressing [?] or [Tab].
+
+If [Enter] is pressed and no file name has been entered, the default image 
+is booted.
+
+
+Boot command-line options
+-------------------------
+
+LILO is also able to pass command-line options to the kernel. Command-line 
+options are words that follow the name of the boot image and that are 
+separated by spaces.
+
+Example:
+
+boot: linux single root=200
+
+This document only gives an overview of boot options. Please consult Paul 
+Gortmaker's BootPrompt-HOWTO for a more complete and more up to date list. 
+You can get it from 
+ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/BootPrompt-HOWTO.gz or from one 
+of the many mirror sites.
+
+
+Standard options
+- - - - - - - -
+
+Recent kernels recognize a large number of options, among them are  debug ,  
+no387 ,  no-hlt ,  ramdisk=<size> ,  reserve=<base>,<size>,... ,  
+root=<device> ,  ro , and  rw . All current init programs also recognize 
+the option  single . The options  lock  and  vga  are processed by the boot 
+loader itself. Boot command-line options are always case-sensitive.
+
+ single  boots the system in single-user mode. This bypasses most system 
+initialization procedures and directly starts a root shell on the console. 
+Multi-user mode can typically be entered by exiting the single-user shell 
+or by rebooting.
+
+ root=<device>  changes the root device. This overrides settings that may 
+have been made in the boot image and on the LILO command line. <device> is 
+either the hexadecimal device number or the full path name of the device, 
+e.g. /dev/hda3.*
+
+  *  The device names are hard-coded in the kernel. Therefore, only the 
+    "standard" names are supported and some less common devices may not be 
+    recognized. In those cases, only numbers can be used.
+
+ reserve=<base>,<size>,...  reserves IO port regions. This can be used to 
+prevent device drivers from auto-probing addresses where other devices are 
+located, which get confused by the probing.
+
+ ro  instructs the kernel to mount the root file system read-only.  rw  
+mounts it read-write. If neither  ro  nor  rw  is specified, the setting 
+from the boot image is used.
+
+ no-hlt  avoids executing a  HLT  instructions whenever the system is idle.  
+HLT  normally significantly reduces power consumption and therefore also 
+heat dissipation of the CPU, but may not work properly with some clone 
+CPUs.  no387  disables using the hardware FPU even if one is present.
+
+ debug  enables more verbose console logging.
+
+Recent kernels also accept the options  init=<name>  and  noinitrd .  init  
+specifies the name of the init program to execute. Therefore, if single 
+mode cannot be entered because init is mis-configured, one may still be 
+able to reach a shell using init=/bin/sh.  noinitrd  disables automatic 
+loading of the initial RAM disk. Instead, its content is then available on 
+/dev/initrd.
+
+ vga=<mode>  alters the VGA mode set at startup. The values  normal ,  
+extended ,  ask  or a decimal number are recognized. (See also "Booting 
+kernel images from a file".)
+
+ kbd=<code>,...  preloads a sequence of keystrokes in the BIOS keyboard 
+buffer. The keystrokes have to be entered as 16 bit hexadecimal numbers, 
+with the upper byte containing the scan code and the lower byte containing 
+the ASCII code. Note that most programs only use the ASCII code, so the 
+scan code can frequently be omitted. Scan code tables can be found in many 
+books on PC hardware. Note that scan codes depend on the keyboard layout.
+
+Finally,  lock  stores the current command-line as the default 
+command-line, so that LILO boots the same image with the same options 
+(including  lock ) when invoked the next time.
+
+
+Device-specific options
+- - - - - - - - - - - -
+
+There is also a plethora of options to specify certain characteristics 
+(e.g. IO and memory addresses) of devices. Some common ones are  ether ,  
+floppy ,  hd ,  bmouse , and  sound . The usage of these options is  
+<option>=<number>,... . Please consult the corresponding FAQs and HOWTOs 
+for details. For an overview of all available options, consult the file 
+init/main.c in the kernel source tree.
+
+
+Other options
+- - - - - - -
+
+Options of the type  <variable>=<value>  which are neither standard options 
+nor device-specific options, cause the respective variables to be set in 
+the environment passed to init. The case of the variable name is preserved, 
+i.e. it isn't automatically converted to upper case.
+
+Note that environment variables passed to init are typically available in 
+system initialization scripts (e.g. /etc/rc.local), but they're not visible 
+from ordinary login sessions, because the login program removes them from 
+the user's environment.
+
+
+Repeating options
+- - - - - - - - -
+
+The effect of repeating boot command-line options depends on the options.* 
+There are three possible behaviours:
+
+  *  Options are frequently repeated when a string defined with APPEND or 
+    LITERAL is prepended to the parameters typed in by the user. Also, LILO 
+    implicitly prepends the options  ramdisk ,  ro ,  root , or  rw  when 
+    RAMDISK, READ-ONLY, READ-WRITE, or ROOT, respectively, are set in the 
+    configuration file. ( lock  and  vga  are handled by a different 
+    internal mechanism.)
+
+Options that only enable or disable a certain functionality can be repeated 
+any number of times.  debug ,  lock ,  no-hlt , and  no387  fall into this 
+category.
+
+Other options change a global setting whenever they appear, so only the 
+value or presence of the last option matters. The antagonists  ro  and  rw  
+are such options. Also,  ramdisk ,  root , and  vga  work this way. 
+Example:  ro rw  would mount the root file system read-write.
+
+Finally, when  reserve  and many device-specific options are repeated, each 
+occurrence has its own meaning, e.g.  hd=... hd=...  would configure two 
+hard disks, and  reserve=0x300,8 reserve=0x5f0,16  would reserve the ranges 
+0x300 to 0x307 and 0x5f0 to 0x5ff (which is equivalent to writing  
+reserve=0x300,8,0x5f0,16 ).
+
+
+Implicit options
+- - - - - - - -
+
+LILO always passes the string  BOOT_IMAGE=<name>  to the kernel, where 
+<name> is the name by which the kernel is identified (e.g. the label). This 
+variable can be used in /etc/rc to select a different behaviour, depending 
+on the kernel.
+
+When booting automatically, i.e. without human intervention, the word  auto  
+is also passed on the command line. This can be used by init to suppress 
+interactive prompts in the boot phase.
+
+
+Boot image selection
+--------------------
+
+The details of selecting the boot image are somewhat complicated. The 
+following tables illustrate them. First, if neither PROMPT is set nor a 
+shift key is being pressed:
+
+Externally  Command   |  Auto-  Booted image             
+ provided   line in   |  matic                           
+cmd. line* map file** | boot***                          
+---------------------------------------------------------
+    No         No     |   Yes   Default image            
+   Yes         -      |   Yes   Specified by external    
+                      |         command line             
+    No        Yes     |   Yes   Specified by command line
+                      |         in map file              
+       
+
+  *  Externally provided command lines could be used to add front-ends to 
+    LILO. They would pass the respective command string to LILO, which 
+    would then interpret it like keyboard input. This feature is currently 
+    not used.
+
+  **  This command line is set by invoking the map installer with the  -R  
+    option, by using the boot command-line option  lock , or if a fallback 
+    command line is set (with FALLBACK).
+
+  ***  I.e. the keyword  auto  is added.
+
+If PROMPT is not set and a shift key is being pressed:
+
+ Input  Empty  Extern. Cmd.l. | Auto- Booted image         
+timeout cmd.l. cmd.l.  in map | matic                      
+                        file  | boot                       
+-----------------------------------------------------------
+  No      No      -      -    |  No   Specified by the user
+  No     Yes      -      -    |  No   Default image        
+  Yes    n/a      -      -    |  Yes  Default image        
+
+Finally, if the configuration variable PROMPT is set:
+
+ Input  Empty  Extern. Cmd.l. | Auto- Booted image         
+timeout cmd.l. cmd.l.  in map | matic                      
+                        file  | boot                       
+-----------------------------------------------------------
+  No      No     No      No   |  No   Specified by the user
+  No     Yes     No      No   |  No   Default image        
+  Yes    n/a     No      No   |  Yes  Default image        
+  n/a    n/a     Yes     -    |  Yes  Specified by external
+                              |       command line         
+  n/a    n/a     No     Yes   |  Yes  Specified by command 
+                              |       line in map file     
+
+Note that LILO pauses for the amount of time specified in DELAY when at the 
+end of a default command line. The automatic boot can then be interrupted 
+by pressing a modifier key ([Shift], [Ctrl], etc.).
+
+The default image is the first image in the map file or the image specified 
+with the DEFAULT variable. However, after an unsuccessful boot attempt, the 
+respective image becomes the default image.
+
+
+Map installer
+=============
+
+The map installer program /sbin/lilo updates the boot sector and creates 
+the map file. If the map installer detects an error, it terminates 
+immediately and does not touch the boot sector and the map file.
+
+Whenever the map installer updates a boot sector, the original boot sector 
+is copied to /boot/boot.<number>, where <number> is the hexadecimal device 
+number. If such a file already exists, no backup copy is made. Similarly, a 
+file  /boot/part.<number>  is created if LILO modifies the partition table. 
+(See "General per-image options".)
+
+
+Command-line options
+--------------------
+
+The LILO map installer can be invoked in the following ways:
+
+
+Show current installation
+- - - - - - - - - - - - -
+
+The currently mapped files are listed. With  -v , also many parameters are 
+shown.
+
+  /sbin/lilo [ -C <config_file> ] -q [ -m <map_file> ] [ -v ... ]  
+
+   -C <config_file>    
+     Specifies the configuration file that is used by the map installer 
+    (see section "Configuration"). If  -C  is omitted, /etc/lilo.conf is 
+    used. 
+   -m <map_file>    
+     Specifies an alternate map file. See also sections "Options 
+    corresponding to configuration variables" and "Global options". 
+   -q    
+     Lists the currently mapped files. 
+   -v ...    
+     Increase verbosity. See also sections "Options corresponding to 
+    configuration variables" and "Global options". 
+
+
+Create or update map
+- - - - - - - - - -
+
+A new map is created for the images described in the configuration file 
+/etc/lilo.conf and they are registered in the boot sector.
+
+  /sbin/lilo [ -C <config_file> ] [ -b <boot_device> ] [ -c ] [ -l ] [ -i 
+    <boot_sector> ] [ -f <disk_tab> ] [ -m <map_file> ] [ -d <delay> ] [ -v 
+    ... ] [ -t ] [ -s <save_file> | -S <save_file> ] [ -P fix | -P ignore ] 
+    [ -r <root_dir> ]  
+
+   -b <boot_device>    
+     Specifies the boot device. See also sections "Options corresponding to 
+    configuration variables" and "Global options". 
+   -c    
+     Enables map compaction. See also sections "Options corresponding to 
+    configuration variables" and "Global options". 
+   -C <config_file>    
+     Specifies an alternate configuration file. See also section "Show 
+    current installation". 
+   -d <delay>    
+     Sets the delay before LILO boots the default image. Note that the 
+    delay is specified in _tenths_ of a second. See also sections "Options 
+    corresponding to configuration variables" and "Global options". 
+   -D <name>    
+     Specifies the default image. See also sections "Options corresponding 
+    to configuration variables" and "Global options". 
+   -f <disk_tab>    
+     Specifies a disk parameter table file. See also sections "Options 
+    corresponding to configuration variables" and "Global options". 
+   -i <boot_sector>    
+     Specifies an alternate boot file. See also sections "Options 
+    corresponding to configuration variables" and "Global options". 
+   -L    
+     Enables lba32 sector addresses. See also sections "Options 
+    corresponding to configuration variables" and "Global options". 
+   -l    
+     Enables linear sector addresses. See also sections "Options 
+    corresponding to configuration variables" and "Global options". 
+   -m <map_file>    
+     Specifies an alternate map file. See also sections "Options 
+    corresponding to configuration variables" and "Global options". 
+   -P <mode>    
+     Specifies how invalid partition table entries should be handled. See 
+    also sections "Options corresponding to configuration variables" and 
+    "Global options". 
+   -r <root_directory>    
+     Chroots to the specified directory before doing anything else. This is 
+    useful when running the map installer while the normal root file system 
+    is mounted somewhere else, e.g. when recovering from an installation 
+    failure with a recovery disk. The  -r  option is implied if the 
+    environment variable  ROOT  is set.* The current directory is changed 
+    to the new root directory, so using relative paths may not work. 
+   -s <save_file>    
+     Specifies an alternate boot sector save file. See also sections 
+    "Options corresponding to configuration variables" and "Global 
+    options". 
+   -S <save_file>    
+     Like  -s , but overwrites old save files. 
+   -t    
+     Test only. This performs the entire installation procedure except 
+    replacing the map file, writing the modified boot sector and fixing 
+    partition tables. This can be used in conjunction with the  -v  option 
+    to verify that LILO will use sane values. 
+   -v ...    
+     Increase verbosity. See also sections "Options corresponding to 
+    configuration variables" and "Global options". 
+
+  *  E.g. if your root partition is mounted on /mnt, you can update the map 
+    by simply running  ROOT=/mnt /mnt/sbin/lilo 
+
+
+Change default command line
+- - - - - - - - - - - - - -
+
+Changes LILO's default command line. See also section "Boot image 
+selection".
+
+  /sbin/lilo [ -C <config_file> ] [ -m <map_file> ] -R [ <word> ... ]  
+
+   -C <config_file>    
+     Specifies an alternate configuration file. See also section "Show 
+    current installation". 
+   -m <map_file>    
+     Specifies an alternate map file. See also sections "Options 
+    corresponding to configuration variables" and "Global options". 
+   -R <word ...>    
+     Stores the specified words in the map file. The boot loader uses those 
+    words as the default command line when booting the next time. That 
+    command line is removed from the map file by the boot loader by 
+    overwriting the sector immediately after reading it. The first word has 
+    to be the name of a boot image. If  -R  is not followed by any words, 
+    the current default command line in the map file is erased.* If the 
+    command line isn't valid, the map installer issues an error message and 
+    returns a non-zero exit code. 
+
+  *   -R  is typically used in reboot scripts, e.g.
+     #!/bin/sh
+     cd /
+     /sbin/lilo -R "$*" && reboot
+
+
+Kernel name translation
+- - - - - - - - - - - -
+
+Determines the path of the kernel.
+
+  /sbin/lilo [ -C <config_file> ] -I <name> [ <options> ]  
+
+   -C <config_file>    
+     Specifies an alternate configuration file. See also section "Show 
+    current installation". 
+   -I <name> [ <options> ]    
+     Translates the specified label name to the path of the corresponding 
+    kernel image and prints that path on standard output. This can be used 
+    to synchronize files that depend on the kernel (e.g. the ps database). 
+    The image name can be obtained from the environment variable  
+    BOOT_IMAGE . An error message is issued and a non-zero exit code is 
+    returned if no matching label name can be found. The existence of the 
+    image file is verified if the option character  v  is added. 
+
+
+De-installation
+- - - - - - - -
+
+Restores the boot sector that was used before the installation of LILO. 
+Note that this option only works properly if LILO's directories (e.g. 
+/boot) have not been touched since the first installation. See also section 
+"LILO de-installation".
+
+  /sbin/lilo [ -C <config_file> ] [ -s <save_file> ] -u | -U [ 
+    <boot_device> ]  
+
+   -C <config_file>    
+     Specifies an alternate configuration file. See also section "Show 
+    current installation". 
+   -s <save_file>    
+     Specifies an alternate boot sector save file. See also sections 
+    "Options corresponding to configuration variables" and "Global 
+    options". 
+   -u [ <device_name> ]    
+     Restores the backup copy of the specified boot sector. If no device is 
+    specified, the value of the boot variable is used. If this one is also 
+    unavailable, LILO uses the current root device. The name of the backup 
+    copy is derived from the device name. The -s option or the backup 
+    variable can be used to override this. LILO validates the backup copy 
+    by checking a time stamp. 
+   -U [ <device_name> ]    
+     Like -u, but does not check the time stamp. 
+
+
+Print version number
+- - - - - - - - - -
+
+  /sbin/lilo -V  
+
+   -V    
+     Print the version number and exit. 
+
+
+Options corresponding to configuration variables
+- - - - - - - - - - - - - - - - - - - - - - - -
+
+There are also many command-line options that correspond to configuration 
+variables. See section "Global options" for a description.
+
+Command-line option | Configuration variable    
+------------------------------------------------
+-b <boot_device>    | boot=<boot_device>        
+-c                  | compact                   
+-d <tsecs>          | delay=<tsecs>             
+-D <name>           | default=<name>            
+-i <boot_sector>    | install=<boot_sector>     
+-L                  | lba32                     
+-l                  | linear                    
+-m <map_file>       | map=<map_file>            
+-P fix              | fix-table                 
+-P ignore           | ignore-table              
+-s <backup_file>    | backup=<backup_file>      
+-S <backup_file>    | force-backup=<backup_file>
+-v ...              | verbose=<level>           
+
+
+Configuration
+-------------
+
+The configuration information is stored in the file /etc/lilo.conf and 
+consists of variable assignments.
+
+
+Syntax
+- - -
+
+The following syntax rules apply:
+
+  - flag variables consist of a single word and are followed by whitespace 
+    or the end of the file. 
+  - string variables consist of the variable name, optional whitespace, an 
+    equal sign, optional whitespace, the value and required whitespace, or 
+    the end of the file. 
+  - a non-empty sequence of blanks, tabs, newlines and comments counts as 
+    whitespace. 
+  - variable names are case-insensitive. Values are usually case-sensitive, 
+    but there are a few exceptions. (See below.) 
+  - tabs and newlines are special characters and may not be part of a 
+    variable name or a value. The use of other control characters and 
+    non-ASCII characters is discouraged. 
+  - blanks and equal signs may only be part of a variable name or a value 
+    if they are escaped by a backslash or if the value is embedded in 
+    double quotes. An equal sign may not be the only character in a name or 
+    value. 
+  - an escaped tab is converted to an escaped blank. An escaped newline is 
+    removed from the input stream. An escaped backslash (i.e. two 
+    backslashes) is converted to a backslash. Inside quoted strings, only 
+    double quotes, backslashes, dollar signs, and newlines can be escaped. 
+  - quoted strings can be continued over several lines by ending each 
+    incomplete line with a backslash. A single space is inserted in the 
+    string for the line end and all spaces or tabs that follow immediately 
+    on the next line. 
+  - environment variables can be used by specifying them in the form 
+    $<name> or ${<name>}. Dollar signs can be escaped. 
+  - comments begin with a number sign and end with the next newline. All 
+    characters (including backslashes) until the newline are ignored. 
+
+Example:
+
+boot = $FD
+install = menu 
+map = $MNT/map
+compact
+read-only
+append = "nfsroot=/home/linux-install/root \
+  nfsaddrs=128.178.156.28:128.178.156.24::255.255.255.0:lrcinst"
+image = $MNT/zImage
+
+
+Global options
+- - - - - - -
+
+/etc/lilo.conf begins with a possibly empty global options section. Many 
+global options can also be set from the command line, but storing permanent 
+options in the configuration file is more convenient.
+
+The following global options are recognized:
+
+  BACKUP=<backup_file>  Copy the original boot sector to <backup_file> 
+    (which may also be a device, e.g. /dev/null) instead of 
+    /boot/boot.<number> 
+  BOOT=<boot_device>  Sets the name of the device (e.g. a hard disk 
+    partition) that contains the boot sector. If BOOT is omitted, the boot 
+    sector is read from (and possibly written to) the device that is 
+    currently mounted as root. 
+  CHANGE-RULES  Defines partition type numbers. See section "Partition type 
+    change rules" for details. 
+  COMPACT  Tries to merge read requests for adjacent sectors into a single 
+    read request. This drastically reduces load time and keeps the map 
+    smaller. Using COMPACT is especially recommended when booting from a 
+    floppy disk. COMPACT may conflict with LINEAR or LBA32, see section 
+    "Other problems". 
+  DEFAULT=<name>  Uses the specified image as the default boot image. If 
+    DEFAULT is omitted, the image appearing first in the configuration file 
+    is used. 
+  DELAY=<tsecs>  Specifies the number of _tenths_ of a second LILO should 
+    wait before booting the first image. This is useful on systems that 
+    immediately boot from the hard disk after enabling the keyboard. LILO 
+    doesn't wait if DELAY is omitted or if DELAY is set to zero. 
+  DISK=<device_name>  Defines non-standard parameters for the specified 
+    disk. See section "Disk geometry" for details. 
+  FIX-TABLE  Allows LILO to adjust 3D addresses in partition tables. Each 
+    partition entry contains a 3D (sector/head/cylinder) and a linear 
+    32-bit address of the first and the last sector of the partition. If a 
+    partition is not track-aligned and if certain other operating systems 
+    (e.g. PC/MS-DOS or OS/2) are using the same disk, they may change the 
+    3D address. LILO can store its boot sector only on partitions where 
+    both address types correspond. LILO re-adjusts incorrect 3D start 
+    addresses if FIX-TABLE is set.
+
+     _WARNING:_ This does not guarantee that other operating systems may 
+    not attempt to reset the address later. It is also possible that this 
+    change has other, unexpected side-effects. The correct fix is to 
+    re-partition the drive with a program that does align partitions to 
+    tracks. Also, with some disks (e.g. some large EIDE disks with address 
+    translation enabled), under some circumstances, it may even be 
+    unavoidable to have conflicting partition table entries. 
+  FORCE-BACKUP=<backup_file>  Like BACKUP, but overwrite an old backup copy 
+    if it exists. BACKUP=<backup_file> is ignored if FORCE-BACKUP appears 
+    in the same configuration file. 
+  IGNORE-TABLE  Tells LILO to ignore corrupt partition tables and to put 
+    the boot sector even on partitions that appear to be unsuitable for 
+    that. 
+  INSTALL=<boot_sector>  Install the specified file as the new boot sector. 
+    If INSTALL is omitted, install=text is used as the default. 
+  KEYTABLE=<table_file>  Re-map the keyboard as specified in this file. See 
+    section "Keyboard translation" for details. 
+  LBA32  Generate 32-bit Logical Block Addresses instead of 
+    sector/head/cylinder addresses. If the BIOS supports packet addressing, 
+    then packet calls will be used to access the disk. This allows booting 
+    from any partition on disks with more than 1024 cylinders. If the BIOS 
+    does not support packet addressing, then LBA32 addresses are translated 
+    to C:H:S, just as for LINEAR. All floppy disk references are retained 
+    in C:H:S form. Use of LBA32 is recommended on all post-1998 systems. 
+    LBA32 may conflict with COMPACT, see section "Other problems". 
+  LINEAR  Generate linear sector addresses instead of sector/head/cylinder 
+    addresses. Linear addresses are translated at run time and do not 
+    depend on disk geometry. Note that boot disks may not be portable if 
+    LINEAR is used, because the BIOS service to determine the disk geometry 
+    does not work reliably for floppy disks. When using LINEAR with large 
+    disks, /sbin/lilo may generate references to inaccessible disk areas 
+    (see section "BIOS restrictions"), because 3D sector addresses are not 
+    known before boot time. LINEAR may conflict with COMPACT, see section 
+    "Other problems". 
+  MAP=<map_file>  Specifies the location of the map file. If MAP is 
+    omitted, a file /boot/map is used. 
+  MESSAGE=<message_file>  Specifies a file containing a message that is 
+    displayed before the boot prompt. No message is displayed while waiting 
+    for a modifier key ([Shift], etc.) after printing "LILO ". In the 
+    message, the  FF  character ([Ctrl L]) clears the local screen. The 
+    size of the message file is limited to 65535 bytes. The map file has to 
+    be rebuilt if the message file is changed or moved. 
+  NOWARN  Disables warnings about possible future dangers. 
+  PROMPT  Forces entering the boot prompt without expecting any prior 
+    key-presses. Unattended reboots are impossible if PROMPT is set and 
+    TIMEOUT isn't. 
+  SERIAL=<parameters>  Enables control from a serial line. The specified 
+    serial port is initialized and LILO is accepting input from it and from 
+    the PC's keyboard. Sending a break on the serial line corresponds to 
+    pressing a shift key on the console in order to get LILO's attention. 
+    All boot images should be password-protected if the serial access is 
+    less secure than access to the console, e.g. if the line is connected 
+    to a modem. The parameter string has the following syntax:
+      <port>,<bps><parity><bits> 
+     The components <bps>, <parity> and <bits> can be omitted. If a 
+    component is omitted, all following components have to be omitted too. 
+    Additionally, the comma has to be omitted if only the port number is 
+    specified. 
+
+      <port>  the number of the serial port, zero-based. 0 corresponds to 
+        COM1 alias /dev/ttyS0, etc. All four ports can be used (if 
+        present). 
+      <bps>  the baud rate of the serial port. The following baud rates are 
+        supported: 110, 300, 1200, 2400, 4800, 9600, 19200, and 38400 bps. 
+        Default is 2400 bps. 
+      <parity>  the parity used on the serial line. LILO ignores input 
+        parity and strips the 8th bit. The following (upper or lower case) 
+        characters are used to describe the parity:  n  for no parity,  e  
+        for even parity and  o  for odd parity. 
+      <bits>  the number of bits in a character. Only 7 and 8 bits are 
+        supported. Default is 8 if parity is "none", 7 if parity is "even" 
+        or "odd". 
+
+    If SERIAL is set, the value of DELAY is automatically raised to 20.
+
+     Example: serial=0,2400n8 initializes COM1 with the default parameters. 
+  TIMEOUT=<tsecs>  Sets a timeout (in tenths of a second) for keyboard 
+    input. If no key is pressed for the specified time, the first image is 
+    automatically booted. Similarly, password input is aborted if the user 
+    is idle for too long. The default timeout is infinite. 
+  VERBOSE=<level>  Turns on lots of progress reporting. Higher numbers give 
+    more verbose output. If  -v  is additionally specified on the command 
+    line, <level> is increased accordingly. The following verbosity levels 
+    exist: 
+
+      <0  only warnings and errors are shown 
+      0  prints one line for each added or skipped image 
+      1  mentions names of important files and devices and why they are 
+        accessed. Also displays informational messages for exceptional but 
+        harmless conditions and prints the version number. 
+      2  displays statistics and processing of temporary files and devices 
+      3  displays disk geometry information and partition table change 
+        rules 
+      4  lists sector mappings as they are written into the map file (i.e. 
+        after compaction, in a format suitable to pass it to the BIOS) 
+      5  lists the mapping of each sector (i.e. before compaction, raw) 
+
+    When using the  -q  option, the levels have a slightly different 
+    meaning: 
+
+      0  displays only image names 
+      1  also displays all global and per-image settings 
+      2  displays the address of the first map sector 
+
+Additionally, the kernel configuration parameters APPEND, INITRD, RAMDISK, 
+READ-ONLY, READ-WRITE, ROOT and VGA, and the general per-image options 
+FALLBACK, LOCK, OPTIONAL, PASSWORD, RESTRICTED, and SINGLE-KEY can be set 
+in the global options section. They are used as defaults if they aren't 
+specified in the configuration sections of the respective images. See below 
+for a description.
+
+The plethora of options may be intimidating at first, but in "normal" 
+configurations, hardly any options but BOOT, COMPACT, DELAY, ROOT, and VGA 
+are used.
+
+
+General per-image options
+- - - - - - - - - - - - -
+
+The following options can be specified for all images, independent of their 
+type: 
+
+  ALIAS=<name>  Specifies a second name for the current entry. 
+  FALLBACK=<command_line>  Specifies a string that is stored as the default 
+    command line if the current image is booted. This is useful when 
+    experimenting with kernels which may crash before allowing interaction 
+    with the system. If using the FALLBACK option, the next reboot (e.g. 
+    triggered by a manual reset or by a watchdog timer) will load a 
+    different (supposedly stable) kernel. The command line by the fallback 
+    mechanism is cleared by removing or changing the default command line 
+    with the  -R  option, see "Change default command line". 
+  LABEL=<name>  By default, LILO uses the main file name (without its path) 
+    of each image specification to identify that image. A different name 
+    can be used by setting the variable LABEL. 
+  LOCK  Enables automatic recording of boot command lines as the defaults 
+    for the following boots. This way, LILO "locks" on a choice until it is 
+    manually overridden. 
+  OPTIONAL  Omit this image if its main file is not available at map 
+    creation time. This is useful to specify test kernels that are not 
+    always present. 
+  PASSWORD=<password>  Ask the user for a password when trying to load this 
+    image. Because the configuration file contains unencrypted passwords 
+    when using this option, it should only be readable for the super-user. 
+    Passwords are always case-sensitive. 
+  RESTRICTED  Relaxes the password protection by requiring a password only 
+    if parameters are specified on the command line (e.g. single). 
+    RESTRICTED can only be used together with PASSWORD. 
+  SINGLE-KEY  Enables booting the image by hitting a single key, without 
+    the need to press [Enter] afterwards. SINGLE-KEY requires that either 
+    the image's label or its alias (or both) is a single character. 
+    Furthermore, no other image label or alias may start with that 
+    character, e.g. an entry specifying a label  linux  and an alias  l  is 
+    not allowed with SINGLE-KEY. Note that you can't specify command-line 
+    parameters for an entry for which only SINGLE-KEYed names exist. 
+
+All general per-image options, with the exception of LABEL and ALIAS, can 
+also be set in the global options section as defaults for all images.
+
+Example:
+
+password = Geheim
+single-key
+image = /vmlinuz
+  label = linux
+  alias = 1
+  restricted
+other = /dev/hda1
+  label = dos
+  alias = 2
+
+
+Per-image options for kernels
+- - - - - - - - - - - - - - -
+
+Each (kernel or non-kernel) image description begins with a special 
+variable (see section "Booting kernel images from a device") which is 
+followed by optional variables. The following variables can be used for all 
+image descriptions that describe a Linux kernel:
+
+  APPEND=<string>  Appends the options specified in <string> to the 
+    parameter line passed to the kernel. This is typically used to specify 
+    parameters of hardware that can't be entirely auto-detected, e.g.
+     append = "aha152x=0x140,11" 
+  INITRD=<name>  Specifies the file that will be loaded at boot time as the 
+    initial RAM disk. 
+  LITERAL=<string>  like APPEND, but removes all other options (e.g. 
+    setting of the root device). Because vital options can be removed 
+    unintentionally with LITERAL, this option cannot be set in the global 
+    options section. 
+  RAMDISK=<size>  Specifies the size of the optional RAM disk. A value of 
+    zero indicates that no RAM disk should be created. If this variable is 
+    omitted, the RAM disk size configured into the boot image is used. 
+  READ-ONLY  Specifies that the root file system should be mounted 
+    read-only. Typically, the system startup procedure re-mounts the root 
+    file system read-write later (e.g. after fsck'ing it). 
+  READ-WRITE  specifies that the root file system should be mounted 
+    read-write. 
+  ROOT=<root_device>  Specifies the device that should be mounted as root. 
+    If the special name CURRENT is used, the root device is set to the 
+    device on which the root file system is currently mounted. If the root 
+    has been changed with  -r , the respective device is used. If the 
+    variable ROOT is omitted, the root device setting contained in the 
+    kernel image is used. It can be changed with the rdev program. 
+  VGA=<mode>   Specifies the VGA text mode that should be selected when 
+    booting. The following values are recognized (case is ignored): 
+
+      NORMAL  select normal 80x25 text mode. 
+      EXTENDED  select 80x50 text mode. The word EXTENDED can be 
+        abbreviated to EXT. 
+      ASK  stop and ask for user input (at boot time). 
+      <number>  use the corresponding text mode. A list of available modes 
+        can be obtained by booting with  vga=ask  and pressing [Enter]. 
+
+    If this variable is omitted, the VGA mode setting contained in the 
+    kernel image is used. rdev supports manipulation of the VGA text mode 
+    setting in the kernel image. 
+
+All kernel per-image options but LITERAL can also be set in the global 
+options section as defaults for all kernels.
+
+If one of RAMDISK, READ-ONLY, READ-WRITE, ROOT, or VGA is omitted in the 
+configuration file and the corresponding value in the kernel image is 
+changed, LILO or the kernel will use the new value.
+
+It is perfectly valid to use different settings for the same image, because 
+LILO stores them in the image descriptors and not in the images themselves.
+
+Example:
+
+image = /vmlinuz
+  label = lin-hd
+  root = /dev/hda2
+image = /vmlinuz
+  label = lin-fd
+  root = /dev/fd0
+
+
+Boot image types
+----------------
+
+LILO can boot the following types of images: 
+
+  - kernel images from a file. 
+  - kernel images from a block device. (E.g. a floppy disk.) 
+  - the boot sector of some other operating system. 
+
+The image type is determined by the name of the initial variable of the 
+configuration section.
+
+The image files can reside on any media that is accessible at boot time. 
+There's no need to put them on the root device, although this certainly 
+doesn't hurt.
+
+
+Booting kernel images from a file
+- - - - - - - - - - - - - - - - -
+
+The image is specified as follows: IMAGE=<name>
+
+Example:
+
+image = /linux
+
+See sections "Per-image options for kernels" and "Boot image types" for the 
+options that can be added in a kernel image section.
+
+
+Booting kernel images from a device
+- - - - - - - - - - - - - - - - - -
+
+The range of sectors that should be mapped has to be specified. Either a 
+range ( <start>-<end> ) or a start and a distance ( <start>+<number> ) have 
+to be specified. <start> and <end> are zero-based. If only the start is 
+specified, only that sector is mapped.
+
+The image is specified as follows: IMAGE=<device_name> Additionally, the 
+RANGE variable must be set.
+
+Example:
+
+image = /dev/fd0
+  range = 1+512
+
+All kernel options can also be used when booting the kernel from a device.
+
+
+Booting a foreign operating system
+- - - - - - - - - - - - - - - - -
+
+LILO can even boot other operating systems, i.e. MS-DOS. To boot an other 
+operating system, the name of a loader program, the device or file that 
+contains the boot sector and the device that contains the partition table 
+have to be specified.
+
+The boot sector is merged with the partition table and stored in the map 
+file.
+
+Currently, the loaders chain.b and os2_d.b exist. chain.b simply starts the 
+specified boot sector.* os2_d.b it a variant of chain.b that can boot OS/2 
+from the second hard disk. The MAP-DRIVE option has to be used with os2_d.b 
+to actually swap the drives.
+
+  *  The boot sector is loaded by LILO's secondary boot loader before 
+    control is passed to the code of chain.b.
+
+The image is specified as follows: OTHER=<device_name> or OTHER=<file_name>
+
+In addition to the options listen in section "Per-image options for 
+kernels", the following variables are recognized: 
+
+  CHANGE  Change the partition table according to the rules specified in 
+    this CHANGE section. This option is intended for booting systems which 
+    find their partitions by examining the partition table. See section 
+    "Partition type changes" for details. 
+  LOADER=<chain_loader>  Specifies the chain loader that should be used. If 
+    it is omitted, /boot/chain.b is used. 
+  MAP-DRIVE=<bios_device_code>  Instructs chain.b to installs a resident 
+    driver that re-maps the floppy or hard disk drives. This way, one can 
+    boot any operating system from a hard disk different from the first 
+    one, as long as that operating system uses _only_ the BIOS to access 
+    that hard disk.* This is known to work for PC/MS-DOS.
+
+      *  So you should be very suspicious if the operating system requires 
+        any specific configuration or even drivers to use the disk it is 
+        booted from. Since there is a general trend to use optimized 
+        drivers to fully exploit the hardware capabilities (e.g. 
+        non-blocking disk access), booting systems from the second disk may 
+        become increasingly difficult.
+
+     MAP-DRIVE is followed by the variable TO=<bios_device_code> which 
+    specifies the drive that should effectively be accessed instead of the 
+    original one. The list of mappings is only searched until the first 
+    match is found. It is therefore possible to "swap" drives, see the 
+    second example below. 
+  TABLE=<device>  Specifies the device that contains the partition table. 
+    LILO does not pass partition information to the booted operating system 
+    if this variable is omitted. (Some operating systems have other means 
+    to determine from which partition they have been booted. E.g. MS-DOS 
+    usually stores the geometry of the boot disk or partition in its boot 
+    sector.) Note that /sbin/lilo must be re-run if a partition table 
+    mapped referenced with TABLE is modified. 
+  UNSAFE  Do not access the boot sector at map creation time. This disables 
+    some sanity checks, including a partition table check. If the boot 
+    sector is on a fixed-format floppy disk device, using UNSAFE avoids the 
+    need to put a readable disk into the drive when running the map 
+    installer. UNSAFE and TABLE are mutually incompatible. 
+
+None of these options can be set in the global options section.
+
+Examples:
+
+other = /dev/hda2
+  label = dos
+  table = /dev/hda
+
+other = /dev/hdb2
+  label = os2
+  loader = /boot/os2_d.b
+  map-drive = 0x80
+    to = 0x81
+  map-drive = 0x81
+    to = 0x80
+
+
+Disk geometry
+-------------
+
+For floppies and most hard disks, LILO can obtain the disk geometry 
+information from the kernel. Unfortunately, there are some exotic disks or 
+adapters which may either not supply this information or which may even 
+return incorrect information.
+
+If no geometry information is available, LILO reports either the error
+  geo_query_dev HDIO_GETGEO (dev 0x<number>) 
+ or
+  Device 0x<number>: Got bad geometry <sec>/<hd>/<cyl> 
+
+If incorrect information is returned, booting may fail in several ways, 
+typically with a partial "LILO" banner message. In this document, that is 
+called a "geometry mismatch".
+
+The next step should be to attempt setting the LBA32 or LINEAR 
+configuration variable or the  -L  or  -l  command-line option. If this 
+doesn't help, the entire disk geometry has to be specified explicitly. Note 
+that LINEAR doesn't always work with floppy disks.
+
+Another common use of disk sections is if an (E)IDE and a SCSI drive are 
+used in the same system and the BIOS is configured to use the SCSI drive as 
+the first drive. (Normally, the (E)IDE drive would be the first drive and 
+the SCSI drive would be the second one.) Since LILO doesn't know how the 
+BIOS is configured, it needs to be told explicitly about this arrangement. 
+(See the second example below.)
+
+
+Obtaining the geometry
+- - - - - - - - - - -
+
+The disk geometry parameters can be obtained by booting MS-DOS and running 
+the program DPARAM.COM with the hexadecimal BIOS code of the drive as its 
+argument, e.g. dparam 0x80 for the first hard disk. It displays the number 
+of sectors per track, the number of heads per cylinder and the number of 
+cylinders. All three numbers are one-based.
+
+Alternatively, the geometry may also be determined by reading the 
+information presented by the "setup" section of the ROM-BIOS or by using 
+certain disk utilities under operating systems accessing the disk through 
+the BIOS.
+
+
+Specifying the geometry
+- - - - - - - - - - - -
+
+Disk geometry parameters are specified in the options section of the 
+configuration file. Each disk parameter section begins with 
+DISK=<disk_device>, similar to the way how boot images are specified. It is 
+suggested to group disk parameter sections together, preferably at the 
+beginning or the end of the options section.
+
+For each disk, the following variables can be specified: 
+
+  BIOS=<bios_device_code>  Is the number the BIOS uses to refer to that 
+    device. Normally, it's  0x80  for the first hard disk and  0x81  for 
+    the second hard disk. Note that hexadecimal numbers have to begin with 
+    "0x". If BIOS is omitted, LILO tries to "guess" that number. 
+  SECTORS=<sectors>  and 
+  HEADS=<heads>  specify the number of sectors per track and the number of 
+    heads, i.e. the number of tracks per cylinder. Both parameters have to 
+    be either specified together or they have to be entirely omitted. If 
+    omitted, LILO tries to obtain that geometry information from the 
+    kernel. 
+  CYLINDERS=<cylinders>  Specifies the number of cylinders. This value is 
+    only used for sanity checks. If CYLINDERS is omitted, LILO uses the 
+    information obtained from the kernel if geometry information had to be 
+    requested in order to determine some other parameter. Otherwise,* it 
+    just assumes the number of cylinders to be 1024, which is the cylinder 
+    limit imposed by the BIOS. 
+  INACCESSIBLE  Marks the device as inaccessible (for the BIOS). This is 
+    useful if some disks on the system can't be read by the BIOS, although 
+    LILO "thinks" they can. If one accidentally tries to use files located 
+    on such disks for booting, the map installer won't notice and the 
+    system becomes unbootable. The most likely use of INACCESSIBLE is to 
+    prevent repetition after experiencing such a situation once. No other 
+    variables may be specified if a device is configured as INACCESSIBLE. 
+
+  *  I.e. if the BIOS device code, the number of sectors, the number of 
+    heads and the partition start are specified. Note that the number of 
+    cylinders may appear to vary if CYLINDERS is absent and only some of 
+    the partition starts are specified.
+
+Additionally, partition subsections can be added with 
+PARTITION=<partition_device>. Each partition section can contain only one 
+variable: 
+
+  START=<partition_offset>  Specifies the zero-based number of the start 
+    sector of that partition. The whole disk always has a partition offset 
+    of zero. The partition offset is only necessary when using devices for 
+    which the kernel does not provide that information, e.g. CD-ROMs. 
+
+Examples:
+
+disk = /dev/sda
+  bios = 0x80
+  sectors = 32
+  heads = 64
+  cylinders = 632
+  partition = /dev/sda1
+    start = 2048
+  partition = /dev/sda2
+    start = 204800
+  partition = /dev/sda3
+    start = 500000
+  partition = /dev/sda4
+    start = 900000
+
+disk = /dev/sda
+  bios = 0x80
+disk = /dev/hda
+  bios = 0x81
+
+
+Partition table manipulation
+----------------------------
+
+Some non-Linux operating systems obtain information about their partitions 
+(e.g. their equivalent of the root file system) from the partition table. 
+If more than one such operating system is installed on a PC, they may have 
+conflicting interpretations of the content of the partition table. Those 
+problems can be avoided by changing the partition table, depending on which 
+operating system is being booted.
+
+Partition table changes are specified in a CHANGE section in the 
+configuration file section describing the foreign operating system. Note 
+that CHANGE sections are only accepted if the build-time option  
+REWRITE_TABLE  is set.
+
+The CHANGE section contains subsections for each partition whose table 
+entry needs to be modified. Partitions are specified with 
+PARTITION=<device_name>
+
+Changes are applied in the sequence in which they appear in the 
+configuration file. Configurations containing changes that are redundant 
+either by repeating a previous change or by changing its result further are 
+invalid and refused by the map installer.
+
+Internally, all changes are expressed as rules which specify the location 
+(disk and offset in the partition table), the value this location must 
+contain before the change, and the value that has to be stored. As a safety 
+measure, the rule is ignored if the previous value is found to be 
+different.
+
+
+Partition activation
+- - - - - - - - - -
+
+This option is intended for booting systems which determine their boot 
+partition by examining the active flag in the partition table. The flag is 
+enabled with ACTIVATE and disabled with DEACTIVATE. Note that only the 
+current partition is affected. LILO does not automatically change the 
+active flags of other partitions and it also allows more than one partition 
+to be active at the same time.
+
+Example:
+
+other = /dev/sda4
+  label = sco
+  change
+    partition = /dev/sda4
+      activate
+    partition = /dev/sda3
+      deactivate
+
+
+Partition type change rules
+- - - - - - - - - - - - - -
+
+Partition type changes are normally a transition between two possible 
+values, e.g. a typical convention is to set the lowest bit in the upper 
+nibble of the partition type (i.e. 0x10) in order to "hide", and to clear 
+it to "unhide" a partition. LILO performs these changes based on a set of 
+rules. Each rule defines the name of a partition type, its normal value, 
+and the value when hidden. Those rules are defined in the options section 
+of the configuration file. The section defining them begins with 
+CHANGE-RULES.
+
+The following options and variables can appear in the section: 
+
+  RESET  Removes all previously defined rules. This is needed if a user 
+    doesn't wish to use the pre-defined rules (see below). 
+  TYPE=<name>  Adds a rule for the type with the specified name. Type names 
+    are case-insensitive. The values are defined with NORMAL=<byte> and 
+    HIDDEN=<byte>. Values can be specified as decimal or as hexadecimal 
+    numbers with a leading  0x . If only one of the values is present, the 
+    other value is assumed to be the same number, but with the most 
+    significant bit inverted. 
+
+LILO pre-defines rules for the three partition types of DOS partitions. The 
+following example removes the pre-defined rules and creates them again:
+
+change-rules
+  reset
+  type = DOS12
+    normal = 0x01
+    hidden = 0x11
+  type = DOS16_small
+    normal = 4 # hidden is 0x14
+  type = DOS16_big
+    hidden = 0x16
+
+
+Partition type changes
+- - - - - - - - - - -
+
+Partition type changes are specified in the partition section as 
+SET=<name>_<state>, where <name> is the name of the partition type, and 
+<state> is its state, i.e. NORMAL or HIDDEN.
+
+Example:
+
+other = /dev/sda3
+  label = dos
+  change
+    partition = /dev/sda2
+      set = dos16_big_normal
+    partition = /dev/sda3
+      activate
+      set = DOS16_big_normal
+
+Only one SET variable is allowed per partition section. In the rare event 
+that more than one SET variable is needed, further partition sections can 
+be used.
+
+
+Keyboard translation
+--------------------
+
+The PC keyboard emits so-called scan codes, which are basically key 
+numbers. The BIOS then translates those scan codes to the character codes 
+of the characters printed on the key-caps. By default, the BIOS normally 
+assumes that the keyboard has a US layout. Once an operating system is 
+loaded, this operating system can use a different mapping.
+
+At boot time, LILO only has access to the basic services provided by the 
+BIOS and therefore receives the character codes for an US keyboard. It 
+provides a simple mechanism to re-map the character codes to what is 
+appropriate for the actual layout.*
+
+  *  The current mechanism isn't perfect, because it sits on top of the 
+    scan code to character code translation performed by the BIOS. This 
+    means that key combinations that don't produce any useful character on 
+    the US keyboard will be ignored by LILO. The advantage of this approach 
+    is its simplicity.
+
+
+Compiling keyboard translation tables
+- - - - - - - - - - - - - - - - - - -
+
+LILO obtains layout information from the keyboard translation tables Linux 
+uses for the text console. They are usually stored in 
+/usr/lib/kbd/keytables. LILO comes with a program keytab-lilo.pl that reads 
+those tables and generates a table suitable for use by the map installer. 
+keytab-lilo.pl invokes the program loadkeys to print the tables in a format 
+that is easy to parse.*
+
+  *  On some systems, only root can execute loadkeys. It is then necessary 
+    to run keytab-lilo.pl as root too.
+
+keytab-lilo.pl is used as follows:
+
+  keytab-lilo.pl [ -p <old_code>=<new_code> ] ... 
+    [<path>]<default_layout>[.<extension>] ]
+     [<path>]<kbd_layout>[.<extension>] ]  
+
+   -p <old_code>=<new_code>    
+     Specifies corrections ("patches") to the mapping obtained from the 
+    translation table files. E.g. if pressing the upper case "A" should 
+    yield an at sign, -p 65=64 would be used. The  -p  option can be 
+    repeated any number of times. The codes can also be given as 
+    hexadecimal or as octal numbers if they are prefixed with 0x or 0, 
+    respectively. 
+  <path>  The directory in which the file resides. The default path is 
+    /usr/lib/kbd/keytables. 
+  <extension>  Usually the trailing .map, which is automatically added if 
+    the file name doesn't contain dots. 
+  <default_layout>  Is the layout which specifies the translation by the 
+    BIOS. If none is specified, us is assumed. 
+  <kbd_layout>  Is the actual layout of the keyboard. 
+
+keytab-lilo.pl writes the resulting translation table as a binary string to 
+standard output. Such tables can be stored anywhere with any name, but the 
+suggested naming convention is /boot/<kbd>.ktl ("Keyboard Table for Lilo"), 
+where <kbd> is the name of the keyboard layout.
+
+Example:
+
+keytab-lilo.pl de >/boot/de.ktl
+
+
+Using keyboard translation tables
+- - - - - - - - - - - - - - - - -
+
+The keyboard translation table file is specified with the global 
+configuration option  keytable=<table_file> . The complete name of the file 
+has to be given.
+
+Example:
+
+keytable = /boot/de.klt
+
+
+Installation and updates
+========================
+
+
+Installation
+------------
+
+This section describes the installation of LILO. See section "LILO 
+de-installation" for how to uninstall LILO.
+
+
+Compatibility
+- - - - - - -
+
+The kernel header files have to be in /usr/include/linux and the kernel 
+usually has to be configured by running  make config  before LILO can be 
+compiled.
+
+/bin/sh has to be a real Bourne shell. bash is sufficiently compatible, but 
+some ksh clones may cause problems.
+
+A file named INCOMPAT is included in the distribution. It describes 
+incompatibilities to older versions of LILO and may also contain further 
+compatibility notes.
+
+
+Quick installation
+- - - - - - - - -
+
+If you want to install LILO on your hard disk and if you don't want to use 
+all its features, you can use the quick installation script. Read QuickInst 
+for details.
+
+QuickInst can only be used for first-time installations or to entirely 
+replace an existing installation, _not_ to update or modify an existing 
+installation of LILO. Be sure you've extracted LILO into a directory that 
+doesn't contain any files of other LILO installations.
+
+
+Files
+- - -
+
+Some of the files contained in lilo-21.tar.gz:
+
+  lilo/README   
+     This documentation in plain ASCII format. Some sections containing 
+    complex tables are only included in the LaTeX version in doc/user.tex 
+  lilo/INCOMPAT   
+     List of incompatibilities to previous versions of LILO. 
+  lilo/CHANGES   
+     Change history. 
+  lilo/VERSION   
+     The version number of the respective release. 
+  lilo/QuickInst   
+     Quick installation script. 
+  lilo/lilo-<version>.lsm   
+     The LSM ("Linux Software Map") entry of the respective LILO release. 
+  lilo/Makefile   
+     Makefile to generate everything else. 
+  lilo/*.c, lilo/*.h   
+     LILO map installer C source and common header files. 
+  lilo/*.S   
+     LILO boot loader assembler source. 
+  lilo/activate.c   
+     C source of a simple boot partition setter. 
+  lilo/dparam.s   
+     Assembler source of a disk parameter dumper. 
+  lilo/mkdist   
+     Shell script used to create the current LILO distribution. 
+  lilo/keytab-lilo.pl   
+     Perl script to generate keyboard translation tables. 
+  lilo/doc/README   
+     Description of how to generate the documentation. 
+  lilo/doc/Makefile   
+     Makefile used to convert the LaTeX source into either DVI output or 
+    the plain ASCII README file. 
+  lilo/doc/user.tex   
+     LaTeX source of LILO's user's guide (this document). 
+  lilo/doc/tech.tex   
+     LaTeX source of LILO's technical overview. 
+  lilo/doc/*.fig   
+     Various xfig pictures used in the technical overview. 
+  lilo/doc/fullpage.sty   
+     Style file to save a few square miles of forest. 
+  lilo/doc/rlatex   
+     Shell script that invokes LaTeX repeatedly until all references have 
+    settled. 
+  lilo/doc/t2a.pl   
+     Perl script to convert the LaTeX source of the user's guide to plain 
+    ASCII. 
+
+Files created after  make  in lilo/ (among others):
+
+  lilo/boot.b   
+     Combined boot sector.  make install  puts this file into /boot 
+  lilo/chain.b   
+     Generic chain loader.  make install  puts this file into /boot 
+  lilo/os2_d.b   
+     Chain loader to load OS/2 from the second hard disk.  make install  
+    puts this file into /boot 
+  lilo/lilo   
+     LILO (map) installer.  make install  puts this file into /sbin 
+  lilo/activate   
+     Simple boot partition setter. 
+  lilo/dparam.com   
+     MS-DOS executable of the disk parameter dumper. 
+
+
+Normal first-time installation
+- - - - - - - - - - - - - - -
+
+First, you have to install the LILO files:
+
+  - extract all files from lilo-<version>.tar.gz in a new directory.* 
+  - configure the Makefile (see section "Build-time configuration") 
+  - run  make  to compile and assemble all parts. 
+  - run  make install  to copy all LILO files to the directories where 
+    they're installed. /sbin should now contain the file lilo, /usr/sbin 
+    should contain keytab-lilo.pl, and /boot should contain boot.b, 
+    chain.b, and os2_d.b. 
+
+  *  E.g. /usr/src/lilo
+
+If you want to use LILO on a non-standard disk, you might have to determine 
+the parameters of your disk(s) and specify them in the configuration file. 
+See section "Disk geometry" for details. If you're using such a 
+non-standard system, the next step is to test LILO with the boot sector on 
+a floppy disk:
+
+  - insert a blank (but low-level formatted) floppy disk into /dev/fd0. 
+  - run  echo image=<kernel_image>  |
+      /sbin/lilo -C - -b /dev/fd0 -v -v -v 
+     If you've already installed LILO on your system, you might not want to 
+    overwrite your old map file. Use the  -m  option to specify an 
+    alternate map file name. 
+  - reboot. LILO should now load its boot loaders from the floppy disk and 
+    then continue loading the kernel from the hard disk. 
+
+Now, you have to decide, which boot concept you want to use. Let's assume 
+you have a Linux partition on /dev/hda2 and you want to install your LILO 
+boot sector there. The DOS-MBR loads the LILO boot sector.
+
+  - get a working boot disk, e.g. an install or recovery disk. Verify that 
+    you can boot with this setup and that you can mount your Linux 
+    partition(s) with it. 
+  - if the boot sector you want to overwrite with LILO is of any value 
+    (e.g. it's the MBR or if it contains a boot loader you might want to 
+    use if you encounter problems with LILO), you should mount your boot 
+    disk and make a backup copy of your boot sector to a file on that 
+    floppy, e.g. dd if=/dev/hda of=/fd/boot_sector bs=512 count=1 
+  - create the configuration file /etc/lilo.conf, e.g.
+     <global settings>
+     <image specification>
+       <per-image options>
+     ...
+     Be sure to use absolute paths for all files. Relative paths may cause 
+    unexpected behaviour when using the  -r  option. 
+  - now, you can check what LILO would do if you were about to install it 
+    on your hard disk:
+     /sbin/lilo -v -v -v -t 
+  - if you need some additional boot utility (i.e. BOOTACTV), you should 
+    install that now 
+  - run /sbin/lilo to install LILO on your hard disk 
+  - if you have to change the active partition, use fdisk or activate to do 
+    that 
+  - reboot 
+
+
+Build-time configuration
+- - - - - - - - - - - -
+
+Certain build-time parameters can be configured. They can either be edited 
+in the top-level Makefile or they can be stored in a file 
+/etc/lilo.defines. Settings in the Makefile are ignored if that file 
+exists.
+
+The following items can be configured: 
+
+   BEEP   Enables beeping after displaying "LILO". This is useful on 
+    machines which don't beep at the right time when booting and when 
+    working over a serial console. This option is disabled by default. 
+   IGNORECASE   Makes image name matching case-insensitive, i.e. "linux" 
+    and "Linux" are identical. This option is enabled by default. Note that 
+    password matching is always case-sensitive. 
+   LARGE_EDBA   Loads LILO at a lower address in order to leave more space 
+    for the EBDA (Extended BIOS Data Area). This is necessary on some 
+    recent MP systems. Note that enabling  LARGE_EDBA  reduces the maximum 
+    size of "small" images (e.g. "Image" or "zImage"). 
+   NO1STDIAG   Do not generate diagnostics on read errors in the first 
+    stage boot loader. This avoids possibly irritating error codes if the 
+    disk controller has transient read problems. This option is disabled by 
+    default. 
+   NODRAIN   The boot loader empties the keyboard buffer when starting, 
+    because it may contain garbage on some systems. Draining the keyboard 
+    buffer can be disabled by setting the  NODRAIN  option.  NODRAIN  is 
+    disabled by default. 
+   NOINSTDEF   If the option INSTALL is omitted, don't install a new boot 
+    sector, but try to modify the old boot sector instead. This option is 
+    disabled by default. 
+   ONE_SHOT   Disables the command-line timeout (configuration variable 
+    TIMEOUT) if any key is pressed. This way, very short timeouts can be 
+    used if PROMPT is set.  ONE_SHOT  is disabled by default. 
+   READONLY   Disallows overwriting the default command line sector of the 
+    map file. This way, command lines set with  -R  stay in effect until 
+    they are explicitly removed.  READONLY  also disables LOCK, FALLBACK, 
+    and everything enabled by  REWRITE_TABLE . This option is disabled by 
+    default. 
+   REWRITE_TABLE   Enables rewriting the partition table at boot time. This 
+    may be necessary to boot certain operating systems who expect the 
+    active flag to be set on their partition or who need changes in 
+    partition types. See also section "Partition table manipulation". This 
+    option is _dangerous_ and it is disabled by default. 
+   USE_TMPDIR   Use the directory indicated in the  TMPDIR  environment 
+    variable when creating temporary device files. If  TMPDIR  is not set 
+    or if LILO is compiled without  USE_TMPDIR , temporary device files are 
+    created in /tmp.* This option is disabled by default. 
+   VARSETUP   Enables the use of variable-size setup segments. This option 
+    is enabled by default and is only provided to fall back to fixed-size 
+    setup segments in the unlikely case of problems when using prehistoric 
+    kernels. 
+   XL_SECS=<sectors>   Enable support for extra large (non-standard) floppy 
+    disks. The number of sectors is set in the BIOS disk parameter table to 
+    the specified value. Note that this hack may yield incorrect behaviour 
+    on some systems. This option is disabled by default. 
+
+  *  Note that, while honoring  TMPDIR  is the "right" thing to do, the 
+    fact that LILO has to create temporary device files at all may indicate 
+    that the operating environment is not completely set up, so  TMPDIR  
+    may point to an invalid location.
+
+/etc/lilo.defines should be used if one wishes to make permanent 
+configuration changes. The usual installation procedures don't touch that 
+file. Example:
+
+-DIGNORECASE -DONE_SHOT
+
+After changing the build-time configuration, LILO has to be recompiled with 
+the following commands:
+
+make distclean
+make
+
+
+Floppy disk installation
+- - - - - - - - - - - -
+
+In some cases*, it may be desirable to install LILO on a floppy disk in a 
+way that it can boot a kernel without accessing the hard disk.
+
+  *  E.g. if no hard disk is accessible through the BIOS.
+
+The basic procedure is quite straightforward (see also section "BIOS 
+restrictions"): 
+
+  - a file system has to be created on the file system 
+  - the kernel and boot.b have to be copied to the floppy disk 
+  - /sbin/lilo has to be run to create the map file 
+
+This can be as easy as
+
+/sbin/mke2fs /dev/fd0
+[ -d /fd ] || mkdir /fd
+mount /dev/fd0 /fd
+cp /boot/boot.b /fd
+cp /zImage /fd
+echo image=/fd/zImage label=linux |
+  /sbin/lilo -C - -b /dev/fd0 -i /fd/boot.b -c -m /fd/map
+umount /fd
+
+The command line of /sbin/lilo is a little tricky.  -C -  takes the 
+configuration from standard input (naturally, one could also write the 
+configuration into a file),  -b /dev/fd0  specifies that the boot sector is 
+written to the floppy disk,  -i /fd/boot.b  takes the first and second 
+stage loaders from the floppy,  -c  speeds up the load process, and  -m 
+/fd/map  puts the map file on the floppy too.
+
+
+Updates
+-------
+
+LILO is affected by updates of kernels, the whole system and (trivially) of 
+LILO itself. Typically, only /sbin/lilo has to be run after any of those 
+updates and everything will be well again (at least as far as LILO is 
+concerned).
+
+
+LILO update
+- - - - - -
+
+Before updating to a new version of LILO, you should read at least the file 
+INCOMPAT which describes incompatibilities with previous releases.
+
+After that, the initial steps are the same as for a first time 
+installation: extract all files, configure the Makefile, run  make  to 
+build the executables and run  make install  to install the files.
+
+The old versions of boot.b, chain.b, etc. are automatically renamed to 
+boot.old, chain.old, etc. This is done to ensure that you can boot even if 
+the installation procedure does not finish. boot.old, chain.old, etc. can 
+be deleted after the map file is rebuilt.
+
+Because the locations of boot.b, chain.b, etc. have changed and because the 
+map file format may be different too, you have to update the boot sector 
+and the map file. Run /sbin/lilo to do this.
+
+
+Kernel update
+- - - - - - -
+
+Whenever any of the kernel files that are accessed by LILO is moved or 
+overwritten, the map has to be re-built.* Run /sbin/lilo to do this.
+
+  *  It is advisable to keep a second, stable, kernel image that can be 
+    booted if you forget to update the map after a change to your usual 
+    kernel image.
+
+The kernel has a make target "zlilo" that copies the kernel to /vmlinuz and 
+runs /sbin/lilo.
+
+
+System upgrade
+- - - - - - -
+
+Normally, system upgrades (i.e. installation or removal of packages, 
+possibly replacement of a large part of the installed binaries) do not 
+affect LILO. Of course, if a new kernel is installed in the process, the 
+normal kernel update procedure has to be followed (see section "Kernel 
+update"). Also, if kernels are removed or added, it may be necessary to 
+update the configuration file.
+
+If LILO is updated by this system upgrade, /sbin/lilo should be run before 
+booting the upgraded system. It is generally a good idea not to rely on the 
+upgrade procedure to perform this essential step automatically.
+
+However, system upgrades which involve removal and re-creation of entire 
+partitions (e.g. /, /usr, etc.) are different. First, they should be 
+avoided, because they bear a high risk of losing other critical files, e.g. 
+the /etc/XF86Config you've spent the last week fiddling with. If an upgrade 
+really has to be performed in such a brute-force way, this is equal with 
+total removal of LILO, followed by a new installation. Therefore, the 
+procedures described in the sections "LILO de-installation" and "LILO 
+update" have to be performed. If you've forgotten to make a backup copy of 
+/etc/lilo.conf before the destructive upgrade, you might also have to go 
+through section "Normal first-time installation" again.
+
+
+LILO de-installation
+--------------------
+
+In order to stop LILO from being invoked when the system boots, its boot 
+sector has to be either removed or disabled. All other files belonging to 
+LILO can be deleted _after_ removing the boot sector, if desired.*
+
+  *  Backup copies of old boot sectors may be needed when removing the boot 
+    sector. They are stored in /boot.
+
+Again, _when removing Linux, LILO must be de-installed before (!) its files 
+(/boot, etc.) are deleted._ This is especially important if LILO is 
+operating as the MBR.
+
+LILO 14 (and newer) can be de-installed with lilo -u. If LILO 14 or newer 
+is currently installed, but the first version of LILO installed was older 
+than 14, lilo -U may work. When using -U, the warning at the end of this 
+section applies.
+
+If LILO's boot sector has been installed on a primary partition and is 
+booted by the "standard" MBR or some partition switcher program, it can be 
+disabled by making a different partition active. MS-DOS' FDISK, Linux fdisk 
+or LILO's activate can do that.
+
+If LILO's boot sector is the master boot record (MBR) of a disk, it has to 
+be replaced with a different MBR, typically MS-DOS' "standard" MBR. When 
+using MS-DOS 5.0 or above, the MS-DOS MBR can be restored with FDISK /MBR. 
+This only alters the boot loader code, not the partition table.
+
+LILO automatically makes backup copies when it overwrites boot sectors. 
+They are named /boot/boot.<nnnn>, with <nnnn> corresponding to the device 
+number, e.g.  0300  is /dev/hda,  0800  is /dev/sda, etc. Those backups can 
+be used to restore the old MBR if no easier method is available. The 
+commands are
+  dd if=/boot/boot.0300 of=/dev/hda bs=446 count=1  or
+  dd if=/boot/boot.0800 of=/dev/sda bs=446 count=1 
+ respectively.
+
+_WARNING:_ Some Linux distributions install boot.<nnnn> files from the 
+system where the distribution was created. Using those files may yield 
+unpredictable results. Therefore, the file creation date should be 
+carefully checked.
+
+
+Installation of other operating systems
+---------------------------------------
+
+Some other operating systems (e.g. MS-DOS 6.0) appear to modify the MBR in 
+their install procedures. It is therefore possible that LILO will stop to 
+work after such an installation and Linux has to be booted from floppy 
+disk. The original state can be restored by either re-running /sbin/lilo 
+(if LILO is installed as the MBR) or by making LILO's partition active (if 
+it's installed on a primary partition).
+
+It is generally a good idea to install LILO after the other operating 
+systems have been installed. E.g. OS/2 is said to cause trouble when 
+attempting to add it to an existing Linux system. (However, booting from 
+floppy and running /sbin/lilo should get around most interferences.)
+
+Typically, the new operating system then has to be added to LILO's 
+configuration (and /sbin/lilo has to be re-run) in order to boot it.
+
+See also section "Other problems" for a list of known problems with some 
+other operating systems.
+
+
+Troubleshooting
+===============
+
+All parts of LILO display some messages that can be used to diagnose 
+problems.
+
+
+Map installer warnings and errors
+---------------------------------
+
+Most messages of the map installer (/sbin/lilo) should be self-explanatory. 
+Some messages that indicate common errors are listed below. They are 
+grouped into fatal errors and warnings (non-fatal errors).
+
+
+Fatal errors
+- - - - - - 
+
+   Boot sector of <device_name> doesn't have a boot signature   
+   Boot sector of <device_name> doesn't have a LILO signature    
+     The sector from which LILO should be uninstalled doesn't appear to be 
+    a LILO boot sector. 
+   Can't put the boot sector on logical partition <number>    
+     An attempt has been made to put LILO's boot sector on the current root 
+    file system partition which is on a logical partition. This usually 
+    doesn't have the desired effect, because common MBRs can only boot 
+    primary partitions. This check can be bypassed by explicitly specifying 
+    the boot partition with the  -b  option or by setting the configuration 
+    variable BOOT. 
+   Checksum error    
+     The descriptor table of the map file has an invalid checksum. Refresh 
+    the map file _immediately_ ! 
+   Device 0x<number>: Configured as inaccessible.    
+     There is a DISK section entry indicating that the device is 
+    inaccessible from the BIOS. You should check carefully that all files 
+    LILO tries to access when booting are on the right device. 
+   Device 0x<number>: Got bad geometry <sec>/<hd>/<cyl>    
+     The device driver for your SCSI controller does not support geometry 
+    detection. You have to specify the geometry explicitly (see section 
+    "Disk geometry"). 
+   Device 0x<number>: Invalid partition table, entry <number>    
+     The 3D and linear addresses of the first sector of the specified 
+    partition don't correspond. This is typically caused by partitioning a 
+    disk with a program that doesn't align partitions to tracks and later 
+    using PC/MS-DOS or OS/2 on that disk. LILO can attempt to correct the 
+    problem, see "General per-image options". 
+   Device 0x<number>: Partition type 0x<number> does not seem suitable for 
+  a LILO boot sector    
+     The location where the LILO boot sector should be placed does not seem 
+    to be suitable for that. (See also also section "Disk organization"). 
+    You should either adjust the partition type to reflect the actual use 
+    or put the boot sector on a different partition. This consistency check 
+    only yields a warning (i.e. LILO continues) if the option IGNORE-TABLE 
+    is set. 
+   <device_name> is not a valid partition device    
+     The specified device is either not a device at all, a whole disk, or a 
+    partition on a different disk than the one in whose section its entry 
+    appears. 
+   <device_name> is not a whole disk device    
+     Only the geometry of whole disks (e.g. /dev/hda, /dev/sdb, etc.) can 
+    be redefined when using DISK sections. 
+   DISKTAB and DISK are mutually exclusive    
+     You cannot use a disktab file and disk geometry definitions in the 
+    configuration file at the same time. Maybe /etc/disktab was 
+    accidentally used, because that's the default for 
+    backward-compatibility. You should delete /etc/disktab after completing 
+    the transition to DISK sections. 
+   Duplicate entry in partition table    
+     A partition table entry appears twice. The partition table has to be 
+    fixed with fdisk. 
+   Duplicate geometry definition for <device_name>    
+     A disk or partition geometry definition entry for the same device 
+    appears twice in the configuration file. Note that you mustn't write a 
+    partition section for the whole disk - its start sector is always the 
+    first sector of the disk. 
+   First sector of <device> doesn't have a valid boot signature    
+     The first sector of the specified device does not appear to be a valid 
+    boot sector. You might have confused the device name.* 
+   geo_comp_addr: Cylinder <number> beyond end of media (<number>)    
+     A file block appears to be located beyond the last cylinder of the 
+    disk. This probably indicates an error in the disk geometry 
+    specification (see section "Disk geometry") or a file system 
+    corruption. 
+   geo_comp_addr: Cylinder number is too big (<number> > 1023)    
+     Blocks of a file are located beyond the 1024th cylinder of a hard 
+    disk. LILO can't access such files, because the BIOS limits cylinder 
+    numbers to the range 0...1023. Try moving the file to a different 
+    place, preferably a partition that is entirely within the first 1024 
+    cylinders of the disk. 
+   Hole found in map file (<location>)    
+     The map installer is confused about the disk organization. Please 
+    report this error. 
+   <item> doesn't have a valid LILO signature    
+     The specified item has been located, but is not part of LILO. 
+   <item> has an invalid stage code (<number>)    
+     The specified item has probably been corrupted. Try re-building LILO. 
+   <item> is version <number>. Expecting version <number>.    
+     The specified entity is either too old or too new. Make sure all parts 
+    of LILO (map installer, boot loaders and chain loaders) are from the 
+    same distribution. ** 
+   Kernel <name> is too big    
+     The kernel image (without the setup code) is bigger than 512 kbytes 
+    (or 448 kbytes, if built with  LARGE_EDBA ). LILO would overwrite 
+    itself when trying to load such a kernel. This limitation only applies 
+    to old kernels which are loaded below 0x10000 (e.g. "Image" or 
+    "zImage"). Try building the kernel with "bzImage". If this is 
+    undesirable for some reason, try removing some unused drivers and 
+    compiling the kernel again. This error may also occur if the kernel 
+    image is damaged or if it contains trailing "junk", e.g. as the result 
+    of copying an entire boot floppy to the hard disk. 
+   LOCK and FALLBACK are mutually exclusive    
+     Since LOCK and FALLBACK both change the default command line, they 
+    can't be reasonably used together. 
+   Map <path> is not a regular file.    
+     This is probably the result of an attempt to omit writing a map file, 
+    e.g. with  -m /dev/null . The  -t  option should be used to accomplish 
+    this. 
+   Must specify SECTORS and HEADS together    
+     It is assumed that disks with a "strange" number of sectors will also 
+    have a "strange" number of heads. Therefore, it's all or nothing. 
+   No geometry variables allowed if INACCESSIBLE    
+     If a device is configured as INACCESSIBLE (see section "Specifying the 
+    geometry"), its DISK section must not contain any geometry variables. 
+   No image <image> is defined    
+     The command line specified either with the  -R  option or with 
+    FALLBACK does not contain the name of a valid image. Note that optional 
+    images which have not been included in the map file are not considered 
+    as valid. 
+   Partition entry not found    
+     The partition from which an other operating system should be booted 
+    isn't listed in the specified partition table. This either means that 
+    an incorrect partition table has been specified or that you're trying 
+    to boot from a logical partition. The latter usually doesn't work. You 
+    can bypass this check by omitting the partition table specification 
+    (e.g. omitting the variable TABLE). 
+   Single-key clash: "<name>" vs. "<name>"    
+     The specified image labels or aliases conflict because one of them is 
+    a single character and has the SINGLE-KEY option set, and the other 
+    name begins with that character. 
+   Sorry, don't know how to handle device <number>    
+     LILO uses files that are located on a device for which there is no 
+    easy way to determine the disk geometry. Such devices have to be 
+    explicitly described, see section "Disk geometry". 
+   This LILO is compiled READONLY and doesn't support ...    
+     If LILO is not allowed to write to the disk at boot time (see section 
+    "Build-time configuration"), options like LOCK and FALLBACK are 
+    unavailable. 
+   This LILO is compiled without REWRITE_TABLE and doesn't support ...    
+     If LILO is not allowed to rewrite partition tables at boot time (see 
+    section "Partition table manipulation"), options like ACTIVATE and SET 
+    (in a CHANGE section) are unavailable. You may also get this error if 
+    LILO is compiled with  READONLY  enabled. 
+   Timestamp in boot sector of <device> differs from date of <file>    
+     The backup copy of the boot sector does not appear to be an ancestor 
+    of the current boot sector. If you are absolutely sure that the boot 
+    sector is indeed correct, you can bypass this check by using  -U  
+    instead of  -u . 
+   Trying to map files from unnamed device 0x<number> (NFS ?)    
+     This is probably the same problem as described below, only with the 
+    root file system residing on NFS. 
+   Trying to map files from your RAM disk. Please check -r option or ROOT 
+  environment variable.    
+     Most likely, you or some installation script is trying to invoke LILO 
+    in a way that some of the files is has to access reside on the RAM 
+    disk. Normally, the  ROOT  environment variable should be set to the 
+    mount point of the effective root device if installing LILO with a 
+    different root directory. See also sections "Create or update map" and 
+    "Normal first-time installation". 
+   VGA mode presetting is not supported by your kernel.    
+     Your kernel sources appear to be very old ('93 ?). LILO may work on 
+    your system if you remove the VGA option. 
+   write <item>: <error_reason>    
+     The disk is probably full or mounted read-only. 
+
+  *  Because different partition programs may display the partitions in a 
+    different order, it is possible that what you think is your first 
+    partition isn't /dev/hda1, etc. A good method to verify the content of 
+    a partition is to try to mount it.
+
+  **  The expected version number may be different from the version number 
+    of the LILO package, because file version numbers are only increased 
+    when the file formats change.
+
+
+Warnings
+- - - -
+
+Messages labeled with "Warning" can be turned off with the NOWARN option.
+
+   FIGETBSZ <file_name>: < error_reason>    
+     The map installer is unable to determine the block size of a file 
+    system. It assumes a block size of two sectors (1kB). 
+   Ignoring entry '<variable_name>'    
+     The command-line option corresponding to the specified variable is 
+    set. Therefore, the configuration file entry is ignored. 
+   Setting DELAY to 20 (2 seconds)    
+     Because accidentally booting the wrong kernel or operating system may 
+    be very inconvenient on systems that are not run from a local display, 
+    the minimum delay is two seconds if the SERIAL variable is set. 
+   (temp) <item>: <error_reason>    
+     Deleting a temporary file has failed for the specified reason. 
+   Warning: BIOS drive 0x<number> may not be accessible    
+     Because most BIOS versions only support two floppies and two hard 
+    disks, files located on additional disks may be inaccessible. This 
+    warning indicates that some kernels or even the whole system may be 
+    unbootable. 
+   Warning: COMPACT may conflict with LINEAR on some systems    
+     Please see section "Other problems" for a description of this problem. 
+   Warning: <config_file> should be owned by root    
+     In order to prevent users from compromising system integrity, the 
+    configuration file should be owned by root and write access for all 
+    other users should be disabled. 
+   Warning: <config_file> should be readable only for root if using 
+  PASSWORD    
+     Users should not be allowed to read the configuration file when using 
+    the PASSWORD option, because then, it contains unencrypted passwords. 
+   Warning: <config_file> should be writable only for root    
+     See " Warning: <config_file> should be owned by root ". 
+   Warning: device 0x<number> exceeds 1024 cylinder limit    
+     A disk or partition exceeds the 1024 cylinder limit imposed by the 
+    BIOS. This may result in a fatal error in the current installation run 
+    or in later installation runs. See " geo_comp_addr: Cylinder number is 
+    too big (<number> > 1023) " for details. 
+   Warning: <device> is not on the first disk    
+     The specified partition is probably not on the first disk. LILO's boot 
+    sector can only be booted from the first disk unless some special boot 
+    manager is used. 
+   WARNING: The system is unbootable !    
+     One of the last installation steps has failed. This warning is 
+    typically followed by a fatal error describing the problem. 
+
+
+Boot loader messages
+--------------------
+
+The boot loader generates three types of messages: progress and error 
+messages while it is loading, messages indicating disk access errors, and 
+error messages in response to invalid command-line input. Since messages of 
+the latter type are usually self-explanatory, only the two other categories 
+are explained.
+
+
+LILO start message
+- - - - - - - - -
+
+When LILO loads itself, it displays the word "LILO". Each letter is printed 
+before or after performing some specific action. If LILO fails at some 
+point, the letters printed so far can be used to identify the problem. This 
+is described in more detail in the technical overview.
+
+Note that some hex digits may be inserted after the first "L" if a 
+transient disk problem occurs. Unless LILO stops at that point, generating 
+an endless stream of error codes, such hex digits do not indicate a severe 
+problem.
+
+  (<nothing>)  No part of LILO has been loaded. LILO either isn't installed 
+    or the partition on which its boot sector is located isn't active. 
+   L <error> ...   The first stage boot loader has been loaded and started, 
+    but it can't load the second stage boot loader. The two-digit error 
+    codes indicate the type of problem. (See also section "Disk error 
+    codes".) This condition usually indicates a media failure or a geometry 
+    mismatch (e.g. bad disk parameters, see section "Disk geometry"). 
+   LI   The first stage boot loader was able to load the second stage boot 
+    loader, but has failed to execute it. This can either be caused by a 
+    geometry mismatch or by moving /boot/boot.b without running the map 
+    installer. 
+   LIL   The second stage boot loader has been started, but it can't load 
+    the descriptor table from the map file. This is typically caused by a 
+    media failure or by a geometry mismatch. 
+   LIL?   The second stage boot loader has been loaded at an incorrect 
+    address. This is typically caused by a subtle geometry mismatch or by 
+    moving /boot/boot.b without running the map installer. 
+   LIL-   The descriptor table is corrupt. This can either be caused by a 
+    geometry mismatch or by moving /boot/map without running the map 
+    installer. 
+   LILO   All parts of LILO have been successfully loaded. 
+
+
+Disk error codes
+- - - - - - - -
+
+If the BIOS signals an error when LILO is trying to load a boot image, the 
+respective error code is displayed. The following BIOS error codes are 
+known:
+
+   0x00   "Internal error". This code is generated by the sector read 
+    routine of the LILO boot loader whenever an internal inconsistency is 
+    detected. This might be caused by corrupt files. Try re-building the 
+    map file. Another possible cause for this error are attempts to access 
+    cylinders beyond 1024 while using the LINEAR option. See section "BIOS 
+    restrictions" for more details and for how to solve the problem. 
+   0x01   "Illegal command". This shouldn't happen, but if it does, it may 
+    indicate an attempt to access a disk which is not supported by the 
+    BIOS. See also "Warning: BIOS drive 0x<number> may not be accessible" 
+    in section "Warnings". 
+   0x02   "Address mark not found". This usually indicates a media problem. 
+    Try again several times. 
+   0x03   "Write-protected disk". This should only occur on write 
+    operations. 
+   0x04   "Sector not found". This typically indicates a geometry mismatch. 
+    If you're booting a raw-written disk image, verify whether it was 
+    created for disks with the same geometry as the one you're using. If 
+    you're booting from a SCSI disk or a large IDE disk, you should check, 
+    whether LILO has obtained correct geometry data from the kernel or 
+    whether the geometry definition corresponds to the real disk geometry. 
+    (See section "Disk geometry".) Removing COMPACT may help too. So may 
+    adding LBA32 or LINEAR. 
+   0x06   "Change line active". This should be a transient error. Try 
+    booting a second time. 
+   0x07   "Invalid initialization". The BIOS failed to properly initialize 
+    the disk controller. You should control the BIOS setup parameters. A 
+    warm boot might help too. 
+   0x08   "DMA overrun". This shouldn't happen. Try booting again. 
+   0x09   "DMA attempt across 64k boundary". This shouldn't happen, but may 
+    inicate a disk geometry mis-match. Try omitting the COMPACT option. You 
+    may need to specify the disk geometry yourself. 
+   0x0C   "Invalid media". This shouldn't happen and might be caused by a 
+    media error. Try booting again. 
+   0x10   "CRC error". A media error has been detected. Try booting several 
+    times, running the map installer a second time (to put the map file at 
+    some other physical location or to write "good data" over the bad 
+    spot), mapping out the bad sectors/tracks and, if all else fails, 
+    replacing the media. 
+   0x11   "ECC correction successful". A read error occurred, but was 
+    corrected. LILO does not recognize this condition and aborts the load 
+    process anyway. A second load attempt should succeed. 
+   0x20   "Controller error". This shouldn't happen. 
+   0x40   "Seek failure". This might be a media problem. Try booting again. 
+   0x80   "Disk timeout". The disk or the drive isn't ready. Either the 
+    media is bad or the disk isn't spinning. If you're booting from a 
+    floppy, you might not have closed the drive door. Otherwise, trying to 
+    boot again might help. 
+   0xBB   "BIOS error". This shouldn't happen. Try booting again. If the 
+    problem persists, removing the COMPACT option or adding/removing LINEAR 
+    or LBA32 might help. 
+
+If the error occurred during a write operation, the error code (two hex 
+digits) is prefixed with a "W". Although write errors don't affect the boot 
+process, they might indicate a severe problem, because they usually imply 
+that LILO has tried to write to an invalid location. If spurious write 
+errors occur on a system, it might be a good idea to configure LILO to run 
+read-only (see section "Build-time configuration").
+
+Generally, invalid geometry and attempts to use more than two disks without 
+a very modern BIOS may yield misleading error codes. Please check carefully 
+if /sbin/lilo doesn't emit any warnings. Then try using the LINEAR or LBA32 
+option (see section "Global options").
+
+
+Other problems
+--------------
+
+This section contains a collection of less common problems that have been 
+observed. See also section "Installation of other operating systems" for 
+general remarks on using LILO with other operating systems. Some of the 
+problems are obscure and so are the work-arounds.
+
+  - If LILO doesn't go away even if you erase its files, format your Linux 
+    partition, etc., you've probably installed LILO as your MBR and you've 
+    forgotten to deinstall it before deleting its files. See section "LILO 
+    de-installation" for what you can do now. 
+  - For yet unknown reasons, LILO may fail on some systems with AMI BIOS if 
+    the "Hard Disk Type 47 RAM area" is set to "0:300" instead of "DOS 1K". 
+  - Some disk controller BIOSes perform disk geometry/address translations 
+    that are incompatible with the way the device's geometry is seen from 
+    Linux, i.e. without going through the BIOS. Particularly, large IDE 
+    disks and some PCI SCSI controllers appear to have this problem. In 
+    such cases, either the translated geometry has to be specified in a 
+    DISK section or the sector address translation can be deferred by using 
+    the LINEAR option. In a setup where floppies are not normally used for 
+    booting, the LINEAR approach should be preferred, because this avoids 
+    the risk of specifying incorrect numbers. 
+  - OS/2 is said to be bootable from a logical partition with LILO acting 
+    as the primary boot selector if LILO is installed on the MBR, the OS/2 
+    BootManager is on an active primary partition and LILO boots 
+    BootManager. Putting LILO on an extended partition instead is said to 
+    crash the OS/2 FDISK in this scenario.
+
+     Note that booting LILO from BootManager (so BootManager is the primary 
+    selector) or booting OS/2 directly from a primary partition (without 
+    BootManager) should generally work. See also section "Installation of 
+    other operating systems". 
+  - Windows NT is reported to be bootable with LILO when LILO acts as the 
+    MBR and the Windows NT boot loader is on the DOS partition. However, 
+    NT's disk manager complains about LILO's MBR when trying to edit the 
+    partition table. 
+  - Some PC UNIX systems (SCO and Unixware have been reported to exhibit 
+    this problem) depend on their partition being active. See section 
+    "Partition table manipulation" for how this can be accomplished. 
+  - Future Domain TMC-1680 adapters with the BIOS versions 3.4 and 3.5 
+    assign BIOS device numbers in the wrong order, e.g. on a two-disk 
+    system, /dev/sda becomes  0x81  and /dev/sdb becomes  0x80 . This can 
+    be fixed with the following DISK section:
+     disk=/dev/sda bios=0x81 disk=/dev/sdb bios=0x80
+     Note that this is only valid for a two-disk system. In three-disk 
+    systems, /dev/sdc would become  0x80 , etc. Also, single-disk systems 
+    don't have this problem (and the "fix" would break them). 
+  - Some BIOSes don't properly recognize disks with an unusual partition 
+    table (e.g. without any partition marked active) and refuse to boot 
+    from them. This can also affect the second hard disk and the problem 
+    may only occur if the system is booted in a particular way (e.g. only 
+    after a cold boot). 
+  - On some systems, using LINEAR and COMPACT or LBA32 and COMPACT together 
+    leads to a boot failure. The exact circumstances under which this 
+    happens are still unknown. 
diff --git a/readme/README.bitmaps b/readme/README.bitmaps
new file mode 100644 (file)
index 0000000..95bbbf8
--- /dev/null
@@ -0,0 +1,314 @@
+       Notes on the use of Bitmap boot screens
+               LILO 22.3 -- 11-Apr-2002
+
+
+SUMMARY OF CHANGES (LILO 22.3)
+==============================
+
+LILO 22.3 no longer requires placement parameters in the configuration
+file (/etc/lilo.conf).  Instead, text menu size, placement, and colors
+may be edited into the bitmap file header using "lilo -E file.bmp".  The
+parameters may also be saved from the bitmap file header to a companion
+configuration file, "file.dat", as an option to the edit command. Param-
+eters may be transferred from the companion '.dat' file to the bitmap
+file header using the command "lilo -E file.dat".  LILO 22.3 still rec-
+ognizes bitmap file formating commands in '/etc/lilo.conf'.
+
+This change allows bitmap graphics to be exchanged among users without the
+tedious need to exchange the color/positioning information separately.
+
+
+
+MOTIVATION
+==========
+
+The makers of several Linux distributions which include LILO as the boot
+loader have issued patched versions which support graphical screens for
+kernel selection.  However, each distribution seems to have chosen a
+different screen resolution, and different file-type to implement the
+graphical (bitmapped) background.  In order to try to bring some order
+to this array of different implementations, and to support common code
+across all Linux distributions, I submit the following implementation of
+a graphical background and menu driven interface (cursor keys only) for
+kernel selection.
+
+The choice then was to have the implementation run on the widest array
+of graphics hardware in use today.  VGA is the common standard, and this
+dictates a choice of two color modes:  320x200x256 and 640x480x16.  The
+VGA/VESA standard extends the modes to add 640x400x256, 640x480x256, and
+800x600x256 as possible choices.  However, most high-end graphics cards
+provide graphics acceleration through other means than the VESA standard;
+and, in actual fact, are moving away from supporting the full spectrum of
+VESA modes.  Older VGA systems often do not have VESA extensions in ROM
+BIOS, so the choice narrows to the two modes in the original IBM VGA BIOS.
+
+Character generation in the 320x200x256 mode is generally limited to an
+8x8 character cell, and is not visually appealing.  The 640x480x16 mode
+uses an 8x16 character cell, and is acceptable.  The question was the
+limitations to 16 colors.  This is less of a restriction than one might
+think it is.  There are the 16 EGA-compatible colors, which are the BIOS
+defaults on all systems; but the VGA palette is programmable with 6 bits
+alloted to each primary color.  Some experimentation with graphics images
+convinced me that very appealing logos could easily be generated, as long
+as the graphics editor in use would allow ANY 16 colors to be chosen from
+among the 256K available.  Good dithering algorithms exist, and the screens
+that I produced with dithered 16-color images, in my opinion, were more
+acceptable than 256-color images.  In these latter cases, as a color area
+transitions from one shade to another, the stepping effect is more notice-
+able, and more objectionable, than a good dither.
+
+With this said, the choice of VGA 640x480x16 (mode 0x12) was settled upon.
+
+Then the choice of a graphics screen file format had to be settled.  It
+had to be universally supported, be well documented, allow for image
+compression, and allow for easy decompression.  File formats considered
+included PCX, GIF, and BMP.  The last was chosen because it is understand-
+able, and the run-length compression is very easy to expand.
+
+
+USAGE
+=====
+
+Update (22.3):  The three keywords 'bmp-table', 'bmp-colors', and 'bmp-timer'
+are now primarily to be used in the configuration file used as a companion
+to a bitmap file.  The bitmap file must have the filename extension ".bmp",
+and the companion configuration file must have the filename extension
+".dat".
+
+Four keywords are added to 'lilo.conf' to allow the usage of bitmap screens:
+
+       bitmap     =            #specifies the bitmap file to be used as
+                               #a background
+
+       bmp-table  =            #specifies the location of the table of
+                               #image/other names, and its layout
+
+       bmp-colors =            #specifies the color attributes of the table
+                               #entries, normal & highlighted
+
+       bmp-timer  =            #specifies the position and color attributes
+                               #of the timeout timer
+
+       install = bmp           #specify the boot loader with bitmap
+                               #graphics capability
+
+'bitmap=' specifies the graphic file to be used as a background screen.  It
+must be 640 x 480 x 16 colors, and may be saved as an uncompressed bitmap
+file (153718 bytes), run-length encoded (compressed) bitmap file, or an OS2
+bitmap file (153674 bytes).  It is suggested that you use the smallest,
+which will probably be the RLE (compressed) file.  When a 'bitmap=' file is
+in use, 'message=' may not be used, and vice versa.
+
+'bmp-table=<list>' specifies the position and table layout of the boot 
+selection menu.  The list is a series of up to 5 decimal values, separated
+by commas, and containing no spaces.  Values may be omitted in order to use
+default values, but the comma separators are required as placeholders.  In
+designing the bmp-table layout, consideration must be given to the upper
+limit on kernel image/other names.  LILO guarantees that up to 16 may be
+specified, and the current implementation allows up to 19.  It is suggested
+that the table layout design allow for 18 entries.
+
+  bmp-table = [x],[y],[ncol],[nrow],[xspc],[spill]
+
+       [x]     specifies the column position [1..80] of the first column
+               of the table.  Character addressing is assumed, unless the
+               coordinate is suffixed with 'p', in which case pixel ad-
+               dressing will be used [0p..632p].
+
+       [y]     specifies the row position [1..30] of the top row of the
+               table.  All screen text is placed on a 30 row grid.  Pixel
+               addressing [0p..464p] is allowed.
+
+       [ncol]  specifies the number of columns used for the display of the
+               kernel image/other entries.  The current implementation
+               requires the number of columns to be in the range [1..4].
+
+       [nrow]  specifies the number of rows in each column; i.e., the
+               height of each column in the table.
+
+       [xspc]  specifies the column spacing from the beginning of one
+               column to the beginning of the next column.  Since names in
+               the table are up to 15 characters, plus 2 spacers, 17 is an
+               absolute minimum for this value.  The column spacing
+               increases as this value is increased.  Too large a value may
+               spill characters beyond the edge of the screen.  Pixel
+               addressing is allowed, if the value is suffixed with a 'p'.
+
+       [spill] specifies the number of entries which may fill a column
+               before the column spills to the next column.  The default
+               value for this is 4 entries.  (LILO 22.3)
+
+
+'bmp-colors=<list>' specifies a list of six color numbers, each in the range
+[0..15].  The first three specify the color attributes of normal text in the
+boot selection table, and the second three specify the color attributes of
+the highlighted text in the menu.  The list is comma or semicolon separated,
+with no spaces.  However, default values may be indicated by omitting a
+numerical value altogether.  Each of the two triples consists of a fore-
+ground color, background color, and a shadow color.  The foreground color is
+the color used to display the letter or numeral.  The background color is
+the fill-color of the 8x16 box which encloses the character.  If the back-
+ground color value is omitted from the list, then "transparent" is assumed.
+The shadow color is the color used to display a character shadow displaced
+one pixel in both X & Y toward the lower right.  If shadows are used, they
+generally specify a color of low luminance.
+
+  bmp-colors = [fg],[bg],[sh];[h-fg],[h-bg],[h-sh]
+
+       [fg]    specifies the foreground color for normal text.
+
+       [bg]    specifies the background color for normal text.  If omitted,
+               the background is taken to be transparent, and the
+               underlying bitmap color shows through.
+
+       [sh]    specifies the shadow color for the character.  If omitted,
+               no shadow is displayed.
+
+       [h-fg]  specifies the foreground color for the line of highlighted
+               text.
+
+       [h-bg]  specifies the background color for highlighted text.  If
+               omitted, the highlighted background is taken to be
+               transparent.
+
+       [h-sh]  specifies the shadow color for highlighted text.  If
+               omitted, no shadow is displayed.
+
+               Note:  in the list specification above, the semicolon has
+               no special significance; it could have been a comma.  Its
+               use is suggested merely for distinguishing the two triples,
+               as spaces (blanks) are not allowed in the list.
+
+
+'bmp-timer=<list>' specifies the position at which the 'timeout=' timer will
+be displayed, as well as the color attributes of the characters in the
+display.  If the line 'bmp-timer=' is not used, then no timer will be
+displayed.  If the <list> is specified as "none", then no timer (as speci-
+fied in the bitmap file header) will be displayed.
+
+  bmp-timer = [tx],[ty];[t-fg],[t-bg],[t-sh]
+
+       [tx]    specifies the column at which the first of five characters
+                in the timer display will be positioned.  It must be in the
+               range [1..80], or [0p..632p] if pixel addresses are used.
+
+       [ty]    specifies the character row position of the timer display. 
+               It must be in the range [1..30], or [0p..464p] if pixel
+               addresses are used.
+
+       [t-fg]  specifies the foreground color of the timer characters.  If
+               omitted, the normal foreground text color will be used.
+
+       [t-bg]  specifies the background color of the timer character
+               display.  If omitted, color '0' will be used.  It is not
+               possible to have a transparent timer background.
+
+       [t-sh]  specifies the shadow color for timer display characters.  If
+               omitted, no shadow is displayed.
+
+               Note:  the semicolon in the list specification is for
+               readability only; a comma could have been used as well.
+
+
+
+EXAMPLE
+=======
+
+The following is excerpted from 'bmp.conf', a LILO configuration file which
+has been used during the development of the bitmap-capable boot loader.
+
+File:  bmp.conf (substitute for 'lilo.conf'):
+
+       ...
+       #
+       #  The following parameters select appropriate colors
+       #  and proper screen positions for the 'logo64a.bmp' graphic.
+       #
+       bitmap=logo64a.bmp
+       bmp-colors=6,9,0;15,9,0
+       bmp-table=59,5,1,19,
+       bmp-timer=66,28,6,8,0
+       ...
+
+Update (22.3):  If the color information and screen positions specified on
+the last three lines above have been transferred to the LILO sub-header in
+the bitmap file "logo64a.bmp", then the entry in 'lilo.conf' can be
+shortened to:
+
+       ...
+       #
+       #  Select the bitmap file to display.  Text positioning information
+       #  is in the LILO subheader in the bitmap file.
+       #
+       bitmap=logo64a.bmp
+       ...
+
+
+       ...
+       #
+       #  The following parameters select appropriate colors
+       #  and proper screen positions for the 'ins64a.bmp' graphic.
+       #
+       bitmap=ins64a.bmp
+       bmp-colors=14,11,;15,9,0        # omit this line for lilo 22.3
+       bmp-table=21,287p,2,4,175p      #  ditto
+       bmp-timer=73,29,12,8,0          #  ditto
+       ...
+
+Both bitmap files are available in the source code tarball at:
+
+       http://lilo.go.dyndns.org/pub/linux/lilo
+
+They are located in the 'sample' subdirectory, along with companion
+'.dat' configuration files.
+
+
+USAGE COMMAND
+=============
+
+With version 22.3, '/sbin/lilo' becomes, in addition to the boot installer,
+the bitmap file header editor.  A single switch, '-E' is added to accomplish
+this new task.  It has two uses:
+
+       lilo -E filename.bmp
+               or
+       lilo -E filename.dat
+
+In the first case, if the bitmap file is fresh out of a graphics editor, it
+will have no LILO sub-header.  The first edit command is used to alter the
+default values for color and positioning information, and to save the new
+values to the LILO sub-header in the bitmap file.  The editor is
+interactive, and allows you to change one parameter at a time.  When you
+write out the updated bitmap file, you are given the chance to create a
+companion text configuration file, 'filename.dat', which contains a readable
+copy of all of the text color and positioning information in the header.
+
+In the second case, the abbreviated configuration file, 'filename.dat',
+contains only the commands:  "bitmap=", "bmp-table=", "bmp-colors=", or
+"bmp-timer="; all are optional.  If "bitmap=" is omitted, then
+'filename.dat' is taken to correspond to the bitmap file 'filename.bmp';
+i.e., same name, diffenent file extension.  Otherwise, the configuartion
+file corresponds to the bitmap file specified by the "bitmap=" option.  The
+color, positioning, and timer information in the configuration file is
+transferred to the LILO header in the bitmap file.  If no such header
+exists, one is created.
+
+The primary use for the '.dat' file is to save the LILO header information,
+so that the bitmap graphic may be edited with a graphics editor.  No
+graphichs editor recognizes the LILO header, so an updated bitmap graphic
+file will be without the LILO header.  The second form of the edit command
+allows the header to be recreated very quickly, exacltly as it was before.
+
+
+TRADEMARKS
+==========
+
+Windows is a trademark of Microsoft Corporation.
+OS/2 and OS2 are trademarks of IBM Corporation.
+
+(end)
+written 05/07/2001 -- John Coffman <johninsd@san.rr.com>
+updated 05/10/2001 -- John Coffman
+updated 11/25/2001 -- John Coffman (typos corrected)
+updated 04/11/2002 -- John Coffman (update to LILO 22.3)
+
diff --git a/readme/README.common.problems b/readme/README.common.problems
new file mode 100644 (file)
index 0000000..0155e36
--- /dev/null
@@ -0,0 +1,69 @@
+file:  README.common.problems
+date:  04-Oct-2000
+revised:  03-Jan-2001, 07-Jan-2001, 04-Apr-2001, 25-May-2001
+
+
+Caution:  All of the LILO components are installed in the proper
+================================================================
+default directories ONLY if you use "make install".
+===================================================
+
+
+Problem:  LILO won't 'make'
+==========================
+If you get errors trying to 'make all', and the errors are occurring
+during the assembly of 'temp2.s', you have encountered the most common
+problem trying to build LILO:  the lines in error all have the assembler
+directive 'near' on them.  This problem occurs when your assembler for
+the real-mode bootstrap code is out-of-date:  'as86'.  Certain current
+distributions of Linux distribute version 4 of this assembler; whereas
+the current version is 15.
+
+Two sources for an updated version are:
+
+Redhat RPM distribution:
+     site: http://www.redhat.com      (search for 'dev86')
+     pkg:  dev86-0.15.0-2.i386.rpm  
+
+or Robert de Bath's page at:
+     site: http://www.cix.co.uk/~mayday
+     link: bin86-0.15.1.tar.gz
+
+
+Problem:  When I boot, all I get is 'LI'
+=======================================
+This means the first-stage loader gained control; it thought it success-
+fully loaded the second-stage loader; but it never got there.  This most
+often occurs when the second-stage loader, '/boot/boot.b', is not load-
+able using the BIOS.
+
+First, have you tried specifying 'lba32' in your 'lilo.conf' file?  On
+newer systems, this will almost always work, since the loader will now
+use the newer EDD packet calls, which are not cylinder-limited.
+
+Second, do you know your disk geometry?  This means, do you know the
+numbers of cylinders/heads/sectors of all your hard drives; and are these
+the numbers that LILO is using when it installs the boot loader.  Three
+reports of the disk geometry may be obtained:
+
+  1.  Run 'lilo -t -v5' and check the geometry reports for each device.
+  2.  Run 'lilo -Tgeom' and see if the same numbers are reported.  (This
+      may fail on some systems, where LILO has trouble running BIOS 
+      calls in v86 mode.)
+  3.  Create the diagnostic floppy (see README.disk) and check the
+      reported disk geometries.
+
+If any of the geometry reports differ, then you may have to specify the
+disk geometry to LILO using 'disk= heads= sectors='.  Use the actual
+numbers reported by the BIOS:  #3 above, or #2.
+
+The reports above will also indicate the BIOS device codes used by each
+disk.  LILO uses heuristics to obtain these device codes, and usually gets
+the codes right on all-IDE or all-SCSI systems.  However, systems with
+multiple IDE controllers, mixed IDE/SCSI systems, and SCSI systems on
+Future Domain controllers, will require you to tell LILO what disks are
+assigned to what device codes.  This can be done using 'disk= bios=' lines
+in 'lilo.conf'.
+
+John Coffman <johninsd@san.rr.com>
+(end)
diff --git a/readme/README.disk b/readme/README.disk
new file mode 100644 (file)
index 0000000..76cfc0a
--- /dev/null
@@ -0,0 +1,41 @@
+file: README.disk
+date: 01-Oct-2000
+
+The LILO source directory contains the source code to produce a diag-
+nostic floppy disk for determining the BIOS capabilities of your sys-
+tem, as well as the disk geometry of each of your hard drives.
+
+Creating the floppy
+===================
+Change into the LILO source code directory.  Insert a formatted floppy
+disk into the A: drive (/dev/fd0).  Type the command "make floppy". 
+After the files have assembled, the bootable floppy disk will be created.
+
+Running the diagnostic
+======================
+Use CTRL-ALT-DELETE to re-boot your system from the floppy disk.  This
+allows the diagnostic program, disk.com, to interrogate your BIOS with-
+out having an operating system between it and your BIOS and hardware.
+The diagnostic program will report on the EBDA (Extended BIOS DATA Area),
+as the size of this area affects where LILO loads into memory.  It will
+also report on your disk geometry:  the number of cylinders, heads, and
+sectors that LILO will see in trying to boot your machine.  Sometimes
+the diagnostic will report two different sets of geometry for the same
+hard drive.  This happens when the old BIOS call (fn=0x08, int=0x13),
+which is limited to 1024 cylinders, is unable to address all sectors
+on your disk.  The second line is from the new BIOS call (the EDD packet
+interface on int=0x13), which allows addressing all sectors on the 
+disk.
+
+Caution
+=======
+If you have an older system, and run a "soft" BIOS, such as EZ-DRIVE,
+MaxBlast, or Disk Manager, you must allow the soft BIOS to install first
+from your hard drive, then follow the instructions to boot from floppy.
+Remember, LILO will see the soft BIOS in booting from the hard drive, 
+so you must be sure that the diagnostic utility booted from floppy also
+sees the soft BIOS.  If you boot from the A: drive ahead of the C: drive
+in this case, the diagnostic floppy report may be misleading.
+
+John Coffman  <johninsd@san.rr.com>
+(end)
diff --git a/readme/README.nokeyboard b/readme/README.nokeyboard
new file mode 100644 (file)
index 0000000..221ba59
--- /dev/null
@@ -0,0 +1,119 @@
+        Notes for use of LILO on systems with NO keyboard
+               (Version 22.7.2 and later)
+
+
+INTRODUCTION
+============
+
+It is possible on some systems to run without a keyboard.   This may be
+desirable on certain servers, if permitted by the BIOS.  Not all systems
+will permit this mode of operation.
+
+Without a keyboard, it may be desirable to alter the default descriptor
+booted, rather than boot the default descriptor all the time.  That is
+to say, if no keyboard is present on the system, then a different default
+descriptor may be selected for booting.
+
+
+LIMITATIONS
+===========
+
+The keyboard detection code accesses the ports used by the original IBM
+PC/AT or PC/XT keyboard.  No attempt is made to check for the presence of
+one of the newer USB keyboards.  The phase "no keyboard", therefore, means
+"no IBM PC keyboard" throughout this document.
+
+If anyone has any idea how to detect the presence/absence of a USB keyboard,
+please contact the LILO maintainer at the e-mail address below.
+
+
+USAGE
+=====
+
+After LILO has been reconfigured, two new keywords are available for use
+in the configuration file (e.g., /etc/lilo.conf).  The global option:
+
+nokbdefault = <descriptor>
+
+specifies the label or alias of the descriptor which is to be booted instead
+of the "default=<descr>" default, or the first descriptor (no usage of 
+"default=").
+
+Additionally, individual descriptors may be marked unavailable for booting
+if no keyboard is present.  Note that with a serial console present (see
+"serial=" in the "lilo.conf" man page or user manual) it is possible to 
+select other boot descriptors.  If this is not desirable, then certain 
+descriptors may be marked unbootable on an individual basis; viz.,
+
+       ...
+       boot = /dev/hda
+       default = linux
+       nokbdefault = linux-nokbd
+       read-only
+       ...
+       image=/boot/vmlinuz
+               label=linux             # default descriptor
+               root=/dev/hda1
+               initrd=/boot/initrd
+               append=" ... standard options ..."
+       image=/boot/vmlinuz2
+               label=linux-nokbd
+               root=/dev/hda1
+               initrd=/boot/initrd2
+               append=" ... no keyboard options, e.g, console=ttS0..."
+       other=/dev/hda2
+               label=DOS
+               nokbdisable
+               table=/dev/hda
+
+In the example above, "linux", the first descriptor, is the default boot
+selection (which may be overridden at the system console at boot time).
+However, if no keyboard is plugged into the system, "linux-nokbd" will
+be the default descriptor booted.  And further, with no keyboard, "DOS"
+will not be a boot option.
+
+Note that if the "nokbdefault=" line is omitted from the above configur-
+ation file, then when no keyboard is present, the default boot will be
+"linux", and "DOS" will still not be a boot option.
+
+With no keyboard and no serial interface in use (see "serial=" in the
+"lilo.conf" man pages), the "prompt" and "timeout=" options will be
+ignored, and booting of the "nokbdefault=" (or "default=") image will
+occur after the appropriate "delay=".  If either the keyboard or serial
+interface is present, then "prompt" and "timeout=" will be honored
+as documented.
+
+
+RECONFIGURING
+=============
+
+The "NOKEYBOARD" compilation option and associated keywords "nokbdefault"
+and "nokbdisable" are new with LILO version 22.7.2 of 25-Nov-2005.
+
+Since the keyboard detection code accesses the hardware I/O ports directly,
+this code is not included in the standard LILO distribution.  If the added
+capability is desired, then LILO must be recompiled with an additional
+compile-time option:  NOKEYBOARD.
+
+The options used for compilation are described at the top of the LILO
+"Makefile", and specified on the line which begins, "CONFIG=..."  To enable
+the NOKEYBOARD option, simply append:  " -DNOKEYBOARD" to the final line
+of the "CONFIG=" setting.  Now recompile LILO by executint the shell 
+commands:
+
+       > make clean            # set up for a clean compile
+       > make all              # recompile all source codes
+       > make install          # install the new boot loader
+
+At this point you have added support for the configuration file 
+"nokbdefault=" global option, and the "nokbdisable" local option.  Now
+edit "/etc/lilo.conf", the default configuration file, and re-install
+the boot loader by running:
+
+       > lilo -t               # test installation
+       > lilo                  # actual installation
+
+
+(end)
+written 11/25/05 -- John Coffman <johninsd@san.rr.com>
+updated 11/26/05 -- John Coffman
diff --git a/readme/README.pseudo b/readme/README.pseudo
new file mode 100644 (file)
index 0000000..79baf48
--- /dev/null
@@ -0,0 +1,67 @@
+                           03-Jun-2002
+               Notes on booting arbitrary REAL mode
+                       binaries at 1000:0000
+
+
+THIS IS NOT A PART OF THE STANDARD LILO DISTRIBUTION.
+
+Arbitrary real mode binaries cannot be loaded directly by LILO.  However, if
+they are made to look like a "kernel image loaded LOW," then LILO can be
+induced to load them, thinking they are an out-of-date kernel image.
+
+Such files are limited to 512K bytes; less if you have a very large Extended
+BIOS Data Area (EBDA), which intrudes upon the 0x9000 segment.  The start
+addresss of the file MUST be at offset 0 in the file.  It will be loaded at
+0x1000:0000, and jumped to at that address (segment=0x1000, offset=0000) in
+16-bit real mode.
+
+In order to make the arbitrary binary, call it "foo.b", look like a kernel,
+the file "pseudo.b", the pseudo kernel header, must be pre-pended; viz.,
+
+       cat pseudo.b foo.b >foo.img
+
+"foo.img" is the bootable pseudo-kernel.
+
+In the configuration file, usually '/etc/lilo.conf', the following lines
+must be added:
+
+       image = foo.img
+           root = current
+
+The root directory specification MUST be added (this is a "kernel" after
+all), to avoid a fatal LILO error message (unspecified numeric value). 
+Optionally, the arbitrary image may be given a name; viz.,
+
+           label = foo-test
+
+The image should then be bootable from the LILO boot prompt.
+
+EXAMPLE:  Add the LILO diagnostic program "test4.com" to the LILO boot menu.
+
+The test program is created by "make floppy", which will write a floppy disk
+image, but it also may be added to the LILO boot menu with the following
+commands:
+
+       make all
+       cd diagnose
+       make test4.com
+       cd ..
+       cat pseudo.b diagnose/test4.com >/boot/test4.img
+
+Then append the following lines to '/etc/lilo.conf':
+
+       image = /boot/test4.img
+         root = current
+          label = diagnostic
+
+Now, install the boot loader with the new menu item:
+
+       /sbin/lilo
+
+The last item on the boot menu should be "diagnostic", which will run
+"test4.com" from the LILO boot prompt.
+
+--John Coffman <johninsd@san.rr.com>
+(end)
+
+
diff --git a/readme/README.raid1 b/readme/README.raid1
new file mode 100644 (file)
index 0000000..62c57e7
--- /dev/null
@@ -0,0 +1,481 @@
+        Notes for use of LILO on RAID installations.
+
+(LILO version 22.0 through 22.4.1 -- 17-Apr-2001)
+(LILO version 22.5 and later -- 14-Mar-2003) see NEW CONSIDERATIONS
+
+
+RESTRICTIONS
+============
+
+Only RAID1 is supported.  LILO may be used to boot a system
+containing other RAID level partitions, but it may not be installed
+on any RAID partition other than RAID level 1.
+
+
+GOAL
+====
+
+The goal of a RAID1 installation of LILO is redundancy.  Redundancy to
+the point that a failure of one disk in an array will not render the
+system difficult to boot.
+
+A secondary goal of LILO on a RAID installation is to maintain array
+coherency when the LILO command line is written back to the map file. 
+This writeback occurs when the '-R' switch command line is cleared,
+when the user has specified the 'lock' option, or if a 'fallback'
+command line is in use.
+
+
+INSTALLATION ON A RAID SET
+==========================
+
+A RAID installation of the LILO boot loader is initiated by
+specifying that the boot record is to be placed in the boot area of
+a RAID partition.  This is accomplished by the 'boot=' line in the
+LILO configuration file, '/etc/lilo.conf'.  For instance, a system
+running with '/dev/md1' mounted as root ('/'), would use the line:
+
+   boot = /dev/md1
+
+to initiate a RAID installation.  As directed, the boot record is
+written to the RAID partition.  Unfortunately, in the event of
+failure of the RAID set disk from which booting occurs, the boot record
+on the surviving disk(s) will only be usable if the disks are entirely
+"parallel" to the disk that originally booted the system.
+
+To continue, we first need some terminology for talking about RAID 1
+partitions.
+
+
+TERMINOLOGY
+===========
+
+RAID 1 writes the same data to the corresponding disk blocks of the
+partitions which make up the RAID set.  Two partitions are said to be
+"parallel" if they start at exactly the same sector address on their
+respective drives.  This means that files on the two disks have their
+data written at exactly the same absolute sector addresses on both
+drives.  
+
+Two partitions are said to be "skewed" if they do not start at the
+same sector address on their respective drives.  Data within each
+partition will be at the same offset from the beginning of each
+partition, but not at the same absolute sector address.
+
+
+PARALLEL CASE
+=============
+
+"Parallel" RAID sets are the easiest for LILO to handle.  One boot
+record, written to the boot area of the RAID partition, references the
+same sectors, no matter which disk is operational at boot time.  For
+"parallel" RAID installations, LILO has no need to write boot records
+outside of the RAID partition, if primary.  This is in contrast to
+previous versions of LILO based upon the "lilo.raid1" patch file to
+vanilla version 21, which wrote the LILO boot record to the Master Boot
+Records of all of the drives in the array, and not to the RAID
+partition.
+
+With the boot record written to the RAID partition on "parallel" RAID
+sets, every drive has a boot record which will boot the system. 
+There is now only one map file, and this file may be referenced by
+any of the boot records, since it is at exactly the same sector
+address on every drive.  To insure that it is possible to boot from
+this simplest LILO installation to "parallel" RAID set partitions,
+one must insure that they are primary partitions; i.e., partition
+numbers 1-4 on their respective disks, and that each disk has written
+to it a "master" boot loader which boots the partition marked "active".
+And on each disk, mark the RAID set partition active.  Booting normally
+occurs from the drive with the lowest BIOS device code (0x80).  In
+the event this drive fails, another drive assumes the role of BIOS
+device code 0x80, and in the case of a "parallel" RAID installation,
+will be perfectly bootable.
+
+The unusual event of RAID set partitions which are parallel, but not
+primary partitions will be described later.
+
+
+MORE TERMINOLOGY
+================
+
+A boot record is "accessible", if it exists on a primary parition,
+which may be marked "active"; or it is a Master Boot Record (MBR),
+written to sector 0 of a drive.
+
+Non-RAID LILO installations write accessible boot records when they
+write to primary partitions, such as:
+
+   boot = /dev/hda1
+
+or,
+
+   boot = /dev/sdb3
+
+Boot records are written to the MBR by specifying the drive; viz.,
+
+   boot = /dev/hdb
+
+writes to the MBR of the slave drive on the primary IDE controller.
+
+Similarly, a boot record is "inaccessible" if it is written to a
+logical (or secondary) partition; i.e., partition numbers 5 and
+above.  These partitions are not booted by any of the usual MBR boot
+loaders which search the partition table for a partition marked
+"active".  They may be booted from a boot manager, such as the LILO
+boot menu, and are booted as 'other=' entries in the configuration
+file, '/etc/lilo.conf'.
+
+
+SKEWED CASE
+===========
+
+"Skewed" installations are not quite as simple.  Here the partitions
+are not likely to be primary, and their distinguishing characteristic
+is that files on the filesystem within the partition lie at different
+absolute sector addresses:  kernel files, initrd files, and the LILO
+map file, in particular.  Thus any boot record written to '/dev/mdX',
+the RAID partition, will have sector addresses which cannot be
+guaranteed accurate for all drives.  Worst case is that they are
+accurate for only one drive.  Hence, this boot will work for one
+drive, but it is not universal.  It will fail for some drive or
+drives in the array.
+
+In this case, LILO needs to place boot records in "accessible" places
+so that all drives will be bootable in a recovery situation.
+
+Here the need for the user to specify alternative actions becomes
+necessary.  There is a new keyword now recoginzed in the
+configuration file, and a new command line switch corresponding to
+the keyword:  'raid-extra-boot=' and the '-x' switch.  The following
+description will be for the configuration file option, but is equally
+applicable to the command line switch.
+
+For the simplest of "skewed" installations, it may be undesirable to
+have LILO automatically write boot records outside of the RAID
+partition.  In this case, 'raid-extra-boot=' should be specified,
+literally, as "none"; viz.,
+
+   boot = /dev/md1
+   raid-extra-boot = none
+
+With this specification, LILO will write the boot record to
+'/dev/md1' only.  If the RAID disk on the lowest BIOS device code
+fails, the array may not be bootable, except from a floppy disk.
+
+Without the specification "none", the default LILO action in the case
+of a skewed installation is:
+
+   boot = /dev/md1
+   raid-extra-boot = auto
+
+This requests LILO to place recovery boot records on the MBRs of any
+drives for which the the '/dev/md1' boot record is not valid, because
+of partition skew.  Even with "auto" specified, or implied by having
+no 'raid-extra-boot=' line, LILO will never write a boot record to
+the MBR of BIOS device 0x80.  This MBR is considered so critical,
+that it will never be written, unless you specifically request it.
+
+It is strongly suggested that before any LILO installation on a RAID
+set, that LILO be run with the 'test' flag:  '-t'.  LILO will go
+through all the motions of mapping the kernel(s) to be booted, but it
+will tell you where it wants to write any additional boot records.
+
+  lilo -t
+
+Is strongly recommended, especially if you are not sure whether you
+have a "skewed" (extra boot records needed) or "parallel" RAID
+installation.
+
+If boot records are desired on all MBRs of all disks with partitions
+in the raid set, then the following specification is used:
+
+   boot = /dev/md1             # OR,   -b /dev/md1
+   raid-extra-boot = mbr       # OR,   -x mbr
+
+If there are three disks with partitions that are part of the /dev/md1
+raid set, then the Master Boot Records of all three will receive
+additional boot records. With this specification, the MBR of BIOS
+device 0x80 will be overwritten. 
+
+The caution to run 'lilo -t' first, just to see where LILO will write
+boot records, is reemphasized.
+
+The keyword 'raid-extra-boot=' may also be used to specify exactly
+where you want LILO to write the auxiliary boot records.  Consider
+the following RAID installation:  disk 0:  /dev/hdc6; disk 1: 
+/dev/sda1.  The installation is "skewed".  Disks /dev/hda and
+/dev/hdb exist, and occupy BIOS device codes 0x80 and 0x81,
+respectively.  /dev/hdc is BIOS device code 0x82, and /dev/sda is
+BIOS device code 0x83.  If the configuration file looks something
+like:
+
+   boot = /dev/md1
+   #  the following line is not needed, but may be used to
+   #  force the device code which the RAID set will boot as
+   #disk=/dev/md1 bios=0x82
+   #  disks hda and hdb are on the expected bios codes 80 & 81
+   #
+   disk=/dev/hdc bios=0x82
+   disk=/dev/sda bios=0x83
+   #
+   image = /boot/vmlinuz
+      label = linux
+      root = /dev/md1
+      read-only
+   other = /dev/hda
+      label = MBR
+
+then LILO will write the boot record to boot from 0x82, the lowest
+device code of any disk in the RAID set.  An additional boot record
+will be written to the MBR of '/dev/hdc'.  Disk '/dev/sda' is
+bootable should '/dev/hdc' fail under the following circumstance: 
+'/dev/hdc' is removed, freeing BIOS device code 0x82.  '/dev/sda' now
+installs on the lowest code, 0x82, and will boot as long as partition
+1 is marked active.
+
+The same effect could be achieved with the configuration file having
+the extra line:
+
+  raid-extra-boot = /dev/hdc
+
+Further, the use of extra boot records could be extended as follows:
+
+  raid-extra-boot = "/dev/hdc,/dev/sda"
+
+Now both disks in the RAID set have usable boot records on the MBRs. 
+There is no need to worry about "active" partitions in a recovery
+situation.
+
+
+BACKWARD COMPATIBLITY
+=====================
+
+Backward compatibility with earlier versions of LILO raid is provided
+by (versions 21 through 21.7.5)
+
+   raid-extra-boot = mbr-only
+
+Use of "mbr-only" defeats writing the boot record to the RAID
+partition, '/dev/md1' in the examples above, defeats the protection
+against writing to the MBR of BIOS device 0x80 (which is usually
+'/dev/hda' or '/dev/sda'), and writes to all MBRs of the drives in
+the RAID set.  Except for not writing to the boot record of the 
+raid partition, this option is otherwise the same as the "raid-
+extra-boot=mbr" specification discussed above.
+
+On XFS filesystems, writing a boot record to the RAID partition itself
+would be catastrophic.  Hence, on XFS filesystems, use of this option
+is MANDATORY.
+
+
+MASTER BOOT RECORDS and ACTIVE PRIMARY PARTITIONS
+=================================================
+
+The active partition, /dev/sda1 in the case above is booted by a
+"Master Boot Record" written to /dev/sda.   LILO may be requested
+to write such a Master record with the command:
+
+   lilo -M /dev/sda     # write master boot record
+
+The Master Boot Record performs the same function as the DOS utility
+'fdisk /mbr', except that the DOS code is only used for the C: drive. 
+The LILO master boot record facility may be placed on sector 0 of
+any drive.  It serves an additional function in RAID1 installations,
+in that it will determine, and pass to the boot sector of the active
+partition the correct BIOS device code of the drive, whether it is
+0x80, 0x81, or higher.
+
+The active partition may be set with the -A flag; viz.,
+
+   lilo -A /dev/sda 1   # note the space!!!
+
+or checked; viz.,
+
+   lilo -A /dev/sda     # check active partition
+
+(response:  /dev/sda1)
+
+
+REMINDERS
+=========
+
+Unstated, but required by an installation of LILO to a RAID
+partition, all of the files used in booting must reside on the RAID
+set.  This means:  initrd, kernel, and message files; plus the LILO
+internal files:  map, boot.b, and chain.b, if used.  Normally, the
+internal files are kept in the '/boot' directory.  Many distributions
+of Linux also place the kernel and initrd files in this same
+directory.  Others place them in the root, '/', directory.  Either
+location is acceptable, as long as they are within the same RAID
+partition which you are making bootable.
+
+LILO variations:  version 22.2 enforces the placement of the map file
+on the RAID parition.  Version 22.3 eliminates the need for the
+boot.b and chain.b files, and relaxes the restriction that the
+message file be on the RAID partition by copying it into the map
+file.  Likewise, any bitmap= file is copied into the map file, so it
+too may reside anywhere.  It remains the user's responsibility to see
+that the Kernel and Initrd files are on the bootable raid partition. 
+The /boot directory, with the map file, is the recommended location for
+these files.
+
+If for some reason you want to write the MBR of BIOS device 0x80, you
+will have to specify it explicitly.  Since LILO tells you where all
+other auxiliary boot records have been written, if any, you will have
+to mention these in addition to the MBR on drive 0x80.
+
+(versions 22.0 through 22.4.1):
+When making an installation of LILO to a RAID set, remember that LILO
+will only make the disk with the lowest device code bootable.  For
+very many RAID installations, this will be BIOS device code 0x80. 
+The second and succeeding disks in the RAID set are not bootable in
+the running RAID configuration; they only become bootable if the disk
+on device code 0x80 is removed, so that one of them becomes BIOS
+drive 0x80.
+
+
+ERROR MESSAGES (versions 22.0 through 22.4.1):
+==============
+
+If LILO is unable to write all of the auxiliary boot records it would
+like, or your map file is not on the RAID partition, you will get the 
+error message:
+
+  "Warning: FLAG_RAID_NOWRITE has been set"
+
+This warning has two consequences.  First, the clearing the '-R'
+stored command line will not take place; 'lock' will not work
+properly; and 'fallback' will not work properly.  All of these LILO
+options require LILO to re-write the stored boot command line before
+the kernel is booted.  Because RAID set consistency cannot be
+maintained, the boot loader will fall back to a read-only mode of
+operation.  For many installations this is acceptable.  The command
+line switch, '-R' will still work from a running system, since the
+kernel RAID codes will maintain set coherency.
+
+The second consequence of this message, is a warning that not all
+boot records needed for booting in a disk failure scenario were
+written.  The system may boot fine with the lowest BIOS code disk
+running, but be prepared to use a boot floppy in the event this disk
+fails.  This may or may not be acceptable.
+
+This message will most often appear when 'raid-extra-boot=' was
+specified as "none"; or, if specified as (or defaulted to), "auto",
+the extra boot record it could not write was to the MBR of BIOS
+device 0x80, usually '/dev/hda' or '/dev/sda'.  This could happen
+with a skewed installation, where the RAID set partition on BIOS
+device code 0x80 is not a primary partition.  If it were a primary
+partition, then the RAID partition boot record written to '/dev/md?'
+would be used, and there would be no necessity to write to the MBR of
+BIOS disk 0x80.
+
+
+NEW CONSIDERATIONS        (version 22.5 and later)
+==================
+
+Booting is now based upon a 32-bit industry standard Volume ID,
+rather than the 8-bit BIOS device code.  Device codes are still
+generated, but are used primarily as an index into a volume id table. 
+This means that the LILO-installed boot sector must contain the
+volume id of the drive containing the map file, since this is where
+the second stage loader is guaranteed to be located.  The record on
+the first sector of a RAID1 partition is not unique, but is shared
+among all the partitions in the raid set.  These partitions span two
+or more drives.  
+
+The worst case scenario is that the boot scheme falls back to actual
+device codes, and is as reliable as the version 22.4.1 and earlier
+codes.  A failed installation will still boot, as long a the failed
+(first) drive is removed, and the backup (second) drive fills the
+emptied BIOS device code slot formerly occupied by the failed drive.
+
+Version 22.5 (and later) installations are more robust, as long as
+the boot record on the RAID1 partition has access to the BIOS device
+code under which it is booting; or, booting takes place from an
+auxiliary boot record installed using the option "mbr"; or by
+explicit declaration.  Auxiliary boot records are not shared across
+drives, so they may have variations within them, such as their own
+unique volume id's, for use in accessing the correct map file.  (They
+also contain unique offset information, in the case of skewed
+partitions.)
+
+The most fault tolerant systems will be those installed using the
+"mbr" (or "mbr-only") specification.
+
+
+CONSERVATIVE INSTALLATION    (version 22.5.1 and later)
+=========================
+
+The most robust RAID1 installations, PARALLEL or SKEWED, are installed
+with:
+
+   lilo -x mbr
+
+This installation will boot any disk with a RAID partition on any
+BIOS device code. It is not restricted to PARALLEL installations only
+as is the next method.
+
+Equally robust PARALLEL installations will use the new Master Boot
+Record, activate the RAID1 partition on each drive, and install using
+the specification that the MBR bios can be relied upon to pass the
+correct BIOS device code in the DL register:
+
+   lilo -x auto
+     or
+   lilo -x none
+
+will produce a warning message telling you that the following is needed:
+
+   lilo -M /dev/sda    # install new MBR
+   lilo -A /dev/sda 3  # activate the correct partition (# 3)
+   lilo -M /dev/sdb    # install new MBR
+   lilo -A /dev/sdb 2   # activate the correct partition (# 2)
+
+If the partitions of the PARALLEL installation are not all primary, the
+warning message will not be issued, and non-primary partitions will not
+be bootable.  (The MBR from LILO version 22.5.1 or later MUST be used.
+Once installed, it does not have to be re-installed each time you update
+the boot record on the RAID partition.)
+
+Since it is easier to achieve the most robust state of affairs with
+the "-x mbr" or "raid-extra-boot=mbr" specification, it is the
+suggested method of installation.
+
+
+REMEMBER
+========
+
+With a RAID installation, always run:
+
+   lilo -t
+
+first -- just to let LILO tell you what it is about to do.  Use the
+'-v' flag, too, for more verbose output.
+
+
+REFERENCES
+==========
+
+The 'man' pages for "lilo" and "lilo.conf" have been updated, and are
+the main reference material for using the new switches and config
+options.
+
+The 'README' file in the LILO source directory, generated from the
+doc materials, is still the best tutorial on booting, as well as a good
+reference for many of the more obscure lilo options.  The 'man' pages
+now contain most of this reference material, but in a condensed form.
+
+
+CREDITS
+=======
+
+Thanks to Piete Brooks <lilo+pb@cl.cam.ac.uk> for prodding me
+into attacking the RAID1 issues, for his incisive criticism of the
+resulting work as it emerged, and for testing the early codes.
+
+(end)
+written 04/19/01 -- John Coffman <johninsd@san.rr.com>
+updated 05/10/01 -- John Coffman
+updated 08/08/01 -- John Coffman
+updated 03/15/03 -- John Coffman (to version 22.5.1)
+updated 09/07/04 -- John Coffman (spelling & punctuation)
diff --git a/readme/README.volumeID b/readme/README.volumeID
new file mode 100644 (file)
index 0000000..78116b0
--- /dev/null
@@ -0,0 +1,239 @@
+          Technical Documentation for LILO 22.5 and later
+               Use of the Volume ID (aka serial number)
+
+                       updated: 20-May-2003
+
+
+MOTIVATION
+==========
+
+In the past, the biggest headache to getting LILO to boot reliably was the
+determination of the assignment of BIOS device codes to disks.  This
+assignment is made by the BIOS, and is quite simple on single hard disk
+systems:  the hard disk receives BIOS device code 0x80.  However, even two
+disk systems can confuse LILO if the disks are attached non-sequentially:
+viz., if the disks are /dev/hda and /dev/hdb, they are assigned device codes
+0x80 and 0x81, respectively; however, if the disks are /dev/hda and /dev/hdc
+(perhaps, /dev/hdb is an IDE CDROM), LILO will mistakenly think that the
+second disk is 0x82.  Just because /dev/hdb is not mentioned in the
+configuration file (/etc/lilo.conf), does not mean that it does not exist. 
+But on a two-disk system, attaching the second disk to the second IDE
+controller has performance advantages.  The solution was to explicitly tell
+LILO, in the configuration file, that the second disk was attached as
+/dev/hdc:  viz.,
+
+   disk = /dev/hda   bios = 0x80
+   disk = /dev/hdc   bios = 0x81
+
+
+The above assignment can be determined automatically in most cases, if the
+system was booted with a recent version of LILO that supports the "BIOS data
+check".  This scheme makes the results of certain key BIOS calls available
+to the Boot Installer (/sbin/lilo), even though it cannot execute BIOS calls
+directly (far too dangerous).  However, if one used a rescue disk created
+with another boot loader, the BIOS data check information is not available,
+and the necessity of the two lines above becomes necessary for the initial
+installation of LILO.
+
+The BIOS device code assignment situation becomes very unpredictable on
+systems with multiple disk controllers:  IDE and SCSI, IDE and super-IDE, or
+three or more controllers.
+
+Very recent BIOS's now recognize multiple controllers, and will allow
+designation of ANY disk on ANY controller as the first hard disk to boot. 
+Since this disk is the boot disk, it will receive BIOS device code 0x80, and
+the other disks will received BIOS device codes in some order (known only to
+the BIOS).  Booting from a different disk tomorrow, the BIOS device codes
+will be assigned in a still different manner.  Hence, on today's newest
+systems, the BIOS device code is quite variable, a major departure from the
+past.
+
+
+THE VOLUME ID
+=============
+
+LILO for over four years now, has been aware of an 8 byte area of the Master
+Boot Record (sector 0) lying just below the Partition Table.  DR-DOS and
+Windows NT have used 4 bytes of this area for some years now as a unique
+32-bit Volume ID, or disk Serial Number.  The usage continues with Windows
+2000, and probably Windows XP (I haven't used this last, but this is a good
+guess.)  As far as I know, Windows 98 and earlier never use this Volume ID.
+
+The power of a unique 32-bit identifier on each physical disk volume, is
+that a volume can now be identified, even if the BIOS device code changes. 
+So, since the LILO boot record is limited to one sector, and its main goal
+is to get the bulk of the boot loader into memory, the boot sector no longer
+needs to know the BIOS device code of the Second Stage Loader; it now needs
+to know the Volume ID of the disk which contains the Second Stage Loader. 
+In the past, if the BIOS device code of the volume with the Second Stage
+Loader ever changed, the dreaded:
+
+L 01 01 01 01 01 01 ...
+
+screen would indicate the failure of the First Stage (boot sector) to
+successfully load the Second Stage.  Sometimes the BIOS error code varied,
+but the result was the same:  time to go find the rescue floppy.
+
+
+LILO 22.5
+=========
+
+Beginning with 22.5, LILO now insists that every disk have a unique 32-bit
+identifier in the Volume ID field, and that all volume ID's on a system are
+unique.  BIOS device codes are still assigned, but they are no more that
+indices into a table of Volume ID's written into the Second Stage Loader
+parameter area.  With the table of Volume ID's, a correspondence may be
+established between BIOS device codes at install-time, and BIOS device codes
+at boot-time.  If a tranlation from one BIOS device code to another is
+needed, it will be made.
+
+Version 22.5 treated only 0x00000000 as an "empty" (or unassigned) Volume
+ID, and would generate a new one.  Version 22.5.1 treats 0xFFFFFFFF as an
+unassigned Volume ID also.  More recent field experience indicates that some
+low-level format programs leave a residue of identical bytes behind, so
+version 22.5.4 now treats ANY occurrence of repeated bytes in the Volume ID
+field as unassigned:  viz.,
+
+       0x00000000
+       0x6c6c6c6c
+       0xa5a5a5a5
+       0xFFFFFFFF
+
+are all considered to be "unassigned" Volume ID's, and will be filled in
+with a unique 32-bit value.  Any other combination of bits, whether assigned
+by LILO, or by Windows NT, or by DR-DOS, will be treated as valid, and will
+not be altered by LILO, except on explicit command.
+
+Note:  Any failure to locate a Volume ID during the boot process will cause
+the LILO loader to fall back to the BIOS device code assigned at
+install-time.  Hence, the boot algorithm will fall back to the older 22.4
+and earlier scheme, where BIOS device codes are considered fixed.  Thus it
+is a good idea to get them right at install-time, but no longer absolutely
+mandatory with Volume ID's in place.
+
+
+PICTURE OF A MASTER BOOT RECORD
+===============================
+
+The Master Boot Record is sector 0 (cylinder 0, head 0, sector 1) of every
+hard disk.
+
+struct BootSector {
+    char code[0x1b6];  /* boot code, BPB, other stuff */
+
+    short unused;      /* spacer, which is not used AFAIK */
+    long  Volume_ID;   /* 32-bit unique physical volume ID */
+    short marker;      /* who wrote the Volume ID */
+
+    struct PartitionTable {
+       char pt_entry[16];      /* primary partition table entry */
+    } partitions[4];   /* entire partition table is 64 bytes */
+
+    short bootID;      /* MUST be 0xAA55 to indicate disk is bootable */
+} boot_sector;         /* size must be exactly 512 bytes */
+
+Note:  Floppy disks do not contain partition tables; hence, floppies do not
+ever have Volume ID's, per the scheme above.  Floppy disk booting is based
+on BIOS device code, as with all previous versions of LILO.
+
+
+VOLUME ID MAINTENANCE
+=====================
+
+1. Duplicate Volume ID's
+
+LILO will complain if two disks have duplicate Volume ID's.  This usually
+happens when the Volume ID field is a residue of a low-level format, or a
+residue of some older boot program which overwrites the Volume ID field. 
+With duplicated Volume ID's, LILO will be unable to distinguish the two
+offending disks at boot-time, hence it may make an error and read the wrong
+disk.  Thus, it will refuse to install a boot loader as long as this
+condition persists.  Unassigned ID's are automatically overwritten, and a
+backup copy of the sector is created, so the fix is to write an "unassigned"
+value to one of the duplicated fields.  Say /dev/hda and /dev/hdb have
+duplicate Volume ID's.  Choose the disk with the higher BIOS device code,
+since it will not be a Windows NT or 2000 disk, and set the Volume ID to
+zero; viz.,
+
+       lilo -z -M /dev/hdb
+
+The disk will receive a new Master Boot Record (which boots the first active
+partition), and the Volume ID will be set to zero.  A subsequent
+installation of LILO:
+
+       lilo -v
+
+Should no longer complain about duplicated Volume ID's on /dev/hda and
+/dev/hdb.  /dev/hdb will at this time receive a newly generated Volume ID,
+which will be checked for uniqueness against all other disks in the system.
+
+CAUTION:  NEVER CHANGE THE VOLUME ID OF A WINDOWS 2000 BOOT DISK.
+
+Windows NT, 2000, and XP (presumably), all use the Volume ID during the boot
+process.  Changing the ID can render Windows unbootable.  Recovery seems to
+be possible by zeroing the Volume ID, although Windows would prefer that the
+Boot Volume ID remain unchanged.  No trouble has been encountered with
+changing the Volume ID of Windows 2000 data disks, other than the necessity
+of resetting the drive letter to its former value.  Basically, if you run
+Windows NT or later, your disks probably already have Volume ID's assigned
+by Windows.  If they do, leave them alone.  The Windows ID's are completely
+compatible with the LILO scheme, and vice versa.
+
+2.  Volume ID check
+
+The following command was added in LILO 22.5.4:
+
+       lilo -T vol-ID
+
+The volume ID's will be printed in BIOS order (as of the most recent LILO
+boot), based upon the BIOS data check information.  If you did not boot with
+LILO the last time, then the information as of the last boot will not be
+available.  Any conflicts will be noted, along with the corrective action
+LILO will take the next time a boot loader is installed (/sbin/lilo
+command).  This is the preferred check of the state of Volume ID's on the
+disks.
+
+Sample output from "lilo -T vol-id":
+
+  BIOS     Volume ID
+
+  0x80     B21AB21A 
+  0x81     EBF5EB74 
+  0x82     EBF5EB7B 
+  0x83     34225390 
+  0x84     78711C09 
+
+Volume ID's are all unique.
+
+
+A volume ID check (Volume S/N) will be printed with the following command:
+
+       lilo -t -v2
+
+The "-t" switch means a "test mode" install, with no boot record written,
+and your system unmodified.  The "-v2" is needed to set the verbosity of the
+output high enough to print the table of BIOS device codes used by LILO (not
+necessarily the same as the BIOS itself), and the corresponding disk Volume
+ID's.  This information indicates the order of the BIOS device code
+translate table, as it would be set up for the next boot.  Disks are
+indicated by major/minor device numbers, in hex.
+
+Sample output from "lilo -t -v2 | tail":
+
+...
+Mapped 6 (4+1+1) sectors.
+Added Windows
+
+ BIOS  Volume S/N  Device
+  80    B21AB21A    0300
+  81    EBF5EB74    0340
+  82    EBF5EB7B    1600
+  83    34225390    2100
+  84    78711C09    0800
+The boot sector and the map file have *NOT* been altered.
+
+
+In the two examples above, the Volume ID's are in the same BIOS order,
+indicating that the BIOS device codes are being assigned by LILO for the
+boot loader in the correct sequence on this 5 disk system.
+
diff --git a/sample/Makefile b/sample/Makefile
new file mode 100644 (file)
index 0000000..aaf1670
--- /dev/null
@@ -0,0 +1,17 @@
+# -*- makefile -*-
+
+# adding variables
+include ../make.vars
+
+all:
+
+install:
+       mkdir -p $$DESTDIR$(CFG_DIR)
+       install -m 0644 lilo.example.conf $$DESTDIR$(CFG_DIR)/lilo.conf_example
+
+clean:
+
+distclean:
+
+uninstall:
+       rm -f $$DESTDIR$(CFG_DIR)/lilo.conf_example
diff --git a/sample/lilo.example.conf b/sample/lilo.example.conf
new file mode 100644 (file)
index 0000000..b82bcf7
--- /dev/null
@@ -0,0 +1,189 @@
+# /etc/lilo.conf  -   systemwide LILO configuration (LILO 23)
+# details see in manpages: lilo(8) and lilo.conf(5)
+
+# +-------------------------------------------------------------+
+# |                        !! Reminder !!                       |
+# |                                                             |
+# | Don't forget to run 'lilo' after you make changes to this   |
+# | conffile or you have installed a new kernel.                |
+# +-------------------------------------------------------------+
+
+
+# #################### LILO global section ######################
+
+# With all newer systems (until year 2004) you can use the RAM
+# above 15 MB. This option allows the use of this range of RAM.
+#large-memory
+
+# With all newer systems you can boot from any partition on disks 
+# with more than 1024 cylinders. This option allows the use of 
+# partitions above 1024 cylinders.
+lba32
+
+# Specifies the boot device.  This is where Lilo installs its boot
+# block.  It can be either a partition, or the raw device, in which
+# case it installs in the MBR, and will overwrite the current MBR.
+# With newer kernel you should use the ID of the boot device, which
+# can be found here: /dev/disks/by-id/ata*.
+boot = /dev/sda
+
+# This option may be needed for some software RAID installs.
+#raid-extra-boot = mbr-only
+
+# Enable map compaction.  This tries to merge read requests for 
+# adjacent sectors into a single read request. This drastically 
+# reduces load time and keeps the map smaller.  Using 'compact' 
+# is especially recommended when booting from a floppy disk.  
+# It is disabled here by default because it doesn't always work.
+#compact
+
+# Set the verbose level for bootloader installation. Value range:
+# 0 to 5. Default value is 0.
+#verbose = 1
+
+# Specifies the location of the map file. Lilo creates the (sector) 
+# map file of direct sector addresses which are independent of any
+# filesystem.
+map = /boot/map
+
+# ---------------------------------------------------------------
+
+# Specifies the menu interface. You have the choice between:
+#   text: simple text menu with black background and white text
+#   menu: configurable text menu with background and text colors.
+#   bmp:  graphical menu with 640x480 bitmap background.
+install = menu
+
+# A) Customized boot message for choice 'text'.
+# For the simple text menu you can set an extra message in the 
+# created file. Its text will be displayed before boot prompt.
+#message = /boot/message.txt
+
+# B) Configuration of the scheme for choice 'menu'.
+# Use following coding: <text>:<highlight>:<border>:<title>
+# The first character of each part sets the text frontcolor, 
+# the second character of earch part sets the text backcolor,
+# an upper-case character sets bold face text (frontcolor).
+# i.g. 'menu-scheme=wm:rw:wm:Wm'. Possible colors: 
+# k=black, b=blue, g=green, c=cyan, r=red, m=magenta, y=yellow, w=white.
+menu-scheme = Wb:Yr:Wb:Wb
+#menu-title = " DESDEMONA Boot-Manager "
+
+# C) Configuration of the image for choice 'bmp'.
+# For the graphical menu you need a bitmap file, which needs a special
+# menu configuration in the file header (see: lilo -E). Ideally you 
+# use one of the delivered images of the lilo package.
+#   with 16 colors:    onlyblue, tuxlogo, inside
+#   with 256 colors:   coffee
+#   for Debian:        debianlilo, debian, debian-de
+#bitmap = /boot/tuxlogo.bmp
+
+# ---------------------------------------------------------------
+
+# Specifies the number of deciseconds (0.1 seconds) how long LILO 
+# should wait before booting the first image.  LILO doesn't wait if
+# 'delay' is omitted or set to zero. You do not see the defined menu.
+#delay = 20
+
+# Prompt to start one certain kernel from the displayed menu.
+# It is very recommeded to also set 'timeout'. Without timeout boot 
+# will not take place unless you hit return. Timeout is the number
+# of deciseconds (0.1 seconds) after there the default image will 
+# be started. With 'single-key' alias numbers for each menu line can
+# be used.
+prompt
+timeout = 100
+#single-key
+
+# ---------------------------------------------------------------
+
+# Specifying the VGA text mode that should be selected when booting.
+# The following values are recognized (case is ignored):
+#   vga=normal    80x25 text mode (default)
+#   vga=extended  80x50 text mode (abbreviated to 'ext')
+#   vga=ask       stop and ask for user input: choice of text mode
+#   vga=<mode>    use the corresponding text mode number. A list of  
+#                   available modes can be obtained by booting with  
+#                   vga=ask'  and then pressing [Enter].
+# Another way is the use of frame buffer mode. Then the kernel 
+# will switch from the normal vga text mode (80x25) to the frame
+# buffer mode (if frame buffer support is in the kernel):
+#   vga=0x314      800x600 @ 16 bit
+#   vga=0x317     1024x768 @ 16 bit
+#   vga=0x318     1024x768 @ 24 bit
+#vga = ask
+vga = normal
+#vga = 0x317
+
+# ---------------------------------------------------------------
+
+# Kernel command line options that apply to all installed images go
+# here.  See 'kernel-parameters.txt' in the Linux kernel 'Documentation'
+# directory. I.g. for start into 'init 5' write:  append="5"
+#append = ""
+# If you used a serial console to install Debian, this option should be
+# enabled by default.
+#serial = 0,9600
+
+# Set the image which should be started after delay or timeout.
+# If not set, the first defined image will be started.
+#default = Linux
+
+
+# ################### LILO per-image section ####################
+
+# Each image is configured with the linux kernel (=image) and
+# usually with the initrd file. Configure all GNU/Linux systems
+# on other partitions, too.
+
+# first example (default)
+image = /boot/vmlinuz-2.6.32-2-generic
+       label = "Linux"
+       root = /dev/sda2
+       read-only
+#      restricted
+#      alias = 1
+#      optional
+       initrd = /boot/initrd.img-2.6.32-2-generic
+
+# second example
+image = /boot/vmlinuz-2.6.32-1-generic
+       label = "LinuxOLD"
+       root = /dev/sdb1
+       read-only
+#      restricted
+#      alias = 2
+       optional
+       initrd = /boot/initrd.img-2.6.32-1-generic
+
+# third example
+image = /mnt/testsystem/boot/vmlinuz-2.6.26-1-custom
+       label = "Testsystem"
+       root = /dev/sda3
+       read-only
+#      restricted
+#      alias = 3
+       optional
+       initrd = /mnt/testsystem/boot/initrd.img-2.6.26-1-custom
+
+# other examples
+# Booting other OS on this machine must set with 'other'. Changing 
+# the device name on the `other' line to the partition of your other 
+# system.
+
+other = /dev/sda1
+       label = "Windows XP"
+#      restricted
+#      alias = 4
+
+other = /dev/sdb2
+       label = "GNU/Hurd"
+#      restricted
+#      alias = 5
+
+other = /dev/sdb3
+       label = "Windows 2003"
+#      restricted
+#      alias = 6
+       boot-as = 0x80
diff --git a/sample/lilo.old-raid.conf b/sample/lilo.old-raid.conf
new file mode 100644 (file)
index 0000000..f2c4aad
--- /dev/null
@@ -0,0 +1,120 @@
+#
+#   lilo.raid.conf
+#
+#
+# A RAID installation is called for.  With (version 22) of LILO
+# the boot record will be installed on the RAID partition.  The
+# Master Boot Record will find the record on (hda2), which is marked
+# as an active partition.  (sdb1) is also marked active.  If (hda) fails,
+# it will be possible to boot by disabling the IDE controller in BIOS,
+# which will cause (sdb) to become device 0x80, and boot appropriately.
+
+boot = /dev/md1
+
+#
+# Auxiliary boot records will be installed automatically.  Since
+# this is a PARALLEL raid device, there will be no boot records
+# other that the one written to the RAID set  (sdb1, hda2).
+
+raid-extra-boot = auto
+
+#
+# The SCSI controller BIOS assigns device codes backwards
+# from what one might expect, so we make the BIOS device
+# code assignment by the BIOS explict:
+
+disk=/dev/hda
+   bios=0x80
+disk=/dev/sda
+   bios=0x82
+disk=/dev/sdb
+   bios=0x81
+
+#
+# Always prompt for a boot selection, timing out after
+# 30.0 seconds
+
+prompt
+  timeout=300
+
+#
+# Use the MENU interface, specifying the title and color scheme
+#
+#install = /boot/boot-menu.b   # versions before 22.3
+
+install = menu                 # syntax since 22.3 ("text", "menu", "bmp")
+menu-title = " RAID boot on CARMEN "
+menu-scheme = "wk:Wg:wk:Gk"
+
+#
+#  Specify the kernel to boot if the use makes no selection
+#  withing the 'timeout=' period.
+
+default=linux
+
+# 
+#  Both kernels below use the same root directory, which
+#  is mounted initially "read-only"
+
+root=/dev/md1
+  read-only
+
+
+#########################################
+# end sample-raid.conf Global section  #
+#########################################
+
+#
+#  This is the kernel we usually boot
+
+image=/boot/vmlinuz-2.4.2-2
+       label=linux 
+       append="reboot=warm"
+       initrd=/boot/initrd-2.4.2-2.img
+
+#
+#  This is an alternate kernel
+
+image=/boot/vmlinuz-2.2.14-5.0
+       label=linux.bak
+       append="reboot=warm"
+       initrd=/boot/initrd-2.2.14-5.0.img
+
+#
+#  This system also will run DOS, but we have
+#  to fake DOS into thinking it is booting from
+#  drive C:
+
+other=/dev/sdb2
+       label=dosB2
+       map-drive = 0x80  to = 0x81
+       map-drive = 0x81  to = 0x82
+       map-drive = 0x82  to = 0x80
+
+#
+#  We can boot OS/2 from a secondary partition.  The 'table='
+#  specification tells OS/2 that the secondary (boot) parition
+#  mounts as drive E:.  Versions of LILO prior to version 22 will 
+#  require a special boot loader, but as of version 22, all
+#  chain loader functions have been combined into the default
+#  chain loader, '/boot/chain.b'.
+
+other=/dev/sda5
+#      loader=/boot/os2_d.b
+       label=os2
+       table=E:
+       change
+         partition=/dev/hda1
+           set=DOS16_big_hidden
+         partition=/dev/hda2
+           set=NTFS_hidden
+
+#  Partition change rules are required to force drive E: to 
+#  be assinged properly.  MS & IBM partitions may be NORMAL
+#  or HIDDEN.
+
+#########################################
+# end sample-raid.conf                 #
+#########################################
+
+
diff --git a/sample/lilo.old-special.conf b/sample/lilo.old-special.conf
new file mode 100644 (file)
index 0000000..adac51d
--- /dev/null
@@ -0,0 +1,152 @@
+#
+#  lilo.sample.conf
+#
+#      This example has been updated to version 22.5.5 and beyond
+#
+# The boot record is installed on the second primary partition
+# Which will have to be marked active to get to it.
+
+boot = /dev/hda2
+
+#
+# The map file is placed in the default location, but
+# we change the name to '.map', since it is a critical system file.
+# DON'T use "System.map" -- you'll overwrite the kernel loader map.
+# lilo CREATES the (sector) map file of direct sector addresses which
+# are independent of any filesystem.
+
+map = /boot/.map
+
+#
+# LBA32 is needed to address all sectors of the 27Gb disks
+# on this system
+
+lba32
+
+#
+# We ask for the MENU interface (works on VGA, EGA, and MDA video cards)
+# by installing this boot loader:
+
+install = menu         # syntax since version 22.3 (see the man pages)
+#install = /boot/boot-menu.b   # outdated syntax, but selection is based on
+                               # the substring "menu", so it still works
+
+#
+# and specify the color scheme and menu title
+# for the computer named DESDEMONA
+
+menu-scheme=wm:rw:wm:Wm
+menu-title=" DESDEMONA (2.4.2) boot "
+
+#
+# We always want to see the prompt with a 15 second timeout
+
+prompt
+timeout=150
+
+# 
+# If a LOCKed command line, or pre-stored command line is present
+# delay 3 seconds to allow cancellation with the Shift key (or Alt, or Ctrl)
+
+delay=30
+
+#
+# All filesystems will initially be mounted 'read-only'
+
+read-only
+
+#
+# Booting may be performed from the serial interface 
+
+serial=0,9600
+
+#
+# All other= sections use this chain loader (version 22)
+
+#loader=/boot/chain.b          # outdated; there is now only one chain
+                               # loader, so this line is not really needed
+
+# This system is complicated -- leave no doubt about how the
+# BIOS has assigned the device codes:
+
+disk=/dev/hda  bios=0x80
+disk=/dev/hdb  bios=0x81
+disk=/dev/hdc  bios=0x82
+disk=/dev/sda  bios=0x83
+disk=/dev/sdb  inaccessible            # has no device code, so mark it
+                                       # off-limits
+disk=/dev/fd0   bios=0x00              # got a 2.88Mb floppy, so specify all
+       sectors=36  heads=2  cylinders=80
+
+# Version 22.5.6 and later will likely get the drive assignment correct, so
+# the above really applies to earlier LILO versions.  
+
+#################################################
+# end of sample-lilo.conf Global section       #
+#################################################
+
+#
+# The first image is the default image
+
+image=/dd/boot/vmlinuz-2.4.2
+       label=2.4.2
+       root=current
+       append="reboot=warm"
+
+#
+# Yes, we run Windoze, too
+
+other=/dev/hda1
+       label=win_2k
+       table=/dev/hda
+#      master-boot             # not really needed, since this drive is
+                               # already 0x80, but "master-boot" is a good
+                               # idea to put on any "other=" that must
+                               # boot from the "C:" drive.
+
+
+#
+# This is the backup kernel from RedHat
+
+image=/dd/boot/vmlinuz-2.2.14-5.0
+       label=RH62
+       initrd=/dd/boot/initrd-2.2.14-5.0.img
+       append="reboot=warm"
+       root=/dev/hda7
+
+#
+# The D: drive has a Win98 installation
+# Fake booting from drive C: with the map-drive options
+
+other=/dev/hdb1
+       label=win_98
+#      map-drive=0x80 to=0x81          # obsolete, but still allowed
+#      map-drive=0x81 to=0x80          #
+       boot-as = 0x80                  # 22.5.5 syntax
+       
+#
+# This is an experimental, small kernel
+
+image=/dd/boot/zImage-2.2.14
+       label=zI-2.2.14
+       root=/dev/hda7
+
+#
+# And a route back to the Master Boot Record, if wanted
+
+other=/dev/hda                 # route back to the master LILO boot menu
+       label=MBR               # on the Master Boot Record
+       master-boot             # guarantee that it boots as 0x80
+
+#
+# Allow us to boot the floppy drive from the main LILO boot menu
+
+other=/dev/fd0                 # no "label=", so it appears as "fd0"
+       master-boot             # it boots as the master floppy (0x00)
+       unsafe                  # and it may not be inserted, so do not 
+                               # try to read the boot sector during LILO
+                               # installation
+
+#################################################
+# end of sample-lilo.conf                      #
+#################################################
diff --git a/src/Makefile b/src/Makefile
new file mode 100644 (file)
index 0000000..d1c142e
--- /dev/null
@@ -0,0 +1,317 @@
+# -*- makefile -*-
+
+# adding variables
+include ../make.vars
+
+#
+#  Do not modify anything below this point
+#
+
+SHELL=/bin/sh
+CC=gcc
+CPP=$(CC) -E
+AS86=as86 -0 -a
+LD86=ld86 -0
+NASM=nasm
+G=`cat foo1 foo2 | grep version | cut -d " " -f 3`
+
+CFLAGS=$(OPT) -Wall -g $(PCONFIG)
+LDFLAGS=#-Xlinker -qmagic
+LIBS=$(DEVMAPPER)
+
+OBJS=lilo.o raid.o map.o geometry.o boot.o device.o common.o bsect.o cfg.o \
+  partition.o identify.o probe.o shs2.o edit.o temp.o
+
+EDIT=edit.c common.o
+
+LIS=chain.lis disk.lis dparam.lis os2_d.lis first.lis second.lis \
+  bootsect.lis third.lis mbr.lis bitmap.lis pseudo.lis mbr2.lis \
+  pseudo1.lis loader.lis pseudo3.lis
+BFILES=first.b second.b third.b bitmap.b chain.b mbr.b mbr2.b \
+  bootsect.b pseudo1.b pseudo2.b pseudo3.b
+CFILES=boot.c bsect.c cfg.c common.c device.c edit.c geometry.c \
+  identify.c lilo.c map.c partition.c probe.c raid.c shs2.c temp.c
+HFILES=bdata.h bitmap.h boot.h bsect.h cfg.h common.h config.h device.h \
+  edit.h geometry.h identify.h lilo.h loader.h map.h md-int.h partition.h \
+  probe.h raid.h shs2.h temp.h version.h vesainfo.h
+
+.SUFFIXES:     .img .b .com .S .s
+
+
+#
+# everything needed to run, just short of installation
+#
+all:   lilo bootsect.b
+
+#
+# everything above plus the statically linked version
+#
+alles: all diag1.img lilo.static
+
+#
+# make the bootable diagnostic floppies
+#
+floppy1: disk.com bootsect.b
+       @echo
+       @echo Creating Diagnostic Floppy 1.6
+       @echo
+       @echo Insert a blank, formatted, floppy into drive 0
+       @echo "Press <Enter> to continue, <^C> to abort ..."
+       @read
+       cat bootsect.b disk.com | dd of=/dev/fd0 bs=512
+
+floppy2: disk.b
+       @echo
+       @echo Creating Diagnostic Floppy 2.4
+       @make -C ../diagnose check
+       @make -C ../diagnose floppy
+
+diagnostic: ../test.img diag1.img diag2.img diag3.img
+
+manpath:
+       echo $(MAN_DIR)
+
+.c.o:
+               $(CC) -c $(CFLAGS) $*.c
+
+.s.o:
+               $(AS86) -w -l $*.lis -o $*.o $*.s
+
+.o.img:
+               $(LD86) -s -o $*.img $*.o
+
+.img.b:
+               dd if=$*.img of=$*.b bs=32 skip=1
+
+edit:          $(EDIT)
+               $(CC) -Wall -s -O -DSTANDALONE -o edit $(EDIT) $(LDFLAGS)
+
+loader.i:      mkloader first.b second.b third.b bitmap.b mbr.b \
+                       chain.b os2_d.b mbr2.b
+               ./mkloader >loader.i
+
+disk.com:      disk.b
+               cp disk.b disk.com
+
+disk.s:                disk.S read.S bdata.h biosdata.S lilo.h Makefile
+               $(CPP) -traditional $(PCONFIG) -o disk.s  disk.S
+
+mbr.s:         mbr.S lilo.h Makefile
+               $(CPP) -traditional $(PCONFIG) -DMBR=0xafbbe760 \
+                       -o mbr.s  mbr.S
+
+mbr.b:         mbr.img
+               dd if=$*.img of=$*.b bs=32 skip=49
+
+mbr2.s:                mbr.S lilo.h Makefile
+               $(CPP) -traditional $(PCONFIG) -DMBX=0x93c00848 \
+                       -o mbr2.s  mbr.S
+
+mbr2.b: mbr2.img
+       dd if=$*.img of=$*.b bs=32 skip=49
+
+bootsect.s: bootsect.S disk.b
+       $(CPP) -traditional $(PCONFIG) \
+               -DSIZEDISKB=`wc -c <disk.b | sed "s/ //g"` \
+               -o bootsect.s  bootsect.S
+
+pseudo1.s: bootsect.S pseudo.S disk.com
+       cat bootsect.S pseudo.S >$(TMP).S
+       $(CPP) -traditional $(PCONFIG) \
+               -DSIZEKRNL=`wc -c <disk.com | sed "s/ //g"` \
+               -DSIZEDISKB=512 -o pseudo1.s $(TMP).S
+       rm -f $(TMP).S
+
+pseudo2.s: bootsect.S pseudo.S
+       make -C ../diagnose all
+       cat bootsect.S pseudo.S >$(TMP).S
+       $(CPP) -traditional $(PCONFIG) \
+               -DSIZEKRNL=`wc -c <../diagnose/test4.com | sed "s/ //g"` \
+               -DSIZEDISKB=512 -o pseudo2.s $(TMP).S
+       rm -f $(TMP).S
+
+pseudo3.s: bootsect.S pseudo.S
+       make -C ../diagnose all
+       cat bootsect.S pseudo.S >$(TMP).S
+       $(CPP) -traditional $(PCONFIG) \
+               -DSIZEKRNL=`wc -c <../diagnose/test5.com | sed "s/ //g"` \
+               -DSIZEDISKB=512 -o pseudo3.s $(TMP).S
+       rm -f $(TMP).S
+
+pseudo1.b:     pseudo1.s
+pseudo2.b:     pseudo2.s
+pseudo3.b:     pseudo3.s
+
+
+diag1.img:     disk.com pseudo1.b
+       cat pseudo1.b disk.com >diag1.img
+
+diag2.img: pseudo2.b
+       make -C ../diagnose all
+       cat pseudo2.b ../diagnose/test4.com >diag2.img
+
+diag3.img: pseudo3.b
+       make -C ../diagnose all
+       cat pseudo3.b ../diagnose/test5.com >diag3.img
+
+flags.i:       ../test.img Makefile version $(CFILES) $(HFILES)
+       echo "#define CFLAGS \"" $(CFLAGS) "\"" >flags.i
+       tail -$$((`wc -l <Makefile`-`sed /\#\#\#/q <Makefile | wc -l`)) \
+         <Makefile | grep -v "0x" >$(TMP)
+       for i in $(CFILES) $(HFILES) ; do cat $$i >>$(TMP) ; done
+       echo "#define CSOURCE " `./version $(TMP)` >>flags.i
+       rm -f $(TMP)
+
+
+dparam.com:    dparam.img
+               dd if=dparam.img of=dparam.com bs=288 skip=1
+
+dparam.s:      dparam.S
+               cp -p dparam.S dparam.s
+
+lilo:          $(OBJS)
+               $(CC) -o lilo $(LDFLAGS) $(OBJS) $(LIBS)
+
+lilo.static:   $(OBJS)
+               $(CC) -o lilo.static -static $(LDFLAGS) $(OBJS) $(LIBS)
+
+common.s:      common.h
+               $(CPP) -C -traditional -DLILO_ASM -o common.s common.h
+
+bitmap.o: bitmap.s common.s
+third.o: third.s common.s
+second.o: second.s common.s
+first.o: first.s common.s
+chain.o: chain.s common.s
+
+first.s:       first.S lilo.h version.h Makefile
+               $(CPP) $(PCONFIG) -DFIRST=0x62177489 -o first.s first.S
+
+second.s:      second.S read.S volume.S mapper.S biosdata.S shs3.S bdata.h lilo.h version.h \
+                       graph.S menu.S strlen.S bitmap.S crt.S display4.S Makefile
+               $(CPP) $(PCONFIG) -DTEXT=0x9dd476ec second.S -o second.s
+
+third.s:       second.S read.S volume.S mapper.S biosdata.S shs3.S bdata.h lilo.h version.h \
+                       graph.S menu.S strlen.S bitmap.S crt.S display4.S Makefile
+               $(CPP) $(PCONFIG) -DMENU=0x2012a4a7 second.S -o third.s
+
+bitmap.s:      second.S read.S volume.S mapper.S biosdata.S shs3.S bdata.h lilo.h version.h \
+                       graph.S menu.S strlen.S bitmap.S crt.S display4.S Makefile
+               $(CPP) $(PCONFIG) -DBITMAP=0x2ece2fbe second.S -o bitmap.s
+
+chain.s:       chain.S lilo.h version.h first.b Makefile
+               $(CPP) $(PCONFIG) -DCHAIN=0x536a7646 chain.S -o chain.s
+
+os2_d.s:       chain.S lilo.h version.h first.b Makefile
+               $(CPP) $(PCONFIG) chain.S -DDOS_D -o os2_d.s
+
+xxx.s:         chain.S lilo.h Makefile
+               $(CPP) chain.S -DXXX -o xxx.s
+
+$(OBJS):       Makefile
+
+#
+# shorthand install, if one knows that one has the 'bcc' compiler
+#
+ins:   diag install
+
+#
+#  normal install, but doesn't make the diagnostic binaries
+#
+install:
+       mkdir -p $$DESTDIR$(SBIN_DIR) $$DESTDIR$(CFG_DIR) 
+       mkdir -p $$DESTDIR$(BOOT_DIR) $$DESTDIR$(USRSBIN_DIR)
+
+       @if [ -e $$DESTDIR$(BOOT_DIR)/boot.b -o -e $$DESTDIR$(BOOT_DIR)/boot.old ]; then \
+         rm -f $$DESTDIR$(BOOT_DIR)/boot.b; rm -f $$DESTDIR$(BOOT_DIR)/boot.old; fi
+       @if [ -f $$DESTDIR$(BOOT_DIR)/boot-bmp.b -o -f $$DESTDIR$(BOOT_DIR)/boot-bmp.old ]; then \
+         rm -f $$DESTDIR$(BOOT_DIR)/boot-bmp.b; rm -f $$DESTDIR$(BOOT_DIR)/boot-bmp.old; fi
+       @if [ -f $$DESTDIR$(BOOT_DIR)/boot-menu.b -o -f $$DESTDIR$(BOOT_DIR)/boot-menu.old ]; then \
+         rm -f $$DESTDIR$(BOOT_DIR)/boot-menu.b; rm -f $$DESTDIR$(BOOT_DIR)/boot-menu.old; fi
+       @if [ -f $$DESTDIR$(BOOT_DIR)/boot-text.b -o -f $$DESTDIR$(BOOT_DIR)/boot-text.old ]; then \
+         rm -f $$DESTDIR$(BOOT_DIR)/boot-text.b; rm -f $$DESTDIR$(BOOT_DIR)/boot-text.old; fi
+       @if [ -f $$DESTDIR$(BOOT_DIR)/chain.b ]; then \
+         mv $$DESTDIR$(BOOT_DIR)/chain.b $$DESTDIR$(BOOT_DIR)/chain.old; fi
+       @if [ -f $$DESTDIR$(BOOT_DIR)/os2_d.b ]; then \
+         mv $$DESTDIR$(BOOT_DIR)/os2_d.b $$DESTDIR$(BOOT_DIR)/os2_d.old; fi
+       @if [ -f $$DESTDIR$(BOOT_DIR)/mbr.b ]; then \
+         mv $$DESTDIR$(BOOT_DIR)/mbr.b $$DESTDIR$(BOOT_DIR)/mbr.old; fi
+
+       if [ -f os2_d.b -a  $(BUILTIN) -eq 0 ]; then cp os2_d.b $$DESTDIR$(BOOT_DIR); fi
+       if [ -f chain.b -a  $(BUILTIN) -eq 0 ]; then cp chain.b $$DESTDIR$(BOOT_DIR); fi
+       if [ -f mbr.b   -a  $(BUILTIN) -eq 0 ]; then cp mbr.b   $$DESTDIR$(BOOT_DIR); fi
+       if [ -f diag1.img ]; then cp -f diag1.img $$DESTDIR$(BOOT_DIR); fi
+       if [ -f diag2.img ]; then cp -f diag2.img $$DESTDIR$(BOOT_DIR); fi
+
+       cp lilo $$DESTDIR$(SBIN_DIR)/lilo
+       strip $$DESTDIR$(SBIN_DIR)/lilo
+       cp ../mkrescue $$DESTDIR$(USRSBIN_DIR)/mkrescue
+       cp ../keytab-lilo.pl $$DESTDIR$(USRSBIN_DIR)/keytab-lilo
+
+dep:
+       sed '/\#\#\# Dependencies/q' <Makefile >tmp_make
+       $(CPP) $(CFLAGS) -MM *.c >>tmp_make
+       mv tmp_make Makefile
+
+version:       common.c lilo.h common.h
+       $(CC) $(CFLAGS) -DSHS_MAIN -o version common.c
+
+mkloader:      temp.c
+       $(CC) $(CFLAGS) -DLILO_BINARY -o mkloader temp.c
+
+
+tidy:
+       rm -f core $(LIS) *.shs *.crc $(TMP)*
+       rm -rf sbin boot usr
+       if [ -x lilo ]; then strip lilo; fi
+       if [ -x lilo.static ]; then strip lilo.static; fi
+
+clean:
+       rm -f *.o *.s *.i *.img *.b tmp_make version
+       rm -f lilo lilo.static edit mkloader
+
+distclean:
+       rm -f *~ */*~ *.b *.com lilo*tar.gz
+
+uninstall:
+       rm -f $$DESTDIR$(SBIN_DIR)/lilo
+       rm -f $$DESTDIR$(USRSBIN_DIR)/mkrescue
+       rm -f $$DESTDIR$(USRSBIN_DIR)/keytab-lilo
+       rm -f $$DESTDIR$(BOOT_DIR)/diag1.img
+       rm -f $$DESTDIR$(BOOT_DIR)/diag2.img
+
+       if [ -f $$DESTDIR$(BOOT_DIR)/os2_d.b ]; then \
+         rm -f $$DESTDIR$(BOOT_DIR)/os2_d.b; fi
+       if [ -f $$DESTDIR$(BOOT_DIR)/chain.b ]; then \
+         rm -f $$DESTDIR$(BOOT_DIR)/chain.b; fi
+       if [ -f $$DESTDIR$(BOOT_DIR)/mbr.b ]; then \
+         rm -f $$DESTDIR$(BOOT_DIR)/mbr.b; fi
+
+
+### Dependencies
+boot.o: boot.c config.h lilo.h version.h common.h geometry.h device.h \
+  cfg.h map.h partition.h boot.h loader.h
+bsect.o: bsect.c config.h lilo.h version.h common.h raid.h cfg.h device.h \
+  geometry.h map.h temp.h partition.h boot.h bsect.h bitmap.h probe.h \
+  loader.h edit.h shs2.h
+cfg.o: cfg.c lilo.h version.h common.h temp.h cfg.h
+common.o: common.c lilo.h version.h common.h
+device.o: device.c config.h lilo.h version.h common.h temp.h device.h \
+  geometry.h partition.h cfg.h probe.h md-int.h
+edit.o: edit.c config.h lilo.h version.h common.h cfg.h temp.h bsect.h \
+  bitmap.h edit.h
+geometry.o: geometry.c config.h lilo.h version.h common.h device.h raid.h \
+  geometry.h cfg.h md-int.h probe.h
+identify.o: identify.c lilo.h version.h common.h cfg.h
+lilo.o: lilo.c config.h lilo.h version.h common.h cfg.h raid.h boot.h \
+  device.h flags.i geometry.h map.h bsect.h identify.h partition.h \
+  probe.h temp.h loader.h md-int.h edit.h bitmap.h
+map.o: map.c lilo.h version.h common.h geometry.h map.h
+partition.o: partition.c config.h lilo.h version.h common.h cfg.h \
+  device.h geometry.h partition.h boot.h loader.h
+probe.o: probe.c lilo.h version.h common.h device.h geometry.h \
+  partition.h bsect.h bdata.h probe.h
+raid.o: raid.c config.h lilo.h version.h common.h raid.h boot.h device.h \
+  geometry.h bsect.h cfg.h partition.h md-int.h
+shs2.o: shs2.c lilo.h version.h shs2.h
+temp.o: temp.c lilo.h version.h common.h temp.h loader.i
diff --git a/src/bdata.h b/src/bdata.h
new file mode 100644 (file)
index 0000000..2548f70
--- /dev/null
@@ -0,0 +1,33 @@
+/* bdata.h
+ * 
+ * Copyright 2000-2007 John Coffman
+ * Copyright 2009-2010 Joachim Wiedorn
+ * All rights reserved.
+ * 
+ * Licensed under the terms contained in the file 'COPYING'
+ * in the source directory.
+ */
+
+#ifndef _BDATA_H
+#define _BDATA_H
+
+#define PROBE_VERSION 6
+
+/* GET_VIDEO defines how much video information to retrieve
+ *
+ *     0 = none
+ *     1 = mode info
+ *     2 = VGA adapter info
+ *     3 = VESA checks, too
+ */
+#define BD_GET_VIDEO 3
+
+/* maximun number of floppy drives to check for 2 or 4 */
+#define BD_MAX_FLOPPY 2
+
+/* maximum number of hard drives to check for 2 to 16  */
+#define BD_MAX_HARD 16
+
+
+
+#endif /* _BDATA_H  */
diff --git a/src/biosdata.S b/src/biosdata.S
new file mode 100644 (file)
index 0000000..7814a48
--- /dev/null
@@ -0,0 +1,573 @@
+;  biosdata.S  is
+;
+;  Copyright 2002-2004 John Coffman.
+;  All rights reserved.
+;
+;  Licensed under the terms contained in the file 'COPYING' in the 
+;  source directory.
+;
+;
+
+
+io_sig:        .long   0               ; space for CRC
+       .ascii  PROBE_SIGNATURE ; "LiLo"
+       .word   PROBE_VERSION   ; sanity check
+io_lth:        .word   0               ; byte count overall
+io_good_disk:
+       .byte   0       ; last good drive (in low byte)
+       .byte   BD_GET_VIDEO
+       .byte   BD_MAX_FLOPPY
+       .byte   BD_MAX_HARD
+io_flp:        .word   0
+io_hrd:        .word   0
+io_pt: .word   0
+
+#if PROBE_VERSION >= 5
+io_eqp:        .word   0
+io_vid:        .word   0
+#endif
+
+io_l_sig       = *-io_sig
+
+; read partition table of device in DL
+;
+; save PT
+;
+io_get_pt:
+       push    ds
+       push    es
+
+       push    #0
+       pop     es
+       mov     bx,#BOOTSEG*16+SECTOR_SIZE
+       mov     cx,#1
+       mov     dh,#0
+       mov     ax,#0x201               ; read 1 sector
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Read partition table\n"
+       .byte   0
+       popa
+#endif
+       call    dsk_do_rw               ; make 5 tries
+       push    es
+       pop     ds
+
+       pop     es
+#if  PROBE_VERSION == 3
+       lea     si,(bx+PART_TABLE_OFFSET)
+       mov     cx,#4*16
+#elif  PROBE_VERSION >= 4
+       lea     si,(bx+PART_TABLE_OFFSET-8)
+       mov     cx,#4*16+8
+#endif
+       jc      io_get_pt_err
+       rep
+         movsb
+io_get_pt_ret:
+       pop     ds
+       ret
+
+io_get_pt_err:
+       mov     al,#-1
+       rep
+         stosb
+       jmp     io_get_pt_ret
+
+
+
+; check a hard drive for EDD support
+;
+;      device code is in DL
+;
+;
+io_do_edd_check:
+       push    dx
+       mov     ah,#0x41
+       mov     bx,#0x55AA
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Check EDD present\n"
+       .byte   0
+       popa
+#endif
+       int     0x13
+
+       xchg    al,ah
+       lahf
+       pop     dx
+
+       stosw
+       mov     ax,bx
+       stosw
+       xchg    ax,cx
+       stosw
+
+       jc      io_do_edd_check_ret
+       cmp     bx,#0xAA55
+       jne     io_do_edd_check_ret
+#if PROBE_VERSION < 6
+       test    al,#EDD_SUBSET  ; test for EDD call supported
+       jz      io_do_edd_check_ret
+#endif
+
+; get the EDD parameters
+
+       push    dx              ; paranoia, protect DL
+       push    es              ; more paranoia
+       push    ds
+
+       push    es
+       pop     ds
+       mov     si,di           ; DS:SI points at return area
+       push    di
+       mov     ah,#0x48
+       mov     word (si),#EDD_LTH      ; set max count to return
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Get EDD parameters\n"
+       .byte   0
+       popa
+#endif
+       int     0x13
+       pop     di
+
+       xchg    al,ah
+       lahf
+       
+       add     di,#EDD_LTH
+       stosw                   ; save the return flags
+
+       pop     ds
+       pop     es
+       pop     dx
+
+io_do_edd_check_ret:
+       ret
+
+
+
+;
+; io_biosdata: examine hard disk BIOS devices
+;              and video state
+;
+;  Enter with:
+;              DS == CS
+;              direction flag clear
+;
+;
+;  Exit with:
+;              All registers preserved
+;              
+;              Side effect is to write the low memory disk data area
+;
+;
+;
+
+io_biosdata:
+       pusha                   ;save all registers
+       push    es
+
+       push    #PROBESEG       ;save area is at 0060:0000 (0x000600)
+       pop     es
+       mov     di,#io_l_sig    ;skip over header area
+
+; get the equipment configuration flags
+
+#if PROBE_VERSION >= 5
+       mov     io_eqp,di       ;save equipment pointer
+       push    dx              ; protect this register
+#endif
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Get equipment configuration\n"
+       .byte   0
+       popa
+#endif
+       int     0x11
+       stosw
+
+; get the conventional memory size
+
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Get conventional memory size\n"
+       .byte   0
+       popa
+#endif
+       int     0x12
+       stosw                   ; save the number
+
+#if PROBE_VERSION >= 5
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Save boot device code\n"
+       .byte   0
+       popa
+#endif
+       pop     ax              ; get saved DX register
+       stosw                   
+#endif
+
+; collect the video information
+
+#if PROBE_VERSION >= 5
+       mov     io_vid,di       ; set the pointer
+#endif
+#if BD_GET_VIDEO >= 1
+       mov     ah,#0x0F        ; get video mode
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Get video mode\n"
+       .byte   0
+       popa
+#endif
+       int     0x10
+
+       push    ds
+       push    #0x40
+       pop     ds
+       mov     bl,[0x84]       ; get rows, too
+       pop     ds
+
+       stosw                   ; save AX
+       xchg    ax,bx
+       stosw                   ; save BX
+       cmp     bl,#7           ; is it MDA
+       beq     io_floppies     ; yup, skip it all
+       cmp     bh,#80          ; number of columns on screen
+       jb      io_floppies1    ; probably CGA
+
+#endif
+#if BD_GET_VIDEO >= 2
+#if 1
+       mov     ah,#0x12
+       mov     bx,#0xFF10      ; get configuration information
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Get video configuration\n"
+       .byte   0
+       popa
+#endif
+       int     0x10
+
+       stosw                   ; save AX
+       xchg    ax,bx
+       stosw                   ; save BX
+       cmp     ah,#1
+       ja      io_floppies1
+
+#endif
+       mov     ax,#0x1A00      ; get display combination code
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Get display combination\n"
+       .byte   0
+       popa
+#endif
+       int     0x10
+
+       stosw                   ; save AX
+       xchg    ax,bx
+       stosw                   ; save BX
+       cmp     bl,#0x1A        ; is function supported?
+#ifndef BD_VERBOSE
+       jne     io_floppies
+#else
+       bne     io_floppies
+io_floppies1   equ     *-3
+#endif
+       cmp     al,#4
+       jb      io_floppies1
+
+#if PROBE_VERSION >= 5
+
+; test to see if registers get trashed (some geforce video bios trashes dx)
+       push    ds
+       push    es
+       push    di
+
+       mov     cx,#0x1234
+       mov     dx,#0x5680
+       mov     bp,#0x4321
+
+       mov     ax,#0x1200
+       mov     bx,#0x0036
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Enable Screen Refresh\n"
+       .byte   0
+       popa
+#endif
+       int     0x10            ; enable screen refresh
+
+       pop     di
+       pop     es
+       pop     ds
+       stosw                   ; AX
+       xchg    ax,cx
+       stosw                   ; CX
+       xchg    ax,dx
+       stosw                   ; DX
+       xchg    ax,bp
+       stosw                   ; BP
+#endif
+
+#endif  /* BD_GET_VIDEO >= 2 */
+
+#if BD_GET_VIDEO >= 3
+       mov     ax,#0x4F00      ; check VESA present
+; ES:DI is already set
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Check VESA present\n"
+       .byte   0
+       popa
+#endif
+       int     0x10
+
+       seg es
+         mov   bx,(di)         ; possible "VE"
+       seg es
+         mov   cx,(di+2)       ; possible "SA"
+       stosw                   ; save AX
+       xchg    ax,bx
+       stosw                   ; possible "VE"
+       xchg    ax,cx           ; possible "SA"
+       stosw
+       cmp     bx,#0x004F      ; good return
+       jne     io_floppies
+       cmp     cx,#0x4556      ; "VE"
+       jne     io_floppies
+       cmp     ax,#0x4153      ; "SA"
+       jne     io_floppies
+       
+       mov     ax,#0x4F01
+       mov     cx,#0x0101      ; get mode information
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Get VESA mode information 1\n"
+       .byte   0
+       popa
+#endif
+       int     0x10    
+
+       seg es
+         mov   bx,(di)         ; get bits
+       stosw                   ; save AX
+       xchg    ax,bx
+       stosw                   ; save bits
+
+       mov     ax,#0x4F01
+       mov     cx,#0x0103      ; get mode information
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Get VESA mode information 3\n"
+       .byte   0
+       popa
+#endif
+       int     0x10    
+
+       seg es
+         mov   bx,(di)         ; get bits
+       stosw                   ; save AX
+       xchg    ax,bx
+       stosw                   ; save bits
+#else
+       mov     ax,#-1          ; flag for VESA not present
+       stosw
+       stosw
+       stosw
+;      jmp     io_floppies     ; exit to this point
+#endif
+
+; now go after the disk drive information
+
+io_floppies:
+#ifndef BD_VERBOSE
+io_floppies1:
+#endif
+       mov     cx,#BD_MAX_FLOPPY       ;test 4 floppies
+       xor     dx,dx
+       mov     io_flp,di               ;set pointer to floppy info
+
+io_next_drive:
+       push    cx
+
+; get the drive type
+
+       mov     ah,#0x15
+       push    dx
+#ifdef BD_VERBOSE
+       pusha
+       test    dl,#3           ; pause every 4th drive
+       jnz     io_no_pause
+       call    pause
+io_no_pause:
+       call    say
+       .ascii  "Get drive type "
+       .byte   0
+       mov     al,dl
+       call    bout
+       call    say
+       .byte   10,0
+       popa
+#endif
+       int     0x13
+
+       xchg    al,ah           ;code to AL
+       lahf                    ;flags to AH
+
+       stosw                   ; save AX
+       xchg    ax,dx
+       stosw                   ; save DX (low order)
+       xchg    ax,cx
+       stosw                   ; save CX (high order)
+       xchg    ax,dx           ; restore code to AL
+       pop     dx
+
+       jc      io_no_disk      ; error means no disk present
+       dec     al              ; AL==0 means no disk present
+       jns     io_get_param    ; if S=0, some disk type is present
+
+io_no_disk:
+       or      dl,dl
+       jns     io_get_param    ;do it all on floppies
+
+       pop     cx              ;premature loop termination
+       jmp     io_loop_end     ;skip the rest on fixed disks
+
+io_get_param:
+
+; get drive parameters
+
+       push    dx
+       push    es              ; supposedly clobbered for floppies only
+       push    di              ; do not trust anyone
+
+       mov     ah,#0x08
+#ifdef BD_VERBOSE
+       pusha
+       call    say
+       .ascii  "Get drive parameters\n"
+       .byte   0
+       popa
+#endif
+       int     0x13
+       xchg    al,ah
+       lahf
+       
+       mov     bp,di           ; save floppy param pointer
+       mov     bx,es
+
+       pop     di
+       pop     es
+
+       stosw                   ; save return code & flags
+       xchg    ax,cx
+       stosw
+       xchg    ax,dx
+       stosw
+       pop     dx
+
+       jc      io_fh_check     ; bad return above
+;;;    mov     [io_good_disk],dl       ; save DL
+
+       cmp     dl,#0x80        ; check for first HD
+       jne     io_fh_check
+       cbw                     ; former DL has disk count
+       pop     cx              ; get HD count
+       push    ax              ; set new HD count
+
+io_fh_check:
+       or      dl,dl           ; check floppy/hard disk
+       js      io_check_edd
+       xchg    ax,bp           ; was DI
+       stosw
+       xchg    ax,bx           ; was ES
+       stosw
+       jmp     io_skip_edd
+
+; check EDD extensions present
+
+io_check_edd:
+
+       call    io_do_edd_check
+
+io_skip_edd:
+
+       mov     [io_good_disk],dl       ;save last disk checked
+       pop     cx
+       inc     dl
+#ifndef BD_VERBOSE
+       loop    io_next_drive
+#else
+       dec     cx
+       bne     io_next_drive
+#endif
+io_loop_end:
+       or      dl,dl           ; set the S flag
+       push    di              ;
+       mov     cx,#BD_MAX_HARD ; do not touch flags ***
+       mov     dl,#0x80        ; do not touch flags ***
+#ifndef BD_VERBOSE
+       jns     io_next_drive   ; do the hard drives if not done
+#else
+       bpl     io_next_drive
+#endif
+       pop     word [io_pt]    ; save pt pointer
+       pop     word [io_hrd]   ; save hd pointer
+
+; now save the partition tables
+       
+io_get: 
+       cmp     dl,io_good_disk
+       ja      io_got
+       call    io_get_pt
+       inc     dx
+       jmp     io_get
+io_got:
+
+io_checksum_it:
+
+; now must record and checksum the results
+
+       mov     io_lth,di               ; address of end is overall count
+
+       push    di
+       xor     di,di                   ;move to here
+       mov     si,#io_sig              ;move from here
+       mov     cx,#io_l_sig            ;this number of bytes
+       rep
+         movsb                         ;
+       pop     di
+       mov     si,#4                   ; skip long at beginning
+       sub     di,si
+#ifndef BD_VERBOSE
+       push    dword #CRC_POLY1
+       call    crc32
+
+       seg     es
+       mov     [0],eax                 ; save that crc
+#endif
+
+; restore the registers and return
+
+       pop     es
+       popa
+       ret
+
+; end biosdata.S
diff --git a/src/bitmap.S b/src/bitmap.S
new file mode 100644 (file)
index 0000000..4f48948
--- /dev/null
@@ -0,0 +1,598 @@
+; bitmap.S
+;
+; Copyright 2001-2005 John Coffman.
+; All rights reserved.
+; 
+; Licensed under the terms contained in the file 'COPYING' in the 
+; source directory.
+;
+;
+#define ncol KEYTABLE+256+mt_ncol
+
+
+; menu_setup:
+;   main setup menu for LILO boot selection process
+;
+;   replaces code to load & display the message in second.S
+;
+;   exit with DS=ES=CS
+;
+menu_setup:
+       pusha
+
+;;     BEG_FS
+;;     SEG_FS                  ! message disabled ?
+       cmp     word ptr par2_msg_len+SSDIFF,#0         ;MSG_OFF+SSDIFF,#0
+;;     END_FS
+       je      ms_do_find      ! yes -> skip this
+
+
+;BEG_FS
+;SEG_FS                ! load the message file
+       mov     cx,mt_msg+KEYTABLE+256                  ;MSG_OFF+SSDIFF+2
+;SEG_FS
+       mov     dx,mt_msg+2+KEYTABLE+256
+;SEG_FS
+       mov     al,mt_msg+4+KEYTABLE+256
+;END_FS
+       mov     bx,#MAP
+       call    sread
+       call    loadfile
+
+       push    #SYSSEG
+       pop     es
+       xor     bx,bx
+       push    es              ; save for later
+       push    bx
+
+       call    _display4       ; ES:BX points to the Message or BITMAP
+
+       pop     bx
+
+;;     BEG_FS
+;;     SEG_FS
+       xchg    bx,par2_msg_len+SSDIFF          ;MSG_OFF+SSDIFF
+;;     END_FS
+
+       cmp     ax,#1
+       jb      good_bitmap             ; AX==0, bitmap was displayed
+
+       pop     ds      
+       ja      ms_do_find              ; AX==2, 3, or 4; "BM" sig found, but
+                                       ; wrong bitmap or no VGA adapter
+                                       ; or no VESA support (4)
+
+       ; AX==1, no "BM" signature, assume "message"
+
+       mov     byte ptr (bx),#0
+       call    crlf
+       xor     bx,bx           ! display the message
+       call    say
+       jmp     ms_do_find
+;--------------------------------------------
+
+good_bitmap:
+       pop     es
+       inc     word [suppress]
+       mov     word [abs_cx],#0x101    ; mark screen in use    
+
+
+ms_do_find:
+       push    cs
+       pop     ds              ; make sure DS is good
+       xor     si,si           ; number of names
+       xor     di,di           ; max. name length
+       mov     cx,#IMAGES      ; get max number to search
+       mov     bx,#DESCR0      ; get address to start at
+findl1:        call    strlen          ; get length in ax
+       or      ax,ax
+       jz      findl3
+#ifdef LCF_VIRTUAL
+       test    word ptr (bx+id_flags),#FLAG_VMDEFAULT
+       jz      findl1c
+       call    vmtest
+       jnc     findl1c
+       mov     [vimage],si
+findl1c:
+#endif
+#ifdef LCF_NOKEYBOARD
+       test    word ptr (bx+id_flags),#FLAG_NOKBDEFAULT
+       jz      findl1d
+       call    kbtest
+       jc      findl1d
+       mov     [vimage],si
+findl1d:
+#endif
+       cmp     ax,di
+       jb      findl2
+       xchg    ax,di
+findl2:        add     bx,#id_size
+       inc     si
+       loop    findl1
+
+findl3:        mov     [nimage],si
+       mov     [limage],di
+;;;
+       mov     ax,si                   ; number of images
+       mov     bx,[ncol]               ; 
+       add     ax,bx
+       dec     ax
+       div     bl
+;MINROW = 4
+       cmp     al,[KEYTABLE+256+mt_mincol]
+       ja      row1
+       mov     al,[KEYTABLE+256+mt_mincol]
+row1:
+       mov     bx,[KEYTABLE+256+mt_maxcol]     ;
+       cmp     al,bl
+       jbe     row2
+       xchg    ax,bx
+row2:
+       mov     [nrow],al
+;;;
+       xor     ax,ax                   ;display the list of names
+       mov     cx,si
+findl4:        call    lowlite
+       inc     ax
+       loop    findl4
+       mov     ax,[dimage]             ; bug fix
+#if defined(LCF_VIRTUAL) || defined(LCF_NOKEYBOARD)
+       test    byte ptr [cmdline],#0xFF
+       jnz     vdone3
+       mov     ax,[vimage]
+vdone3:
+#endif
+       call    hilite
+
+       push    cs
+       pop     es                      ; make sure ES is good on exit
+
+       popa
+       ret
+; end of menu_setup subroutine
+#if DEBUG_NEW
+no_bmp:        .ascii  " = AL; NOT a bitmap file\n"
+       .byte   0
+#endif
+
+
+#if 0
+; find_image
+;      if there is something on the command line
+;      return the image number it selects
+;
+;      enter with:
+;              nothing
+;      exit with:
+;              If nothing selected:
+;                  Carry Clear
+;                  AX==0
+;              If an image is selected:
+;                  Carry SET
+;                  AX==#image
+;                  BX==pointer to descriptor
+;                  
+;
+;      side effect:
+;              The selected image is hi-lited if the menu is displayed
+;
+find_image:
+       push    cx
+       push    si
+       push    di
+       
+       mov     cx,#IMAGES      ! test all names
+       mov     si,#DESCR0
+       push    si
+fi_nextn:
+       mov     di,#cmdline
+fi_nextc:
+       mov     al,(si)         ! get next character in descr
+                               ! get the character
+#ifdef LCF_IGNORECASE
+       call    upcase
+#endif
+       mov     ah,al
+       mov     al,(di)         ! get next char in cmdline
+#ifdef LCF_IGNORECASE
+       call    upcase
+#endif
+       or      ah,ah           ! NUL in descriptor name
+       jz      fi_dscend
+       cmp     al,ah           ! character equal ?
+       jne     fi_skipn                ! no -> try next one
+       inc     si              ! test next character
+       inc     di
+       jmp     fi_nextc
+fi_dscend:     
+       cmp     al,#32          ! space or NUL -> equal
+       je      fi_found
+       or      al,al
+       jz      fi_found
+
+fi_skipn:
+       pop     si
+       add     si,#id_size     ! test next name
+       push    si
+       loop    fi_nextn
+
+       pop     si
+       xor     ax,ax           ; clears the carry
+fi_exit:
+       pop     di
+       pop     si
+       pop     cx
+       ret
+       
+fi_found:
+       pop     bx              ! BX is matched descriptor
+       mov     ax,bx
+       sub     ax,#DESCR0
+       mov     cl,#id_size
+       div     cl
+       cbw
+       mov     di,[dimage]
+       cmp     ax,di
+       je      fi_nochange
+       mov     [dimage],ax
+       cmp     byte [abs_cx+1],#0      ! see if menu is displayed
+       je      fi_nochange
+       xchg    ax,di
+       call    lowlite
+       xchg    ax,di
+       call    hilite
+fi_nochange:
+       stc
+       jmp     fi_exit
+#endif
+
+
+; menu_delline:
+;      delete the current command line
+;                              common code from original second.S
+;
+;      enter with:
+;              BX = command line pointer
+;
+;      exit with:
+;              BX = updated command line pointer
+;
+;
+menu_delline:
+       cmp     bx,#cmdline     ! done ?
+       je      mdel9           ! yes -> done
+       push    bx              ! display BS,SPC,BS
+       mov     bx,#bs
+       call    say
+       pop     bx
+       dec     bx              ! move the pointer
+       jmp     menu_delline            ! next one
+mdel9: ret
+
+
+; menu_setcmd:
+;      set currently selected image to be the command line
+;
+;      enter with:
+;              AX = image# to select
+;              BX = cmdline pointer
+;
+;      exit with:
+;              BX = updated
+;
+;
+menu_setcmd:
+       push    si
+
+       push    ax
+
+       call    menu_delline    ; delete the current line
+
+       pop     si              ; get image# back
+
+       imul    si,#id_size
+       add     si,#DESCR0
+mset1: lodsb
+       or      al,al
+       jz      mset6
+       mov     (bx),al
+       inc     bx
+       push    bx
+       call    display
+       pop     bx
+       jmp     mset1
+       
+mset6:
+       pop     si      
+       ret
+
+
+; arrow
+;
+;   Code that handles the arrow keys:  left, up, down, right
+;
+;
+arrow: cbw                     ; signed delta vector in AL
+       mov     dx,[dimage]     ;
+       add     dx,ax           ; new position
+       or      dx,dx
+       jns     arr1
+arr0:  xor     dx,dx           ; set to zero if neg.
+arr1:  mov     ax,[nimage]
+       cmp     dx,ax           ; compare to max.
+       jb      arr2
+       mov     dx,ax
+       dec     dx
+arr2:                  ; we know the one to hi-lite is in range
+       mov     ax,[dimage]
+       cmp     ax,dx
+       je      arr6
+
+       call    lowlite         ; un-hilite the old
+       xchg    ax,dx
+       call    hilite
+
+       call    menu_setcmd     ; set new command line
+arr6:
+       jmp     arr_vector
+
+       
+null:  mov     al,#1
+       cmp     ah,#0x50                ; down arrow
+       je      arrow
+
+       neg     al
+       cmp     ah,#0x48                ; up arrow
+       je      arrow
+
+       mov     dx,[nimage]
+       cmp     ah,#0x4f                ; end
+       je      arr1
+
+       cmp     ah,#0x47                ; home
+       je      arr0
+
+       mov     al,[nrow]
+       xchg    ax,dx
+       mov     ax,[dimage]
+       div     dl                      
+       xchg    ax,dx                   ; DL = cur col.
+
+       cmp     ah,#0x4d                ; right arrow
+       jne     arr8
+       inc     dx                      ; similar to  dec al
+       cmp     dl,[ncol]               ; cmp (CUR COL + 1) : (NCOL)
+       jb      arrow
+       jmp     arr9
+       
+arr8:
+       cmp     ah,#0x49                ; pg up
+       jne     arr84
+       neg     dh                      ; remainder [0..(nrow-1)]
+       mov     al,dh
+arrow1:        jmp     arrow
+
+arr84:
+       cmp     ah,#0x51                ; pg dn
+       jne     arr88
+       not     dh
+       add     al,dh
+       jmp     arrow
+
+arr88:
+       neg     al
+       cmp     ah,#0x4b                ; left arrow
+       jne     arr9
+       or      dl,dl
+       jnz     arrow1
+
+arr9:
+       cmp     ah,#0x53                ; DEL
+       jne     arr_vector
+       br      delch                   ; treat as 0177 (rubout)
+
+arr_vector:
+       br      input           ; ignore the rest
+
+; menu_exit:
+;      erase the menu box to black
+;
+menu_exit:
+       push    es
+       pusha
+#if DEBUG_NEW
+       call    me1
+       .ascii  "menu_exit entered"
+       .byte   10,0
+me1:   pop     bx
+       call    say
+;;     call    pause
+#endif
+       xor     ax,ax
+       cmp     word [abs_cx],ax
+       mov     word [suppress],ax
+       mov     word [abs_cx],ax
+       je      mn_exit_ret
+       call    _done4
+#if DEBUG_NEW
+       call    me2
+       .ascii  "called done4"
+       .byte   10,0
+me2:   pop     bx
+       call    say
+;;     call    pause
+#endif
+mn_exit_ret:
+#if DEBUG_NEW
+       call    me3
+       .ascii  "exit from menu_exit"
+       .byte   10,0
+me3:   pop     bx
+       call    say
+;;     call    pause
+#endif
+       popa
+       pop     es
+       ret
+
+#if 0
+; menu_form_feed:
+;      simulate a FF on the console
+;
+menu_form_feed:
+       ret
+#endif
+
+; timer_display:
+;      check the timer 'cntdown' and display changes
+;
+timer_display:
+       push    es
+       pusha
+
+       test    byte [KEYTABLE+256+mt_t_row+1],#0xff    ; see if not initialized
+       js      timer99
+
+       mov     dx,#0x2d2d      ; get "--" means disabled
+       mov     [tim_min],dx
+       mov     [tim_sec],dx
+       mov     ax,[cntdown]    ; get timer countdown location
+       cmp     ax,[tim_tick]
+       je      timer99
+       mov     [tim_tick],ax   ; save last tick count  
+       inc     ax
+       jz      timer8
+
+       mul     c55             ; get time remaining in ms.
+       div     c1000           ; convert to seconds
+       cmp     ax,[tim_old]    
+       je      timer99
+       mov     [tim_old],ax    ; save seconds remaining
+       xor     dx,dx
+       div     c60             ; minutes in AX, seconds in DX  
+       aam
+       add     ax,#0x3030
+       xchg    ah,al
+       mov     [tim_min],ax    ; put characters in buffer
+       xchg    ax,dx
+       aam
+       add     ax,#0x3030
+       xchg    ah,al
+       mov     [tim_sec],ax    ; put characters in buffer
+
+timer8:
+       push    ds              ;sch-hi
+       push    #KEYTABLE+256+mt_t_fg
+       push    #5              ; len
+       push    ds              ; cp -hi
+       push    #tim_min
+       push    word [KEYTABLE+256+mt_t_row]
+       push    word [KEYTABLE+256+mt_t_col]
+       call    _text
+       add     sp,#14
+timer99:
+       popa
+       pop     es
+       ret
+
+tim_min: db    0,0
+       .ascii  ":"
+tim_sec: db    0,0
+
+tim_old:  dw   0               ; last # seconds
+tim_tick: dw   0               ; last timer tick value examined
+
+c55:   .word   2197            ;was 55, now 54.925*40
+c1000: .word   40000           ;was 1000, now 40*1000
+c60:   .word   60
+
+
+
+; hilite/lowlite
+;      enter with:
+;              AX = number [0..(nimage-1)] of entry to hilite
+;
+hilite:
+       push    es
+       pusha
+       mov     [dimage],ax             ;remember one hilited
+       push    cs
+       push    #KEYTABLE+256+mt_h_fg
+       jmp     lowlite1
+
+lowlite:
+       push    es
+       pusha
+       push    cs                      ; sch hi
+       push    #KEYTABLE+256+mt_fg     ; sch low
+
+lowlite1:
+       cmp     BYTE [abs_cx+1],#0
+       je      lowlite9
+
+       mov     bx,ax           ;save argument in BX
+       mov     al,#0x20        ; SP
+       mov     cx,[limage]
+       inc     cx
+       inc     cx
+       mov     di,#im_name
+       push    cx                      ; len
+       push    ds                      ; cp hi
+       push    di                      ; cp low
+
+       push    ds
+       pop     es
+       rep
+         stosb
+       imul    si,bx,#id_size
+       add     si,#DESCR0
+       mov     di,#im_name+1
+lowlite2:
+       lodsb
+       or      al,al
+       jz      lowlite3
+       stosb
+       jmp     lowlite2
+lowlite3:
+
+       mov     cx,[KEYTABLE+256+mt_col]
+       mov     ax,[KEYTABLE+256+mt_row]
+       mov     si,[nrow]
+lowlite4:
+       cmp     bx,si
+       jb      lowlite5
+       add     cx,[KEYTABLE+256+mt_xpitch]
+       sub     bx,si
+       jmp     lowlite4
+lowlite5:
+#ifdef PIXADDRESS
+       shl     bx,#4           ;use pixel addressing
+#endif
+       add     ax,bx
+       push    ax
+       push    cx
+       call    _text
+       add     sp,#10
+lowlite9:
+       add     sp,#4
+       popa
+       pop     es
+       ret
+
+
+im_name:  .blkb        MAX_IMAGE_NAME+3
+
+       .even
+dimage:        dw      0       ; default image
+#if defined(LCF_VIRTUAL) || defined(LCF_NOKEYBOARD)
+vimage:        dw      0       ; vmdefault image
+#endif
+nimage:        dw      0       ; number of images
+limage:        dw      0       ; longest length of image name
+nrow:  dw      0       ; number of rows of selections
+;nrow  equ     KEYTABLE+256+mt_maxcol
+;ncol: dw      0       ; number of columns (default=2)
+;ncol  equ     KEYTABLE+256+mt_ncol
+abs_cx:        dw      0       ; upper left of scrolling area
+
+; end of bitmap.S
diff --git a/src/bitmap.h b/src/bitmap.h
new file mode 100644 (file)
index 0000000..014f707
--- /dev/null
@@ -0,0 +1,104 @@
+/* bitmap.h
+ * 
+ * Copyright 2001-2007 John Coffman
+ * Copyright 2009-2010 Joachim Wiedorn
+ * All rights reserved.
+ * 
+ * Licensed under the terms contained in the file 'COPYING'
+ * in the source directory.
+ */
+
+#ifndef BITMAP_H
+#define BITMAP_H
+
+typedef unsigned int  bm_uint32;
+typedef signed int    bm_sint32;
+typedef unsigned short bm_uint16;
+typedef signed short   bm_sint16;
+typedef unsigned char  bm_byte;
+
+
+/* Windows/OS2 bitmap header */
+typedef struct BitMapHeader {
+   bm_uint32   size;
+   bm_sint32   width;
+   bm_sint32   height;
+   bm_uint16   numBitPlanes;
+   bm_uint16   numBitsPerPlane;
+   bm_uint32   compressionScheme;
+   bm_uint32   sizeImageData;
+   bm_uint32   xResolution, yResolution;
+   bm_uint32   numColorsUsed, numImportantColors;
+} BITMAPHEADER;
+
+
+/* OS2 bitmap header */
+typedef struct BitMapHeader2 {
+   bm_uint32   size;
+   bm_sint16   width;
+   bm_sint16   height;
+   bm_uint16   numBitPlanes;
+   bm_uint16   numBitsPerPlane;
+} BITMAPHEADER2;
+
+
+typedef struct Rgb {
+   bm_byte  blue, green, red, null;
+} RGB;
+
+typedef struct Rgb2 {
+   bm_byte  blue, green, red;
+} RGB2;
+
+
+/* common BM file header */
+typedef struct BitMapFileHeader {
+   bm_uint16   magic;      /* must be "BM" */
+   bm_uint16   size[2];                                /* actually bm_uint32 */
+   bm_sint16   xHotspot, yHotspot;
+   bm_uint16   offsetToBits[2];                        /* actually bm_uint32 */
+} BITMAPFILEHEADER;    /* needed to compensate for GCC's alignment rules */
+
+/* LILO scheme */
+typedef struct Scheme {
+   short int fg, bg, sh;
+   } SCHEME;
+
+/* LILO bitmap header text color and placement parameters */
+typedef struct BitmapLiloHeader {
+   bm_uint16   size[2];
+   char        magic[4];       /* "LILO" */
+
+/* items below this point must correspond EXACTLY with the MENUTABLE items
+   in 'common.h'
+   
+;*/    short row, col, ncol;           /* BMP row, col, and ncols
+                                               mt_row:         .blkw   1
+                                               mt_col:         .blkw   1
+                                               mt_ncol:        .blkw   1
+;*/    short maxcol, xpitch;           /* BMP max per col, xpitch between cols
+                                               mt_maxcol:      .blkw   1
+                                               mt_xpitch:      .blkw   1
+;*/    short fg, bg, sh;               /* BMP normal text fore, backgr, shadow
+                                               mt_fg:          .blkw   1
+                                               mt_bg:          .blkw   1
+                                               mt_sh:          .blkw   1
+;*/    short h_fg, h_bg, h_sh;         /* highlight fg, bg, & shadow
+                                               mt_h_fg:        .blkw   1
+                                               mt_h_bg:        .blkw   1
+                                               mt_h_sh:        .blkw   1
+;*/    short t_fg, t_bg, t_sh;         /* timer fg, bg, & shadow colors
+                                               mt_t_fg:        .blkw   1
+                                               mt_t_bg:        .blkw   1
+                                               mt_t_sh:        .blkw   1
+;*/    short t_row, t_col;             /* timer position
+                                               mt_t_row:       .blkw   1
+                                               mt_t_col:       .blkw   1
+;*/    short mincol, reserved[3];      /* BMP min per col before spill to next, reserved spacer
+                                               mt_mincol:      .blkw   1
+                                                               .blkw   3
+;*/
+} BITMAPLILOHEADER;
+
+#endif
+/* end bitmap.h */
diff --git a/src/boot.c b/src/boot.c
new file mode 100644 (file)
index 0000000..0669f91
--- /dev/null
@@ -0,0 +1,555 @@
+/* boot.c  -  Boot image composition
+ * 
+ * Copyright 1992-1998 Werner Almesberger
+ * Copyright 1999-2007 John Coffman
+ * Copyright 2009-2010 Joachim Wiedorn
+ * All rights reserved.
+ * 
+ * Licensed under the terms contained in the file 'COPYING'
+ * in the source directory.
+ */
+
+#define BIG_CHAIN 5
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "config.h"
+#include "lilo.h"
+#include "common.h"
+#include "geometry.h"
+#include "device.h"
+#include "cfg.h"
+#include "map.h"
+#include "partition.h"
+#include "boot.h"
+#include "loader.h"
+
+/*
+ * The number of sectors between the 15M memory hole and 1M
+ * is the largest size for a bzImage kernel + initrd = 14M 
+ * if "small-memory" is set. To use larger kernel + initrd 
+ * use option "large-memory" or "mem=XXX" raises the limit
+ */
+#define HIGH_SECTORS   ((15-1)*1024*1024/SECTOR_SIZE) 
+#define HIGH_4M                (3*1024*1024/SECTOR_SIZE)
+
+static GEOMETRY geo;
+static struct stat st;
+
+
+static void check_size(char *name,int setup_secs,int sectors)
+{
+    if (sectors > setup_secs+MAX_KERNEL_SECS)
+       die("Kernel %s is too big",name);
+}
+
+
+void boot_image(char *spec,IMAGE_DESCR *descr)
+{
+       BOOT_SECTOR buff;
+       SETUP_HDR hdr;
+       char *initrd;
+       int setup,fd,sectors,hi_sectors=MAX_KERNEL_SECS*4;
+       int modern_kernel;
+
+       if (verbose > 0) {
+               printf("Boot image: %s",spec);
+               show_link(spec);        /* in common.c */
+               printf("\n");
+    }
+       fd = geo_open(&geo,spec,O_RDONLY);
+       if (fstat(fd,&st) < 0)  die("fstat %s: %s",spec,strerror(errno));
+       if (read(fd,(char *) &buff,SECTOR_SIZE) != SECTOR_SIZE)
+               die("read %s: %s",spec,strerror(errno));
+       setup = buff.sector[VSS_NUM] ? buff.sector[VSS_NUM] : SETUPSECS;
+       if (read(fd,(char *) &hdr,sizeof(hdr)) != sizeof(hdr))
+               die("read %s: %s",spec,strerror(errno));
+    modern_kernel = !strncmp(hdr.signature,NEW_HDR_SIG,4) && hdr.version >= 
+               NEW_HDR_VERSION;
+       if (modern_kernel) descr->flags |= FLAG_MODKRN;
+       if (verbose > 1)
+               printf("Setup length is %d sector%s.\n",setup,setup == 1 ? "" : "s");
+       if (setup > MAX_SETUPSECS)
+               die("Setup length exceeds %d maximum; kernel setup will overwrite boot loader", MAX_SETUPSECS);
+       map_add(&geo,0,(st.st_size+SECTOR_SIZE-1)/SECTOR_SIZE);
+       sectors = map_end_section(&descr->start,setup+SPECIAL_SECTORS+SPECIAL_BOOTSECT);
+       if (!modern_kernel || !(hdr.flags & LFLAG_HIGH))
+               check_size(spec,setup,sectors);
+       else {
+               if (hdr.start % PAGE_SIZE)
+                       die("Can't load kernel at mis-aligned address 0x%08lx\n",hdr.start);
+               descr->flags |= FLAG_LOADHI;    /* load kernel high */
+               hi_sectors = sectors - setup;   /* number of sectors loaded high */
+               hi_sectors *= 6;                /* account for decompression */
+               if (hi_sectors < HIGH_4M) hi_sectors = HIGH_4M;    
+    }
+    geo_close(&geo);
+
+    if (verbose > 1)
+       printf("Mapped %d sector%s.\n",sectors,sectors == 1 ? "" : "s");
+    if ((initrd = cfg_get_strg(cf_kernel,"initrd")) || (initrd = cfg_get_strg(
+      cf_options,"initrd"))) {
+       if (!modern_kernel) die("Kernel doesn't support initial RAM disks");
+       if (verbose > 0) {
+           printf("Mapping RAM disk %s",initrd);
+           show_link(initrd);
+           printf("\n");
+       }
+       fd = geo_open(&geo,initrd,O_RDONLY);
+       if (fstat(fd,&st) < 0) die("fstat %s: %s",initrd,strerror(errno));
+#if 1
+       *(unsigned int *) descr->rd_size = st.st_size;
+#else
+       descr->rd_size = (st.st_size + SECTOR_SIZE - 1)/SECTOR_SIZE;
+#endif
+       map_begin_section();
+       map_add(&geo,0,(st.st_size+SECTOR_SIZE-1)/SECTOR_SIZE);
+       sectors = map_end_section(&descr->initrd,0);
+       if (verbose > 1)
+               printf("RAM disk: %d sector%s.\n",sectors,sectors == 1 ?  "" : "s");
+
+#ifdef LCF_INITRDLOW
+       if (hi_sectors + sectors > HIGH_SECTORS) {
+               descr->flags |= FLAG_TOOBIG;
+               warn("The initial RAM disk is TOO BIG to fit in the memory below 15M.");
+       }
+#else
+       if (cfg_get_flag(cf_options,"large-memory")
+                       && !cfg_get_flag(cf_options,"small-memory")) {
+               /* CASE 10 = large & not small */
+               if (verbose>=2)
+               printf("The initial RAM disk will be loaded in the high memory above 16M.\n");
+       } else if (hi_sectors + sectors > HIGH_SECTORS) {
+               descr->flags |= FLAG_TOOBIG;
+               if (cfg_get_flag(cf_options,"small-memory")) {
+                       /* CASE 01 or 11 = small */
+                       warn("The initial RAM disk is TOO BIG to fit in the memory below 15M.\n"
+                               "  It will be loaded in the high memory it will be \n"
+                               "  assumed that the BIOS supports memory moves above 16M.");
+               } else {
+                       /* CASE 00 = !large & !small */
+                       if (verbose>=1)
+                       printf("The initial RAM disk will be loaded in the high memory above 16M.\n");
+               }
+       } else {
+               /* CASE 01 or 10 or 11 */
+               if (verbose>=2)
+               printf("The initial RAM disk will be loaded in the low memory below 15M.\n");
+       }
+#endif 
+
+       geo_close(&geo);
+    }
+}
+
+
+void boot_device(char *spec,char *range,IMAGE_DESCR *descr)
+{
+    char *here;
+    int start,secs;
+    int sectors;
+
+    if (verbose > 0) printf("Boot device: %s, range %s\n",spec,range);
+    (void) geo_open(&geo,spec,O_NOACCESS);
+    here = strchr(range,'-');
+    if (here) {
+       *here++ = 0;
+       start = to_number(range);
+       if ((secs = to_number(here)-start+1) < 0) die("Invalid range");
+    }
+    else {
+       here = strchr(range,'+');
+       if (here) {
+           *here++ = 0;
+           start = to_number(range);
+           secs = to_number(here);
+       }
+       else {
+           start = to_number(range);
+           secs = 1;
+       }
+    }
+    map_add(&geo,start,secs);
+    check_size(spec,SETUPSECS,sectors = map_end_section(&descr->start,60));
+                               /* this is a crude hack ... ----------^^*/
+    geo_close(&geo);
+    if (verbose > 1)
+       printf("Mapped %d sector%s.\n",sectors,sectors == 1 ? "" : "s");
+}
+
+
+void do_map_drive(void)
+{
+    const char *tmp;
+    char *end;
+    int from,to;
+
+    tmp = cfg_get_strg(cf_other,"map-drive");
+    from = strtoul(tmp,&end,0);
+    if (from > 0xff || *end)
+       cfg_error("Invalid drive specification \"%s\"",tmp);
+    cfg_init(cf_map_drive);
+    (void) cfg_parse(cf_map_drive);
+    tmp = cfg_get_strg(cf_map_drive,"to");
+    if (!tmp) cfg_error("TO is required");
+    to = strtoul(tmp,&end,0);
+    if (to > 0xff || *end)
+       cfg_error("Invalid drive specification \"%s\"",tmp);
+    if (from || to) { /* 0 -> 0 is special */
+       int i;
+
+       for (i = 0; i < curr_drv_map; i++) {
+           if (drv_map[i] == ((to << 8) | from))
+               die("Mapping 0x%02x to 0x%02x already exists",from,to);
+           if ((drv_map[i] & 0xff) == from)
+               die("Ambiguous mapping 0x%02x to 0x%02x or 0x%02x",from,
+                 drv_map[i] >> 8,to);
+       }
+       if (curr_drv_map == DRVMAP_SIZE)
+           cfg_error("Too many drive mappings (more than %d)",DRVMAP_SIZE);
+       if (verbose > 1)
+           printf("  Mapping BIOS drive 0x%02x to 0x%02x\n",from,to);
+       drv_map[curr_drv_map++] = (to << 8) | from;
+    }
+    cfg_unset(cf_other,"map-drive");
+}
+
+/* 
+ *  Derive the name of the MBR from the partition name
+ *  e.g.
+ *   /dev/scsi/host2/bus0/target1/lun0/part2   => disc
+ *   /dev/sd/c0b0t0u0p7                                => c0b0t0u0
+ *   /dev/sda11                                        => sda
+ *
+ * If table==0, do no check for primary partition; if table==1, check
+ * that we started from a primary (1-4) partition.
+ *
+ * A NULL return indicates an error
+ *
+ */
+char *boot_mbr(const char *boot, int table)
+{
+#if 0
+    char *part, *npart, *endptr;
+    int i, j, k;
+    
+    npart = stralloc(boot);
+    part = strrchr(npart, '/');
+    if (!part++) die ("No '/' in partition/device name.");
+    
+    i = strlen(part);
+    endptr = part + i - 1;
+    
+   /* j is the count of digits at the end of the name */ 
+    j = 0;
+    while (isdigit(*endptr)) { j++; --endptr; }
+    if (j==0 && !table) die ("Not a partition name; no digits at the end.");
+    
+    k = !table || (j==1 && endptr[1]>='1' && endptr[1]<='4');
+    
+   /* test for devfs  partNN */
+    if (strncmp(part, "part", 4)==0) {
+       strcpy(part, "disc");
+    } 
+   /* test for ..NpNN */
+    else if (*endptr=='p' && isdigit(endptr[-1])) {
+        *endptr = 0;  /* truncate the pNN part */
+    }
+   /* test for old /dev/hda3 or /dev/sda11 */
+    else if (endptr[-1]=='d' && endptr[-3]=='/' &&
+               (endptr[-2]=='h' || endptr[-2]=='s')
+           ) {
+        endptr[1] = 0;  /* truncate the NN part */
+    }
+    else 
+       k = 0;
+
+#else
+    struct stat st;
+    dev_t dev;
+    DEVICE d;
+    int mask, k;
+    char *npart = NULL;
+    
+    k = 0;
+    if (stat(boot,&st) < 0) die("stat %s: %s",boot,strerror(errno));
+    dev = S_ISREG(st.st_mode) ? st.st_dev : st.st_rdev;
+    if ( (mask = has_partitions(dev)) ) {
+       k = dev & ~mask;
+       k = !table ? 1 : k>=1 && k<=4;
+       if (k) {
+           dev_open(&d, dev&mask, O_BYPASS);   /* bypass any open */
+           npart = stralloc(d.name); 
+           dev_close(&d);
+       }
+    }
+    
+
+#endif
+    if (verbose>=3) {
+        printf("Name: %s  yields MBR: %s  (with%s primary partition check)\n",
+           boot, k ? npart : "(NULL)", table ? "" : "out");
+    }
+
+    if (k) return npart;
+    else return NULL;
+}
+
+
+
+#define PART(s,n) (((struct partition *) (s)[0].par_c.ptable)[(n)])
+
+
+void boot_other(char *loader,char *boot,char *part,IMAGE_DESCR *descr)
+{
+    int b_fd,p_fd,walk,found,size;
+#ifdef LCF_BUILTIN
+    BUILTIN_FILE *chain;
+    char *cname;
+#else
+    int l_fd;
+#endif
+    unsigned short magic;
+#ifdef BIG_CHAIN
+    BOOT_SECTOR buff[BIG_CHAIN];
+    BOOT_SECTOR zbuff;
+    int mapped;
+#else
+    BOOT_SECTOR buff[SETUPSECS-1];
+#endif
+    struct stat st;
+    char *pos;
+    int i, code;
+    int letter = 0;
+    int unsafe;
+
+    if (!loader) loader = DFL_CHAIN;
+#ifdef LCF_BUILTIN
+#ifndef LCF_SOLO_CHAIN
+    if (strstr(loader,"os2")) {
+       chain = &Os2_d;
+       cname = "OS/2";
+    }
+    else
+#endif
+    {
+       chain = &Chain;
+       cname = "CHAIN";
+    }
+#endif
+    if (part && strlen(part)>0 && strlen(part)<=2) {
+       if (part[1]==0 || part[1]==':') {
+           letter = toupper(part[0]);
+           if (letter>='C' && letter<='Z') {
+               letter += 0x80-'C';
+               part = NULL;
+           }
+           else letter = 0;
+       }
+    }
+    unsafe = cfg_get_flag(cf_other, "unsafe");
+    if (!part && !unsafe) part = boot_mbr(boot, 1);
+    /* part may still be NULL */
+
+    if (verbose > 0) {
+#ifdef LCF_BUILTIN
+       printf("Boot other: %s%s%s, loader %s\n",
+               boot,
+               part ? ", on " : "",
+               part ? part : "",
+               cname);
+#else
+       printf("Boot other: %s%s%s, loader %s",
+               boot,
+               part ? ", on " : "",
+               part ? part : "",
+               loader);
+       show_link(loader);
+       printf("\n");
+#endif
+    }
+
+#ifdef LCF_AUTOAUTO
+    if (!cfg_get_flag(cf_other, "change")) {
+       autoauto = 1;   /* flag that change rules may be automatically inserted */
+        do_cr_auto();
+        autoauto = 0;
+    }
+#endif    
+
+    if (unsafe) {
+       (void) geo_open_boot(&geo,boot);
+       if (part) die("TABLE and UNSAFE are mutually incompatible.");
+    }
+    else {
+       b_fd = geo_open(&geo,boot,O_RDONLY);
+       if (fstat(b_fd,&st) < 0)
+           die("fstat %s: %s",boot,strerror(errno));
+       if (!geo.file) part_verify(st.st_rdev,0);
+       else if (st.st_size > SECTOR_SIZE) {
+           warn("'other = %s' specifies a file that is longer\n"
+               "    than a single sector.", boot);
+           if (st.st_size >= SECTOR_SIZE*(SETUPSECS-1) &&
+               read(b_fd, buff[0].sector, SECTOR_SIZE*(SETUPSECS-1)) == 
+                       SECTOR_SIZE*(SETUPSECS-1)   &&
+               !strncmp((char*)buff[2].sector+2,"HdrS",4)
+                               ) {
+               warn("This file may actually be an 'image ='");
+           }
+       }
+       if (lseek(b_fd,(int) BOOT_SIG_OFFSET,SEEK_SET) < 0)
+           die("lseek %s: %s",boot,strerror(errno));
+       if ((size = read(b_fd, (char *)&magic, 2)) != 2) {
+           if (size < 0) die("read %s: %s",boot,strerror(errno));
+           else die("Can't get magic number of %s",boot); }
+       if (magic != BOOT_SIGNATURE)
+           die("First sector of %s doesn't have a valid boot signature",boot);
+    }
+
+/* process the 'master-boot' or 'boot-as' options */
+    i = cfg_get_flag(cf_other,"master-boot");
+    pos = cfg_get_strg(cf_other,"boot-as");
+    if (i && pos) die("'master-boot' and 'boot-as' are mutually exclusive 'other=' options");
+    if (!i && !pos) {
+       i = cfg_get_flag(cf_options,"master-boot");
+       pos = cfg_get_strg(cf_options,"boot-as");
+       if (i && pos) die("'master-boot' and 'boot-as' are mutually exclusive global options");
+    }
+    if (i) code = -1;  /* master-boot in use */
+    else if (pos) {
+       code = to_number(pos);
+       if (code >= 80 && code <= 89) {
+           /* convert to 0x80 to 0x89 */
+           warn("Radix error, 'boot-as=%d' taken to mean 'boot-as=0x%x'",
+                               code, code+0x30);
+           code += 0x30;
+       }
+       if ( !((code>=0 && code<=3) || (code>=0x80 && code<=DEV_MASK)) )
+           die("Illegal BIOS device code specified in 'boot-as=0x%02x'", code);
+    }
+    else code = -2;
+    
+    if (code != -2) {
+       curr_drv_map += 2;      /* add 2 spaces */
+       if (curr_drv_map >= DRVMAP_SIZE)
+           cfg_error("Too many drive mappings (more than %d)",DRVMAP_SIZE);
+       if (verbose > 1) {
+           char *s, n[8];
+           if (code==-1) s = "0/0x80";
+           else sprintf((s=n),"0x%02x", code);
+           printf("  Swapping BIOS boot drive with %s, as needed\n", s);
+       }
+       for (i=curr_drv_map-1; i>1; i--) drv_map[i] = drv_map[i-2];
+       drv_map[0] = 0xFFFF;    /* reserve 2 slots */
+       drv_map[1] = code<<8 | 0xFF;
+    }
+
+    memset(buff,0,sizeof(buff));
+#ifdef BIG_CHAIN
+    zbuff = buff[0];   /* zero out zbuff */
+#endif
+#ifndef LCF_BUILTIN
+    if ((l_fd = open(loader,O_RDONLY)) < 0)
+       die("open %s: %s",loader,strerror(errno));
+    if ((size = read(l_fd,buff,sizeof(buff)+1)) < 0)
+       die("read %s: %s",loader,strerror(errno));
+    if (size > sizeof(buff))
+       die("Chain loader %s is too big",loader);
+    check_version(buff,STAGE_CHAIN);
+#else
+    size = chain->size;
+    if (size > sizeof(buff))
+       die("Chain loader %s is too big",loader);
+    memcpy(buff, chain->data, size);
+#endif
+    if (!part) {
+        p_fd = -1; /* pacify GCC */
+        PART(buff,0).boot_ind = geo.device;
+        PART(buff,0).start_sect = geo.start;     /* pseudo partition table */
+        if (verbose > 0) printf("Pseudo partition start: %d\n", geo.start);
+    }
+    else {
+       if ((p_fd = open(part,O_RDONLY)) < 0)
+           die("open %s: %s",part,strerror(errno));
+       if (lseek(p_fd,(int) PART_TABLE_OFFSET,SEEK_SET) < 0)
+           die("lseek %s: %s",part,strerror(errno));
+       if (read(p_fd,(char *) buff[0].par_c.ptable,PART_TABLE_SIZE) !=
+         PART_TABLE_SIZE)
+           die("read %s: %s",part,strerror(errno));
+       found = 0;
+       for (walk = 0; walk < PARTITION_ENTRIES; walk++)
+           if (!PART(buff,walk).sys_ind || PART(buff,walk).start_sect !=
+             geo.start) {
+               /*
+                * Don't remember what this is supposed to be good for :-(
+                */
+               if (PART(buff,walk).sys_ind != PART_DOS12 && PART(buff,walk).
+                 sys_ind != PART_DOS16_SMALL && PART(buff,walk).sys_ind !=
+                 PART_DOS16_BIG)
+                 PART(buff,walk).sys_ind = PART_INVALID;
+           }
+           else {
+               if (found) die("Duplicate entry in partition table");
+               buff[0].par_c.offset = walk*PARTITION_ENTRY;
+               PART(buff,walk).boot_ind = 0x80;
+               found = 1;
+           }
+       if (!found) die("Partition entry not found.");
+       (void) close(p_fd);
+    }
+#ifndef LCF_BUILTIN
+    (void) close(l_fd);
+#endif
+    buff[0].par_c.drive = geo.device;
+    buff[0].par_c.head = letter ? letter : geo.device;
+               /* IBM boot manager passes drive letter in offset 0x25 */
+    if (verbose>=5) printf("boot_other:  drive=0x%02x   logical=0x%02x\n",
+                       buff[0].par_c.drive, buff[0].par_c.head);
+    drv_map[curr_drv_map] = 0;
+    prt_map[curr_prt_map] = 0;
+    pos = (char *) buff+buff[0].par_c.drvmap;
+    memcpy(pos,drv_map,sizeof(drv_map));
+    memcpy(pos+sizeof(drv_map),prt_map,sizeof(prt_map)-2);
+
+    size = (size + SECTOR_SIZE - 1) / SECTOR_SIZE;
+#ifndef BIG_CHAIN
+    map_add_zero();
+#else
+    if (size > SETUPSECS-1) {
+       zbuff.sector[VSS_NUM] = mapped = size+1;
+       map_add_sector(zbuff.sector);
+    }
+    else {
+       map_add_zero();
+       mapped = SETUPSECS;
+    }
+#endif
+    for (i = 0; i < size; i++) map_add_sector(&buff[i]);
+    for (i = size; i < SETUPSECS-1; i++) map_add_zero();
+    map_add(&geo,0,1);
+
+#ifndef BIG_CHAIN
+    (void) map_end_section(&descr->start,SETUPSECS+SPECIAL_SECTORS);
+       /* size is known */
+    geo_close(&geo);
+    if (verbose > 1)
+       printf("Mapped %d (%d+1+1) sectors.\n",
+               SETUPSECS+SPECIAL_SECTORS, SETUPSECS);
+#else
+    (void) map_end_section(&descr->start, mapped+SPECIAL_SECTORS+SPECIAL_BOOTSECT);
+       /* size is known */
+    geo_close(&geo);
+    if (verbose > 1)
+       printf("Mapped %d (%d+1+1) sectors.\n",
+               mapped+SPECIAL_SECTORS, mapped);
+#endif
+}
diff --git a/src/boot.h b/src/boot.h
new file mode 100644 (file)
index 0000000..6d7effa
--- /dev/null
@@ -0,0 +1,44 @@
+/* boot.h  -  Boot image composition
+ * 
+ * Copyright 1992-1995 Werner Almesberger
+ * Copyright 1999-2007 John Coffman
+ * Copyright 2009-2010 Joachim Wiedorn
+ * All rights reserved.
+ * 
+ * Licensed under the terms contained in the file 'COPYING'
+ * in the source directory.
+ */
+
+#ifndef BOOT_H
+#define BOOT_H
+
+
+void boot_image(char *spec,IMAGE_DESCR *descr);
+
+/* Maps a "classic" boot image. */
+
+void boot_device(char *spec,char *range,IMAGE_DESCR *descr);
+
+/* Maps sectors from a device as the boot image. Can be used to boot raw-written
+   disks. */
+
+void boot_unstripped(char *boot,char *setup,char *kernel,IMAGE_DESCR *descr);
+
+/* Maps an unstripped kernel image as the boot image. The setup (without the
+   header) is prepended. */
+
+char *boot_mbr(const char *boot, int table);
+/* derive name of MBR from partition name; check for primary partition
+   if table==1
+ */
+
+void boot_other(char *loader,char *boot,char *part,IMAGE_DESCR *descr);
+
+/* Merges a loader with a partition table and appends a boot sector. This mix
+   is used to boot non-Linux systems. */
+
+void dump(char *spec,IMAGE_DESCR *descr);
+
+/* Maps a crash dump file. */
+
+#endif
diff --git a/src/bootsect.S b/src/bootsect.S
new file mode 100644 (file)
index 0000000..77e5b45
--- /dev/null
@@ -0,0 +1,507 @@
+!
+!      bootsect.s              Copyright (C) 1991, 1992 Linus Torvalds
+!      modified by Drew Eckhardt
+!      modified by Bruce Evans (bde)
+!      modified by John Coffman for LILO disk.b diagnostic (27-Mar-2000)
+!                                                          (09-Mar-2001)
+!
+!
+! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
+! itself out of the way to address 0x90000, and jumps there.
+!
+! bde - should not jump blindly, there may be systems with only 512K low
+! memory.  Use int 0x12 to get the top of memory, etc.
+!
+! It then loads 'setup' directly after itself (0x90200), and the system
+! at 0x10000, using BIOS interrupts. 
+!
+! NOTE! currently system is at most (8*65536-4096) bytes long. This should 
+! be no problem, even in the future. I want to keep it simple. This 508 kB
+! kernel size should be enough, especially as this doesn't contain the
+! buffer cache as in minix (and especially now that the kernel is 
+! compressed :-)
+!
+! The loader has been made as simple as possible, and continuous
+! read errors will result in a unbreakable loop. Reboot by hand. It
+! loads pretty fast by getting whole tracks at a time whenever possible.
+
+;#include <linux/config.h> /* for CONFIG_ROOT_RDONLY */
+;#include <asm/boot.h>
+
+.text
+
+SIZEBYTES = SIZEDISKB+511              ! round disk.b size for division
+SETUPSECS = SIZEBYTES/512              ! size of disk.b in sectors
+BOOTSEG   = 0x07C0                     ! original address of boot-sector
+INITSEG   = 0x9000                     ! we move boot here - out of the way
+SETUPSEG  = INITSEG+0x20               ! setup starts here
+SYSSEG    = 0x1000                     ! system loaded at 0x10000 (65536).
+MAX_SETUPSECS = 31                     ! same as  lilo.h
+STK_SIZE  = MAX_SETUPSECS*512+512      ! 0x4000
+
+#ifndef SIZEKRNL
+SYSSIZE          = 0x8000                      ! system size: number of 16-byte clicks
+                                       ! to be loaded
+#else
+SIZEKRNLP      = SIZEKRNL+15
+SYSSIZE                = SIZEKRNLP/16
+#endif
+ASK_VGA   = 0xfffd
+
+! ROOT_DEV & SWAP_DEV are now written by "build".
+ROOT_DEV = 0
+SWAP_DEV = 0
+#ifndef SVGA_MODE
+#define SVGA_MODE ASK_VGA
+#endif
+#ifndef RAMDISK
+#define RAMDISK 0
+#endif 
+#ifndef CONFIG_ROOT_RDONLY
+#define CONFIG_ROOT_RDONLY 1
+#endif
+
+! ld86 requires an entry symbol. This may as well be the usual one.
+.globl _main
+_main:
+       mov     ax,#BOOTSEG
+       mov     ds,ax
+
+       int     0x12
+       sub     ax,#STK_SIZE/1024
+       shl     ax,#10-4
+       mov     bx,#INITSEG
+       cmp     ax,bx
+       jb      *+3
+       xchg    ax,bx
+
+       mov     es,ax
+       mov     cx,#256
+       sub     si,si
+       sub     di,di
+       cld
+       rep
+       movsw
+
+       mov     di,#STK_SIZE-12 ! 0x4000 is arbitrary value >= length of
+                               ! bootsect + length of setup + room for stack
+                               ! 12 is disk parm size
+
+! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde).  We
+! wouldn't have to worry about this if we checked the top of memory.  Also
+! my BIOS can be configured to put the wini drive tables in high memory
+! instead of in the vector table.  The old stack might have clobbered the
+! drive table.
+
+       mov     ds,ax
+       mov     ss,ax           ! put stack at INITSEG:0x4000-12.
+       mov     sp,di
+;      jmpi    go,INITSEG
+       push    es
+       push    #go
+       retf
+
+! ax and es already contain INITSEG
+
+go:
+       add     ax,#0x20        ! seg offset to SETUPSEG
+       mov     setupseg,ax
+
+/*
+ *     Many BIOS's default disk parameter tables will not 
+ *     recognize multi-sector reads beyond the maximum sector number
+ *     specified in the default diskette parameter tables - this may
+ *     mean 7 sectors in some cases.
+ *
+ *     Since single sector reads are slow and out of the question,
+ *     we must take care of this by creating new parameter tables
+ *     (for the first disk) in RAM.  We will set the maximum sector
+ *     count to 36 - the most we will encounter on an ED 2.88.  
+ *
+ *     High doesn't hurt.  Low does.
+ *
+ *     Segments are as follows: ds=es=ss=cs - INITSEG,
+ *             fs = 0, gs is unused.
+ */
+
+! cx contains 0 from rep movsw above
+
+       mov     bx,#0x78                ! fs:bx is parameter table address
+       push    ds
+       push    cx                      ! contains 0 from  rep movsw above
+       pop     ds
+       lds     si,(bx)                 ! ds:si is source
+
+       mov     cl,#6                   ! copy 12 bytes
+       cld
+       push    di
+
+       rep
+       movsw
+
+       pop     di
+       pop     ds
+
+       movb    4(di),*36               ! patch sector count
+
+;;;    seg fs
+       push    ds
+       push    #0
+       pop     ds
+       mov     (bx),di
+;;;    seg fs
+       mov     2(bx),es
+       pop     ds
+
+! load the setup-sectors directly after the bootblock.
+! Note that 'es' is already set up.
+! Also cx is 0 from rep movsw above.
+
+load_setup:
+       xor     ah,ah                   ! reset FDC 
+       xor     dl,dl
+       int     0x13    
+
+       xor     dx, dx                  ! drive 0, head 0
+       mov     cl,#0x02                ! sector 2, track 0
+       mov     bx,#0x0200              ! address = 512, in INITSEG
+       mov     ah,#0x02                ! service 2, nr of sectors
+       mov     al,setup_sects          ! (assume all on head 0, track 0)
+       int     0x13                    ! read it
+       jnc     ok_load_setup           ! ok - continue
+
+       push    ax                      ! dump error code
+       call    print_nl
+       mov     bp, sp
+       call    print_hex
+       pop     ax      
+       
+       jmp     load_setup
+
+ok_load_setup:
+
+! Get disk drive parameters, specifically nr of sectors/track
+
+#if 0
+
+! bde - the Phoenix BIOS manual says function 0x08 only works for fixed
+! disks.  It doesn't work for one of my BIOS's (1987 Award).  It was
+! fatal not to check the error code.
+
+       xor     dl,dl
+       mov     ah,#0x08                ! AH=8 is get drive parameters
+       int     0x13
+       xor     ch,ch
+#else
+
+! It seems that there is no BIOS call to get the number of sectors.  Guess
+! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
+! 15 if sector 15 can be read.  Otherwise guess 9.
+
+       mov     si,#disksizes           ! table of sizes to try
+
+probe_loop:
+       lodsb
+       cbw                             ! extend to word
+       mov     sectors, ax
+       cmp     si,#disksizes+4
+       jae     got_sectors             ! if all else fails, try 9
+       xchg    ax, cx                  ! cx = track and sector
+       xor     dx, dx                  ! drive 0, head 0
+       xor     bl, bl
+       mov     bh,setup_sects
+       inc     bh
+       shl     bh,#1                   ! address after setup (es = cs)
+       mov     ax,#0x0201              ! service 2, 1 sector
+       int     0x13
+       jc      probe_loop              ! try next value
+
+#endif
+
+got_sectors:
+
+
+! Print some inane message
+
+       mov     ah,#0x03                ! read cursor pos
+       xor     bh,bh
+       int     0x10
+       
+       mov     cx,#9
+       mov     bx,#0x0007              ! page 0, attribute 7 (normal)
+       mov     bp,#msg1
+       mov     ax,#0x1301              ! write string, move cursor
+       int     0x10
+
+! ok, we've written the message, now
+! we want to load the system (at 0x10000)
+
+#if 0
+       mov     ax,#SYSSEG
+       mov     es,ax           ! segment of 0x010000
+#else
+       push    #SYSSEG
+       pop     es
+#endif
+#ifdef SIZEKRNL
+       call    read_it
+#endif
+       call    kill_motor
+       call    print_nl
+
+! After that we check which root-device to use. If the device is
+! defined (!= 0), nothing is done and the given device is used.
+! Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8),
+! depending on the number of sectors we pretend to know we have.
+
+#if 0
+;;     seg cs
+       mov     ax,root_dev
+       or      ax,ax
+       jne     root_defined
+;;     seg cs
+       mov     bx,sectors
+       mov     ax,#0x0208              ! /dev/ps0 - 1.2Mb
+       cmp     bx,#15
+       je      root_defined
+       mov     al,#0x1c                ! /dev/PS0 - 1.44Mb
+       cmp     bx,#18
+       je      root_defined
+       mov     al,#0x20                ! /dev/fd0H2880 - 2.88Mb
+       cmp     bx,#36
+       je      root_defined
+       mov     al,#0                   ! /dev/fd0 - autodetect
+root_defined:
+;;     seg cs
+       mov     root_dev,ax
+#endif
+
+! after that (everything loaded), we jump to
+! the setup-routine loaded directly after
+! the bootblock:
+
+       jmpi    0,SETUPSEG
+setupseg       =       *-2
+
+! This routine loads the system at address 0x10000, making sure
+! no 64kB boundaries are crossed. We try to load it as fast as
+! possible, loading whole tracks whenever we can.
+!
+! in:  es - starting address segment (normally 0x1000)
+!
+sread: .word 0                 ! sectors read of current track
+head:  .word 0                 ! current head
+track: .word 0                 ! current track
+
+read_it:
+       mov     al,setup_sects
+       inc     al
+       mov     sread,al
+       mov ax,es
+       test ax,#0x0fff
+die:   jne die                 ! es must be at 64kB boundary
+       xor bx,bx               ! bx is starting address within segment
+rp_read:
+#ifdef __BIG_KERNEL__
+#define CALL_HIGHLOAD_KLUDGE .word 0x1eff,0x220 ! call far * bootsect_kludge
+                               ! NOTE: as86 can't assemble this
+       CALL_HIGHLOAD_KLUDGE    ! this is within setup.S
+#else
+       mov ax,es
+       sub ax,#SYSSEG
+#endif
+       cmp ax,syssize          ! have we loaded all yet?
+       jbe ok1_read
+       ret
+ok1_read:
+       mov ax,sectors
+       sub ax,sread
+       mov cx,ax
+       shl cx,#9
+       add cx,bx
+       jnc ok2_read
+       je ok2_read
+       xor ax,ax
+       sub ax,bx
+       shr ax,#9
+ok2_read:
+       call read_track
+       mov cx,ax
+       add ax,sread
+       cmp ax,sectors
+       jne ok3_read
+       mov ax,#1
+       sub ax,head
+       jne ok4_read
+       inc track
+ok4_read:
+       mov head,ax
+       xor ax,ax
+ok3_read:
+       mov sread,ax
+       shl cx,#9
+       add bx,cx
+       jnc rp_read
+       mov ax,es
+       add ah,#0x10
+       mov es,ax
+       xor bx,bx
+       jmp rp_read
+
+read_track:
+       pusha
+       pusha   
+       mov     ax, #0xe2e      ! loading... message 2e = .
+       mov     bx, #7
+       int     0x10
+       popa            
+
+       mov     dx,track
+       mov     cx,sread
+       inc     cx
+       mov     ch,dl
+       mov     dx,head
+       mov     dh,dl
+       and     dx,#0x0100
+       mov     ah,#2
+       
+       push    dx                              ! save for error dump
+       push    cx
+       push    bx
+       push    ax
+
+       int     0x13
+       jc      bad_rt
+       add     sp, #8
+       popa
+       ret
+
+bad_rt:        push    ax                              ! save error code
+       call    print_all                       ! ah = error, al = read
+       
+       
+       xor ah,ah
+       xor dl,dl
+       int 0x13
+       
+
+       add     sp, #10
+       popa    
+       jmp read_track
+
+/*
+ *     print_all is for debugging purposes.  
+ *     It will print out all of the registers.  The assumption is that this is
+ *     called from a routine, with a stack frame like
+ *     dx 
+ *     cx
+ *     bx
+ *     ax
+ *     error
+ *     ret <- sp
+ *
+*/
+print_all:
+       mov     cx, #5          ! error code + 4 registers
+       mov     bp, sp  
+
+print_loop:
+       push    cx              ! save count left
+       call    print_nl        ! nl for readability
+
+       cmp     cl, #5
+       jae     no_reg          ! see if register name is needed
+       
+       mov     ax, #0xe05 + 'A - 1
+       sub     al, cl
+       int     0x10
+
+       mov     al, #'X
+       int     0x10
+
+       mov     al, #':
+       int     0x10
+
+no_reg:
+       add     bp, #2          ! next register
+       call    print_hex       ! print it
+       pop     cx
+       loop    print_loop
+       ret
+
+print_nl:
+       mov     ax, #0xe0d      ! CR
+       int     0x10
+       mov     al, #0xa        ! LF
+       int     0x10
+       ret
+
+/*
+ *     print_hex is for debugging purposes, and prints the word
+ *     pointed to by ss:bp in hexadecimal.
+*/
+
+print_hex:
+       mov     cx, #4          ! 4 hex digits
+       mov     dx, (bp)        ! load word into dx
+print_digit:
+       rol     dx, #4          ! rotate so that lowest 4 bits are used
+       mov     ax, #0xe0f      ! ah = request, al = mask for nybble
+       and     al, dl
+#if 0
+       add     al, #0x90       ! convert al to ASCII hex (four instructions)
+       daa
+       adc     al, #0x40
+       daa
+#else
+       daa                     ! shorter conversion routine
+       add     al,#0xF0
+       adc     al,#0x40        ! is now a hex char 0..9A..F
+#endif
+       int     0x10
+       loop    print_digit
+       ret
+
+
+/*
+ * This procedure turns off the floppy drive motor, so
+ * that we enter the kernel in a known state, and
+ * don't have to worry about it later.
+ */
+kill_motor:
+       push    dx
+       mov     dx,#0x3f2
+       xor     al,al
+       out     dx,al           ; outb
+       pop     dx
+       ret
+
+sectors:
+       .word 0
+
+disksizes:
+       .byte 36,18,15,9
+
+msg1:
+       .byte 13,10
+       .ascii "Loading"
+       .byte 0
+
+.org 497
+setup_sects:
+       .byte SETUPSECS
+root_flags:
+       .word CONFIG_ROOT_RDONLY
+syssize:
+       .word SYSSIZE
+swap_dev:
+       .word SWAP_DEV
+ram_size:
+       .word RAMDISK
+vid_mode:
+       .word SVGA_MODE
+root_dev:
+       .word ROOT_DEV
+boot_flag:
+       .word 0xAA55
diff --git a/src/bsect.c b/src/bsect.c
new file mode 100644 (file)
index 0000000..25b2744
--- /dev/null
@@ -0,0 +1,1708 @@
+/* bsect.c  -  Boot sector handling
+ * 
+ * Copyright 1992-1998 Werner Almesberger
+ * Copyright 1999-2007 John Coffman
+ * Copyright 2009-2010 Joachim Wiedorn
+ * All rights reserved.
+ * 
+ * Licensed under the terms contained in the file 'COPYING'
+ * in the source directory.
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/statfs.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+
+#ifdef _SYS_STATFS_H
+#define        _I386_STATFS_H  /* two versions of statfs is not good ... */
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+#include <assert.h>
+
+#include "config.h"
+#include "lilo.h"
+#include "common.h"
+#include "raid.h"
+#include "cfg.h"
+#include "device.h"
+#include "geometry.h"
+#include "map.h"
+#include "temp.h"
+#include "partition.h"
+#include "boot.h"
+#include "bsect.h"
+#include "bitmap.h"
+#include "probe.h"
+#include "loader.h"
+#include "edit.h"
+
+#ifdef SHS_PASSWORDS
+#include "shs2.h"
+#endif
+#if defined(LCF_UNIFY) || defined(LCF_BUILTIN)
+#define EARLY_MAP
+#endif
+
+
+int boot_dev_nr;
+
+static BOOT_SECTOR bsect,bsect_orig;
+static MENUTABLE menuparams;
+static DESCR_SECTORS descrs;
+static char secondary_map[SECTOR_SIZE];
+static unsigned char table[SECTOR_SIZE];       /* keytable & params */
+static DEVICE dev;
+static char *boot_devnam,*map_name;
+static int use_dev_close = 0;
+static int fd;
+static int image_base = 0,image = 0;
+static char temp_map[PATH_MAX+1];
+static char *fallback[MAX_IMAGES];
+static int fallbacks = 0;
+static unsigned short stage_flags;
+static int image_menu_space = MAX_IMAGES;
+static char *getval_user;
+static BOOT_PARAMS_2 param2;
+static off_t here2;            /* sector address of second stage loader */
+static int adapter = -1;       /* video adapter in use */
+
+typedef struct Pass {
+    int crc[MAX_PW_CRC];
+    char *unique;
+    char *label;
+    struct Pass *next;
+    } PASSWORD;
+
+static PASSWORD *pwsave = NULL;
+
+BUILTIN_FILE *select_loader(void)
+{
+    BUILTIN_FILE *loader = &Third;     /* MENU interface is the default */
+    char *install = cfg_get_strg(cf_options,"install");
+    char *bitmap  = cfg_get_strg(cf_options,"bitmap");
+
+    if (!install) {
+       if (bitmap) loader = &Bitmap;
+    } 
+    else if (strstr(install,"text")) loader = &Second;  /* text interface */
+    else if (strstr(install,"menu")) loader = &Third;
+    else if (strstr(install,"bmp") || bitmap) loader = &Bitmap;   /* menu interface (MDA, EGA, VGA) */
+       
+    adapter = get_video();     /* from probe.c */
+
+    if (adapter <= VIDEO_UNKNOWN && (verbose>=2 || loader==&Bitmap))
+           warn("Unable to determine video adapter in use in the present system.");
+    if (loader == &Third && adapter == VIDEO_CGA)
+           warn("Video adapter (CGA) is incompatible with the boot loader selected for\n"
+                               "  installation ('install = menu').");
+    if (loader == &Bitmap && adapter < VIDEO_MCGA && adapter > VIDEO_UNKNOWN)
+           warn("Video adapter (%s) is incompatible with the boot loader selected for\n"
+                               "  installation ('install = bitmap').", adapter==VIDEO_CGA ? "CGA" :
+                               adapter==VIDEO_MDA ? "MDA" : "unknown");
+    
+    return loader;
+}
+
+
+/* kludge:  'append="..."' may not contain keywords acted upon by 
+   the LILO boot loader -- except "mem=XXX"
+ */
+#define MEM_OKAY 1
+static void check_options(char *options)
+{
+static char *disallow[] = { 
+#if !MEM_OKAY
+                       "mem=",
+#endif
+                               "vga=", "kbd=", "lock", "nobd", NULL };
+    char *here, **dis = disallow;
+    int error = 0;
+
+    if (verbose >= 5) printf("check_options: \"%s\"\n", options);
+    if (strlen(options) > COMMAND_LINE_SIZE-1) {
+       warn("Command line options > %d will be truncated.", COMMAND_LINE_SIZE-1);
+    }
+    while (*dis) {
+       here = strstr(options, *dis);
+       if (here  &&  (here==options || here[-1] == ' ') ) {
+           if (here[3] == '=') error=2;
+           if (here[3] != '=' && (here[4]==' ' || here[4]==0) ) error=2;
+#if !MEM_OKAY
+           if (*dis == disallow[0] && here[4]>='0' && here[4]<='9')
+               error = 1 
+               /*        + (cfg_get_strg(cf_kernel,"initrd") != NULL ||
+                            cfg_get_strg(cf_options,"initrd") != NULL) */
+                            ;
+#endif
+       }
+       if (error>1) die ("APPEND or LITERAL may not contain \"%s\"", *dis);
+#if !MEM_OKAY
+       if (error==1) {
+           warn("APPEND or LITERAL may not contain \"mem=\".");
+           error = 0;
+       }
+#endif
+       ++dis;
+    }    
+}
+
+static int getval(char **cp, int low, int high, int default_value, int factor)
+{
+    int temp;
+    
+    if (!**cp) {
+       if (factor && eflag) {
+           if (low==1) default_value--;
+           default_value *= factor;
+       }
+    }
+    else if (ispunct(**cp)) {
+       (*cp)++;
+       if (factor && eflag) {
+           if (low==1) default_value--;
+           default_value *= factor;
+       }
+    } else {
+       temp = strtol(*cp, cp, 0);
+       if (!factor) default_value = temp;
+       else {
+           if (**cp == 'p' || **cp == 'P') {
+               (*cp)++;
+               default_value = temp;
+               temp /= factor;
+               if (low==1) temp++;
+           } else {
+               default_value = (low==1 ? temp-1 : temp)*factor;
+           }
+       }
+       
+       if (temp < low || temp > high)
+               die("%s: value out of range [%d,%d]", getval_user, low, high);
+       if (**cp && !ispunct(**cp)) die("Invalid character: \"%c\"", **cp);
+       if (**cp) (*cp)++;
+    }
+    if (verbose>=5) printf("getval: %d\n", default_value);
+    
+    return default_value;
+}
+
+void bmp_do_timer(char *cp, MENUTABLE *menu)
+{
+    if (!cp) {
+       if (eflag) menu->t_row = menu->t_col = -1;  /* there is none, if not specified during edit */
+    } else if (strcasecmp(cp,"none")==0) {
+       menu->t_row = menu->t_col = -1;  /* there is none, if specified as "none" */
+    } else {
+       getval_user = "bmp-timer";
+       menu->t_col = getval(&cp, 1, 76, menu->t_col, 8);
+       menu->t_row = getval(&cp, 1, 30, menu->t_row, 16);
+
+       if (!*cp && !eflag) return;
+       menu->t_fg = getval(&cp, 0, colormax, menu->fg, 0);
+       menu->t_bg = getval(&cp, 0, colormax, eflag?colormax^menu->t_fg:menu->t_bg, 0);
+       menu->t_sh = getval(&cp, 0, colormax, menu->t_fg, 0);
+    }
+}
+
+
+void bmp_do_table(char *cp, MENUTABLE *menu)
+{
+    if (!cp) {
+       if (eflag) cp = "";
+       else return;            /* dont change anything */
+    }
+    
+    getval_user = "bmp-table";
+    menu->col = getval(&cp, 1, 80-MAX_IMAGE_NAME, menu->col/8 + 1, 8);
+    menu->row = getval(&cp, 1, 29, menu->row/16 + 1, 16);
+#if 0
+    menu->ncol = getval(&cp, 1, 80/(MAX_IMAGE_NAME+2), 1, 0);
+    menu->maxcol = getval(&cp, 3, MAX_IMAGES, (MAX_IMAGES+menu->ncol-1)/menu->ncol, 0);
+    menu->xpitch = getval(&cp, MAX_IMAGE_NAME+2, 80/menu->ncol, MAX_IMAGE_NAME+6, 8);
+#else
+    menu->ncol = getval(&cp, 1, 80/(MAX_IMAGE_NAME+1), menu->ncol, 0);
+    menu->maxcol = getval(&cp, 2, 30 - menu->row/16, eflag?30 - menu->row/16:menu->maxcol, 0);
+    menu->xpitch = getval(&cp, MAX_IMAGE_NAME+1, menu->ncol==1?80-menu->col/8:(80-menu->col/8-MAX_IMAGE_NAME*menu->ncol)/(menu->ncol-1)+MAX_IMAGE_NAME, menu->xpitch/8, 8);
+    menu->mincol = getval(&cp, 1, menu->maxcol, menu->mincol, 0);
+#endif
+    if ((menu->row + menu->maxcol*16 > 480 || 
+        menu->col + (MAX_IMAGE_NAME+1)*8 + (menu->ncol-1)*menu->xpitch > 640))  
+                warn("'bmp-table' may spill off screen");
+}
+
+
+void bmp_do_colors(char *cp, MENUTABLE *menu)
+{
+    if (!cp) {
+       if (eflag) cp = "";
+       else return;            /* dont change anything */
+    }
+
+    getval_user = "bmp-colors";
+    menu->fg = getval(&cp, 0, colormax, menu->fg, 0);
+    if (!*cp && !eflag) return;
+    menu->bg = getval(&cp, 0, colormax, menu->fg, 0);
+    menu->sh = getval(&cp, 0, colormax, menu->fg, 0);
+
+    menu->h_fg = getval(&cp, 0, colormax, menu->h_fg, 0);
+    if (!*cp && !eflag) return;
+    menu->h_bg = getval(&cp, 0, colormax, menu->h_fg, 0);
+    menu->h_sh = getval(&cp, 0, colormax, menu->h_fg, 0);      
+}
+
+void pw_file_update(int passw)
+{
+    PASSWORD *walk;
+    int i;
+    
+    if (verbose>=4) printf("pw_file_update:  passw=%d\n", passw);
+
+    if (passw && !test && pw_file) {
+       if (fseek(pw_file,0L,SEEK_SET)) perror("pw_file_update");
+    
+       for (walk=pwsave; walk; walk=walk->next) {
+           fprintf(pw_file, "label=<\"%s\">", walk->label);
+           for (i=0; i<MAX_PW_CRC; i++) fprintf(pw_file, " 0x%08X", walk->crc[i]);
+           fprintf(pw_file, "\n");
+       }
+    }
+    if (pw_file) fclose(pw_file);
+}
+
+void pw_fill_cache(void)
+{
+    char line[MAX_TOKEN+1];
+    char *brace;
+    char *label;
+    PASSWORD *new;
+    int i;
+     
+    if (verbose>=5) printf("pw_fill_cache\n");    
+    if (fseek(pw_file,0L,SEEK_SET)) perror("pw_fill_cache");
+    
+    while (fgets(line,MAX_TOKEN,pw_file)) {
+       if (verbose>=5) printf("   %s\n", line);
+       brace = strrchr(line,'>');
+       label = strchr(line,'<');
+       if (label && label[1]=='"' && brace && brace[-1]=='"') {
+           brace[-1] = 0;
+           if ( !(new = alloc_t(PASSWORD)) ) pdie("Out of memory");
+           new->next = pwsave;
+           pwsave = new;
+           new->unique = NULL;
+           new->label = stralloc(label+2);
+           if (verbose>=2) printf("Password file: label=%s\n", new->label);
+           brace++;
+           for (i=0; i<MAX_PW_CRC; i++) {
+               new->crc[i] = strtoul(brace,&label,0);
+               brace = label;
+           }
+       }
+       else die("Ill-formed line in .crc file");
+    }
+    if (verbose >=5) printf("end pw_fill_cache\n");
+}
+
+static void hash_password(char *password, int crcval[])
+{
+#ifdef CRC_PASSWORDS
+   static int poly[] = {CRC_POLY1, CRC_POLY2, CRC_POLY3, CRC_POLY4, CRC_POLY5};
+#endif
+       int crc;
+       int j;
+       int i = strlen(password);
+       
+#ifdef SHS_PASSWORDS
+       shsInit();
+       shsUpdate((BYTE*)password, i);
+       shsFinal();
+#endif
+       for (j=0; j<MAX_PW_CRC; j++) {
+           crcval[j] = crc =
+#ifdef CRC_PASSWORDS
+                               crc32((unsigned char *)password, i, poly[j]);
+  #define PWTYPE "CRC-32"
+#else
+                               shsInfo.digest[j];
+  #define PWTYPE "SHS-160"
+#endif
+           if(verbose >= 2) {
+               if (j==0) printf("Password " PWTYPE " =");
+               printf(" %08X", crc);
+           }
+       }
+       if (verbose >= 2) printf("\n");
+}
+
+
+void pw_wipe(char *pass)
+{
+    int i;
+    
+    if (!pass) return;
+    i = strlen(pass);
+    while (i) pass[--i]=0;
+    free(pass);
+}
+
+
+char *pw_input(void)
+#if 1
+{
+    char *cp = getpass("");
+    int i = strlen(cp);
+    char *acp = stralloc(cp);
+
+    while (i) cp[i--] = 0;
+    return acp;    
+}
+#else
+{
+    char *pass;
+    char buf[MAX_TOKEN+1];
+    int i, ch;
+    
+    i = 0;
+    fflush(stdout);
+    while((ch=getchar())!='\n') if (i<MAX_TOKEN) buf[i++]=ch;
+    buf[i]=0;
+    pass = stralloc(buf);
+    while (i) buf[--i]=0;
+    return pass;
+}
+#endif
+
+static void pw_get(char *pass, int crcval[], int option)
+{
+    PASSWORD *walk;
+    char *pass2;
+    char *label;
+    
+    label = cfg_get_strg(cf_all, "label");
+    if (!label) label = cfg_get_strg(cf_top, "image");
+    if (!label) label = cfg_get_strg(cf_top, "other");
+    if (!label) die("Need label to get password");
+    if ((pass2 = strrchr(pass,'/'))) label = pass2+1;
+
+    for (walk=pwsave; walk; walk=walk->next) {
+       if (pass == walk->unique ||
+               (!walk->unique && !strcmp(walk->label,label) && (walk->unique=pass)) ) {
+           memcpy(crcval, walk->crc, MAX_PW_CRC*sizeof(int));
+           return;
+       }
+    }
+    walk = alloc_t(PASSWORD);
+    if (!walk) die("Out of memory");
+    walk->next = pwsave;
+    pwsave = walk;
+    walk->unique = pass;
+    walk->label = stralloc(label);
+    
+    printf("\nEntry for  %s  used null password\n", label);
+    pass = pass2 = NULL;
+    do {
+       if (pass) {
+           printf("   *** Phrases don't match ***\n");
+           pw_wipe(pass);
+           pw_wipe(pass2);
+       }
+       printf("Type passphrase: ");
+       pass2 = pw_input();
+       printf("Please re-enter: ");
+       pass = pw_input();
+    } while (strcmp(pass,pass2));
+    printf("\n");
+    pw_wipe(pass2);  
+    hash_password(pass, walk->crc);
+    pw_wipe(pass);
+    memcpy(crcval, walk->crc, MAX_PW_CRC*sizeof(int));
+}
+
+
+static void retrieve_crc(int crcval[])
+{
+    int i;
+    char *pass;
+    
+    if (!pwsave) {
+       if (cfg_pw_open()) pw_fill_cache();
+    }
+    pass = cfg_get_strg(cf_all,"password");
+    if (pass) pw_get(pass,crcval,0);
+    else pw_get(cfg_get_strg(cf_options,"password"),crcval,1);
+
+    if (verbose >= 2) {
+       printf("Password found is");
+       for (i=0; i<MAX_PW_CRC; i++) printf(" %08X", crcval[i]);
+       printf("\n");
+    }
+}
+
+
+
+static void open_bsect(char *boot_dev)
+{
+    struct stat st;
+
+    if (verbose > 0)
+       printf("Reading boot sector from %s\n",boot_dev ? boot_dev :
+         "current root.");
+    boot_devnam = boot_dev;
+    if (!boot_dev || !strcmp(boot_dev, "/") ) {
+       if (stat("/",&st) < 0) pdie("stat /");
+       if (MAJOR(st.st_dev) != MAJOR_MD &&
+               (st.st_dev & P_MASK(st.st_dev)) > PART_MAX)
+           die("Can't put the boot sector on logical partition 0x%04X",
+             (int)st.st_dev);
+       fd = dev_open(&dev,boot_dev_nr = st.st_dev,O_RDWR);
+       boot_devnam = dev.name;
+       use_dev_close = 1;
+    }
+    else {
+       if ((fd = open(boot_dev,O_RDWR)) < 0)
+           die("open %s: %s",boot_dev,strerror(errno));
+       if (fstat(fd,&st) < 0) die("stat %s: %s",boot_dev,strerror(errno));
+       if (!S_ISBLK(st.st_mode)) boot_dev_nr = 0;
+       else boot_dev_nr = st.st_rdev;
+    }
+/* new code to get boot device code */
+/* plus geo_open will trigger VolumeMgmt (pf_hard_disk_scan) before the
+   boot sector is actually read; timing is very important */
+{
+    GEOMETRY geo;
+    geo_open(&geo, boot_devnam, O_RDONLY);
+    bios_boot = geo.device;
+    geo_close(&geo);
+}
+    
+    if (boot_dev_nr && !is_first(boot_dev_nr) )
+       warn("%s is not on the first disk",boot_dev ?
+         boot_dev : "current root");
+    if (read(fd,(char *) &bsect,SECTOR_SIZE) != SECTOR_SIZE)
+       die("read %s: %s",boot_dev ? boot_dev : dev.name,strerror(errno));
+    bsect_orig = bsect;
+    ireloc = part_nowrite(boot_devnam);
+    if (ireloc == PTW_DOS + PTW_NTFS)  ireloc = PTW_DOS;
+/* check for override (-F) command line flag */
+    if (ireloc>PTW_DOS && force_fs) {
+        int nowarn2 = nowarn;
+        nowarn = 0;
+
+       warn("'-F' override used. Filesystem on  %s  may be destroyed.", boot_devnam);
+       if (!yesno("\nProceed? ",0)) exit(0);
+
+        nowarn = nowarn2;
+       ireloc=PTW_OKAY;
+    }
+}
+
+
+void bsect_read(char *boot_dev,BOOT_SECTOR *buffer)
+{
+    open_bsect(boot_dev);
+    *buffer = bsect;
+    (void) close(fd);
+}
+
+
+static void menu_do_scheme(char *scheme, MENUTABLE *menu)
+{
+    static char khar[] = "kbgcrmywKBGCRMYW";
+    unsigned int fg, bg;
+    int i;
+    unsigned char *at;
+    /* order of color attributes is:
+         text, hilighted text, border, title
+    */
+#define color(c) ((int)(strchr(khar,(int)(c))-khar))
+    bg = 0;
+    at = &(menu->at_text);
+    for (i=0; i<4 && *scheme; i++) {
+       fg = color(*scheme);
+       if (fg>=16) die("Invalid menu-scheme color: '%c'", *scheme);
+       if (*++scheme) bg = color(*scheme);
+       else {
+           die("Invalid menu-scheme syntax");
+       }
+       if (bg>=16) die("Invalid menu-scheme color: '%c'", *scheme);
+       if (*++scheme) {
+           if (ispunct(*scheme)) scheme++;
+           else die("Invalid menu-scheme punctuation");
+       }
+       if (bg>=8)
+           warn("menu-scheme BG color may not be intensified");
+       *at++ = ((bg<<4) | fg) & 0x7F;
+    }
+    /* check on the TEXT color */
+    if (menu->at_text == 0) {
+        warn("menu-scheme \"black on black\" changed to \"white on black\"");
+       menu->at_text = 0x07;
+    }
+    /* check on the HIGHLIGHT color */
+    if (menu->at_highlight == 0)  menu->at_highlight = ((menu->at_text<<4)&0x70) | ((menu->at_text>>4)&0x0f);
+    /* check on the BORDER color */
+    if (menu->at_border == 0)  menu->at_border = menu->at_text;
+    /* check on the TITLE color */
+    if (menu->at_title == 0)  menu->at_title = menu->at_border;
+    
+    strncpy(menu->menu_sig, "MENU", 4);
+    if (verbose>=5)
+       printf("Menu attributes: text %02X  highlight %02X  border %02X  title %02X\n",
+                       (int)menu->at_text, (int)menu->at_highlight,
+                       (int)menu->at_border, (int)menu->at_title);
+#undef color
+}
+
+
+void bsect_open(char *boot_dev,char *map_file,char *install,int delay,
+  int timeout, int raid_offset)
+{
+    static char coms[] = "0123";
+    static char parity[] = "NnOoEe";
+    static char bps[] = 
+       "110\000150\000300\000600\0001200\0002400\0004800\0009600\000"
+       "19200\00038400\00057600\000115200\000?\000?\000?\000?\000"
+       "56000\000";
+    GEOMETRY geo;
+    struct stat st;
+    int i, speed, bitmap, j, dataend;
+    int m_fd=0,kt_fd,sectors;
+    char *message,*colon,*serial,*walk,*this,*keytable,*scheme;
+    MENUTABLE *menu;
+    BITMAPFILEHEADER fhv;
+    BITMAPHEADER bmhv;
+    BITMAPLILOHEADER lhv;
+    unsigned int timestamp;
+#ifdef LCF_BUILTIN
+    BUILTIN_FILE *loader;
+#else
+    int i_fd;
+#endif
+
+#if 0
+printf("sizeof(IMAGE_DESCR) = %d\n", sizeof(IMAGE_DESCR));
+printf("sizeof(DESCR_SECTORS) = %d\n", sizeof(DESCR_SECTORS));
+printf("MAX_IMAGES = %d\n", MAX_IMAGES);
+#endif
+    image = image_base = i = 0;
+    memset(&menuparams, 0, sizeof(menuparams));
+    if (stat(map_file,&st) >= 0 && !S_ISREG(st.st_mode))
+       die("Map %s is not a regular file.",map_file);
+    open_bsect(boot_dev);
+    part_verify(boot_dev_nr,1);
+    if (ireloc>PTW_DOS) {
+       die("Filesystem would be destroyed by LILO boot sector: %s", boot_dev);
+    }
+    else if (ireloc==PTW_DOS) {
+       warn("boot record relocation beyond BPB is necessary: %s", boot_dev);
+    }
+
+#ifdef EARLY_MAP
+    if ((colon = strrchr(map_name = map_file,':')) == NULL)
+       strcat(strcpy(temp_map,map_name),MAP_TMP_APP);
+    else {
+       *colon = 0;
+       strcat(strcat(strcpy(temp_map,map_name),MAP_TMP_APP),colon+1);
+       *colon = ':';
+    }
+    map_create(temp_map);
+    temp_register(temp_map);
+#endif
+
+    if (!install) {
+#if !defined(LCF_NOINSTDEF) || defined(LCF_BUILTIN)
+       install = DFL_BOOT;
+#else
+       die("No boot loader specified ('-i' or 'install =')");
+#endif
+    } 
+/*  if (install) */ {
+       timestamp = bsect.par_1.timestamp; /* preserve timestamp */
+
+/* determine which secondary loader to use */
+
+       loader = select_loader();
+       if (verbose > 0) {
+           printf("Using %s secondary loader\n",
+               loader==&Bitmap ? "BITMAP" :
+               loader==&Third  ? "MENU" :
+               "TEXT" );
+       }
+       memcpy(&bsect, First.data, MAX_BOOT_SIZE);
+
+       bsect.par_1.timestamp = timestamp;
+       map_begin_section(); /* no access to the (not yet open) map file
+               required, because this map is built in memory */
+       here2 = map_insert_data (loader->data, loader->size);
+       memcpy(&param2,loader->data,sizeof(param2));
+#ifdef LCF_FIRST6
+       /* write just the 4 bytes (sa6==2) */
+       sectors = map_write((SECTOR_ADDR*)secondary_map, (SECTOR_SIZE-4)/sizeof(SECTOR_ADDR)-2, 1, 2);
+#else
+       sectors = map_write((SECTOR_ADDR*)secondary_map, (SECTOR_SIZE-4)/sizeof(SECTOR_ADDR)-2, 1);
+#endif
+       memcpy(secondary_map+SECTOR_SIZE-4, EX_MAG_STRING, 4);
+
+       /* fill in full size of secondary boot loader in paragraphs */
+       /*bsect.par_1.*/dataend = (sectors + 5 + (COMMAND_LINE_SIZE>256) + MAX_DESCR_SECS) * (SECTOR_SIZE/16);
+
+       if (verbose > 1)
+           printf("Secondary loader: %d sector%s (0x%0X dataend).\n",sectors,sectors == 1 ?
+             "" : "s", /*bsect.par_1.*/dataend*16);
+       stage_flags = ((BOOT_SECTOR*)(loader->data)) -> par_2.stage;
+       if ((stage_flags & 0xFF) != STAGE_SECOND)
+           die("Ill-formed boot loader; no second stage section");
+
+       if (verbose>=4) printf("install(2) flags: 0x%04X\n", (int)stage_flags);
+    }
+
+#ifndef EARLY_MAP
+    if ((colon = strrchr(map_name = map_file,':')) == NULL)
+       strcat(strcpy(temp_map,map_name),MAP_TMP_APP);
+    else {
+       *colon = 0;
+       strcat(strcat(strcpy(temp_map,map_name),MAP_TMP_APP),colon+1);
+       *colon = ':';
+    }
+    map_create(temp_map);
+    temp_register(temp_map);
+#endif
+
+       map_begin_section();
+       map_add_sector(secondary_map);
+#ifdef LCF_FIRST6
+       /* write out six byte address */
+       (void) map_write(&bsect.par_1.secondary,1,0,1);
+#else
+       (void) map_write(&bsect.par_1.secondary,1,0);
+#endif
+
+/* if the state of the BIOS is DL_GOOD, always mark when boot==map
+   if the state of the BIOS is < DL_GOOD, never mark */
+   
+       if ( bios_boot == bios_map  &&
+               (bios_passes_dl == DL_GOOD
+                || (do_md_install && !(extra==X_MBR_ONLY ))
+                 ) )
+           bsect.par_1.prompt |= FLAG_MAP_ON_BOOT;
+       if (bios_boot!=bios_map)
+           warn("The boot sector and map file are on different disks.");
+       if ( (bios_map & 0x80) && !do_md_install &&
+               !cfg_get_flag(cf_options, "static-bios-codes") ) /* hard disk & not raid master */
+           bsect.par_1.map_serial_no = serial_no[bios_map - 0x80];
+       if (verbose>=2)
+           printf("bios_boot = 0x%02X  bios_map = 0x%02X  map==boot = %d  map S/N: %08X\n",
+               bios_boot, bios_map,
+               !!(bsect.par_1.prompt&FLAG_MAP_ON_BOOT),
+               bsect.par_1.map_serial_no);
+    
+/* code to get creation time of map file */
+    if (stat(temp_map, &st) < 0) die("Cannot get map file status");
+    param2.map_stamp = bsect.par_1.map_stamp = st.st_mtime;
+    if (verbose>=4) printf("Map time stamp: %08X\n", (int)bsect.par_1.map_stamp);
+
+    *(unsigned short *) &bsect.sector[BOOT_SIG_OFFSET] = BOOT_SIGNATURE;
+    message = cfg_get_strg(cf_options,"message");
+    scheme = cfg_get_strg(cf_options,"bitmap");
+    if (message && scheme) die("'bitmap' and 'message' are mutually exclusive");
+    param2.msg_len = 0;
+    bitmap = (loader==&Bitmap);
+    if (bitmap) {
+       message = scheme;
+       if (!(stage_flags & STAGE_FLAG_BMP4)) {
+           warn("Non-bitmap capable boot loader; 'bitmap=' ignored.");
+           message = NULL;
+       }
+    }
+    j = -1;
+    if (message) {
+       if (verbose >= 1) {
+           printf("Mapping %s file %s", 
+                       bitmap ? "bitmap" : "message", message);
+           show_link(message);
+           printf("\n");
+       }
+       m_fd = geo_open(&geo,message,O_RDONLY);
+       if (fstat(m_fd,&st) < 0) die("stat %s: %s",message,strerror(errno));
+       /* the -2 below is because of GCC's alignment requirements */
+       i = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPHEADER)+sizeof(RGB)*16+
+                               sizeof(BITMAPLILOHEADER);
+       if (bitmap || st.st_size>i) {
+           int bits=0;
+           
+           j = get_std_headers(m_fd, &fhv, &bmhv, &lhv);
+           if (j<0) die("read %s: %s", message, strerror(errno));
+           if (j==0 || j>2) { /* definitely a bitmap file */
+               BITMAPHEADER *bmh = &bmhv;
+               if (verbose >= 3) {
+                   printf("width=%d height=%d planes=%d bits/plane=%d\n",
+                       (int)bmh->width, (int)bmh->height,
+                       (int)bmh->numBitPlanes, (int)bmh->numBitsPerPlane);
+               }
+               if (bmh->size == sizeof(BITMAPHEADER) &&
+                       bmh->width==640 && bmh->height==480 && 
+                       ((bits = bmh->numBitPlanes * bmh->numBitsPerPlane) == 4 ||
+                         bits == 8) ) {
+                   if (!bitmap) die("Message specifies a bitmap file");
+                   if (bits>4 && adapter<VIDEO_VESA)
+                       warn("Video adapter does not support VESA BIOS extensions needed for\n"
+                                      "  display of 256 colors.  Boot loader will fall back to TEXT only operation.");
+               }
+               else if (bitmap) die("Unsupported bitmap");
+           } else if (bitmap) die("Not a bitmap file");
+       }
+       i = bitmap ? MAX_KERNEL_SECS*SECTOR_SIZE : MAX_MESSAGE;
+       if (st.st_size > i)
+           die("%s is too big (> %d bytes)",message,i);
+       param2.msg_len = bitmap ? (st.st_size+15)/16 : st.st_size;
+       map_begin_section();
+#ifndef LCF_UNIFY
+       map_add(&geo,0,((st.st_size)+SECTOR_SIZE-1)/SECTOR_SIZE);
+#else
+       map_insert_file (&geo,0,(st.st_size+SECTOR_SIZE-1)/SECTOR_SIZE);
+#endif
+       sectors = map_end_section(&menuparams.msg,0);
+       if (verbose >= 2)
+           printf("%s: %d sector%s.\n",bitmap?"Bitmap":"Message",
+                       sectors,sectors == 1 ?  "" : "s");
+       geo_close(&geo);
+    }
+
+    if (cfg_get_flag(cf_options,"el-torito-bootable-cd"))
+       param2.flag2 |= FLAG2_EL_TORITO;
+    if (cfg_get_flag(cf_options,"unattended")) {
+       param2.flag2 |= FLAG2_UNATTENDED;
+       if (timeout < 0) {
+           warn("UNATTENDED used; setting TIMEOUT to 20s (seconds).");
+           timeout = 200;
+       }
+    }
+        
+    serial = cfg_get_strg(cf_options,"serial");
+    if (serial) {
+       if (!(stage_flags & STAGE_FLAG_SERIAL))
+           die("Serial line not supported by boot loader");
+       if (!*serial || !(this = strchr(coms,*serial)))
+           die("Invalid serial port in \"%s\" (should be 0-3)",serial);
+       else param2.port = (this-coms)+1;
+       param2.ser_param = SER_DFL_PRM;
+       if (serial[1]) {
+           if (serial[1] != ',')
+               die("Serial syntax is <port>[,<bps>[<parity>[<bits>]]]");
+           walk = bps;
+           speed = 0;
+           while (*walk && strncmp(serial+2,walk,(i=strlen(walk)))) {
+               speed++;
+               walk += i+1;
+           }
+           if (!*walk) die("Unsupported baud rate");
+           param2.ser_param &= ~0xE4;
+           if (speed==16) speed -= 6;  /* convert 56000 to 57600 */
+           param2.ser_param |= ((speed<<5) | (speed>>1)) & 0xE4;
+           serial += i+2;
+       /* check for parity specified */
+           if (*serial) {
+               if (!(this = strchr(parity,*serial)))
+                   die("Serial speed = %s; valid parity values are N, O and E", walk);
+               i = (int)(this-parity)>>1;
+               if (i==2) i++; /* N=00, O=01, E=11 */
+               param2.ser_param &= ~(i&1); /* 7 bits if parity specified */
+               param2.ser_param |= i<<3;   /* specify parity */
+       /* check if number of bits is there */
+               if (serial[1]) {
+                   if (serial[1] != '7' && serial[1] != '8')
+                       die("Only 7 or 8 bits supported");
+                   if (serial[1]=='7') param2.ser_param &= 0xFE;
+                   else param2.ser_param |= 0x01;
+                   
+                   if (serial[2]) die("Syntax error in SERIAL");
+               }
+           }
+           if (verbose>=4) printf("Serial Param = 0x%02X\n", 
+                                               (int)param2.ser_param);
+       }
+       if (delay < 20 && !cfg_get_flag(cf_options,"prompt")) {
+           warn("no PROMPT with SERIAL; setting DELAY to 20 (2 seconds)");
+           delay = 20;
+       }
+    }
+    bsect.par_1.prompt |= cfg_get_flag(cf_options,"prompt") ? FLAG_PROMPT : 0;
+    if (cfg_get_flag(cf_options,"suppress-boot-time-BIOS-data")) {
+       warn("boot-time BIOS data will not be saved.");
+       bsect.par_1.prompt |= FLAG_NOBD;
+    }
+    if (!fetch() && (bios_map &
+#if VERSION_MINOR>=50
+                       bios_boot &       /* if 'boot=/dev/fd0', force write */
+#endif
+                       0x80)) {
+               bsect.par_1.prompt |= FLAG_BD_OKAY;
+               if (verbose>=2)
+                       printf("BIOS data check was okay on the last boot\n");
+       }
+       else {
+               if (verbose>=2)
+                       printf("BIOS data check will include auto-suppress check\n");
+       }
+       /* set to LARGEMEM only if 'large-memory' ist set AND 'small-memory is not set */
+    if (cfg_get_flag(cf_options,"large-memory")
+                       && !cfg_get_flag(cf_options,"small-memory")) {
+#ifndef LCF_INITRDLOW
+               bsect.par_1.prompt |= FLAG_LARGEMEM;
+#else
+               warn("This LILO is compiled with INITRDLOW option, 'large-memory' ignored.");
+#endif
+    }
+       bsect.par_1.prompt |= raid_flags;
+       bsect.par_1.raid_offset = raid_offset;  /* to be modified in bsect_raid_update */
+
+/* convert timeout in tenths of a second to clock ticks    */
+/* tick interval is 54.925 ms  */
+/*   54.925 * 40 -> 2197       */
+/*  100 * 40 -> 4000          */
+#if 0
+#define        tick(x) ((x)*100/55)
+#else
+#define tick(x) ((x)*4000/2197)
+#endif
+    delay =  delay==36000 ? 0xffff : tick(delay);
+    if (delay > 0xffff) die("Maximum delay is 59:59 (3599.5secs).");
+       else param2.delay = delay;
+
+    timeout =  timeout==36000 ? 0xfffe : tick(timeout);        /* -1 -> -1 ticks */
+    if (timeout == -1) param2.timeout = 0xffff;
+    else if (timeout >= 0xffff) die("Maximum timeout is 59:59 (3599.5secs).");
+       else param2.timeout = timeout;
+
+/* keytable & parameter area setup */
+
+    if (!(keytable = cfg_get_strg(cf_options,"keytable"))) {
+       for (i = 0; i < 256; i++) table[i] = i;
+    }
+    else {
+       if ((kt_fd = open(keytable,O_RDONLY)) < 0)
+           die("open %s: %s",keytable,strerror(errno));
+       if (read(kt_fd,table,256) != 256)
+           die("%s: bad keyboard translation table",keytable);
+       (void) close(kt_fd);
+    }
+#if 0
+    menu = (MENUTABLE*)&table[256];
+    memset(menu, 0, 256);
+#else
+    menu = &menuparams;
+#endif
+    memcpy(&(menu->row), &(lhv.row), sizeof(lhv) - sizeof(lhv.size) - sizeof(lhv.magic));
+
+    if ((scheme = cfg_get_strg(cf_options,"menu-scheme"))) {
+       if (!(stage_flags & STAGE_FLAG_MENU))
+           warn("'menu-scheme' not supported by boot loader");
+       menu_do_scheme(scheme, menu);
+    }
+    if ((scheme = cfg_get_strg(cf_options,"menu-title"))) {
+       if (!(stage_flags & STAGE_FLAG_MENU))
+           warn("'menu-title' not supported by boot loader");
+       if (strlen(scheme) > MAX_MENU_TITLE)
+           warn("menu-title is > %d characters", MAX_MENU_TITLE);
+       strncpy(menu->title, scheme, MAX_MENU_TITLE);
+       menu->len_title = strlen(menu->title);
+    }
+    if ((scheme = cfg_get_strg(cf_options,"bmp-table"))) {
+       if (!(stage_flags & STAGE_FLAG_BMP4))
+           warn("'bmp-table' not supported by boot loader");
+    }
+    bmp_do_table(scheme, menu);
+    if (bitmap) {
+       image_menu_space = menu->ncol * menu->maxcol;
+       if (verbose>=3) printf("image_menu_space = %d\n", image_menu_space);
+    }
+    if ((scheme = cfg_get_strg(cf_options,"bmp-colors"))) {
+       if (!(stage_flags & STAGE_FLAG_BMP4))
+           warn("'bmp-colors' not supported by boot loader");
+    }
+    bmp_do_colors(scheme, menu);
+    if ((scheme = cfg_get_strg(cf_options,"bmp-timer"))) {
+       if (!(stage_flags & STAGE_FLAG_BMP4))
+           warn("'bmp-timer' not supported by boot loader");
+    }
+    bmp_do_timer(scheme, menu);
+#if 0
+    map_begin_section();
+    map_add_sector(table);
+    (void) map_write(&param2.keytab,1,0);
+#endif
+    memset(&descrs,0,SECTOR_SIZE*MAX_DESCR_SECS);
+    if (cfg_get_strg(cf_options,"default")) image = image_base = 1;
+    if (verbose > 0) printf("\n");
+}
+
+
+static int dev_number(char *dev)
+{
+    struct stat st;
+
+    if (stat(dev,&st) >= 0) return st.st_rdev;
+    if (!isdigit(*dev)) die("Illegal 'root=' specification: %s", dev);
+    if (verbose >= 1) 
+       printf("Warning: cannot 'stat' device \"%s\"; trying numerical conversion\n", dev);
+    return to_number(dev);
+}
+
+
+static int get_image(char *name,char *label,IMAGE_DESCR *descr)
+{
+    char *here,*deflt,*tmp;
+    int this_image,other,label_is_name=0;
+    unsigned char *uch;
+
+    if (!label) {
+
+        here = strrchr(label = name,'/');
+        if (here)
+        {
+            label_is_name = 1;
+            label = here+1;
+        }
+    }
+    if (label_is_name)
+    {
+        if (strchr(label,' ')) die("Image name, (which is actually the name) contains a blank character: '%s'", label);
+    }
+    if (!label_is_name)
+    {
+        tmp = label;
+        while (*tmp)
+        {
+            if (*tmp == ' ')
+                    *tmp = '_';
+            *tmp++;
+        }
+    } 
+    if (strlen(label) > MAX_IMAGE_NAME) die("Image name, label, or alias is too long: '%s'",label);
+    for (uch=(unsigned char*)label; *uch; uch++) {
+       if (*uch<' ')  die("Image name, label, or alias contains an illegal character: '%s'", label);
+    }
+    for (other = image_base; other <= image; other++) {
+#ifdef LCF_IGNORECASE
+       if (!strcasecmp(label,descrs.d.descr[other].name))
+#else
+       if (!strcmp(label,descrs.d.descr[other].name))
+#endif
+           die("Duplicate label \"%s\"",label);
+       if ((((descr->flags & FLAG_SINGLE) && strlen(label) == 1) ||
+         (((descrs.d.descr[other].flags) & FLAG_SINGLE) &&
+         strlen(descrs.d.descr[other].name) == 1)) &&
+#ifdef LCF_IGNORECASE
+         toupper(*label) == toupper(*descrs.d.descr[other].name))
+#else
+         *label == *descrs.d.descr[other].name)
+#endif
+           die("Single-key clash: \"%s\" vs. \"%s\"",label,
+             descrs.d.descr[other].name);
+    }
+
+    if (image_base && (deflt = cfg_get_strg(cf_options,"default")) &&
+#ifdef LCF_IGNORECASE
+      !strcasecmp(deflt,label))
+#else
+      !strcmp(deflt,label))
+#endif
+       this_image = image_base = 0;
+    else {
+       if (image == MAX_IMAGES)
+           die("Only %d image names can be defined",MAX_IMAGES);
+       if (image >= image_menu_space)
+           die("Bitmap table has space for only %d images",
+                               image_menu_space);
+       this_image = image++;
+    }
+    descrs.d.descr[this_image] = *descr;
+    strcpy(descrs.d.descr[this_image].name,label);
+
+#ifdef LCF_VIRTUAL
+    if ( (deflt = cfg_get_strg(cf_options,"vmdefault")) &&
+#ifdef LCF_IGNORECASE
+               !strcasecmp(deflt,label))  {
+#else
+               !strcmp(deflt,label))  {
+#endif
+       descrs.d.descr[this_image].flags |= FLAG_VMDEFAULT;
+       param2.flag2 |= FLAG2_VIRTUAL;
+       }
+#endif
+
+#ifdef LCF_NOKEYBOARD
+    if ( (deflt = cfg_get_strg(cf_options,"nokbdefault")) &&
+#ifdef LCF_IGNORECASE
+               !strcasecmp(deflt,label))  {
+#else
+               !strcmp(deflt,label))  {
+#endif
+       descrs.d.descr[this_image].flags |= FLAG_NOKBDEFAULT;
+       param2.flag2 |= FLAG2_NOKBD;
+       }
+#endif
+
+    return this_image;
+}
+
+
+static char options[SECTOR_SIZE]; /* this is ugly */
+
+
+static void bsect_common(IMAGE_DESCR *descr, int image)
+{
+    struct stat st;
+    char *here,*root,*ram_disk,*vga,*password;
+    char *literal,*append,*fback;
+    char fallback_buf[SECTOR_SIZE];
+
+    memset(descr, 0, sizeof(IMAGE_DESCR));     /* allocated on stack by caller */
+    memset(fallback_buf,0,SECTOR_SIZE);
+    memset(options,0,SECTOR_SIZE);
+    
+if (image) { /* long section specific to 'image=' */
+    char *append_local;
+    
+    if ((cfg_get_flag(cf_kernel,"read-only") && cfg_get_flag(cf_kernel,
+      "read-write")) || (cfg_get_flag(cf_options,"read-only") && cfg_get_flag(
+      cf_options,"read-write")))
+       die("Conflicting READONLY and READ_WRITE settings.");
+
+    if (cfg_get_flag(cf_kernel,"read-only") || cfg_get_flag(cf_options,
+      "read-only")) strcat(options,"ro ");
+    if (cfg_get_flag(cf_kernel,"read-write") || cfg_get_flag(cf_options,
+      "read-write")) strcat(options,"rw ");
+    if ((root = cfg_get_strg(cf_kernel,"root")) || (root = cfg_get_strg(
+      cf_options,"root")))  {
+       if (!strcasecmp(root,"current")) {
+           if (stat("/",&st) < 0) pdie("stat /");
+           sprintf(strchr(options,0),"root=%x ",(unsigned int) st.st_dev);
+       }
+       else if (strlen(root)>12 && !strncmp(root,"/dev/mapper/",12)) {
+           sprintf(strchr(options,0),"root=%s ", root);
+       }
+       else if (strlen(root)>6 && !strncmp(root,"LABEL=",6)) {
+           sprintf(strchr(options,0),"root=%s ", root);
+       }
+       else if (strlen(root)>5 && !strncmp(root,"UUID=",5)) {
+           sprintf(strchr(options,0),"root=%s ", root);
+        }
+       else {
+           sprintf(strchr(options,0),"root=%x ",dev_number(root));
+       }
+      }        
+    if ((ram_disk = cfg_get_strg(cf_kernel,"ramdisk")) || (ram_disk =
+      cfg_get_strg(cf_options,"ramdisk")))
+       sprintf(strchr(options,0),"ramdisk=%d ",to_number(ram_disk));
+
+    if ((vga = cfg_get_strg(cf_kernel,"vga")) || (vga = cfg_get_strg(cf_options,
+      "vga"))) {
+#ifndef NORMAL_VGA
+       warn("VGA mode presetting is not supported; ignoring 'vga='");
+#else
+       descr->flags |= FLAG_VGA;
+            if (!strcasecmp(vga,"normal")) descr->vga_mode = NORMAL_VGA;
+       else if (!strcasecmp(vga,"ext") || !strcasecmp(vga,"extended"))
+               descr->vga_mode = EXTENDED_VGA;
+       else if (!strcasecmp(vga,"ask")) descr->vga_mode = ASK_VGA;
+       else descr->vga_mode = to_number(vga);
+#endif
+    }
+
+#ifdef LCF_BOOT_FILE
+    if ((append = cfg_get_strg(cf_top, "image"))) {
+       strcat(options, "BOOT_FILE=");
+       strcat(options, append);
+       strcat(options, " ");
+    }
+#endif
+    append_local = cfg_get_strg(cf_options,"append");  /* global, actually */
+    if ((append = cfg_get_strg(cf_kernel,"append")) ||
+       (append = append_local)  ) {
+               if (strlen(append) > COMMAND_LINE_SIZE-1) die("Command line options > %d", COMMAND_LINE_SIZE-1);
+               strcat(strcat(options,append)," ");
+    }
+
+#if 1
+    append = append_local;     /* append == global append */
+    if ((append_local = cfg_get_strg(cf_kernel,"addappend"))) {
+       if (!append)
+           warn("ADDAPPEND used without global APPEND");
+       if (strlen(options)+strlen(append_local) > SECTOR_SIZE-1) die("Command line options > %d", COMMAND_LINE_SIZE-1);
+       strcat(options,append_local);
+    }
+#endif
+
+} /* end of section specific to 'image=' */
+
+    literal = cfg_get_strg(cf_kernel,"literal");
+    if (literal) strcpy(options,literal);
+    if (*options) {
+       here = strchr(options,0);
+       if (here[-1] == ' ') here[-1] = 0;
+    }
+    check_options(options);
+
+    if (cfg_get_flag(cf_kernel,"lock") || cfg_get_flag(cf_options,"lock")) {
+#ifdef LCF_READONLY
+       die("This LILO is compiled READONLY and doesn't support the LOCK "
+         "option");
+#else
+       descr->flags |= FLAG_LOCK;
+#endif
+    }
+
+    if ((cfg_get_flag(cf_options,"restricted") && 
+            cfg_get_flag(cf_options,"mandatory")) ||
+       (cfg_get_flag(cf_all,"restricted") && 
+            cfg_get_flag(cf_all,"mandatory")))
+        die("MANDATORY and RESTRICTED are mutually exclusive");
+    if (cfg_get_flag(cf_all,"bypass")) {
+       if (cfg_get_flag(cf_all,"mandatory"))
+            die("MANDATORY and BYPASS are mutually exclusive");
+       if (cfg_get_flag(cf_all,"restricted"))
+            die("RESTRICTED and BYPASS are mutually exclusive");
+       if (!cfg_get_strg(cf_options,"password"))
+            die("BYPASS only valid if global PASSWORD is set");
+    }
+    if ((password = cfg_get_strg(cf_all,"password")) && cfg_get_flag(cf_all,"bypass"))
+       die("PASSWORD and BYPASS not valid together");
+    if (password || 
+       ( (password = cfg_get_strg(cf_options,"password")) &&
+         !cfg_get_flag(cf_all,"bypass")  ) ) {
+       if (!*password) {       /* null password triggers interaction */
+           retrieve_crc((int*)descr->password_crc);
+       } else {
+           hash_password(password, (int*)descr->password_crc );
+       }
+       descr->flags |= FLAG_PASSWORD;
+    }
+
+#ifdef LCF_VIRTUAL
+    if (cfg_get_flag(cf_all,"vmwarn")) {
+        descr->flags |= FLAG_VMWARN;
+       param2.flag2 |= FLAG2_VIRTUAL;
+    }
+    if (cfg_get_flag(cf_all,"vmdisable")) {
+        descr->flags |= FLAG_VMDISABLE;
+       param2.flag2 |= FLAG2_VIRTUAL;
+    }
+    if ( (descr->flags & FLAG_VMWARN) && (descr->flags & FLAG_VMDISABLE) )
+       die ("VMWARN and VMDISABLE are not valid together");
+#endif
+#ifdef LCF_NOKEYBOARD
+    if (cfg_get_flag(cf_all,"nokbdisable")) {
+        descr->flags |= FLAG_NOKBDISABLE;
+       param2.flag2 |= FLAG2_NOKBD;
+    }
+#endif
+
+#if 1
+    if (cfg_get_flag(cf_all,"mandatory") || cfg_get_flag(cf_options,
+      "mandatory")) {
+       if (!password) die("MANDATORY is only valid if PASSWORD is set.");
+    }
+    if (cfg_get_flag(cf_all,"restricted") || cfg_get_flag(cf_options,
+      "restricted")) {
+       if (!password) die("RESTRICTED is only valid if PASSWORD is set.");
+       if ((descr->flags & FLAG_PASSWORD) && !cfg_get_flag(cf_all,"mandatory"))
+           descr->flags |= FLAG_RESTR;
+    }
+    if (password && *password && config_read) {
+       warn("%s should be readable only "
+         "for root if using PASSWORD", config_file);
+       config_read = 0;        /* suppress further warnings */
+    }
+#else
+    if (cfg_get_flag(cf_all,"restricted") || cfg_get_flag(cf_options,
+      "restricted")) {
+       if (!password) die("RESTRICTED is only valid if PASSWORD is set.");
+       descr->flags |= FLAG_RESTR;
+    }
+#endif
+    if (cfg_get_flag(cf_all,"bmp-retain") ||
+      cfg_get_flag(cf_options,"bmp-retain")) descr->flags |= FLAG_RETAIN;
+
+    if (cfg_get_flag(cf_all,"single-key") ||
+      cfg_get_flag(cf_options,"single-key")) descr->flags |= FLAG_SINGLE;
+
+    fback = cfg_get_strg(cf_kernel,"fallback");
+    if (fback) {
+#ifdef LCF_READONLY
+       die("This LILO is compiled READONLY and doesn't support the FALLBACK "
+         "option");
+#else
+       if (descr->flags & FLAG_LOCK)
+           die("LOCK and FALLBACK are mutually exclusive");
+       else descr->flags |= FLAG_FALLBACK;
+       *(unsigned short *) fallback_buf = DC_MAGIC;
+       strcpy(fallback_buf+2,fback);
+       fallback[fallbacks++] = stralloc(fback);
+#endif
+    }
+#if 0
+#if 1
+    *(unsigned int *) descr->rd_size = 0; /* no RAM disk */
+#else
+    descr->rd_size = 0; /* no RAM disk */
+#endif
+    descr->start_page = 0; /* load low */
+#endif
+    map_begin_section();
+    map_add_sector(fallback_buf);
+    map_add_sector(options);
+}
+
+
+static void bsect_done(char *name,IMAGE_DESCR *descr)
+{
+    char *alias;
+    int this_image,this;
+
+    if (!*name) die("Invalid image name.");
+    alias = cfg_get_strg(cf_all,"alias");
+    this = alias ? get_image(NULL,alias,descr) : -1;
+    this_image = get_image(name,cfg_get_strg(cf_all,"label"),descr);
+    if ((descr->flags & FLAG_SINGLE) &&
+      strlen(descrs.d.descr[this_image].name) > 1 &&
+      (!alias || strlen(alias) > 1))
+       die("SINGLE-KEYSTROKE requires the label or the alias to be only "
+         "a single character");
+    if (verbose >= 0) {
+       printf("Added %s",descrs.d.descr[this_image].name);
+       if (alias) printf(" (alias %s)",alias);
+#ifdef LCF_VIRTUAL
+       if (descrs.d.descr[this_image].flags & FLAG_VMDEFAULT ||
+               (this>=0 && (descrs.d.descr[this].flags & FLAG_VMDEFAULT)) )
+           printf("  @");
+#endif
+#ifdef LCF_NOKEYBOARD
+       if (descrs.d.descr[this_image].flags & FLAG_NOKBDEFAULT ||
+               (this>=0 && (descrs.d.descr[this].flags & FLAG_NOKBDEFAULT)) )
+           printf("  &");
+#endif
+       if ( descrs.d.descr[this_image].flags & FLAG_TOOBIG ||
+               (this>=0 && (descrs.d.descr[this].flags & FLAG_TOOBIG)) ) {
+               /* show a question mark if small-memory is configured */
+#ifndef LCF_INITRDLOW
+               if (!cfg_get_flag(cf_options,"small-memory")) 
+                       printf("  +");
+               else
+#endif
+               printf("  ?");
+       }
+       /* here the default boot image can be set */
+       if (this_image && this) putchar('\n');
+       else printf("  *\n");
+    }
+    if (verbose >= 3) {
+       printf("%4s<dev=0x%02x,hd=%d,cyl=%d,sct=%d>\n","",
+         descr->start.device,
+         descr->start.head,
+         descr->start.track,
+         descr->start.sector);
+       if (*options) printf("%4s\"%s\"\n","",options);
+    }
+    if (verbose >= 1) putchar('\n');   /* makes for nicer spacing */
+}
+
+
+int bsect_number(void)
+{
+ /* -1 means default= did not exist */
+    return image_base ? -1 : image;
+}
+
+
+static void unbootable(void)
+{
+#if 0
+    fflush(stdout);
+    fprintf(errstd,"\nCAUTION: The system is unbootable !\n");
+    fprintf(errstd,"%9sRun LILO again to correct this.","");
+#else
+    warn("The system is unbootable !\n"
+          "\t Run LILO again to correct this.");
+#endif    
+}
+
+
+#ifdef LCF_VIRTUAL
+void check_vmdefault(void)
+{
+    char * deflt;
+    int i;
+    
+    if ( (deflt = cfg_get_strg(cf_options,"vmdefault")) ) {
+       for (i=0; i<image; ++i) {
+           if (descrs.d.descr[i].flags & FLAG_VMDEFAULT) {
+               if (descrs.d.descr[i].flags & FLAG_VMDISABLE)
+                   die("VMDEFAULT image cannot have VMDISABLE flag set");
+
+                return;
+           }
+       }
+       die("VMDEFAULT image does not exist.");
+    }
+}
+#endif
+
+#ifdef LCF_NOKEYBOARD
+void check_nokbdefault(void)
+{
+    char * deflt;
+    int i;
+    
+    if ( (deflt = cfg_get_strg(cf_options,"nokbdefault")) ) {
+       for (i=0; i<image; ++i) {
+           if (descrs.d.descr[i].flags & FLAG_NOKBDEFAULT) {
+               if (descrs.d.descr[i].flags & FLAG_NOKBDISABLE)
+                   die("NOKBDEFAULT image cannot have NOKBDISABLE flag set");
+
+               return;
+           }
+       }
+       die("NOKBDEFAULT image does not exist.");
+    }
+}
+#endif
+
+
+void check_fallback(void)
+{
+    char *start,*end;
+    int i,image;
+
+    for (i = 0; i < fallbacks; i++) {
+       for (start = fallback[i]; *start && *start == ' '; start++);
+       if (*start) {
+           for (end = start; *end && *end != ' '; end++);
+           if (*end) *end = 0;
+           for (image = 0; image < MAX_IMAGES; image++)
+#ifdef LCF_IGNORECASE
+               if (!strcasecmp(descrs.d.descr[image].name,start)) break;
+#else
+               if (!strcmp(descrs.d.descr[image].name,start)) break;
+#endif
+           if (image == MAX_IMAGES) die("No image \"%s\" is defined",start);
+       }
+    }
+}
+
+void check_unattended(void)
+{
+    if ( (descrs.d.descr[0].flags & (FLAG_PASSWORD + FLAG_RESTR) )
+                                                       == FLAG_PASSWORD
+               &&  cfg_get_flag(cf_options,"unattended") )
+       die("Mandatory PASSWORD on default=\"%s\" defeats UNATTENDED",
+               descrs.d.descr[0].name);
+}
+
+
+void bsect_update(char *backup_file, int force_backup, int pass)
+{
+    BOOT_SECTOR bsect_wr;
+    int temp;
+static int timestamp = 0;
+
+    if (pass>=0) {
+       temp = make_backup(backup_file, force_backup, &bsect_orig,
+                                               boot_dev_nr, "boot sector");
+       if (temp && !timestamp) bsect.par_1.timestamp = timestamp = temp;
+    }
+
+#ifndef LCF_UNIFY
+# error "Bios Translation algorithms require '-DUNIFY' in Makefile"
+#endif
+    if (pass<1) {      /* BIOS_TT logic */
+       MENUTABLE *menu = &menuparams;
+       map_descrs(&descrs, menu->mt_descr, &menuparams.dflcmd);
+       menuparams.raid_dev_mask = raid_mask((int*)menuparams.raid_offset);
+       memcpy(menuparams.serial_no, serial_no, sizeof(serial_no));
+       memcpy(table+256, &menuparams, sizeof(menuparams));
+       ((int*)table)[SECTOR_SIZE/sizeof(int)-2] = crc32(table, SECTOR_SIZE-2*sizeof(int), CRC_POLY1);
+       map_begin_section();
+       map_add_sector(table);
+#ifdef LCF_FIRST6
+       /* still use 5 byte address */
+       (void) map_write(&param2.keytab,1,0,0);
+#else
+       (void) map_write(&param2.keytab,1,0);
+#endif
+       map_close(&param2, here2);
+    }  /* if (pass<1) ...      */
+
+if (pass>=0) {
+    if (lseek(fd,0,SEEK_SET) < 0)
+       die("lseek %s: %s",
+               boot_devnam ? boot_devnam : dev.name,
+               strerror(errno));
+
+#if 1
+    if (ireloc &&
+         bsect.par_1.cli == 0xFA
+                                                        ) {
+/* perform the relocation of the boot sector */
+       int len = bsect.par_1.code_length;
+       int space = BOOT_SIG_OFFSET - len;
+       
+       if (len==0) die ("First stage loader is not relocatable.");
+       
+       space &= 0xFFF0;        /* roll back to paragraph boundary */
+       bsect_wr = bsect_orig;
+       memcpy(&bsect_wr.sector[space], &bsect, len);
+       if (space <= 0x80) {
+           bsect_wr.sector[0] = 0xEB;          /* jmp short */
+           bsect_wr.sector[1] = space - 2;
+           bsect_wr.sector[2] = 0x90;          /* nop */
+       } else {
+           bsect_wr.sector[0] = 0xE9;          /* jmp near */
+           *(short*)&bsect_wr.sector[1] = space - 3;
+       }
+       if (bsect_wr.sector[space+1] == 0xEB)   {  /* jmp short */
+           len = space>>4;
+           space += (signed)bsect_wr.sector[space+2] + 3;
+           if (bsect_wr.sector[space] == 0xB8) /* mov ax,#07C0 */
+               *(short*)&bsect_wr.sector[space+1] += len;
+       }
+/***   bsect = bsect_orig;  ***/
+       if (verbose >= 1) printf("Boot sector relocation performed\n");
+    }
+    else bsect_wr = bsect;
+#endif         
+
+ /* failsafe check */
+#if 1
+    if (verbose >= 3) {
+       printf("Failsafe check:  boot_dev_nr = 0x%04x 0x%04x\n", boot_dev_nr, has_partitions(boot_dev_nr));
+       /*** if (do_md_install) ***/ {
+           printf("map==boot = %d    map s/n = %08X\n",
+               !!(bsect_wr.par_1.prompt & FLAG_MAP_ON_BOOT),
+               bsect_wr.par_1.map_serial_no
+           );
+       }
+    }
+#endif
+    if (
+      has_partitions(boot_dev_nr) &&
+      (P_MASK(boot_dev_nr)&boot_dev_nr)==0 &&
+      memcmp(bsect.sector+MAX_BOOT_SIZE, bsect_wr.sector+MAX_BOOT_SIZE, 64+8)
+      )
+       die("LILO internal error:  Would overwrite Partition Table");
+ /* failsafe check */
+       
+    sync();            /* this may solve possible kernel buffer problem */
+       
+    if (!test && write(fd, (char *)&bsect_wr, SECTOR_SIZE) != SECTOR_SIZE)
+       die("write %s: %s",boot_devnam ? boot_devnam : dev.name,
+         strerror(errno));
+
+} /* if (pass>=0) ... */
+
+    if (use_dev_close) dev_close(&dev);
+    else if (close(fd) < 0) {
+           unbootable();
+           die("close %s: %s",boot_devnam,strerror(errno));
+       }
+
+#if 0
+    if (pass==0) {
+#else
+    if (pass<1) {
+#endif
+       pw_file_update(passw);
+       temp_unregister(temp_map);
+       if (rename(temp_map,map_name) < 0) {
+           unbootable();
+           die("rename %s %s: %s",temp_map,map_name,strerror(errno));
+       }
+    }
+/*  (void) sync();   Now handled in lilo.c (atexit(sync)) */
+       if (verbose>=6) printf("End  bsect_update\n");
+       fflush(stdout);
+}
+
+
+void bsect_cancel(void)
+{
+#if 0
+    map_descrs(&descrs, bsect.par_1.descr, &bsect.par_1.dflcmd);
+#endif
+    map_close(NULL,0);
+    if (!use_dev_close) (void) close(fd);
+    else dev_close(&dev);
+    temp_unregister(temp_map);
+    if (verbose<9) (void) remove(temp_map);
+}
+
+
+static int present(char *var)
+{
+    char *path;
+
+    if (!(path = cfg_get_strg(cf_top,var))) die("No variable \"%s\"",var);
+    if (!access(path,F_OK)) return 1;
+    if (!cfg_get_flag(cf_all,"optional") && !cfg_get_flag(cf_options,
+      "optional")) return 1;
+    if (verbose >= 0) printf("Skipping %s\n",path);
+    return 0;
+}
+
+
+static int initrd_present(void)
+{
+    char *path;
+
+    path = cfg_get_strg(cf_kernel, "initrd");
+    if (!path) path = cfg_get_strg(cf_options, "initrd");
+    if (!path) return 1;
+    if (!access(path,F_OK)) return 1;
+    if (!cfg_get_flag(cf_all,"optional") && !cfg_get_flag(cf_options,
+      "optional")) return 1;
+    if (verbose >= 0) printf("Skipping %s\n", cfg_get_strg(cf_top, "image"));
+    return 0;
+}
+
+
+void do_image(void)
+{
+    IMAGE_DESCR descr;
+    char *name;
+
+/*    memset(&descr, 0, sizeof(descr));        Done in "bsect_common" */
+    cfg_init(cf_image);
+    (void) cfg_parse(cf_image);
+    if (present("image") && initrd_present()) {
+       bsect_common(&descr, 1);
+       descr.flags |= FLAG_KERNEL;
+       name = cfg_get_strg(cf_top,"image");
+       if (!cfg_get_strg(cf_image,"range")) boot_image(name,&descr);
+       else boot_device(name,cfg_get_strg(cf_image,"range"),&descr);
+       bsect_done(name,&descr);
+    }
+    cfg_init(cf_top);
+}
+
+
+void do_other(void)
+{
+    IMAGE_DESCR descr;
+    char *name, *loader;
+
+/*    memset(&descr, 0, sizeof(descr));        Done in "bsect_common" */
+    cfg_init(cf_other);
+    cfg_init(cf_kernel); /* clear kernel parameters */
+    curr_drv_map = curr_prt_map = 0;
+    (void) cfg_parse(cf_other);
+    if (present("other")) {
+       bsect_common(&descr, 0);
+       name = cfg_get_strg(cf_top,"other");
+       loader = cfg_get_strg(cf_other,"loader");
+       if (!loader) loader = cfg_get_strg(cf_options,"loader");
+       boot_other(loader,name,cfg_get_strg(cf_other,"table"),&descr);
+       bsect_done(name,&descr);
+    }
+    cfg_init(cf_top);
+}
+
+
+void bsect_uninstall(char *boot_dev,char *backup_file,int validate)
+{
+    struct stat st;
+    char temp_name[PATH_MAX+1];
+    int bck_file;
+
+    open_bsect(boot_dev);
+    if (*(unsigned short *) &bsect.sector[BOOT_SIG_OFFSET] != BOOT_SIGNATURE)
+       die("Boot sector of %s does not have a boot signature",boot_dev ?
+         boot_dev : dev.name);
+    if (!strncmp(bsect.par_1.signature-4,"LILO",4))
+       die("Boot sector of %s has a pre-21 LILO signature",boot_dev ?
+         boot_dev : dev.name);
+    if (strncmp(bsect.par_1.signature,"LILO",4))
+       die("Boot sector of %s doesn't have a LILO signature",boot_dev ?
+         boot_dev : dev.name);
+    if (!backup_file) {
+       sprintf(temp_name,BACKUP_DIR "/boot.%04X",boot_dev_nr);
+       backup_file = temp_name;
+    }
+    if ((bck_file = open(backup_file,O_RDONLY)) < 0)
+       die("open %s: %s",backup_file,strerror(errno));
+    if (fstat(bck_file,&st) < 0)
+       die("fstat %s: %s",backup_file,strerror(errno));
+    if (validate && st.st_mtime != bsect.par_1.timestamp)
+       die("Timestamp in boot sector of %s differs from date of %s\n"
+         "Try using the -U option if you know what you're doing.",boot_dev ?
+         boot_dev : dev.name,backup_file);
+    if (verbose > 0) printf("Reading old boot sector.\n");
+    if (read(bck_file,(char *) &bsect,PART_TABLE_OFFSET) != PART_TABLE_OFFSET)
+       die("read %s: %s",backup_file,strerror(errno));
+    if (lseek(fd,0,SEEK_SET) < 0)
+       die("lseek %s: %s",boot_dev ? boot_dev : dev.name,strerror(errno));
+    if (verbose > 0) printf("Restoring old boot sector.\n");
+    if (write(fd,(char *) &bsect,PART_TABLE_OFFSET) != PART_TABLE_OFFSET)
+       die("write %s: %s",boot_dev ? boot_dev : dev.name,strerror(errno));
+    if (use_dev_close) dev_close(&dev);
+    else if (close(fd) < 0) {
+           unbootable();
+           die("close %s: %s",boot_devnam,strerror(errno));
+       }
+    exit(0);
+}
+
+
+void bsect_raid_update(char *boot_dev, unsigned int raid_offset, 
+       char *backup_file, int force_backup, int pass, int mask)
+{
+    BOOT_SECTOR bsect_save;
+    int bios;
+    int prompt = bsect.par_1.prompt;
+
+    if (pass<0) bsect_update(backup_file, force_backup, pass);
+
+    if (pass != 0) {    
+       bsect_save = bsect;                     /* save the generated boot sector */
+       open_bsect(boot_dev);
+       memcpy(&bsect, &bsect_save, MAX_BOOT_SIZE);     /* update the subject boot sector */
+       bsect.par_1.raid_offset = raid_offset;  /* put in the new partition offset */
+       bsect.par_1.prompt &= mask;             /* clear all RAID flags */
+       bsect.par_1.prompt |= raid_flags;       /* update the raid flags */
+
+       bios = (raid_flags&FLAG_RAID_DEFEAT) ? bios_map : bios_boot;
+       if (!cfg_get_flag(cf_options, "static-bios-codes")) {
+           if (verbose>=2) printf("Using s/n from device 0x%02X\n", bios);
+           bsect.par_1.map_serial_no = serial_no[bios - 0x80];
+       }
+
+#ifdef LCF_FIRST6
+/* lines added 22.5.7 */
+       ((SECTOR_ADDR6*)&bsect.par_1.secondary)->device = bios;
+#else
+/* lines added 22.5.6 */
+       bsect.par_1.secondary.device &= ~DEV_MASK;
+       bsect.par_1.secondary.device |= bios;
+#endif
+/* ************************************ */
+
+       *(unsigned short *) &bsect.sector[BOOT_SIG_OFFSET] = BOOT_SIGNATURE;
+    }
+    
+    if (pass<0) pass = -pass;
+    
+    bsect_update(backup_file, force_backup, pass);
+
+    bsect.par_1.prompt = prompt;       /* restore the flag byte */
+}
+
+
diff --git a/src/bsect.h b/src/bsect.h
new file mode 100644 (file)
index 0000000..e153860
--- /dev/null
@@ -0,0 +1,89 @@
+/* bsect.h  -  Boot sector handling
+ * 
+ * Copyright 1992-1998 Werner Almesberger
+ * Copyright 1999-2007 John Coffman
+ * Copyright 2009-2010 Joachim Wiedorn
+ * All rights reserved.
+ * 
+ * Licensed under the terms contained in the file 'COPYING'
+ * in the source directory.
+ */
+
+#ifndef BSECT_H
+#define BSECT_H
+#include "common.h"
+
+char *pw_input(void);
+void bmp_do_timer(char *cp, MENUTABLE *menu);
+void bmp_do_table(char *cp, MENUTABLE *menu);
+void bmp_do_colors(char *cp, MENUTABLE *menu);
+
+
+#ifdef LCF_BUILTIN
+BUILTIN_FILE *select_loader(void);
+/* return the pointer to the selected built-in secondary loader */
+#endif
+
+void bsect_read(char *boot_dev,BOOT_SECTOR *buffer);
+/* Read the boot sector stored on BOOT_DEV into BUFFER. */
+
+void bsect_open(char *boot_dev,char *map_file,char *install,int delay,
+  int timeout, int raid_offset);
+
+/* Loads the boot sector of the specified device and merges it with a new
+   boot sector (if install != NULL). Sets the boot delay to 'delay' 1/10 sec.
+   Sets the input timeout to 'timeout' 1/10 sec (no timeout if -1). Creates a
+   temporary map file. */
+
+int bsect_number(void);
+/* Returns the number of successfully defined boot images. */
+
+#ifdef LCF_VIRTUAL
+void check_vmdefault(void);
+/* Verify existence of vmdefault image, if vmdefault is used */
+#endif
+
+#ifdef LCF_NOKEYBOARD
+void check_nokbdefault(void);
+/* Verify existence of nokbdefault image, if nokbdefault is used */
+#endif
+
+void check_fallback(void);
+/* Verifies that all fallback options specify valid images. */
+
+void check_unattended(void);
+/* checks that unattended won't hang up on password */
+
+void bsect_update(char *backup_file, int force_backup, int pass);
+/* Updates the boot sector and the map file. */
+
+void bsect_raid_update(char *boot_dev, unsigned int raid_offset, 
+       char *backup_file, int force_backup, int pass, int mask);
+
+/* Update the boot sector and the map file, with RAID considerations */
+
+void bsect_cancel(void);
+
+/* Cancels all changes. (Deletes the temporary map file and doesn't update
+   the boot sector. */
+
+void do_image(void);
+
+/* Define a "classic" boot image. (Called from the configuration parser.) */
+
+void do_unstripped(void);
+
+/* Define an unstripped kernel. */
+
+void do_other(void);
+
+/* Define an other operating system. */
+
+void bsect_uninstall(char *boot_dev_name,char *backup_file,int validate);
+
+/* Restores the backed-up boot sector of the specified device. If
+   'boot_dev_name' is NULL, the current root device is used. If 'backup_file'
+   is NULL, the default backup file is used. A time stamp contained in the
+   boot sector is verified if 'validate' is non-zero. */
+
+#endif
diff --git a/src/cfg.c b/src/cfg.c
new file mode 100644 (file)
index 0000000..8a67e9a
--- /dev/null
+++ b/src/cfg.c
@@ -0,0 +1,693 @@
+/* cfg.c  -  Configuration file parser
+ * 
+ * Copyright 1992-1997 Werner Almesberger
+ * Copyright 1999-2007 John Coffman
+ * Copyright 2009-2010 Joachim Wiedorn
+ * All rights reserved.
+ * 
+ * Licensed under the terms contained in the file 'COPYING'
+ * in the source directory.
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "lilo.h"
+#include "common.h"
+#include "temp.h"
+#include "cfg.h"
+
+#define NEW_PARSE !__MSDOS__
+
+#define MAX_VAR_NAME MAX_TOKEN
+
+#if !__MSDOS__
+extern void do_image(void);
+extern void do_other(void);
+extern void do_disk(void);
+extern void do_partition(void);
+
+extern void id_image(void);
+extern void id_other(void);
+
+extern void do_map_drive(void);
+extern void do_cr(void);
+extern void do_change(void);
+extern void do_cr_type(void);
+extern void do_cr_reset(void);
+extern void do_cr_part(void);
+extern void do_cr_auto(void);
+
+
+CONFIG cf_top[] = {
+  { cft_strg, "image",         do_image,       NULL,NULL },
+  { cft_strg, "other",         do_other,       NULL,NULL },
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+
+CONFIG cf_identify[] = {
+  { cft_strg, "image",         id_image,       NULL,NULL },
+  { cft_strg, "other",         id_other,       NULL,NULL },
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+#endif /* !__MSDOS__ */
+
+CONFIG cf_options[] = {
+#if !__MSDOS__
+  { cft_strg, "append",                NULL,           NULL,NULL },
+  { cft_strg, "backup",                NULL,           NULL,NULL },
+  { cft_strg, "bios-passes-dl",        NULL,           NULL,NULL },
+  { cft_strg, "bitmap",                NULL,           NULL,NULL },
+  { cft_strg, "bmp-colors",    NULL,           NULL,NULL },
+  { cft_flag, "bmp-retain",    NULL,           NULL,NULL },
+  { cft_strg, "bmp-table",     NULL,           NULL,NULL },
+  { cft_strg, "bmp-timer",     NULL,           NULL,NULL },
+  { cft_strg, "boot",          NULL,           NULL,NULL },
+  { cft_strg, "boot-as",       NULL,           NULL,NULL },
+  { cft_flag, "change-rules",  do_cr,          NULL,NULL },
+  { cft_flag, "compact",       NULL,           NULL,NULL },
+  { cft_strg, "default",       NULL,           NULL,NULL },
+  { cft_strg, "delay",         NULL,           NULL,NULL },
+  { cft_strg, "disk",          do_disk,        NULL,NULL },
+  { cft_strg, "disktab",       NULL,           NULL,NULL },
+  { cft_flag, "el-torito-bootable-cd", NULL,           NULL,NULL },
+  { cft_strg, "fallback",      NULL,           NULL,NULL },
+  { cft_flag, "fix-table",             NULL,           NULL,NULL },
+  { cft_strg, "force-backup",  NULL,           NULL,NULL },
+  { cft_flag, "geometric",      NULL,           NULL,NULL }, 
+  { cft_flag, "ignore-table",   NULL,          NULL,NULL },
+  { cft_strg, "initrd",                NULL,           NULL,NULL },
+  { cft_strg, "install",       NULL,           NULL,NULL },
+  { cft_strg, "keytable",      NULL,           NULL,NULL },
+  { cft_flag, "large-memory",  NULL,           NULL,NULL },
+  { cft_flag, "lba32",          NULL,           NULL,NULL }, 
+  { cft_flag, "linear",        NULL,           NULL,NULL },
+  { cft_strg, "loader",                NULL,           NULL,NULL },
+  { cft_flag, "lock",          NULL,           NULL,NULL },
+  { cft_flag, "mandatory",     NULL,           NULL,NULL },
+#endif /* !__MSDOS__ */
+  { cft_strg, "map",           NULL,           NULL,NULL },
+#if !__MSDOS__
+  { cft_flag, "master-boot",   NULL,           NULL,NULL },
+  { cft_strg, "menu-scheme",   NULL,           NULL,NULL },
+  { cft_strg, "menu-title",    NULL,           NULL,NULL },
+  { cft_strg, "message",       NULL,           NULL,NULL },
+  { cft_flag, "nodevcache",    NULL,           NULL,NULL },
+#ifdef LCF_NOKEYBOARD
+  { cft_strg, "nokbdefault",   NULL,           NULL,NULL },
+#endif
+  { cft_flag, "noraid",                NULL,           NULL,NULL },
+  { cft_flag, "nowarn",                NULL,           NULL,NULL },
+  { cft_flag, "optional",      NULL,           NULL,NULL },
+  { cft_strg, "password",      NULL,           NULL,NULL },
+  { cft_flag, "prompt",                NULL,           NULL,NULL },
+  { cft_strg, RAID_EXTRA_BOOT, NULL,           NULL,NULL },
+  { cft_strg, "ramdisk",       NULL,           NULL,NULL },
+  { cft_flag, "read-only",     NULL,           NULL,NULL },
+  { cft_flag, "read-write",    NULL,           NULL,NULL },
+  { cft_flag, "restricted",    NULL,           NULL,NULL },
+  { cft_strg, "root",          NULL,           NULL,NULL },
+  { cft_strg, "serial",                NULL,           NULL,NULL },
+  { cft_flag, "single-key",    NULL,           NULL,NULL },
+  { cft_flag, "small-memory",  NULL,           NULL,NULL },
+  { cft_flag, "static-bios-codes",     NULL,           NULL,NULL },
+  { cft_flag, "suppress-boot-time-BIOS-data",  NULL,   NULL,NULL },
+  { cft_strg, "timeout",       NULL,           NULL,NULL },
+  { cft_flag, "unattended",    NULL,           NULL,NULL },
+  { cft_strg, "verbose",       NULL,           NULL,NULL },
+  { cft_strg, "vga",           NULL,           NULL,NULL },
+#ifdef LCF_VIRTUAL
+  { cft_strg, "vmdefault",     NULL,           NULL,NULL },
+#endif
+#endif /* !__MSDOS__ */
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+
+#if !__MSDOS__
+CONFIG cf_all[] = {
+  { cft_strg, "alias",         NULL,           NULL,NULL },
+  { cft_flag, "bmp-retain",    NULL,           NULL,NULL },
+  { cft_flag, "bypass",                NULL,           NULL,NULL },
+  { cft_strg, "fallback",      NULL,           NULL,NULL },
+  { cft_strg, "label",         NULL,           NULL,NULL },
+  { cft_strg, "literal",       NULL,           NULL,NULL },
+  { cft_flag, "lock",          NULL,           NULL,NULL },
+  { cft_flag, "mandatory",     NULL,           NULL,NULL },
+#ifdef LCF_NOKEYBOARD
+  { cft_flag, "nokbdisable",   NULL,           NULL,NULL },
+#endif
+  { cft_flag, "optional",      NULL,           NULL,NULL },
+  { cft_strg, "password",      NULL,           NULL,NULL },
+  { cft_flag, "restricted",    NULL,           NULL,NULL },
+  { cft_flag, "single-key",    NULL,           NULL,NULL },
+#ifdef LCF_VIRTUAL
+  { cft_flag, "vmdisable",     NULL,           NULL,NULL },
+  { cft_flag, "vmwarn",                NULL,           NULL,NULL },
+#endif
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+
+CONFIG cf_kernel[] = {
+  { cft_strg, "addappend",     NULL,           NULL,NULL },
+  { cft_strg, "append",                NULL,           NULL,NULL },
+  { cft_strg, "initrd",                NULL,           NULL,NULL },
+  { cft_strg, "ramdisk",       NULL,           NULL,NULL },
+  { cft_flag, "read-only",     NULL,           NULL,NULL },
+  { cft_flag, "read-write",    NULL,           NULL,NULL },
+  { cft_strg, "root",          NULL,           NULL,NULL },
+  { cft_strg, "vga",           NULL,           NULL,NULL },
+  { cft_link, NULL,            &cf_all,        NULL,NULL }};
+
+CONFIG cf_image[] = {
+  { cft_strg, "range",         NULL,           NULL,NULL },
+  { cft_link, NULL,            &cf_kernel,     NULL,NULL }};
+
+CONFIG cf_other[] = {
+  { cft_strg, "boot-as",       NULL,           NULL,NULL },
+  { cft_flag, "change",                do_change,      NULL,NULL },
+  { cft_strg, "loader",                NULL,           NULL,NULL },
+  { cft_strg, "map-drive",     do_map_drive,   NULL,NULL },
+  { cft_flag, "master-boot",   NULL,           NULL,NULL },
+  { cft_strg, "table",         NULL,           NULL,NULL },
+  { cft_flag, "unsafe",                NULL,           NULL,NULL },
+  { cft_link, NULL,            &cf_all,        NULL,NULL }};
+
+CONFIG cf_disk[] = {
+  { cft_strg, "bios",          NULL,           NULL,NULL },
+  { cft_strg, "cylinders",     NULL,           NULL,NULL },
+  { cft_strg, "heads",         NULL,           NULL,NULL },
+  { cft_flag, "inaccessible",  NULL,           NULL,NULL },
+  { cft_strg, "max-partitions",        NULL,           NULL,NULL },
+  { cft_strg, "sectors",       NULL,           NULL,NULL },
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+
+CONFIG cf_partitions[] = {
+  { cft_strg, "partition",     do_partition,   NULL,NULL },
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+
+CONFIG cf_partition[] = {
+  { cft_strg, "start",         NULL,           NULL,NULL },
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+
+CONFIG cf_map_drive[] = {
+  { cft_strg, "to",            NULL,           NULL,NULL },
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+
+CONFIG cf_change_rules[] = {
+  { cft_flag, "reset",         do_cr_reset,    NULL,NULL },
+  { cft_strg, "type",          do_cr_type,     NULL,NULL },
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+
+CONFIG cf_change_rule[] = {
+  { cft_strg, "hidden",                NULL,           NULL,NULL },
+  { cft_strg, "normal",                NULL,           NULL,NULL },
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+
+CONFIG cf_change[] = {
+  { cft_flag, "automatic",     do_cr_auto,     NULL,NULL },
+  { cft_strg, "partition",     do_cr_part,     NULL,NULL },
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+
+CONFIG cf_change_dsc[] = {
+  { cft_flag, "activate",      NULL,           NULL,NULL },
+  { cft_flag, "deactivate",    NULL,           NULL,NULL },
+  { cft_strg, "set",           NULL,           NULL,NULL },
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+
+CONFIG cf_bitmap[] = {
+  { cft_strg, "bitmap",                NULL,           NULL,NULL },
+  { cft_strg, "bmp-colors",    NULL,           NULL,NULL },
+  { cft_strg, "bmp-table",     NULL,           NULL,NULL },
+  { cft_strg, "bmp-timer",     NULL,           NULL,NULL },
+  { cft_end,  NULL,            NULL,           NULL,NULL }};
+#endif /* !__MSDOS__ */
+
+#if NEW_PARSE
+
+static CONFIG *keywords[] = {cf_top, cf_identify, cf_options, cf_all,
+       cf_kernel, cf_image, cf_other, cf_disk, cf_partitions, cf_partition,
+       cf_map_drive, cf_change_rules, cf_change_rule, cf_change, 
+       cf_change_dsc, cf_bitmap, NULL };
+
+#endif
+       
+static FILE *file;
+static char flag_set;
+static char *last_token = NULL,*last_item = NULL,*last_value = NULL;
+static int line_num;
+static char *file_name = NULL;
+static int back = 0; /* can go back by one char */
+
+
+int cfg_open(char *name)
+{
+    line_num = 1;
+    if (!strcmp(name,"-")) file = stdin;
+
+#if __MSDOS__
+    else if (!strcasecmp(name,"none")) return -1;
+#endif /* __MSDOS__ */
+
+    else if (!(file = fopen(file_name = name,"r"))) {
+#if !__MSDOS__
+               die("Cannot open: %s", name);
+#else  /* __MSDOS__ */
+               warn("No configuration file: %s\n", name);
+               return -1;
+#endif /* __MSDOS__ */
+    }
+
+    return fileno(file);
+}
+
+
+void cfg_error(char *msg,...)
+{
+    va_list ap;
+
+    fflush(stdout);
+    va_start(ap,msg);
+    vfprintf(errstd,msg,ap);
+    va_end(ap);
+    if (!file_name) fputc('\n',errstd);
+    else fprintf(errstd," at or above line %d in file '%s'\n",line_num,file_name);
+    exit(1);
+}
+
+
+static int next_raw(void)
+{
+    int ch;
+
+    if (!back) return getc(file);
+    ch = back;
+    back = 0;
+    return ch;
+}
+
+
+static int next(void)
+{
+    static char *var;
+    char buffer[MAX_VAR_NAME+1];
+    int ch,braced;
+    char *put;
+
+    if (back) {
+       ch = back;
+       back = 0;
+       return ch;
+    }
+    if (var && *var) return *var++;
+    ch = getc(file);
+    if (ch == '\r')            /* strip DOS <cr> */
+        ch = getc(file);
+    if (ch == '\\') {
+       ch = getc(file);
+       if (ch == '$') return ch;
+       ungetc(ch,file);
+       return '\\';
+    }
+    if (ch != '$') return ch;
+    ch = getc(file);
+    braced = ch == '{';
+    put = buffer;
+    if (!braced) *put++ = ch;
+    while (1) {
+       ch = getc(file);
+#if 0
+       if (!braced && ch < ' ') {
+           ungetc(ch,file);
+           break;
+       }
+#endif
+       if (ch == EOF) cfg_error("EOF in variable name");
+       if (ch < ' ') cfg_error("control character in variable name");
+       if (braced && ch == '}') break;
+       if (!braced && !isalpha(ch) && !isdigit(ch) && ch != '_') {
+           ungetc(ch,file);
+           break;
+       }
+       if (put-buffer == MAX_VAR_NAME) cfg_error("variable name too long");
+       *put++ = ch;
+    }
+    *put = 0;
+#if !__MSDOS__
+    if (!(var = getenv(buffer))) cfg_error("unknown variable \"%s\"",buffer);
+#endif /* !__MSDOS__ */
+    return next();
+}
+
+
+static void again(int ch)
+{
+    if (back) die("internal error: again invoked twice");
+    back = ch;
+}
+
+
+static char *cfg_get_token(void)
+{
+    char buf[MAX_TOKEN+1];
+    char *here;
+    int ch,escaped;
+
+    if (last_token) {
+       here = last_token;
+       last_token = NULL;
+       return here;
+    }
+    while (1) {
+       while ((ch = next()), ch == ' ' || ch == '\t' || ch == '\n')
+           if (ch == '\n') line_num++;
+       if (ch == EOF) return NULL;
+       if (ch != '#') break;
+       while ((ch = next_raw()), ch != '\n')
+           if (ch == EOF) return NULL;
+       line_num++;
+    }
+    if (ch == '=') return stralloc("=");
+    if (ch == '"') {
+       here = buf;
+       while (here-buf < MAX_TOKEN) {
+           if ((ch = next()) == EOF) cfg_error("EOF in quoted string");
+           if (ch == '"') {
+               *here = 0;
+               return stralloc(buf);
+           }
+           if (ch == '\\') {
+               ch = next();
+               if (ch != '"' && ch != '\\' && ch != '\n')
+                   cfg_error("Bad use of \\ in quoted string");
+               if (ch == '\n') {
+                   while ((ch = next()), ch == ' ' || ch == '\t');
+                   if (!ch) continue;
+                   again(ch);
+                   ch = ' ';
+               }
+           }
+           if (ch == '\n' || ch == '\t')
+               cfg_error("\\n and \\t are not allowed in quoted strings");
+           *here++ = ch;
+       }
+       cfg_error("Quoted string is too long");
+       return 0; /* not reached */
+    }
+    here = buf;
+    escaped = 0;
+    while (here-buf < MAX_TOKEN) {
+       if (escaped) {
+           if (ch == EOF) cfg_error("\\ precedes EOF");
+           if (ch == '\n') line_num++;
+           else *here++ = ch == '\t' ? ' ' : ch;
+           escaped = 0;
+       }
+       else {
+           if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '#' ||
+             ch == '=' || ch == EOF) {
+               again(ch);
+               *here = 0;
+               return stralloc(buf);
+           }
+#if !__MSDOS__
+           if (!(escaped = (ch == '\\')))
+#endif /* !__MSDOS__ */
+               *here++ = ch;
+       }
+       ch = next();
+    }
+    cfg_error("Token is too long");
+    return 0; /* not reached */
+}
+
+
+static void cfg_return_token(char *token)
+{
+    last_token = token;
+}
+
+
+static int cfg_next(char **item,char **value)
+{
+    char *this;
+
+    if (last_item) {
+       *item = last_item;
+       *value = last_value;
+       last_item = NULL;
+       return 1;
+    }
+    *value = NULL;
+    if (!(*item = cfg_get_token())) return 0;
+    if (!strcmp(*item,"=")) cfg_error("Syntax error");
+    if (!(this = cfg_get_token())) return 1;
+    if (strcmp(this,"=")) {
+       cfg_return_token(this);
+       return 1;
+    }
+    if (!(*value = cfg_get_token())) cfg_error("Value expected at EOF");
+    if (!strcmp(*value,"=")) cfg_error("Syntax error after %s",*item);
+    return 1;
+}
+
+
+static void cfg_return(char *item,char *value)
+{
+    last_item = item;
+    last_value = value;
+}
+
+
+void cfg_init(CONFIG *table)
+{
+    while (table->type != cft_end) {
+       switch (table->type) {
+           case cft_strg:
+               if (table->data) free(table->data);
+           case cft_flag:
+               table->data = NULL;
+               break;
+           case cft_link:
+               table = ((CONFIG *) table->action)-1;
+               break;
+           default:
+               die("Unknown syntax code %d",table->type);
+       }
+       table++;
+    }
+}
+
+
+static int cfg_do_set(CONFIG *table,char *item,char *value,int copy,
+    void *context)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++) {
+       if (walk->name && !strcasecmp(walk->name,item)) {
+           if (value && walk->type != cft_strg)
+               cfg_error("'%s' doesn't have a value",walk->name);
+           if (!value && walk->type == cft_strg)
+               cfg_error("Value expected for '%s'",walk->name);
+           if (walk->data) {
+               if (walk->context == context)
+                   cfg_error("Duplicate entry '%s'",walk->name);
+               else {
+                   warn("Ignoring entry '%s'",walk->name);
+                   if (!copy) free(value);
+                   return 1;
+               }
+           }
+           if (walk->type == cft_flag) walk->data = &flag_set;
+           else if (walk->type == cft_strg)
+                   walk->data = copy ? stralloc(value) : value; 
+           walk->context = context;
+           if (walk->action) ((void (*)(void)) walk->action)();
+           break;
+       }
+       if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1;
+    }
+    if (walk->type != cft_end) return 1;
+    cfg_return(item,value);
+    return 0;
+}
+
+
+void cfg_set(CONFIG *table,char *item,char *value,void *context)
+{
+    if (cfg_do_set(table,item,value,1,context) != 1)
+       cfg_error("cfg_set: Can't set %s",item);
+}
+
+
+void cfg_unset(CONFIG *table,char *item)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++)
+       if (walk->name && !strcasecmp(walk->name,item)) {
+           if (!walk->data) die("internal error (cfg_unset %s, unset)",item);
+           if (walk->type == cft_strg) free(walk->data);
+           walk->data = NULL;
+           return;
+       }
+    die("internal error (cfg_unset %s, unknown",item);
+}
+
+#if NEW_PARSE
+
+static int cfg_end (char *item)
+{
+    CONFIG **key;
+    CONFIG *c;
+
+key = keywords;
+while ((c = *key++)) {
+    while (c->name) {
+        if (!strcasecmp(c->name, item)) return 1;
+        c++;
+    }
+}
+    return 0;
+}
+#endif
+
+
+int cfg_parse(CONFIG *table)
+{
+    char *item,*value;
+
+    while (1) {
+       if (!cfg_next(&item,&value)) return 0;
+if(verbose>=6) printf("cfg_parse:  item=\"%s\" value=\"%s\"\n", item, value);
+       if (!cfg_do_set(table,item,value,0,table)) {
+#if NEW_PARSE==0
+               return 1;
+#else
+           if (cfg_end(item)) return 1;
+           else cfg_error("Unrecognized token \"%s\"", item);
+#endif
+       }
+       free(item);
+    }
+}
+
+
+int cfg_get_flag(CONFIG *table,char *item)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++) {
+       if (walk->name && !strcasecmp(walk->name,item)) {
+           if (walk->type != cft_flag)
+               die("cfg_get_flag: operating on non-flag %s",item);
+           return !!walk->data;
+       }
+       if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1;
+    }
+    die("cfg_get_flag: unknown item %s",item);
+    return 0; /* not reached */
+}
+
+
+char *cfg_get_strg(CONFIG *table,char *item)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++) {
+       if (walk->name && !strcasecmp(walk->name,item)) {
+           if (walk->type != cft_strg)
+               die("cfg_get_strg: operating on non-string %s",item);
+           return walk->data;
+       }
+       if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1;
+    }
+    die("cfg_get_strg: unknown item %s",item);
+    return 0; /* not reached */
+}
+
+
+#if !__MSDOS__
+/* open the password file, passw=1 forces a new file to be created */
+
+static char *pw_file_name;
+FILE *pw_file = NULL;
+
+FILE *cfg_pw_open(void)
+{
+    char name[MAX_TOKEN+1];
+    struct stat buf;
+    time_t conf;
+    int fd;
+    
+    strcpy(name, file_name);   /* copy name of config file '/etc/lilo.conf' */
+    strcat(name, PW_FILE_SUFFIX);
+    pw_file_name = stralloc(name);
+#if 1
+    if (stat(file_name, &buf)) die("Cannot stat '%s'", file_name);
+    conf = buf.st_mtime;
+    if (!stat(pw_file_name, &buf) && conf>buf.st_mtime && !passw) {
+        warn("'%s' more recent than '%s'\n"
+              "   Running 'lilo -p' is recommended.",
+              file_name, pw_file_name);
+    }
+#endif    
+
+    if (passw & !test) {
+       if (unlink(pw_file_name) && errno != ENOENT) die("Could not delete '%s'", pw_file_name);
+       if ((fd = creat(pw_file_name, 0600)) < 0) die("Could not create '%s'", pw_file_name);
+       (void) close(fd);
+       pw_file = fopen(pw_file_name, "w+");
+    }
+    else if (passw) return (pw_file=NULL);
+    else {
+        if (!(pw_file = fopen(pw_file_name, "r"))) {
+            if (!test) {
+                passw = 1;                     /* force writing */
+               if ((fd = creat(pw_file_name, 0600)) < 0) die("Could not create '%s'", pw_file_name);
+               (void) close(fd);
+                pw_file = fopen(pw_file_name, "w+");
+            }
+            else return (pw_file=NULL);
+        }
+    }
+    if (!pw_file) die("Could not create '%s'", pw_file_name);
+#if 1
+    if (!stat(pw_file_name, &buf) && (buf.st_mode&0044) ) {
+        warn("'%s' readable by other than 'root'", pw_file_name);
+    }
+#endif    
+    return pw_file;
+}
+
+
+/* allow only the "bitmap" keywords */
+
+void cfg_bitmap_only(void)
+{
+    keywords[0] = cf_bitmap;
+    keywords[1] = NULL;
+}
+
+#if BETA_TEST
+void cfg_alpha_check(void)
+{
+    CONFIG **kw = keywords;
+    CONFIG *cfg;
+    
+    while ((cfg=*kw)) {
+       while (cfg[1].name) {
+           if (strcmp(cfg[0].name, cfg[1].name) >= 0) {
+               die("cfg_alpha_check:  failure at '%s', '%s'", cfg[0].name, cfg[1].name);
+           }
+       cfg++;
+       }
+    kw++;
+    }
+}
+#endif
+
+#endif /* !__MSDOS__ */
diff --git a/src/cfg.h b/src/cfg.h
new file mode 100644 (file)
index 0000000..2e38933
--- /dev/null
+++ b/src/cfg.h
@@ -0,0 +1,87 @@
+/* cfg.h  -  Configuration file parser
+ * 
+ * Copyright 1992-1998 Werner Almesberger
+ * Copyright 1999-2007 John Coffman
+ * Copyright 2009-2010 Joachim Wiedorn
+ * All rights reserved.
+ * 
+ * Licensed under the terms contained in the file 'COPYING'
+ * in the source directory.
+ */
+
+#ifndef CFG_H
+#define CFG_H
+
+typedef enum { cft_strg,cft_flag,cft_link,cft_end } CONFIG_TYPE;
+
+typedef struct {
+    CONFIG_TYPE type;
+    char *name;
+    void *action;
+    void *data;
+    void *context;
+} CONFIG;
+
+#define RAID_EXTRA_BOOT "raid-extra-boot"
+
+extern CONFIG cf_top[],cf_identify[],cf_options[],cf_all[],cf_kernel[],
+  cf_image[],cf_other[],cf_disk[],cf_partitions[],cf_partition[],
+  cf_map_drive[],cf_change_rules[],cf_change_rule[],cf_change[],
+  cf_change_dsc[],cf_bitmap[];
+
+extern FILE *pw_file;
+
+
+int cfg_open(char *name);
+
+/* Opens the configuration file. Returns the file descriptor of the open
+   file. */
+
+void cfg_error(char *msg,...);
+
+/* Signals an error while parsing the configuration file and terminates the
+   program. */
+
+void cfg_init(CONFIG *table);
+
+/* Initializes the specified table. */
+
+void cfg_set(CONFIG *table,char *item,char *value,void *context);
+
+/* Sets the specified variable in table. If the variable has already been set
+   since the last call to cfg_init, a warning message is issued if the context
+   keys don't match or a fatal error is reported if they do. */
+
+void cfg_unset(CONFIG *table,char *item);
+
+/* Unsets the specified variable in table. It is a fatal error if the variable
+   was not set. */
+
+int cfg_parse(CONFIG *table);
+
+/* Parses the configuration file for variables contained in table. A non-zero
+   value is returned if a variable not found in table has been met. Zero is
+   returned if EOF has been reached. */
+
+int cfg_get_flag(CONFIG *table,char *item);
+
+/* Returns one if the specified variable is set, zero if it isn't. */
+
+char *cfg_get_strg(CONFIG *table,char *item);
+
+/* Returns the value of the specified variable if it is set, NULL otherwise. */
+
+
+FILE *cfg_pw_open(void);
+/* open the password file, creating a new file if  passw  is set. */
+
+void cfg_bitmap_only(void);
+/* allow only the "bitmap" keywords */
+
+#if BETA_TEST
+void cfg_alpha_check(void);
+/* check for tables in alphabetical order */
+#endif
+
+
+#endif
diff --git a/src/chain.S b/src/chain.S
new file mode 100644 (file)
index 0000000..0b3fae1
--- /dev/null
@@ -0,0 +1,841 @@
+;  chain.S  -  LILO boot chainer 
+;
+; Copyright 1992-1998 Werner Almesberger.
+; Copyright 1999-2004 John Coffman.
+; All rights reserved.
+;
+; Licensed under the terms contained in the file 'COPYING' in the 
+; source directory.
+;
+
+#define LILO_ASM
+#include "lilo.h"
+get common.s           /* as86 "include" will bypass the CPP */
+
+; for debugging, set the EBDA size in Kilobytes; e.g., 64
+#define EBDA 0
+
+#define REVERSE_DL 1
+
+#if defined(LCF_SOLO_CHAIN) && !defined(DOS_D)
+
+#ifndef DOS_D
+#define DOS_D
+#endif
+
+#ifndef CHECK
+#define CHECK
+#endif
+
+#endif         /* LCF_SOLO_CHAIN */
+
+
+#if VERSION_MINOR >= 50
+#define DEBUG_NEW
+#endif
+
+       .text
+
+       .globl  _main
+       .org    0
+
+_main: cld                     ! make sure !!!
+       jmp     start
+
+       
+       .org    6
+
+       .ascii  "LILO"          ! signature
+
+       .word   STAGE_CHAIN
+       .word   VERSION
+
+offset:        .word   0
+
+! the byte "drive" is filled in by the installer & updated by the second stage 
+
+drive: .byte   0                       ! drive, 0x80, 0x81
+       .byte   0                       ! head, always zero
+
+hint:  .word   drvmap                  ! pointer to drive map
+
+ptable:        .blkw   0x20                    ! partition table to preload
+
+devmap:        .word   0,0                     ! device map filled in by second.S
+
+cmd:   .word   0,0                     ! command line to pass on
+
+; ES:DI contains a pointer to the command line passed from second-stage
+
+start:
+       xor     bx,bx                   ! set SS:SP to 0:7C00
+       mov     ss,bx
+       mov     sp,#BOOTSEG*16          ! #0x7C00
+       mov     bp,sp                   ! address from BP
+#if EBDA
+       push    #0x40
+       pop     ds
+       mov     word ptr [0x13],#640-EBDA       ; simulate EBDA in Kilobytes
+#endif
+       push    cs
+       pop     ds
+
+#ifdef DEBUG_NEW
+       push    bp
+
+       push    es
+       pop     ds
+       mov     si,di
+       call    say
+
+       push    cs
+       pop     ds
+       mov     si,#crlf
+       call    say
+
+       call    bd1
+       .ascii  "Boot drive 0x"
+       .byte   0
+bd1:   pop     si
+       call    say
+       mov     al,drive
+       call    bout
+       mov     si,#crlf
+       call    say
+
+       pop     bp
+#endif
+
+       mov     al,#0x3D                ! '=' sign
+       mov     cx,#-1
+       repne
+         scasb                         ! scan for =
+srch:  seg es
+         mov   al,(di)
+       inc     di
+       cmp     al,#0x20                ! test for space
+       ja      srch
+; real command line if AL==space, no command line if NUL
+       jb      nocmd
+       mov     [cmd],di
+       mov     [cmd+2],es
+nocmd:
+
+;
+; Account for any drive mappings being used by the Second Stage
+;
+       les     di,[parC_devmap]        ! second stage translate table
+                                       ! this was set by the second stage loader
+#if defined DEBUG_NEW
+       mov     ax,es
+       call    wout
+       mov     al,#0x20
+       call    cout
+       mov     ax,di
+       call    wout
+       mov     si,#crlf
+       call    say
+
+       mov     bx,di
+       call    dump_drvmap
+#endif
+
+       call    install_map             ! install it
+
+; 
+; but first, process the two 0xFFFF drive-map records for "master-boot"
+;
+       mov     si,#drvmap              ! our created drive map
+       cmp     WORD (si),#-1           ! test for "master-boot"
+       jne     noswap
+       mov     ah,[drive]              ! boot drive
+       mov     al,(si+3)               ! possible "boot-as="
+       cmp     al,#-1                  ! test for master
+       jne     boot_as
+! make AL the master drive (0 or 80)
+       mov     al,ah
+       and     al,#0x80                ! AL is master drive 0 or 80
+boot_as:
+       mov     (si),ax         ! 80 -> boot
+       xchg    ah,al
+       mov     (si+2),ax               ! boot -> 80
+
+       cmp     ah,al                   ! are they the same
+       jne     domerge
+       add     si,#4                   ! skip a "no-translation"
+       mov     byte (si-1),#-1         ! clear any boot-as
+noswap:
+domerge:
+
+       mov     [devmap],si     ! save updated value
+
+
+;**************************************
+       push    ss
+       pop     es
+
+       mov     cx,#SECTOR_SIZE/2
+mtmp = SETUPSECS-1                     ! broken math ...
+       mov     si,#mtmp*SECTOR_SIZE
+#ifdef DEBUG_NEW
+       mov     di,#boot_sector
+       cmp     si,di
+       ja      use_setupsecs_m_1
+       mov     si,di
+use_setupsecs_m_1:
+#endif
+       mov     di,bp                   ! #0x7C00
+       rep
+         movsw
+#ifdef DOS_D
+#ifdef CHECK
+       mov     si,#BOOTSEG*16+0x24     ; address of first byte to test
+
+       cmp     byte (bp+0x15),#0xf8            ; check media descriptor
+       jne     ck_failed
+
+       seg     es
+         lodsb
+       cmp     al,#0x80                ; check range of device codes
+       jb      ck_failed
+       cmp     al,#0x8f
+       ja      ck_failed
+
+       seg     es
+         lodsb
+       or      al,al                   ; check hi-byte is empty
+       jnz     ck_failed
+
+       seg     es
+         lodsb
+       cmp     al,#0x29                ; I do not know what this byte means
+       je      ck_okay
+       cmp     al,#0x28                ; HPFS marker
+       jne     ck_failed
+
+ck_okay:
+       lea     si,(si+4)               ; address of vol label & fs type
+       mov     cx,#11                  ; volume label (11)
+ck_next:
+       seg     es
+         lodsb
+       or      al,al
+       js      ck_failed               ; not alphabetic if >= 0x80
+       jz      ck_loop                 ; NUL allowed for HPFS
+       cmp     al,#0x20
+       jb      ck_failed               ; not alphabetic if < SPACE
+ck_loop:
+       loop    ck_next
+
+       mov     cx,#8                   ; check Filesystem type
+ck_fstype:
+       seg     es
+         lodsb
+       or      al,al                   ; not alphabetic if >= 0x80
+       js      ck_failed
+       cmp     al,#0x20                ; not alphabetic if < SPACE
+       jb      ck_failed
+       loop    ck_fstype
+
+#endif
+dos4:
+
+       call    revmap1
+
+       mov     (bp+0x24),dx            ! fill in 0x24 and 0x25
+       mov     si,offset
+       mov     edx,ptable+8(si)
+       mov     (bp+0x1C),edx
+
+#ifdef DEBUG_NEW
+       mov     si,#update
+       jmp     ck_say   
+ck_failed:
+       mov     si,#no_update
+ck_say:
+       call    say
+#else
+ck_failed:
+#endif
+
+#endif
+       mov     cx,#0x20                ! move partition table
+       mov     si,#ptable
+       mov     di,#PART_TABLE
+       rep
+       movsw
+                                       ! mess with the partition table
+#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
+       mov     si,#prtmap              ! get partition table change rules
+prtclp:        lodsw                           ! bios == 0 indicates end
+       or      al,al
+       jz      pmend                   ! at end -> quit
+       cmp     al,cache                ! already in cache ?
+       je      incache                 ! yes -> no loading required
+       push    ax                      ! save table data
+       call    flush                   ! flush the cache
+       pop     ax
+       push    ax
+       mov     cache,al                ! remember drive in cache
+#if 0
+       cmp     al,drive                ! boot drive ?
+#else
+       call    revmap1
+       cmp     al,dl
+#endif
+       jne     noc                     ! no -> load into scratch area
+       xor     ax,ax                   ! load at 0000:0600
+       mov     bx,#PARTS_LOAD
+       jmp     loadit
+
+pmend: call    flush                   ! flush table
+       br      nopp                    ! and proceed
+
+noc:   mov     ax,ds
+       mov     bx,#PARTS_SCR           ! scratch area  0000:0800
+loadit:        mov     es,ax                   ! set up pointers and remember them
+       mov     ces,ax
+       mov     cbx,bx
+       mov     ax,#0x201               ! load partition table, one sector
+       mov     dx,cache                ! drive from cache (DH = 0)
+       mov     cx,#1
+#ifdef DEBUG_NEW
+       pusha
+       mov     al,dl                   ! dump device code
+       call    bout
+       mov     si,#msg_load            ! say loading
+       call    say
+       popa
+#endif
+       int     0x13                    ! load it
+       jc      wrfail                  ! error -> abort
+       pop     ax                      ! get BIOS and offset
+incache:les    bx,cbx                  ! load pointer
+       add     bx,#PART_TABLE_OFFSET   ! move to partition table
+       add     bl,ah                   ! offset is always in [0x1be,0x1fd]
+       lodsw                           ! see what we need to do
+       seg     es                      ! match ?
+       cmp     byte ptr (bx),al
+       jne     nocng                   ! no -> do not change
+       seg     es                      ! change
+       mov     byte ptr (bx),ah
+       mov     byte ptr dirty,#1       ! mark as dirty
+nocng: br      prtclp                  ! next one
+
+flush: test    byte ptr dirty,#1       ! dirty ?
+       jz      noflush                 ! no -> do not write
+       mov     ax,#0x301               ! write one sector
+       mov     dx,cache                ! get the drive
+       or      dl,dl                   ! nothing cached ?
+       jz      noflush                 ! no -> do not flush
+       les     bx,cbx                  ! reload pointer
+#ifdef DEBUG_NEW
+       pusha
+       mov     al,dl                   ! dump device code
+       call    bout
+       mov     si,#msg_write           ! say writing
+       call    say
+       popa
+#endif
+       int     0x13                    ! write ...
+       jc      wrfail                  ! argl
+noflush:ret
+wrfail:        mov     si,#failmsg             ! complain
+       call    say
+#if 0
+       mov     ax,#FIRSTSEG            ! try to restart LILO
+       jmpi    #GO,FIRSTSEG
+#else
+       xor     dx,dx                   ! zap the device code
+       jmpi    FIRSTSEG*16,0           ! try to restart at 0000:7c00
+#endif
+cache: .byte   0                       ! drive, 0 means not cached
+       .byte   0                       ! head, always 0
+cbx:   .blkw   1
+ces:   .blkw   1
+dirty: .byte   0
+
+#endif
+
+; reverse drive mapping
+;      uses AX
+;       updates DL
+;
+revmap1:
+       push    si
+       mov     dx,drive        ; get drive/head pair
+       mov     si,#drvmap
+rev0:  lodsw                   ; get to, from pair
+       or      ax,ax           ; test for end
+       jz      rev9            ; done
+       cmp     ah,dl           ; booting from "to"
+       jne     rev0            ; loop if not
+       mov     dl,al           ; substitute the "from"
+rev9:  pop     si              ; restore SI
+       ret
+
+nopp:
+#if 0
+       mov     ax,drvmap               ! need to install mapper ?
+       or      ax,ax
+       jz      noimap                  ! no -> go on
+       call    swap13
+noimap:
+#else
+       mov     di,[devmap]     ! get drive map pointer
+       cmp     word (di),#0
+       je      noimap
+       push    cs
+       pop     es              ; ES:DI points at the current map
+       call    install_map
+noimap:
+#endif
+
+
+#if REVERSE_DL
+       call    revmap1
+#else
+       mov     dx,drive                ! initialize DX (drive and head)
+#endif
+       mov     si,offset               ! DS:SI and ES:SI point to the partition
+       add     si,#PART_TABLE
+#ifdef DEBUG_NEW
+       pusha
+
+       mov     cx,# 4<<4               ; delay 4 seconds
+       xor     dx,dx
+       mov     ah,# 0x86
+       int     0x15                    ! Delay 6 seconds
+#ifdef DEBUG_CONTINUE
+       jnc     delayed
+
+       mov     si,#msg_cont            ! Hit any key ...
+       call    say
+       xor     ax,ax
+       int     0x16    ! AH==0, get key
+delayed:
+#endif
+
+       popa
+#endif
+
+       xor     ax,ax                   ! set DS and ES to zero
+       mov     ds,ax
+       mov     es,ax
+       mov     bx,#BOOTSEG*16
+       
+;;;;   mov     ss,ax                   ! on all processors since the 186
+       mov     sp,bx                   ! these instructions are locked
+       
+#ifdef LCF_COHERENT
+       mov     (si),dl                 ! yes, put it in the partition table
+#endif
+       mov     bp,si                   ! BP==SI flags hard disk boot
+       push    ax
+       push    bx
+       seg ss
+       cmp     byte ptr (bx+par1_cli),#0xFA    ! first.S starts with CLI
+       je      try_sig
+       cmp     byte ptr (bx+par1_cli),#0xEB    ! short jump?
+       jne     gotoit
+       push    ax
+       mov     al,(bx+par1_cli+1)              ! get offset
+       cbw
+       inc     ax
+       inc     ax
+       add     bx,ax                   ! test relocated record
+       pop     ax
+       cmp     byte ptr (bx+par1_cli),#0xFA    ! first.S starts with CLI
+       jne     gotoit                  ! not LILO if no CLI
+try_sig:
+       seg ss
+         cmp   dword ptr (bx+par1_signature),#EX_MAG_HL
+       jne     gotoit          ! LILO signature required for command line
+       seg cs
+         cmp   dword ptr [cmd],#0
+       je      gotoit
+
+;  pass on a command line
+       seg cs
+         les   bx,[cmd]
+       lea     si,(bx-4)
+       seg es
+         mov   dword ptr (si),#EX_MAG_HL
+       mov     dh,dl
+       mov     dl,#EX_DL_MAG
+gotoit:
+       retf
+
+
+#if defined(LCF_REWRITE_TABLE) || defined(DEBUG_NEW)
+
+! Display a NUL-terminated string on the console
+!      DS:SI points at the string
+!
+say:   push    ax
+       push    bx              ! save BX
+say_2: lodsb                   ! get byte
+       or      al,al           ! NUL ?
+       jz      aret            ! yes -> done
+       mov     ah,#14          ! display, tty-style
+       mov     bx,#0007
+       int     0x10
+       jmp     say_2           ! next one
+aret:  pop     bx              ! restore
+       pop     ax
+       ret                     ! done
+
+failmsg:.ascii "Rewrite error."
+       .byte   13,10,0
+
+#endif
+
+;**************************************
+
+
+; Merge the contents of two drive maps
+;
+;      First drive map encountered:    DS:SI
+;      Second drive map encountered:   ES:DI
+;      Output drive map:               DS:BX
+;
+; The output drive coincides with the First drive map
+;
+;      Enter with  DS != CS
+;
+;
+;      
+drive_map_merge:
+       pusha                           ! save all the registers
+
+;
+; this is the guts of the loop to merge the records
+;
+process:
+       lodsw                           ! get drive mapping
+       or      ax,ax
+       jz      copy
+
+       push    di
+       jmp     nextone1
+nextone:
+       inc     di
+       inc     di
+nextone1:
+       seg es
+         cmp   word (di),#0
+       je      atend
+
+       seg es
+         cmp   (di),ah
+       jne     nextone
+
+       seg es
+         mov   ah,(di+1)               ! do the translation
+       seg es
+         mov   word (di),#-1           ! wipe out entry
+atend:
+       cmp     ah,al                   ! remove null translation
+       je      nostore
+       mov     (bx),ax
+       inc     bx
+       inc     bx
+nostore:
+       pop     di
+       jmp     process
+
+; finished merge, copy the rest from the source
+copy:
+       seg es
+         mov   ax,(di)                 !
+       inc     di
+       inc     di
+
+       inc     ax
+       jz      copy                    ! it was -1, skip it
+
+       dec     ax
+       mov     (bx),ax                 ! store value or end marker
+
+       jz      alldone                 ! it was 0, end marker
+
+       inc     bx
+       inc     bx
+       jmp     copy
+
+
+alldone:
+       popa                    ! restore all that we saved
+       ret
+
+; end of drive_map_merge
+
+;**************************************
+
+; Install a drive swapper with a null drive map
+;
+;      Enter with:
+;              DS == CS, SS == 0000
+;
+;      Exit with:
+;              ES:DI points at the null device map
+;
+;              EAX is trashed
+;              All other registers preserved
+;
+;
+swap13_null:
+       push    cx
+       push    si
+#ifdef DEBUG_NEW
+       call    sn11
+       .asciz  "Installing Drive Swapper\r\n"
+sn11:  pop     si
+       call    say
+#endif
+       seg ss
+         dec   word [0x413]    ; allocate 1k
+       int     0x12
+#if EBDA_EXTRA
+       sub     ax,#EBDA_EXTRA  ! allocate extra EBDA
+#endif
+       shl     ax,#10-4        ; convert to paragraphs
+       mov     es,ax           ;
+       xor     di,di           ; DI = 0
+       shl     eax,#16         ; EAX is ES:DI
+       seg ss
+         xchg  eax,[4*0x13]    ; set new int 0x13 vector; get old
+       mov     [old13of],eax
+       mov     cx,#NEW13B/2    ; count of words to move
+       mov     si,#new13       ; source is DS:SI
+       rep
+         movsw                 ; move in the new drive mapper
+       seg es
+         mov   (di),cx         ; CX is zero from the move
+
+       pop     si
+       pop     cx
+       ret
+
+; Install drive mapper map
+;
+;      The map to use is at  ES:DI
+;      If there is an existing drive mapper, the two are merged.
+;      If there is no drive mapper, then one is installed.
+;
+;      Enter with  ES:DI  set to point at the map to install
+;              DS == CS
+;
+;      Exit with  DS=CX
+;              All registers are preserved
+;
+
+install_map:
+       push    es
+       pusha           ; save all the regs
+       mov     bp,sp   ; save stack location
+
+#ifdef DEBUG_NEW
+       call    im111
+       .asciz  "Install Map\r\n"
+im111: pop     si
+       call    say
+#endif
+
+       seg es
+         cmp   word (di),#0
+       je      install_ret     ; nothing to do
+COUNT  =  DRVMAP_SIZE*2
+       mov     cx,#COUNT       ; count of words
+       sub     sp,#COUNT*2     ; now allocate words
+       mov     si,di           ; ES:SI is now source
+       mov     di,sp           ; SS:DI is now destination
+
+       push    ds
+
+       push    es
+       pop     ds
+       push    ss
+       pop     es
+install_move1:
+       lodsw                   ; get part of a map
+       stosw                   ; store it
+       or      ax,ax           ; test for null
+       jz      install_done1
+       loop    install_move1
+       jmp     fatal
+install_done1:                 ; the map is at SS:SP
+       pop     ds
+
+#ifdef DEBUG_NEW
+       mov     bx,sp           ; ES==SS
+       call    dump_drvmap
+#endif
+
+       call    is_prev_mapper  ; is there a previous drive swapper
+                               ; sets ES:DI
+       jnz     install_skip
+
+       call    swap13_null     ; install a new, null drive mapper
+                               ; sets ES:DI to point at  drvmap  in swapper
+                               ; which must be NULL terminated
+install_skip:
+       mov     si,sp           ; SS:SI is place to do the map merge
+       push    ss
+       pop     ds              ; DS:SI is primary map
+       mov     bx,si           ; DS:BX receives the new map
+                               ; and ES:DI points at the existing map
+       call    drive_map_merge
+
+#ifdef DEBUG_NEW
+       mov     bx,sp
+       push    es
+
+       push    ss
+       pop     es
+       call    dump_drvmap
+
+       pop     es
+#endif
+       mov     si,sp           ; DS:SI is the source
+       mov     cx,#COUNT
+       rep
+         movsw
+
+       push    cs
+       pop     ds              ; restore the DS
+
+install_ret:
+       mov     sp,bp   ; get ready for pop
+       popa
+       pop     es
+       ret
+
+fatal: hlt
+       jmp     fatal
+
+#ifdef DEBUG_NEW
+wout:  push    ax
+       xchg    ah,al
+       call    bout            ! write hi-byte
+       pop     ax
+bout:  push    ax              ! save byte
+       shr     al,#4           ! display upper nibble
+       call    nout
+       pop     ax
+nout:  and     al,#0x0F        ! lower nible only
+       daa                     ! smaller conversion routine
+       add     al,#0xF0
+       adc     al,#0x40        ! AL is hex char [0..9A..F]
+cout:
+       push    bx
+       mov     ah,#14          ! display, tty-style
+       mov     bx,#0007
+       int     0x10
+       pop     bx
+       ret
+
+msg_new:
+       .ascii  "Found v.22 drive swapper"
+       .byte   13,10,0
+msg_old:
+       .ascii  "Found v.21 drive swapper"
+       .byte   13,10,0
+msg_swap13:
+       .ascii  "Drive Mapping"
+       .byte   13,10,0
+msg_load:
+       .ascii  " - PT loaded"
+       .byte   13,10,0
+msg_write:
+       .ascii  " - PT written"
+       .byte   13,10,0
+no_update:
+       .ascii  "NO "
+update:
+       .ascii  "24-25 update has occurred"
+crlf:  .byte   13,10,0
+
+#ifdef DEBUG_CONTINUE
+msg_cont: .ascii  "\r\nHit any key to continue ..."
+       .byte   0
+#endif
+
+#endif /* DEBUG_NEW */
+
+#if 0
+/* LILO version 21 (and maybe earlier) drive map header signature code */
+new13_old:
+       push    ax              ! save AX (contains function code in AH)
+       push    bp              ! need BP to mess with stack
+       mov     bp,sp
+       pushf                   ! push flags (to act like interrupt)
+       push    si
+       mov     si,#drvmap-new13
+
+new13_old_drvmap_offs  =       * - new13_old - 2
+new13_old_length       =       new13_old_drvmap_offs
+new13_old_min_offs     =       0x46    ; min seen in old code is 0x49
+new13_old_max_offs     =       0x50    ; maxed out at  21.7.5 at 0x4d
+#endif
+
+#ifdef DEBUG_NEW
+; dump the drive map pointed to by  ES:BX
+;      Beware: DS != CS on some calls
+;
+dump_drvmap:
+       pusha
+       push    ds
+
+       push    cs
+       pop     ds
+
+sw13b: seg es
+         mov   ax,(bx)         ; get drvmap entry
+       or      ax,ax
+       jz      sw13z
+       call    bout
+       mov     si,#sw13p
+       inc     bx
+       call    say
+       seg es
+         mov   al,(bx)
+       call    bout
+       inc     bx
+       mov     si,#crlf
+       call    say
+       jmp     sw13b
+sw13z:
+       mov     si,#msg_swap13
+       call    say
+
+       pop     ds
+       popa
+       ret
+sw13p: .asciz  " -> "
+#endif
+
+
+#define CHAIN_LOADER
+#include "mapper.S"
+
+NEW13B =   drvmap-new13
+
+#if defined(LCF_REWRITE_TABLE)
+prtmap:        .blkw   PRTMAP_SIZE*2+1 ! only first word of last entry is read
+#endif
+
+
+#ifdef CHAIN
+       .org    *+4
+#endif
+theend:
+
+#ifdef CHAIN
+the_end1       = theend+511
+theends        =       the_end1/512
+       .org    theends*512-4
+       .long   CHAIN           ! boot signature check
+#endif
+       .align  512
+boot_sector:
diff --git a/src/common.c b/src/common.c
new file mode 100644 (file)
index 0000000..6baa69d
--- /dev/null
@@ -0,0 +1,285 @@
+/* common.c  -  Common data structures and functions. */
+/*
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2005 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "lilo.h"
+#include "common.h"
+
+#ifndef SHS_MAIN
+LILO_EXTRA extra;
+char *identify = NULL;
+int boot_dev_nr, raid_index, do_md_install;
+int verbose = 0, test = 0, compact = 0, linear = 0, raid_flags = 0, zflag = 0,
+      ireloc = 0, force_fs = 0, force_raid = 0, extended_pt = 0, query = 0,
+      nowarn = 0, lba32 = 0, autoauto = 0, passw = 0, geometric = 0, eflag = 0;
+int colormax = 15, warnings = 0;
+DL_BIOS bios_passes_dl = DL_NOT_SET;
+
+#if !__MSDOS__
+FILE *pp_fd = NULL;
+int bios_boot, bios_map;
+unsigned short drv_map[DRVMAP_SIZE+1]; /* fixup maps ... */
+int curr_drv_map;
+unsigned int prt_map[PRTMAP_SIZE+1];
+int curr_prt_map;
+#endif /* !__MSDOS__ */
+
+/*volatile*/ void pdie(char *msg)
+{
+    fflush(stdout);
+#if !__MSDOS__
+    perror(msg);
+#else
+    fprintf(errstd, "%s\n", msg);
+#endif /* !__MSDOS__ */
+    exit(1);
+}
+
+
+/*volatile*/ void die(char *fmt,...)
+{
+    va_list ap;
+
+    fflush(stdout);
+    fprintf(errstd,"Fatal: ");       /* JRC */
+    va_start(ap,fmt);
+    vfprintf(errstd,fmt,ap);
+    va_end(ap);
+    fputc('\n',errstd);
+    exit(1);
+}
+
+
+/*volatile*/ void warn(char *fmt,...)
+{
+    va_list ap;
+
+    warnings++;
+    if (nowarn > 0) return;
+    
+    fflush(stdout);
+    fprintf(errstd,"Warning: ");
+    va_start(ap,fmt);
+    vfprintf(errstd,fmt,ap);
+    va_end(ap);
+    fputc('\n',errstd);
+    
+    return;
+}
+
+
+void *alloc(int size)
+{
+    void *this;
+
+    if ((this = malloc(size)) == NULL) pdie("Out of memory");
+    memset(this, 0, size);     /* insure consistency */
+
+    return this;
+}
+
+
+void *ralloc(void *old,int size)
+{
+    void *this;
+
+    if ((this = realloc(old,size)) == NULL) pdie("Out of memory");
+    return this;
+}
+
+
+char *stralloc(const char *str)
+{
+    char *this;
+
+    if ((this = strdup(str)) == NULL) pdie("Out of memory");
+    return this;
+}
+
+
+int to_number(char *num)
+{
+    int number;
+    char *end;
+
+    number = strtol(num,&end,0);
+    if (end && *end) die("Not a number: \"%s\"",num);
+    return number;
+}
+
+
+int timer_number(char *num)
+{
+    int number;
+    char *end;
+
+    number = strtol(num,&end,0);
+    if (end && *end) {
+       switch (*end) {
+           case 'h':
+           case 'H':
+               number *= 60;
+           case 'm':
+           case 'M':
+               number *= 60;
+           case 's':
+           case 'S':
+               number *= 10;           /* convert seconds to tenths */
+           case 't':
+           case 'T':
+               break;
+           default:
+               number = -1;
+       }
+    }
+    if (number < 0  ||  number > 36000)  die("Not a valid timer value: \"%s\"",num);
+    return number;
+}
+
+
+static char *name(int stage)
+{
+    switch (stage) {
+       case STAGE_FIRST:
+           return "First boot sector";
+       case STAGE_SECOND:
+           return "Second boot sector";
+       case STAGE_CHAIN:
+           return "Chain loader";
+       default:
+           die("Internal error: Unknown stage code %d",stage);
+    }
+    return NULL; /* for GCC */
+}
+
+
+void check_version(BOOT_SECTOR *sect,int stage)
+{
+    int bs_major, bs_minor;
+
+    if (!strncmp(sect->par_1.signature-4,"LILO",4))
+       die("%s has a pre-21 LILO signature",name(stage));
+    if (strncmp(sect->par_1.signature,"LILO",4))
+       die("%s doesn't have a valid LILO signature",name(stage));
+    if ((sect->par_1.stage&0xFF) != stage)
+       die("%s has an invalid stage code (%d)",name(stage),sect->par_1.stage);
+
+    bs_major = sect->par_1.version & 255;
+    bs_minor = sect->par_1.version >> 8;
+    if (sect->par_1.version != VERSION)
+       die("%s is version %d.%d. Expecting version %d.%d.",name(stage),
+           bs_major,bs_minor, VERSION_MAJOR,VERSION_MINOR);
+}
+
+
+#if !__MSDOS__
+int stat_equal(struct stat *a,struct stat *b)
+{
+    return a->st_dev == b->st_dev && a->st_ino == b->st_ino;
+}
+#endif /* !__MSDOS__ */
+
+#endif /*  !SHS_MAIN */
+
+
+#if !__MSDOS__
+/* accumulate a partial CRC-32 */
+
+unsigned int crc32partial(unsigned char *cp, int nsize,
+                       unsigned int polynomial, unsigned int *accum)
+{
+   unsigned int poly, crc;
+   int i;
+   unsigned char ch;
+
+   crc = ~*accum;
+   while (nsize--) {
+      ch = *cp++;
+      for (i=0; i<8; i++) {
+         if ( ( (crc>>31) ^ (ch>>(7-i)) ) & 1) poly = polynomial;
+         else poly = 0UL;
+         crc = (crc<<1) ^ poly;
+      }
+   }
+   return (*accum = ~crc);
+}
+
+
+/* calculate a CRC-32 polynomial */
+
+unsigned int crc32 (unsigned char *cp, int nsize, unsigned int polynomial)
+{
+    unsigned int crc = 0;
+    return crc32partial(cp, nsize, polynomial, &crc);
+}
+
+
+/* show what a link resolves to */
+
+void show_link(char *name)
+{
+    int count;
+    char lname[1024];
+    
+    count = readlink(name, lname, sizeof(lname)-1);
+    if (count>0) {
+       lname[count] = 0;
+       printf(" -> %s", lname);
+    }
+}
+#else /* __MSDOS__ */
+char * strerror(int err)
+{
+    return NULL;
+}
+#endif /* !__MSDOS__ */
+
+
+#ifdef SHS_MAIN
+#include <fcntl.h>
+
+int main(int argc, char *argv[])
+{
+    unsigned char buf[4096];
+    int fd, n;
+    unsigned int crc;
+    
+    fd = open(argv[1],O_RDONLY);
+    crc = 0;
+    n = read(fd,buf,sizeof(buf));
+    while (n>0) {
+       crc32partial(buf, n, CRC_POLY1, &crc);
+       n = read(fd,buf,sizeof(buf));
+    }
+    close(fd);
+
+    printf("0x%08x\n", (int)crc);
+    if (sizeof(short)!=2) {
+       fprintf(stderr,"***Fatal:  SHORT != 2\n");
+       return 1;
+    }
+    if (sizeof(int)!=4) {
+       fprintf(stderr, "*****Fatal:  INT != 4\n");
+       return 1;
+    }
+    if (sizeof(long)>sizeof(int))
+       fprintf(stderr, "**Note:  LONG is bigger than INT\n");
+       
+    return 0;
+}
+#endif /* SHS_MAIN */
diff --git a/src/common.h b/src/common.h
new file mode 100644 (file)
index 0000000..268a9fe
--- /dev/null
@@ -0,0 +1,462 @@
+#if 0
+  common.h  -  Common data structures and functions.
+
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2005 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+
+#endif
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#ifndef LILO_ASM
+#include <fcntl.h>
+#include <asm/types.h>
+#if !__MSDOS__
+#include <sys/stat.h>
+#endif
+
+#ifndef PAGE_SIZE
+# define PAGE_SIZE 4096U
+#endif
+
+#ifdef O_ACCMODE
+# define O_NOACCESS O_ACCMODE
+#else
+/* open a file for "no access" */
+# define O_NOACCESS 3
+#endif
+
+/* special for LILO, bypass the actual open in  dev_open( , ,-1)   */
+#define O_BYPASS -1
+
+#endif
+
+#if __MSDOS__
+#define const
+#endif
+
+
+/*
+;*/typedef struct {            /*
+                                                       block   0
+;*/    unsigned char sector,track; /* CX 
+                                               sa_sector:      .blkb   1
+                                               sa_track:       .blkb   1
+;*/    unsigned char device,head; /* DX
+                                               sa_device:      .blkb   1
+                                               sa_head:        .blkb   1
+;*/    unsigned char num_sect; /* AL
+                                               sa_num_sect:    .blkb   1
+;*/} SECTOR_ADDR; /*
+                                               sa_size:
+                                                       endb
+
+
+
+
+;*/typedef struct {                    /*
+                                                       block   0
+;*/    char name[MAX_IMAGE_NAME+1];    /* image name, NUL terminated 
+                                               id_name:        .blkb   MAX_IMAGE_NAME_asm+1
+;*/    unsigned short password_crc[MAX_PW_CRC*(sizeof(INT4)/sizeof(short))];  /* 4 password CRC-32 values
+                                               id_password_crc:.blkb   MAX_PW_CRC_asm*4
+;*/    unsigned short rd_size[2]; /* RAM disk size in sectors, 0 if none
+                                               id_rd_size:     .blkb   4               ;don't change the order !!!
+;*/    SECTOR_ADDR initrd,start;  /* start of initrd & kernel
+                                               id_initrd:      .blkb   sa_size         ;  **
+                                               id_start:       .blkb   sa_size         ;  **
+;*/    unsigned short flags,vga_mode; /* image flags & video mode
+                                               id_flags:       .blkb   2               ;  **
+                                               id_vga_mode:    .blkb   2               ;  **
+;*/} IMAGE_DESCR;              /*
+                                               id_size:
+                                                       endb
+
+
+
+;*/typedef struct {                    /*
+                                                       block   0
+;*/    unsigned char  bytes_per_sector[2];     /*
+                                               bpb_bytes_per_sector:   .blkb   2
+;*/    unsigned char  sectors_per_cluster;     /*
+                                               bpb_sectors_per_cluster:.blkb   1
+;*/    unsigned char  reserved_sectors[2];     /*
+                                                               .blkb   2
+;*/    unsigned char  number_of_FATs;          /*
+                                                               .blkb   1
+;*/    unsigned char  root_dir_entries[2];     /*
+                                                               .blkb   2
+;*/    unsigned char  total_sectors[2];                /*
+                                                       .blkb   2
+;*/    unsigned char  media_descriptor;                /*
+                                                       .blkb   1
+;*/    unsigned char  sectors_per_FAT[2];      /*
+                                                       .blkb   2
+;*/    unsigned char  sectors_per_track[2];    /* DOS v.3
+                                                       .blkb   2
+;*/    unsigned char  heads_per_cylinder[2];   /* DOS v.3
+                                                       .blkb   2
+;*/    unsigned char  hidden_sectors[4];       /*
+                                                       .blkb   4
+;*/    unsigned char  total_sectors_long[4];   /* if total_sectors==0
+                                                       .blkb   4
+;*/    unsigned char  reserved[7];             /* pad to 32 bytes
+                                                       .blkb   7
+;*/} BIOS_PARAMETER_BLOCK;     /*
+                                               bpb_size:
+                                                       endb
+                                                       
+                                                       
+                                                       
+;*/typedef struct {            /*
+                                               block   0
+;*/    unsigned char jump[3];  /* jump to boot code
+                                               bpdos_jump:     .blkb   3
+;*/    char system[8];         /* system ID
+                                               bpdos_system:   .blkb   8
+;*/    BIOS_PARAMETER_BLOCK bpb;       /* BIOS parameter block
+                                               bpdos_bpb:      .blkb   bpb_size
+;*/} BOOT_PARAMS_DOS;  /* DOS fat header
+                                               bpdos_size:
+                                                       endb
+                                                       
+                                                       
+
+;*/typedef struct {                                    /*
+                                                       block   0
+;*/    unsigned char cli;     /* clear interrupt flag instruction
+                                               par1_cli:       .blkb   1
+;*/    unsigned char jmp0, jmp1;       /* short jump
+                                               par1_jump:      .blkb   2
+;*/    unsigned char stage;  /*
+                                               par1_stage:     .blkb   1
+;*/    unsigned short code_length;  /* length of the first stage code
+                                               par1_code_len:  .blkb   2
+;*/    char signature[4]; /* "LILO"
+                                               par1_signature: .blkb   4
+;*/    unsigned short version;  /*
+                                               par1_version:   .blkb   2
+;*/    unsigned int map_stamp; /* timestamp for this installation (map creation)
+                                               par1_mapstamp:  .blkb   4
+;*/    unsigned int raid_offset; /* raid partition/partition offset
+                                               par1_raid_offset: .blkb 4
+;*/    unsigned int timestamp; /* timestamp for restoration
+                                               par1_timestamp: .blkb   4
+;*/    unsigned int map_serial_no; /* volume serial no. / id containing the map file
+                                               par1_map_serial_no:     .blkb   4
+;*/    unsigned short prompt; /* FLAG_PROMPT=always, FLAG_RAID install
+                                               par1_prompt:    .blkb   2
+;*/    SECTOR_ADDR secondary; /* sectors of the second stage loader
+                                               par1_secondary: .blkb   sa_size+1
+;*/} BOOT_PARAMS_1; /* first stage boot loader 
+                                                               .align  4
+                                               par1_size:
+                                                       endb
+
+
+
+;*/typedef struct {    /* second stage parameters
+                                                       block   0
+;*/    char jump[6]; /* jump over the data
+                                               par2_jump:      .blkb   6
+;*/    char signature[4]; /* "LILO"
+                                               par2_signature: .blkb   4
+;*/    unsigned short version; /*
+                                               par2_version:   .blkb   2
+;*/    unsigned int map_stamp;         /* time of creation of the map file
+                                               par2_mapstamp:  .blkb   4
+;*/    unsigned short stage;   /*
+                                               par2_stage:     .blkb   2
+;*/    unsigned char port; /* COM port. 0 = none, 1 = COM1, etc. !!! keep these two serial bytes together !!!
+;*/    unsigned char ser_param; /* RS-232 parameters, must be 0 if unused
+                                               par2_port:      .blkb   1       ; referenced together
+                                               par2_ser_param: .blkb   1       ; **
+;*/    unsigned short timeout; /* 54 msec delay until input time-out, 0xffff: never 
+                                               par2_timeout:   .blkb   2
+;*/    unsigned short delay; /* delay: wait that many 54 msec units.
+                                               par2_delay:     .blkb   2
+;*/    unsigned short msg_len; /* 0 if none
+                                               par2_msg_len:   .blkb   2
+;*/    SECTOR_ADDR keytab; /* keyboard translation table
+                                               par2_keytab:    .blkb   sa_size
+;*/    unsigned char flag2;    /*      flags specific to the second stage loader
+                                               par2_flag2:     .blkb   1
+;*/} BOOT_PARAMS_2; /* second stage boot loader
+                                                               .align  4
+                                               par2_size:
+                                                       endb
+
+
+
+
+;*/typedef struct {                    /*
+                                                       block   0
+;*/    char jump[6]; /* jump over the data
+                                               parC_jump:      .blkb   6
+;*/    char signature[4]; /* "LILO" 
+                                               parC_signature: .blkb   4
+;*/    unsigned short stage,version; /* stage is 0x10
+                                               parC_stage:     .blkb   2
+                                               parC_version:   .blkb   2
+;*/    unsigned short offset; /* partition entry offset
+                                               parC_offset:    .blkb   2
+;*/    unsigned char drive; /* BIOS drive code
+                                               parC_drive:     .blkb   1
+;*/    unsigned char head; /* head; always 0
+                                               parC_head:      .blkb   1
+;*/    unsigned short drvmap; /* offset of drive map
+                                               parC_drvmap:    .blkb   2
+;*/    unsigned char ptable[PARTITION_ENTRY*PARTITION_ENTRIES]; /* part. table
+                                               parC_ptable:    .blkb   64
+;*/    unsigned short p_devmap[2];     /* pointer to device map filled in by second.S
+                                               parC_devmap:    .blkb   4
+;*/} BOOT_PARAMS_C; /* chain loader
+                                               parC_size:
+                                                       endb
+
+
+
+;*/typedef struct {                                    /*
+                                                       block   0
+;*/    char menu_sig[4];       /* "MENU" or "BMP4" signature, or NULs if not present
+                                               mt_sig:         .blkb   4
+;*/    unsigned char at_text;  /* attribute for normal menu text
+                                               mt_at_text:     .blkb   1
+;*/    unsigned char at_highlight;     /* attribute for highlighted text
+                                               mt_at_hilite:   .blkb   1
+;*/    unsigned char at_border;        /* attribute for borders
+                                               mt_at_border:   .blkb   1
+;*/    unsigned char at_title;         /* attribute for title
+                                               mt_at_title:    .blkb   1
+;*/    unsigned char len_title;        /* length of the title string
+                                               mt_len_title:   .blkb   1
+;*/    char title[MAX_MENU_TITLE+2];   /* MENU title to override default
+                                               mt_title:       .blkb   MAX_MENU_TITLE_asm+2
+;*/    short row, col, ncol;           /* BMP row, col, and ncols
+                                               mt_row:         .blkw   1
+                                               mt_col:         .blkw   1
+                                               mt_ncol:        .blkw   1
+;*/    short maxcol, xpitch;           /* BMP max per col, xpitch between cols
+                                               mt_maxcol:      .blkw   1
+                                               mt_xpitch:      .blkw   1
+;*/    short fg, bg, sh;               /* BMP normal text fore, backgr, shadow
+                                               mt_fg:          .blkw   1
+                                               mt_bg:          .blkw   1
+                                               mt_sh:          .blkw   1
+;*/    short h_fg, h_bg, h_sh;         /* highlight fg, bg, & shadow
+                                               mt_h_fg:        .blkw   1
+                                               mt_h_bg:        .blkw   1
+                                               mt_h_sh:        .blkw   1
+;*/    short t_fg, t_bg, t_sh;         /* timer fg, bg, & shadow colors
+                                               mt_t_fg:        .blkw   1
+                                               mt_t_bg:        .blkw   1
+                                               mt_t_sh:        .blkw   1
+;*/    short t_row, t_col;             /* timer position
+                                               mt_t_row:       .blkw   1
+                                               mt_t_col:       .blkw   1
+;*/    short mincol, reserved[3];      /* BMP min per col before spill to next, reserved spacer
+                                               mt_mincol:      .blkw   1
+                                                               .blkw   3
+
+;*/    unsigned int serial_no[MAX_BIOS_DEVICES];       /* Known device serial nos. 0x80 .. 0x8F
+                                               mt_serial_no:   .blkw   MAX_BIOS_DEVICES_asm*2
+;*/    unsigned int raid_offset[MAX_RAID_DEVICES];     /* RAID offsets for flagged devices
+                                               mt_raid_offset: .blkw   MAX_RAID_DEVICES_asm*2
+;*/    unsigned short raid_dev_mask;                   /* 16 bit raid device mask flagging items in serial_no
+                                               mt_raid_dev_mask: .blkw 1
+;*/    SECTOR_ADDR msg; /* initial greeting message
+                                               mt_msg: .blkb   sa_size
+;*/    SECTOR_ADDR dflcmd; /* default command line
+                                               mt_dflcmd:      .blkb   sa_size
+;*/    SECTOR_ADDR mt_descr[MAX_DESCR_SECS];   /* descriptor disk addresses
+                                               mt_descr:       .blkb   sa_size*MAX_DESCR_SECS_asm
+;*/    char unused[150-MAX_BIOS_DEVICES*sizeof(int)-(MAX_RAID_DEVICES)*sizeof(int)-MAX_DESCR_SECS*sizeof(SECTOR_ADDR)];                /* spacer
+                                               mt_unused:      .blkb   150-sa_size*MAX_DESCR_SECS_asm-4*MAX_BIOS_DEVICES_asm-4*MAX_RAID_DEVICES_asm
+;*/    short checksum[2];              /* checksum longword
+                                               mt_cksum:       .blkw   2
+;*/    unsigned char mt_flag;          /* contains the FLAG_NOBD only
+                                               mt_flag:        .blkb   1
+;*/    char unused2;                   /* spacer beyond checksum
+                                               mt_unused2:     .blkb   1
+;*/} MENUTABLE;                /* MENU and BITMAP parameters at KEYTABLE+256
+                                               mt_size:
+                                                       endb
+
+;*/
+
+#ifndef LILO_ASM
+
+typedef struct {
+    unsigned char bootcode[MAX_BOOT_SIZE];
+    unsigned short mbz;                /* must be zero */
+    int  volume_id;
+    unsigned short marker;     /* may be zero */
+    unsigned char part[PART_TABLE_SIZE];
+    unsigned short boot_ind;   /* 0xAA55 */
+} BOOT_VOLID;
+    
+typedef union {
+    BOOT_PARAMS_1 par_1;
+    BOOT_PARAMS_2 par_2;
+    BOOT_PARAMS_C par_c;
+    BOOT_PARAMS_DOS par_d;
+    BOOT_VOLID boot;
+    unsigned char sector[SECTOR_SIZE];
+} BOOT_SECTOR;
+
+typedef union {
+    struct {
+       IMAGE_DESCR descr[MAX_IMAGES]; /* boot file descriptors */
+    } d;
+    unsigned char sector[SECTOR_SIZE*MAX_DESCR_SECS];
+    struct {
+       unsigned int sector[SECTOR_SIZE/4*MAX_DESCR_SECS - 1];
+       unsigned int checksum;
+    } l;
+} DESCR_SECTORS;
+
+typedef struct {
+    int size;
+    unsigned char data[1];
+} BUILTIN_FILE;
+
+
+#ifdef LCF_FIRST6
+#pragma pack (2)
+typedef struct {
+    unsigned char device, flags;
+    unsigned int sector;
+} SECTOR_ADDR6;
+#pragma pack ()
+#endif
+
+
+#endif
+/*
+IMAGES_numerator = SECTOR_SIZE_asm*MAX_DESCR_SECS_asm - 4 - 1
+IMAGES = IMAGES_numerator / id_size
+;*/
+#ifndef LILO_ASM
+typedef struct {
+    unsigned short jump;       /*  0: jump to startup code */
+    char signature[4];         /*  2: "HdrS" */
+    unsigned short version;    /*  6: header version */
+    unsigned short x,y,z;      /*  8: LOADLIN hacks */
+    unsigned short ver_offset; /* 14: kernel version string */
+    unsigned char loader;      /* 16: loader type */
+    unsigned char flags;       /* 17: loader flags */
+    unsigned short a;          /* 18: more LOADLIN hacks */
+    unsigned int start;        /* 20: kernel start, filled in by loader */
+    unsigned int ramdisk;      /* 24: RAM disk start address */
+    unsigned int ramdisk_size; /* 28: RAM disk size */
+    unsigned short b,c;                /* 32: bzImage hacks */
+    unsigned short heap_end_ptr;/* 36: 2.01 end of free area after setup code */
+    unsigned char d;           /* 38: padding */
+    unsigned int cmd_line_ptr; /* 40: 2.02 address32 of command line */
+    unsigned int ramdisk_max;  /* 44: 2.03 address32 of highest mem. for ramdisk */
+} SETUP_HDR;
+
+#define alloc_t(t) ((t *) alloc(sizeof(t)))
+
+typedef enum {X_NULL=0, X_NONE, X_AUTO, X_MBR_ONLY, X_MBR, X_SPEC} LILO_EXTRA;
+typedef enum {AD_ANY=0, AD_GEOMETRIC, AD_LINEAR, AD_LBA32=4} ADDR_MODE;
+typedef enum {DL_NOT_SET=0, DL_BAD=1, DL_UNKNOWN, DL_MAYBE, DL_GOOD} DL_BIOS;
+
+extern LILO_EXTRA extra;
+extern char *identify;
+extern int verbose,test,compact,linear,nowarn,lba32,autoauto,passw,geometric;
+extern int bios_boot, bios_map;
+extern int ireloc, force_fs, force_raid, extended_pt, query;
+extern int colormax, warnings;
+extern DL_BIOS bios_passes_dl;
+extern int boot_dev_nr,raid_index,raid_flags,do_md_install,ndisk,zflag,eflag;
+extern unsigned short drv_map[DRVMAP_SIZE+1]; /* needed for fixup maps */
+extern int curr_drv_map;
+extern unsigned int prt_map[PRTMAP_SIZE+1];
+extern int curr_prt_map, config_read;
+extern unsigned int serial_no[MAX_BIOS_DEVICES];
+extern char *config_file;
+extern FILE *errstd;
+extern FILE *pp_fd;
+extern char *identify; /* in identify.c */
+extern int dm_major_list[16];
+extern int dm_major_nr;
+
+#define crc(a,b) (~crc32((a),(b),CRC_POLY1))
+#define brev(x)  \
+ { register unsigned short u1,u2; register unsigned int u=(x); u1=u; u2=u>>16; \
+ u1=(u1>>8)|(u1<<8); u2=(u2>>8)|(u2<<8); x=(unsigned int)u1<<16|u2; }
+#define cc(x) crc(x.data,x.size)
+#define comma (cc(First)|cc(Second)|cc(Third)|cc(Bitmap)|cc(Chain)|cc(Mbr)|cc(Mbr2))
+
+
+/*volatile*/ void pdie(char *msg);
+/* Do a perror and then exit. */
+
+
+/*volatile*/ void die(char *fmt,...);
+/* fprintf an error message and then exit. */
+
+
+/*volatile*/ void warn(char *fmt,...);
+/* issue a warning message if !nowarn */
+
+
+void *alloc(int size);
+/* Allocates the specified number of bytes. Dies on error. */
+
+
+void *ralloc(void *old,int size);
+/* Changes the size of an allocated memory area. Dies on error. */
+
+
+char *stralloc(const char *str);
+/* Like strdup, but dies on error. */
+
+
+int to_number(char *num);
+/* Converts a string to a number. Dies if the number is invalid. */
+
+
+int timer_number(char *num);
+/* Converts a string to a number.  Allows suffix of 't', 's', 'm', 'h'
+for Tenths, Seconds, Minutes, Hours. Dies if number is invalid for 
+"timeout" or "delay" */
+
+
+void check_version(BOOT_SECTOR *sect, int stage);
+/* Verify that a boot sector has the correct version number. */
+
+
+int stat_equal(struct stat *a, struct stat *b);
+/* Compares two stat structures. Returns a non-zero integer if they describe
+   the same file, zero if they don't. */
+
+
+
+unsigned int crc32partial(unsigned char *cp, int nsize,
+                       unsigned int polynomial, unsigned int *accum);
+/* accumulate a partial CRC-32 */
+
+
+
+unsigned int crc32 (unsigned char *cp, int nsize, unsigned int polynomial);
+/* calculate a CRC-32 polynomial */
+
+
+void show_link(char *name);
+/* show what a link resolves to */
+
+#if __MSDOS__
+#undef comma
+#define comma 0
+#define semi ";"
+#endif
+#endif
+#endif
diff --git a/src/config.h b/src/config.h
new file mode 100644 (file)
index 0000000..3818062
--- /dev/null
@@ -0,0 +1,71 @@
+/* config.h  -  Configurable parameters */
+/*
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2006 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+/* undefine LCF_DEVMAPPER if the library is not present */
+#ifdef LCF_DEVMAPPER
+# ifndef HAS_LIBDEVMAPPER_H
+#  undef LCF_DEVMAPPER
+# endif
+#endif
+
+#if !__MSDOS__
+#if !defined(__GLIBC__) || (__GLIBC__ < 2) || \
+        !defined(__GLIBC_MINOR__) || (__GLIBC_MINOR__ < 1)
+# warning "glibc version 2.1 or later is recommended"
+#endif /* !__MSDOS__ */
+
+#define TMP_DEV     "/tmp/dev.%d" /* temporary devices are created here */
+#define MAX_TMP_DEV 50 /* highest temp. device number */
+
+#ifdef LCF_OLD_DIRSTR
+#define LILO_DIR    "/etc/lilo" /* base directory for LILO files */
+#define BACKUP_DIR  LILO_DIR /* boot sector and partition table backups */
+#define DFL_CONFIG  LILO_DIR "/config" /* default configuration file */
+#define DFL_DISKTAB LILO_DIR "/disktab" /* LILO's disk parameter table */
+#define MAP_FILE    LILO_DIR "/map" /* default map file */
+#define MAP_TMP_APP "~" /* temporary file appendix */
+#define DFL_BOOT    LILO_DIR "/boot.b" /* default boot loader */
+#define DFL_CHAIN   LILO_DIR "/chain.b" /* default chain loader */
+#define DFL_MBR            LILO_DIR "/mbr.b"   /* default MBR */
+#else
+#define CFG_DIR            "/etc"              /* location of configuration files */
+#define BOOT_DIR    "/boot"            /* location of boot files */
+#define BACKUP_DIR  BOOT_DIR /* boot sector and partition table backups */
+#define DFL_CONFIG  CFG_DIR "/lilo.conf"/* default configuration file */
+#define DFL_DISKTAB CFG_DIR "/disktab" /* LILO's disk parameter table */
+#define MAP_FILE    BOOT_DIR "/map"    /* default map file */
+#define MAP_TMP_APP "~"                        /* temporary file appendix */
+#define        DFL_BOOT    BOOT_DIR "/boot.b"  /* default boot loader */
+#define DFL_CHAIN   BOOT_DIR "/chain.b"        /* default chain loader */
+#define DFL_MBR            BOOT_DIR "/mbr.b"   /* default MBR */
+#define DFL_KEYTAB  BOOT_DIR "/us.ktl" /* default keytable */
+#endif
+
+#define DEV_DIR                "/dev"  /* devices directory (/dev/mem &c.) */
+#define DEV_DISK_DIR   DEV_DIR /* disk devices are here */
+                                /* alternate might be "/dev/disk" */
+
+#else /* MSDOS */
+#define CFG_DIR            "C:\\ETC"           /* location of configuration files */
+#define BOOT_DIR    "C:\\BOOT"         /* location of boot files */
+#define BACKUP_DIR  BOOT_DIR /* boot sector and partition table backups */
+#define DFL_CONFIG  CFG_DIR "\\LILO.CNF"/* default configuration file */
+#define MAP_FILE    BOOT_DIR "\\MAP"   /* default map file */
+
+#endif
+
+#define MAX_LINE    1024 /* maximum disk parameter table line length */
+
+#endif
diff --git a/src/crt.S b/src/crt.S
new file mode 100644 (file)
index 0000000..6c84e28
--- /dev/null
+++ b/src/crt.S
@@ -0,0 +1,732 @@
+#if 0
+; crt.S  is
+Copyright 2000-2005 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+#endif
+;
+
+XPITCH  =      MAX_IMAGE_NAME+6
+MINROW =       4
+MAX2COL        =       14
+MAXTITLE  =    3
+MAXCOMMENT  =  3
+
+
+; menu_setup:
+;   main setup menu for LILO boot selection process
+;
+menu_setup:
+       pusha
+       call    mn_getcursor
+       push    dx              ; save cursor position
+       call    mn_init
+       mov     dx,cx
+
+       cmp     byte [abs_cx+1],#0
+       jne     findl0          ; skip clearing screen on second time thru
+; clear the screen
+       xor     cx,cx
+       mov     bh,[mn_at_mono]
+       mov     al,#0
+       call    mn_drawbox
+
+findl0:
+       xor     si,si           ; number of names
+       xor     di,di           ; max. name length
+       mov     cx,#IMAGES      ; get max number to search
+       mov     bx,#DESCR0      ; get address to start at
+findl1:        call    strlen          ; get length in ax
+       or      ax,ax
+       jz      findl3
+#ifdef LCF_VIRTUAL
+       test    word ptr (bx+id_flags),#FLAG_VMDEFAULT
+       jz      findl1c
+       call    vmtest
+       jnc     findl1c
+       mov     [vimage],si
+findl1c:
+#endif
+#ifdef LCF_NOKEYBOARD
+       test    word ptr (bx+id_flags),#FLAG_NOKBDEFAULT
+       jz      findl1d
+       call    kbtest
+       jc      findl1d
+       mov     [vimage],si
+findl1d:
+#endif
+       cmp     ax,di
+       jb      findl2
+       xchg    ax,di
+findl2:        add     bx,#id_size
+       inc     si
+       loop    findl1
+
+findl3:        mov     [nimage],si
+       mov     [limage],di
+       mov     bx,#str_title   ;
+       call    strlen
+       mov     bl,[mn_max_row_col]
+       sub     bl,al
+       shr     bl,#1
+
+       push    bx
+
+       mov     ax,si
+       mov     bl,#2           ;set for 2 columns
+       cmp     al,#MAX2COL
+       jle     col1
+       inc     bl
+col1:  mov     [ncol],bl
+       add     al,bl
+       dec     al
+       div     bl
+       cmp     al,#MINROW
+       jg      row1
+       mov     al,#MINROW
+row1:  cbw
+       mov     [nrow],ax
+;;;    add     ax,#4+4+1
+       add     ax,#MAXTITLE+1 +MAXCOMMENT+1 +1
+       mov     dh,al           ; 
+       mov     al,#XPITCH              ; standard width
+       mul     bl
+       mov     dl,al
+       mov     cl,[mn_max_row_col]
+       sub     cl,dl
+       shr     cl,#1
+       mov     ch,#1
+       mov     al,#0x83
+       mov     bh,[mn_at_text]
+       call    mn_drawbox
+        mov     [area_cx],cx
+        mov     [area_dx],dx
+       push    dx
+       add     dx,cx           ; absolute location
+       sub     dx,#0x0306
+       mov     [timer_dx],dx   ; save location of timer
+       pop     dx
+       add     ch,#2           ; title height
+
+       mov     bp,sp
+       xchg    dx,(bp)
+
+       mov     dh,ch
+       mov     bx,#str_title
+       mov     al,[mn_at_title]
+       call    mn_wrstra
+
+       pop     dx
+
+       add     ch,#2
+       mov     al,#1
+       call    mn_hline
+
+       push    cx
+
+       inc     ch
+       add     ch,[nrow]
+       mov     al,#1
+       call    mn_hline
+       mov     dx,cx
+
+       push    dx
+
+       add     dx,#0x102
+       mov     al,[mn_at_text]
+       mov     bx,#str_com1
+       test    byte ptr par2_flag2,#FLAG2_UNATTENDED
+       jz      mn_attended
+       mov     bx,#str_com1u   ; unattended
+mn_attended:
+       call    mn_wrstra
+       inc     dh
+       mov     bx,#str_com2
+       call    mn_wrstra
+       inc     dh
+       mov     bx,#str_com3
+       call    mn_wrstra
+       mov     dx,[timer_dx]
+       mov     bx,#str_timer
+       call    mn_wrstra
+
+       pop     dx
+       pop     cx
+
+       sub     dh,ch
+       mov     ah,[ncol]
+       mov     si,#DESCR0      ; get start pointer
+       mov     di,[nimage]
+       mov     [norigin],cx
+vlines:
+       add     cl,#3
+       mov     al,#1
+       call    mn_vline
+
+       push    cx
+       push    dx
+
+       mov     dx,cx
+       add     dx,#0x102
+       mov     cx,[nrow]
+       cmp     cx,di
+       jb      vl1
+       mov     cx,di
+vl1:   jcxz    vl3
+vl2:   mov     bx,si
+       mov     al,[mn_at_text]
+       call    mn_wrstra
+
+       push    ax
+       push    dx
+       sub     dl,#4
+       mov     ah,al
+       test    word [id_flags](si),#FLAG_TOOBIG        ; test for unbootable
+       mov     al,#0x55                ; 'U' for possibly unbootable
+       jnz     vl20
+       mov     al,#0x46                ; 'F' for fallback
+       test    byte [id_flags](si),#FLAG_FALLBACK
+       jnz     vl20
+       mov     al,#0x4C                ; 'L' for lock
+       test    byte [id_flags](si),#FLAG_LOCK
+#ifdef LCF_VIRTUAL
+       jnz     vl20
+       mov     al,#0x57                ; 'W' for vmWarn
+       test    word [id_flags](si),#FLAG_VMWARN
+#endif
+       jz      vl21
+vl20:  call    mn_wrcha
+vl21:  
+       inc     dl
+       test    byte [id_flags](si),#FLAG_PASSWORD      ; test for password
+       jz      vl23
+       mov     al,#0x50                ; 'P' for password
+       test    byte [id_flags](si),#FLAG_RESTR
+       jz      vl22
+       mov     al,#0x52                ; 'R' for restricted options
+vl22:  call    mn_wrcha
+vl23:  pop     dx
+       pop     ax
+
+       inc     dh
+       dec     di
+       add     si,#id_size
+       loop    vl2
+vl3:
+       pop     dx
+       pop     cx
+
+       add     cl,#XPITCH-3
+       dec     ah
+       jz      vdone
+       mov     al,#2
+       call    mn_vline
+       jmp     vlines
+vdone:
+       mov     ax,[dimage]             ; usually zero
+#if defined(LCF_VIRTUAL) || defined(LCF_NOKEYBOARD)
+       test    byte ptr [cmdline],#0xFF
+       jnz     vdone3
+       mov     ax,[vimage]
+vdone3:
+#endif
+       call    hilite
+
+       pop     dx                      ; get saved cursor position
+       cmp     byte [abs_cx+1],#0
+       jne     nohome
+
+       mov     dx,[area_cx]
+       add     dx,[area_dx]
+       xor     dl,dl
+       add     dh,#2
+       mov     [abs_cx],dx             ; set home cursor position
+nohome:        
+       call    mn_setcursor
+
+       popa
+       ret
+; end of menu_setup subroutine
+
+#if 0
+; find_image
+;      if there is something on the command line
+;      return the image number it selects
+;
+;      enter with:
+;              nothing
+;      exit with:
+;              If nothing selected:
+;                  Carry Clear
+;                  AX==0
+;              If an image is selected:
+;                  Carry SET
+;                  AX==#image
+;                  BX==pointer to descriptor
+;                  
+;
+;      side effect:
+;              The selected image is hi-lited if the menu is displayed
+;
+find_image:
+       push    cx
+       push    si
+       push    di
+       
+       mov     cx,#IMAGES      ! test all names
+       mov     si,#DESCR0
+       push    si
+fi_nextn:
+       mov     di,#cmdline
+fi_nextc:
+       mov     al,(si)         ! get next character in descr
+                               ! get the character
+#ifdef LCF_IGNORECASE
+       call    upcase
+#endif
+       mov     ah,al
+       mov     al,(di)         ! get next char in cmdline
+#ifdef LCF_IGNORECASE
+       call    upcase
+#endif
+       or      ah,ah           ! NUL in descriptor name
+       jz      fi_dscend
+       cmp     al,ah           ! character equal ?
+       jne     fi_skipn                ! no -> try next one
+       inc     si              ! test next character
+       inc     di
+       jmp     fi_nextc
+fi_dscend:     
+       cmp     al,#32          ! space or NUL -> equal
+       je      fi_found
+       or      al,al
+       jz      fi_found
+
+fi_skipn:
+       pop     si
+       add     si,#id_size     ! test next name
+       push    si
+       loop    fi_nextn
+
+       pop     si
+       xor     ax,ax           ; clears the carry
+fi_exit:
+       pop     di
+       pop     si
+       pop     cx
+       ret
+       
+fi_found:
+       pop     bx              ! BX is matched descriptor
+       mov     ax,bx
+       sub     ax,#DESCR0
+       mov     cl,#id_size
+       div     cl
+       cbw
+       mov     di,[dimage]
+       cmp     ax,di
+       je      fi_nochange
+       mov     [dimage],ax
+       cmp     byte [abs_cx+1],#0      ! see if menu is displayed
+       je      fi_nochange
+       xchg    ax,di
+       call    lowlite
+       xchg    ax,di
+       call    hilite
+fi_nochange:
+       stc
+       jmp     fi_exit
+#endif
+
+; menu_delline:
+;      delete the current command line
+;                              common code from original second.S
+;
+;      enter with:
+;              BX = command line pointer
+;
+;      exit with:
+;              BX = updated command line pointer
+;
+;
+menu_delline:
+       cmp     bx,#cmdline     ! done ?
+       je      mdel9           ! yes -> done
+       push    bx              ! display BS,SPC,BS
+       mov     bx,#bs
+       call    say
+       pop     bx
+       dec     bx              ! move the pointer
+       jmp     menu_delline            ! next one
+mdel9: ret
+
+
+; menu_setcmd:
+;      set currently selected image to be the command line
+;
+;      enter with:
+;              AX = image# to select
+;              BX = cmdline pointer
+;
+;      exit with:
+;              BX = updated
+;
+;
+menu_setcmd:
+       push    si
+
+       push    ax
+
+       call    menu_delline    ; delete the current line
+
+       pop     si              ; get image# back
+
+       imul    si,#id_size
+       add     si,#DESCR0
+mset1: lodsb
+       or      al,al
+       jz      mset6
+       mov     (bx),al
+       inc     bx
+       push    bx
+       call    display
+       pop     bx
+       jmp     mset1
+       
+mset6:
+       pop     si      
+       ret
+
+
+; arrow
+;
+;   Code that handles the arrow keys:  left, up, down, right
+;
+;
+arrow: cbw                     ; signed delta vector in AL
+       mov     dx,[dimage]     ;
+       add     dx,ax           ; new position
+       or      dx,dx
+       jns     arr1
+arr0:  xor     dx,dx           ; set to zero if neg.
+arr1:  mov     ax,[nimage]
+       cmp     dx,ax           ; compare to max.
+       jb      arr2
+       mov     dx,ax
+       dec     dx
+arr2:                  ; we know the one to hi-lite is in range
+       mov     ax,[dimage]
+       cmp     ax,dx
+       je      arr6
+
+       call    lowlite         ; un-hilite the old
+       xchg    ax,dx
+       call    hilite
+
+       call    menu_setcmd     ; set new command line
+arr6:
+       jmp     arr_vector
+
+       
+null:  mov     al,#1
+       cmp     ah,#0x50                ; down arrow
+       je      arrow
+
+       neg     al
+       cmp     ah,#0x48                ; up arrow
+       je      arrow
+
+       mov     dx,[nimage]
+       cmp     ah,#0x4f                ; end
+       je      arr1
+
+       cmp     ah,#0x47                ; home
+       je      arr0
+
+       mov     al,[nrow]
+       xchg    ax,dx
+       mov     ax,[dimage]
+       div     dl                      
+       xchg    ax,dx                   ; DL = cur col.
+
+       cmp     ah,#0x4d                ; right arrow
+       jne     arr8
+       inc     dx                      ; similar to  dec al
+       cmp     dl,[ncol]               ; cmp (CUR COL + 1) : (NCOL)
+       jb      arrow
+       jmp     arr9
+       
+arr8:
+       cmp     ah,#0x49                ; pg up
+       jne     arr84
+       neg     dh                      ; remainder [0..(nrow-1)]
+       mov     al,dh
+arrow1:        jmp     arrow
+
+arr84:
+       cmp     ah,#0x51                ; pg dn
+       jne     arr88
+       not     dh
+       add     al,dh
+       jmp     arrow
+
+arr88:
+       neg     al
+       cmp     ah,#0x4b                ; left arrow
+       jne     arr9
+       or      dl,dl
+       jnz     arrow1
+
+arr9:
+       cmp     ah,#0x53                ; DEL
+       jne     arr_vector
+       br      delch                   ; treat as 0177 (rubout)
+
+arr_vector:
+       br      input           ; ignore the rest
+
+; menu_exit:
+;      erase the menu box to black
+;
+menu_exit:
+       pusha
+       mov     cx,[area_cx]
+       mov     dx,[area_dx]
+       mov     al,#0x80
+       mov     bh,[mn_at_mono]
+       call    mn_drawbox
+       popa
+       ret
+
+; menu_form_feed:
+;      simulate a FF on the console
+;
+menu_form_feed:
+       pusha
+;;     push    ds
+;;     push    cs
+;;     pop     ds
+       mov     cx,[abs_cx]     ! get home position
+       mov     dx,[mn_max_row_col]
+       xor     al,al
+       mov     bh,#0x07
+       call    mn_drawbox
+       mov     dx,cx
+       call    mn_setcursor
+;;     pop     ds
+       popa
+       ret
+
+; timer_display:
+;      check the timer 'cntdown' and display changes
+;
+timer_display:
+       pusha
+
+       cmp     word [timer_dx],#0      ; see if not initialized
+       jz      timer99
+
+       mov     dx,#0x2d2d      ; get "--" means disabled
+       mov     [tim_min],dx
+       mov     [tim_sec],dx
+       mov     ax,[cntdown]    ; get timer countdown location
+       cmp     ax,[tim_tick]
+       je      timer99
+       mov     [tim_tick],ax   ; save last tick count  
+       inc     ax
+       jz      timer8
+
+       mul     c55             ; get time remaining in ms.
+       div     c1000           ; convert to seconds
+       xor     dx,dx
+       div     c60             ; minutes in AX, seconds in DX  
+       aam
+       add     ax,#0x3030
+       xchg    ah,al
+       mov     [tim_min],ax    ; put characters in buffer
+       xchg    ax,dx
+       aam
+       add     ax,#0x3030
+       xchg    ah,al
+       mov     [tim_sec],ax    ; put characters in buffer
+
+timer8:
+       call    mn_getcursor
+       push    dx
+       mov     dx,[timer_dx]
+       mov     ah,[mn_at_text]
+       mov     si,#tim_min
+       mov     bx,#tim_old
+       mov     cx,#5
+timer91:
+       lodsb
+       cmp     al,(bx)
+       je      timer92
+       call    mn_wrcha
+       mov     (bx),al
+timer92:
+       inc     bx
+       inc     dl
+       loop    timer91
+       pop     dx
+       call    mn_setcursor
+timer99:
+       popa
+       ret
+
+tim_min: db    0,0
+       .ascii  ":"
+tim_sec: db    0,0
+
+tim_old: .ascii        "*****"
+tim_tick: dw   0               ; last timer tick value examined
+
+c55:   .word   2197            ;was 55, now 54.925*40
+c1000: .word   40000           ;was 1000, now 40*1000
+c60:   .word   60
+
+
+; hilite/lowlite
+;      enter with:
+;              AX = number [0..(nimage-1)] of entry to hilite
+;
+hilite:        push    bx
+       mov     [dimage],ax             ; remember the latest
+       mov     bh,[mn_at_hilite]
+       jmp     lowlite1
+
+lowlite:  push bx
+       mov     bh,[mn_at_text]
+lowlite1:
+       push    cx
+       push    dx
+       push    ax
+
+       call    mn_getcursor
+       push    dx                      ;save current cursor position
+
+       mov     dx,[norigin]
+       add     dx,#0x104
+       mov     cx,[limage]
+       inc     cx
+       inc     cx
+
+       push    bx
+       mov     bx,[nrow]
+ll1:   cmp     ax,bx
+       jb      ll2
+       add     dl,#XPITCH              ; index by column
+       sub     ax,bx
+       jmp     ll1
+ll2:   add     dh,al
+       pop     bx              ; restore attribute in BH
+
+ll3:   call    mn_rdcha        ; read char and attribute
+       mov     ah,bh
+       call    mn_wrcha        ; write back with new attribute
+       inc     dl
+       loop    ll3
+
+       pop     dx              ; restore cursor
+       call    mn_setcursor
+
+       pop     ax
+       pop     dx
+       pop     cx
+       pop     bx
+       ret
+
+
+; title_stuff
+;
+;
+title_stuff:
+       cmp     dword (bx),#0x554e454d  ; "MENU"
+       jne     noschema
+       mov     edx,(bx+4)
+       mov     [mn_attrib],edx
+noschema:
+       add     bx,#9           ; point at possible title
+       mov     al,(bx-1)       ; get length stored by installer
+       or      al,al
+       jz      notitle         ; no title if supplied length is 0
+       cbw
+       xchg    ax,cx           ; supplied length to CX
+       call    strlen
+       cmp     ax,cx
+       jne     notitle
+       cmp     ax,#str_title_len
+       jae     notitle
+       push    di
+       mov     di,#str_title   ;
+titlemov:
+       mov     al,(bx)
+       inc     bx
+       seg ds
+         stosb
+       or      al,al
+       jnz     titlemov
+
+       pop     di
+notitle:
+       ret
+
+
+dimage:        dw      0       ; default image
+#if defined(LCF_VIRTUAL) || defined(LCF_NOKEYBOARD)
+vimage:        dw      0       ; vmdefault image
+#endif
+norigin: dw    0       ; row/col origin of names on screen
+nimage:        dw      0       ; number of images
+limage:        dw      0       ; longest length of image name
+nrow:  dw      0       ; number of rows of selections
+ncol:  dw      0       ; number of columns (default=2)
+;wcol: db      0       ; width of each column (default=XPITCH=21)
+area_cx:  dw    0       ; area of interaction
+area_dx:  dw    0       ; area of interaction
+abs_cx:        dw      0       ; upper left of scrolling area
+;abs_dx:       dw      0       ; lower right of scrolling area
+;       mn_max_row_col is the same as the above (abs_dx)
+timer_dx: dw   0       ; timer location
+
+
+str_title:
+       .ascii  "GNU/Linux - "
+       .ascii  "LILO "
+#ifdef LCF_VERSION
+       .ascii  SA(VERSION_MAJOR)
+       .ascii  " - "   
+#endif
+       .ascii  "Boot Menu"
+       .byte   0
+       .org    str_title+MAX_MENU_TITLE+1
+
+str_timer:
+       .ascii  "--:--"
+       db      0
+
+str_title_len  = str_timer-str_title-1
+
+str_com1:
+       .ascii  "Hit any key to cancel timeout"
+;              "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00:00"
+       db      0
+str_com1u:
+       .ascii  "Hit any key to restart timeout"
+       db      0
+
+str_com2:
+       .ascii  "Use "
+       db      27              ; left-arrow
+       db      24,25           ; up-arrow, down-arrow
+       db      26              ; right-arrow
+       .ascii  " arrow keys to make selection"
+       db      0
+str_com3:
+       .ascii  "Enter choice & options, hit CR to boot"
+       db      0
+
+; end of crt.S
diff --git a/src/device.c b/src/device.c
new file mode 100644 (file)
index 0000000..fb7a9f7
--- /dev/null
@@ -0,0 +1,1393 @@
+/* device.c  -  Device access */
+/*
+Copyright 1992-1997 Werner Almesberger.
+Copyright 1999-2006 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <dirent.h>
+#include <limits.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "config.h"
+#include "lilo.h"
+#include "common.h"
+#include "temp.h"
+#include "device.h"
+#include "geometry.h"
+#include "partition.h"
+#include "cfg.h"
+#include "probe.h"
+#include "md-int.h"
+
+
+typedef struct _cache_entry {
+    const char *name;
+    int number;
+    struct _cache_entry *next;
+} CACHE_ENTRY;
+
+typedef struct _st_buf {
+    struct _st_buf *next;
+    struct stat st;
+} ST_BUF;
+
+
+static CACHE_ENTRY *cache = NULL;
+
+
+#if 1
+int yesno(char *prompt, int expect)
+{
+    char *line, *pr2;
+    int i;
+    size_t n;
+    int ret;
+    if (expect) pr2 = "[Y/n]";
+    else pr2 = "[N/y]";
+    
+    fflush(stdout);
+    do {
+       fprintf(stderr, "%s%s", prompt, pr2);
+       fflush(stderr);
+       n = ret = 0;
+       line = NULL;
+       i = getline(&line, &n, stdin);
+       if (i<0) exit(1);
+       if (i==1) ret=expect|2;
+       if (i>1) {
+               if (*line=='y'||*line=='Y') ret=1;
+               if (*line=='n'||*line=='N') ret=2;
+       }
+       if (ret) break;
+       if (line) free(line);
+    } while(1);
+
+    return ret&1;
+}
+#endif
+
+static int scan_dir(ST_BUF *next,DEVICE *dev,char *parent,int number)
+{
+    DIR *dp;
+    struct dirent *dir;
+    ST_BUF st,*walk;
+    char *start;
+
+    if (verbose >= 5) printf("scan_dir: %s\n", parent);
+    st.next = next;
+    if ((dp = opendir(parent)) == NULL)
+    die("opendir %s: %s",parent,strerror(errno));
+    *(start = strchr(parent,0)) = '/';
+    while ((dir = readdir(dp))) {
+       strcpy(start+1,dir->d_name);
+       if (stat(parent,&st.st) >= 0) {
+          dev->st = st.st;
+          if (S_ISBLK(dev->st.st_mode) && dev->st.st_rdev == number) {
+              (void) closedir(dp);
+              return 1;
+              }
+#if 0
+          if (S_ISDIR(dev->st.st_mode) && strcmp(dir->d_name,".") &&
+            strcmp(dir->d_name,"..")) {
+#else
+          /* stay out of all hidden directories (good for 2.6 kernel) */
+          if (S_ISDIR(dev->st.st_mode) && (dir->d_name)[0] != '.' &&
+            strcmp(dir->d_name, ".udev") && strcmp(dir->d_name, "fd")) {
+#endif
+          for (walk = next; walk; walk = walk->next)
+              if (stat_equal(&walk->st,&st.st)) break;
+          if (!walk && scan_dir(&st,dev,parent,number)) {
+              (void) closedir(dp);
+              return 1;
+              }
+          }
+       }
+    }
+    (void) closedir(dp);
+    *start = 0;
+    return 0;
+}
+
+
+static int lookup_dev(char *name,DEVICE *dev,int number)
+{
+    CACHE_ENTRY **walk;
+
+    if (verbose>=5) printf("lookup_dev:  number=%04X\n", number);
+    for (walk = &cache; *walk; walk = &(*walk)->next)
+       if ((*walk)->number == number) {
+#if 0
+           CACHE_ENTRY *here;
+
+           if (stat((*walk)->name,&dev->st) >= 0)
+               if (S_ISBLK(dev->st.st_mode) && dev->st.st_rdev == number) {
+                   strcpy(name,(*walk)->name);
+                   return 1;
+               }
+           here = *walk; /* remove entry from cache */
+           if (verbose >= 2)
+               printf("Invalidating cache entry for %s (0x%04X)\n",here->name,
+                 here->number);
+           *walk = here->next;
+           free((char *) here->name);
+           free(here);
+           return 0;
+#else
+           strcpy(name,(*walk)->name);
+           return 1;
+#endif
+       }
+    return 0;
+}
+
+
+static int is_devfs(void)
+{
+static int yesno = 0;
+    struct stat st;
+   
+    if (!yesno) {
+       if (stat(DEV_DIR "/.devfsd", &st) < 0)  yesno=1;
+       else yesno=2;
+    }
+   
+   return yesno-1;
+}
+
+
+
+static void cache_add(const char *name,int number)
+{
+    CACHE_ENTRY *entry;
+
+    entry = cache;
+    while (entry) {
+       if (strcmp(entry->name, name) == 0) {
+           if (entry->number != number) die("cache_add: LILO internal error");
+           return;
+       }
+       entry = entry->next;
+    }
+    if (verbose >= 5) printf("Caching device %s (0x%04X)\n",name,number);
+    entry = alloc_t(CACHE_ENTRY);
+    entry->name = stralloc(name);
+    entry->number = number;
+    entry->next = cache;
+    cache = entry;
+}
+
+
+int dev_open(DEVICE *dev,int number,int flags)
+{
+    char name[PATH_MAX];
+    ST_BUF st;
+    int count;
+
+    if (lookup_dev(name,dev,number)) dev->delete = 0;
+    else {
+       if (stat(DEV_DIR,&st.st) < 0)
+           die("stat " DEV_DIR ": %s",strerror(errno));
+       st.next = NULL;
+       dev->delete = !scan_dir(&st,dev,strcpy(name,DEV_DIR),number);
+       if (dev->delete) {
+           for (count = 0; count <= MAX_TMP_DEV; count++) {
+#ifdef LCF_USE_TMPDIR
+               if (!strncmp(TMP_DEV,"/tmp/",5) && getenv("TMPDIR")) {
+                   strcpy(name,getenv("TMPDIR"));
+                   sprintf(name+strlen(name),TMP_DEV+4,count);
+               }
+               else
+#endif
+                   sprintf(name,TMP_DEV,count);
+               if (stat(name,&dev->st) < 0) break;
+           }
+           if (count > MAX_TMP_DEV)
+               die("Failed to create a temporary device");
+           if (mknod(name,0600 | S_IFBLK,number) < 0)
+               die("mknod %s: %s",name,strerror(errno));
+           if (stat(name,&dev->st) < 0)
+               die("stat %s: %s",name,strerror(errno));
+           if (verbose > 1)
+               printf("Created temporary device %s (0x%04X)\n",name,number);
+           temp_register(name);
+       }
+       else cache_add(name,number);
+    }
+#if BETA_TEST
+       if (verbose >= 4) printf("stat-ing %s\n", name);
+       fflush(stdout);
+       stat(name, &st.st);
+#endif
+    if (flags == O_BYPASS) dev->fd = -1;
+    else if ((dev->fd = open(name,flags)) < 0) {
+            fprintf (errstd, "Cannot proceed. Maybe you need to add "
+                        "this to your lilo.conf:\n"
+                         "\tdisk=%s inaccessible\n"
+                        "(real error shown below)\n", name);
+           die("open %s: %s",name,strerror(errno));
+    }
+    dev->name = stralloc(name);
+    return dev->fd;
+}
+
+
+void dev_close(DEVICE *dev)
+{
+    if (dev->fd != -1)
+       if (close(dev->fd) < 0) die("close %s: %s",dev->name,strerror(errno));
+    if (dev->delete) {
+       if (verbose > 1)
+           printf("Removed temporary device %s (0x%04X)\n",dev->name,
+             (unsigned int) dev->st.st_rdev);
+       (void) remove(dev->name);
+       temp_unregister(dev->name);
+    }
+    free(dev->name);
+}
+
+#define MAX 15
+
+void cache_scsi (char *name, int major)
+{
+    char tem[PATH_MAX], format[PATH_MAX];
+    int i, j, dev;
+    int k = strlen(DEV_DISK_DIR) + 3;
+    
+    for (i=15; i>=0; i--) {
+       dev = MKDEV(major,(i<<4));
+#if 0
+       if (is_devfs()) {
+           sprintf(tem,"/dev/scsi/host%d/bus0/target0/lun0/", i);
+           strcat(strcpy(format,tem),"disc");
+           cache_add(format, dev);
+           strcat(strcpy(format,tem),"part%d");
+       }
+       else
+#endif
+       {
+           strcpy(format, name);
+           format[k] += i;
+           cache_add(format, dev);
+           strcat(format, "%d");
+       }
+       for (j = MAX; j; j--) {
+           sprintf(tem, format, j);
+           cache_add(tem, dev | j);
+       }
+    }
+}
+
+
+void cache_ide (char *name, int major)
+{
+    char tem[PATH_MAX], tem2[PATH_MAX];
+    char format[PATH_MAX];
+    char *disc;
+    int i, dev, minor, host, bus, target;
+    int j = strlen(DEV_DISK_DIR) + 3;
+    
+    i = name[j] - 'a';
+    target = i&1;
+    minor = target<<6;
+    i >>= 1;
+    bus = i&1;
+    host = i&(-2);
+    if (is_devfs()) {
+       sprintf(tem2, DEV_DIR "/ide/host%d/bus%d/target%d/lun0/", host, bus, target);
+       strcat(strcpy(format,tem2), "part%d");
+       disc = strcat(tem2, "disc");
+    }
+    else {
+        strcat(strcpy(format, name), "%d");
+        disc = name;
+    }
+    dev = MKDEV(major,minor);
+    for (i = MAX; i; i--) {
+       sprintf(tem, format, i);
+       cache_add(tem, dev | i);
+    }
+    cache_add(disc, dev);
+}
+
+void preload_dev_cache(void)
+{
+    char tmp[PATH_MAX];
+    int i;
+    int vsave;
+
+
+    vsave = verbose;
+#if !BETA_TEST
+    if (verbose>0) verbose--;
+#endif
+
+    if (is_devfs()) {
+       cache_add(DEV_DIR "/floppy/0", 0x0200);
+       cache_add(DEV_DIR "/floppy/1", 0x0201);
+    }
+    else {
+       cache_add(DEV_DIR "/fd0", 0x0200);
+       cache_add(DEV_DIR "/fd1", 0x0201);
+    }
+    
+#if 1
+    cache_ide(DEV_DISK_DIR "/hdt", MAJOR_IDE10);
+    cache_ide(DEV_DISK_DIR "/hds", MAJOR_IDE10);
+    cache_ide(DEV_DISK_DIR "/hdr", MAJOR_IDE9);
+    cache_ide(DEV_DISK_DIR "/hdq", MAJOR_IDE9);
+
+    cache_ide(DEV_DISK_DIR "/hdp", MAJOR_IDE8);
+    cache_ide(DEV_DISK_DIR "/hdo", MAJOR_IDE8);
+    cache_ide(DEV_DISK_DIR "/hdn", MAJOR_IDE7);
+    cache_ide(DEV_DISK_DIR "/hdm", MAJOR_IDE7);
+    
+    cache_ide(DEV_DISK_DIR "/hdl", MAJOR_IDE6);
+    cache_ide(DEV_DISK_DIR "/hdk", MAJOR_IDE6);
+#ifdef MAJOR_IDE5
+    cache_ide(DEV_DISK_DIR "/hdj", MAJOR_IDE5);
+    cache_ide(DEV_DISK_DIR "/hdi", MAJOR_IDE5);
+#endif
+#endif
+    
+    for (i = MAX; i >= 0; i--) {
+       sprintf(tmp, is_devfs() ? DEV_DISK_DIR "/md/%d" : DEV_DISK_DIR "/md%d", i);
+       cache_add(tmp, MKDEV(MAJOR_MD,i));
+    }
+
+    if (!is_devfs()) cache_scsi(DEV_DISK_DIR "/sda", MAJOR_SD);
+    
+    cache_ide(DEV_DISK_DIR "/hdh", MAJOR_IDE4);
+    cache_ide(DEV_DISK_DIR "/hdg", MAJOR_IDE4);
+    cache_ide(DEV_DISK_DIR "/hdf", MAJOR_IDE3);
+    cache_ide(DEV_DISK_DIR "/hde", MAJOR_IDE3);
+
+    for (i = 0; i <= 7; i++) {
+       sprintf(tmp, is_devfs() ? DEV_DIR "/loop/%d" : DEV_DIR "/loop%d", i);
+       cache_add(tmp,0x700+i);
+    }
+
+    cache_ide(DEV_DISK_DIR "/hdd", MAJOR_IDE2);
+    cache_ide(DEV_DISK_DIR "/hdc", MAJOR_IDE2);
+    cache_ide(DEV_DISK_DIR "/hdb", MAJOR_HD);
+    cache_ide(DEV_DISK_DIR "/hda", MAJOR_HD);
+    
+    verbose = vsave;
+}
+
+#undef MAX
+
+#define NDEVICE 256
+static unsigned int idevices[NDEVICE];
+static int maxdev = 0;
+
+/* return 0 if device has not been backed up,          */
+/*       1 if it has been backed up                    */
+
+static int dev_listed(unsigned short dev)
+{
+    int i;
+
+/* scan the device list */
+    for (i=0; i<maxdev; i++) {
+       if (dev==idevices[i]) return 1;         /* already backed up */
+    }
+    
+    if (maxdev < NDEVICE-1) idevices[maxdev++] = dev;
+
+    return 0;  /* new to the list, not listed if too many devices */
+}
+
+
+/* make a backup, returning the timestamp of the backup file */
+/* 0 if no timestamp returned, and no backup file created */
+
+int make_backup(char *backup_file, int force_backup, BOOT_SECTOR *bsect,
+       unsigned int device, char *id)
+{
+    struct stat st;
+    char temp_name[PATH_MAX];
+    int bck_file;
+    int timestamp=0;
+    char *filename = "boot";
+
+    char *cp = NULL;
+    int force = 0;
+
+
+    if ((cp=cfg_get_strg(cf_options,"force-backup"))) force=1;
+    else cp=cfg_get_strg(cf_options,"backup");
+    if (!backup_file) {
+       backup_file = cp;
+       force_backup = force;
+    }
+
+    if (backup_file && stat(backup_file, &st) >= 0) {
+/* file or directory exists */
+       if (S_ISDIR(st.st_mode)) {
+           if (strcmp(backup_file,"/")==0) backup_file = "";
+           sprintf(temp_name, "%s/%s.%04X", backup_file, filename, device);
+           backup_file = temp_name;
+       }
+    /* test for /dev/null */
+       else if (S_ISCHR(st.st_mode) && st.st_rdev==0x0103) return 0;
+       else if (!S_ISREG(st.st_mode))
+           die("make_backup: %s not a directory or regular file", backup_file);
+    }
+
+/* could not stat it, or it was a directory, or it was a regular file */
+
+    if (backup_file) {
+       char *name, *dir, suffix[16];
+       
+       backup_file = strcpy(temp_name, backup_file);
+       sprintf(suffix, "%04X", device);
+       dir = strrchr(backup_file, '/');
+       if (!dir) dir = backup_file;
+       name = strrchr(dir, '.');
+       if (name) {  /* there is a '.' in the name */
+           if (strcmp(name+1, suffix)==0) ; /* do nothing */
+           else if (strlen(name+1)==4) {  /* && the suffix doesn't match */
+               strcpy(name+1,suffix);
+           }
+           else if (name[1]==0) strcat(name,suffix);   /* ended with '.' */
+           else {
+               strcat(name+1,".");
+               strcat(backup_file,suffix);
+           }
+         /* we now have the filename with the correct suffix */
+       }
+       else {
+    /* no '.' in the name, take it as a template */
+           strcat(backup_file,".");
+           strcat(backup_file,suffix);
+       }
+    }
+    else
+  /*  if (!backup_file) */ {
+       sprintf(temp_name, BACKUP_DIR "/%s.%04X", filename, device);
+       backup_file = temp_name;
+    }
+    
+    bck_file = open(backup_file, O_RDONLY);
+    if (bck_file >= 0 && force_backup) {
+       (void) close(bck_file);
+       bck_file = -1;
+    }
+    if (bck_file >= 0) {
+       if (verbose)
+           printf("%s exists - no %s backup copy made.\n", backup_file, id);
+    }
+    else {
+       if (dev_listed(device)) {
+           if (verbose)
+               printf("Backup copy of %s has already been made in %s\n",
+                       id, backup_file);
+       }
+       else if (!test) {
+           if ((bck_file = creat(backup_file, 0644)) < 0)
+               die("creat %s: %s",backup_file, strerror(errno));
+           if (write(bck_file, (char *)bsect, SECTOR_SIZE) != SECTOR_SIZE)
+               die("write %s: %s", backup_file, strerror(errno));
+           if (verbose)
+               printf("Backup copy of %s in %s\n", id, backup_file);
+           if (fstat(bck_file, &st) < 0)
+               die("fstat %s: %s",backup_file,strerror(errno));
+           timestamp = st.st_mtime;
+       }
+       else {
+           if (verbose)
+               printf("Backup copy of %s in %s (test mode)\n", id, backup_file);
+       }
+    }
+    if (bck_file >= 0 && close(bck_file) < 0) die("close %s: %s",backup_file,strerror(errno));
+    
+    return timestamp;
+}
+
+
+
+
+int serial_valid(unsigned int serial, int disk_bios)
+{
+#if 1
+    return (serial != 0);
+#elif 1
+    if (serial == -1 || serial == 0) return 0;
+    return 1;
+#else
+/* if ID is replicated characters, it is invalid */
+/*     Examples of invalid Volume ID's are:
+               00000000
+               6C6C6C6C
+               FFFFFFFF
+BUT: any Volume ID (except 0 or -1) is valid on drive C:
+ - - - - - - - - - - - - - - - - - - - - - - - - - - */
+    unsigned int temp;
+    
+    temp = serial & 0xFF;
+    temp |= temp << 8;
+    temp |= temp << 16;
+
+    return (serial != temp ||
+               (serial!=0 && serial!=0xFFFFFFFFUL && disk_bios==0x80));
+#endif
+}
+
+int new_serial(int dev)
+{
+static int inited = 0;
+   
+    if (!inited) {
+       struct stat st;
+       int fd, random;
+#define RANDOM DEV_DIR "/urandom"      
+
+       inited = time(NULL);
+       if ( stat(RANDOM, &st)==0 && S_ISCHR(st.st_mode)
+           && (fd = open(RANDOM, O_RDONLY)) > 0
+           && read(fd, &random, sizeof(random)) == sizeof(random) )  {
+#if BETA_TEST
+if(verbose>=5) printf("Using " RANDOM " for seeding random number generator\n");           
+#endif
+               close(fd);
+               inited ^= random;
+       }
+
+       srand(inited);
+    }
+    dev = dev % PRIME + SMALL_PRIME;
+    while(dev--) inited = rand();
+    
+    return inited;
+#undef RANDOM
+}
+
+
+
+
+static int inited = 0;
+unsigned int serial_no[MAX_BIOS_DEVICES];
+static int device_code[MAX_BIOS_DEVICES];
+
+/*  register references to various bios devices
+ *  compiles the list of volume IDs
+ *    returns volume ID on success
+ *     0 = no volume ID
+ *     -1 = error
+ */
+unsigned int register_bios(int bios, int device)
+{
+    int i, fd, valid, disk_bios;
+    DEVICE dev;
+    BOOT_SECTOR buff;
+    unsigned int serial = -1;
+    
+#if 0
+    if (!inited) {
+       for (i=0; i<MAX_BIOS_DEVICES; i++) {
+           device_code[i] = 0;
+           serial_no[i] = 0;
+       }
+       inited = 1;
+       srand(time(NULL));
+    }
+#else
+    inited = 1;
+#endif
+    if (!do_md_install && cfg_get_flag(cf_options, "static-bios-codes")) return 0;
+    
+    if (verbose>=4) {
+       printf("registering bios=0x%02X  device=0x%04X\n", bios, device);
+    }
+    
+    disk_bios = bios;
+    if (bios>=0x80 && bios<0x80+MAX_BIOS_DEVICES &&
+                               (i=has_partitions(device))) {
+       bios &= 0x7F;   /* mask to index */
+       device &= i;    /* mask to master device */
+       if (device_code[bios]==0 && serial_no[bios]==0) {  /* slot empty */
+           fd = dev_open(&dev, device, O_RDWR);
+           if (lseek(fd, 0L, SEEK_SET) < 0)
+               die("master boot record seek %04X: %s", device, strerror(errno));
+           if (read(fd, (char*)&buff, SECTOR_SIZE)!=SECTOR_SIZE)
+               die("read master boot record %04X: %s", device, strerror(errno));
+           serial = *(int*)&buff.sector[PART_TABLE_OFFSET-6];
+           valid = serial_valid(serial, disk_bios);
+           if ((!valid || (VERSION_MINOR>=50)) && !test)
+                   make_backup(NULL, 0, &buff, device,
+                                       "master disk volume ID record");
+           if (!valid) {
+               i = device % PRIME + SMALL_PRIME;
+               while(i--) serial = rand();
+               for (; i<5 && !serial_valid(serial, disk_bios); i++) serial = rand();
+               if (!serial_valid(serial, disk_bios)) die("Volume ID generation error");
+
+               *(int*)&buff.sector[PART_TABLE_OFFSET-6] = serial;
+               if (*(short*)&buff.sector[PART_TABLE_OFFSET - 2] == 0)
+                   *(short*)&buff.sector[PART_TABLE_OFFSET - 2] = MAGIC_SERIAL;
+               if (verbose)
+                   printf("Assigning new Volume ID to (%04X) '%s'  ID = %08X\n",
+                                       device, dev.name, (int)serial);
+               if (!test) {
+                   i = lseek(fd, 0L, SEEK_SET);
+                   if (i<0) die("master boot record2 seek %04X: %s", device, strerror(errno));
+                   if (write(fd, (char*)&buff, SECTOR_SIZE)!=SECTOR_SIZE)
+                       die("write master boot record %04X: %s", device, strerror(errno));
+               }
+           }
+           dev_close(&dev);
+           for (i=0; i<MAX_BIOS_DEVICES; i++) {
+               if (device_code[i]==device)
+                   die("register_bios: device code duplicated: %04X", device);
+               if (serial_no[i]==serial)
+                   die("register_bios: volume ID serial no. duplicated: %08lX", serial);
+           }
+           device_code[bios] = device;
+           serial_no[bios] = serial;
+       }
+
+
+       if (device_code[bios]==device) serial = serial_no[bios];
+       else {
+           DEVICE dev, deva;
+           
+           dev_open(&dev, device_code[bios], O_BYPASS);
+           dev_open(&deva, device, O_BYPASS);
+
+           die("Bios device code 0x%02X is being used by two disks\n\t%s (0x%04X)  and  %s (0x%04X)",
+               bios|0x80, dev.name, device_code[bios], deva.name, device);
+       }
+       if (verbose>=3) {
+           printf("Using Volume ID %08X on bios %02X\n", (int)serial, bios+0x80);
+       }
+    }
+    else if (bios>=0 && bios <=3) serial = 0;
+    else serial = -1;
+    
+    return serial;
+}
+
+
+void dump_serial_nos(void)
+{
+    int i,j;
+    
+    printf(" BIOS   VolumeID   Device\n");
+    if (!inited) return;
+    for (j=nelem(serial_no); serial_no[--j]==0; )   ;
+    for (i=0; i<=j; i++)
+       printf("  %02X    %08X    %04X\n",
+               i+0x80,
+               (int)serial_no[i],
+               (int)device_code[i]
+       );
+}
+
+
+enum {ID_GET=0, ID_SET};
+
+static int volid_get_set(int device, int vol_in, int option)
+{
+    BOOT_SECTOR buf;
+    DEVICE dev;
+    int fd;
+    int temp;
+    unsigned short word;
+    
+    if (!has_partitions(device) && (device & P_MASK(device)) )
+       die("VolumeID set/get bad device %04X\n", device);
+       
+    fd = dev_open(&dev, device, option ? O_RDWR : O_RDONLY);
+    if (read(fd, &buf, sizeof(buf)) != sizeof(buf)) {
+       fprintf (errstd, "Cannot proceed. Maybe you need to add "
+                        "this to your lilo.conf:\n"
+                         "\tdisk=%s inaccessible\n"
+                        "(real error shown below)\n", dev.name);
+       die("VolumeID read error: sector 0 of %s not readable", dev.name);
+    }
+    if (option==ID_SET) {
+       make_backup(NULL, 0, &buf, device,
+                                       "master disk volume ID record");
+       word = temp = buf.boot.volume_id & 0xFF;        /* one char */
+       word |= word << 8;
+       temp = word;
+       temp |= temp << 16;
+       if (buf.boot.mbz==word 
+               && buf.boot.volume_id==temp
+               && buf.boot.marker==word) {
+           buf.boot.mbz = buf.boot.marker = 0;
+       }
+       buf.boot.volume_id = vol_in;
+       if (buf.boot.marker == 0) buf.boot.marker = MAGIC_SERIAL;
+       if (!test) {
+           if (lseek(fd, 0L, SEEK_SET) != 0L  ||
+                   write(fd, &buf, PART_TABLE_OFFSET) != PART_TABLE_OFFSET )
+               die("volid write error");
+       }
+    }
+    dev_close(&dev);
+    sync(); /* critical that this be done here */
+    
+    return buf.boot.volume_id;
+}
+
+
+
+
+/* count the number of slashes in a pathname */
+static int slashes(char *cp)
+{
+    int n = 0;
+    
+    while ( (cp=strchr(++cp,'/')) )  n++;
+    
+    return n;
+}
+
+
+static int ndevs=0;
+enum {INVALID=1, DUPLICATE=2, REGENERATE=3, NTCAUTION=4};
+
+struct VolumeMgmt {
+    char *name;                /* the name of the disk; e.g.  "/dev/hda" */
+    unsigned int device;       /* the device number (major, minor) */
+    int sort;          /* the device number used for sorting */
+    int flag;          /* various flag bits */
+    char nt[PART_MAX]; /* flag partitions which might be NT */
+    DT_ENTRY *dt;      /* pointer to any disktab entry */
+    struct {
+       int kernel;     /* volume ID as read using kernel I/O */
+       int probe;      /* volume ID as probed */
+    } vol_id;
+    struct {
+       int user;       /* user used a disk= bios= section */
+       int probe;      /* passed in from the BIOS data check */
+       int actual;     /* this is what we finally decide upon */
+    } bios;            /* BIOS device codes */
+};
+
+
+#ifdef LCF_MDPRAID
+/* return boolean if VM is a component drive of MDP-RAID */
+
+static int is_mdp(struct VolumeMgmt *vm, struct VolumeMgmt *mdp)
+{
+    int mdp_fd;
+    DEVICE dev;
+    struct md_version md_version_info;
+    md_array_info_t raid;
+    int ret=0;
+
+    if (verbose>=2) printf("is_mdp:   %04X : %04X\n",
+          vm->device, mdp->device);
+    
+    if ((mdp_fd=dev_open(&dev, mdp->device, O_NOACCESS) ) < 0)
+       die("Unable to open %s", mdp->name);
+
+    if (ioctl(mdp_fd, RAID_VERSION, &md_version_info) < 0) ret = -1;
+    else if (md_version_info.major > 0  || 
+                         md_version_info.minor < 90) {
+       
+       ret = -2;
+       warn("RAID versions other than 0.90 are not supported");
+    }
+    else if (ioctl(mdp_fd, GET_ARRAY_INFO, &raid) < 0) ret = -1;
+    else if (raid.level == 1) {
+        md_disk_info_t disk;
+       int i;
+       
+       for (i=0; ret==0 && i<raid.active_disks; i++) {
+           disk.number = i;
+           if (ioctl(mdp_fd, GET_DISK_INFO, &disk) < 0) ret = -1;
+           if (vm->device == MKDEV(disk.major, disk.minor)) ret = 1;
+       }
+    }
+    /* else ret = 0;  already */
+    dev_close(&dev);
+
+    if (verbose>=2) printf("is_mdp: returns %d\n", ret);
+    
+    return ret;
+}
+#endif
+
+/* 
+   Returns 0 if not an NT, 2000, or XP boot disk (query user)
+   returns 1 if it is an NT ... boot disk; abort if fatal set
+*/
+static int winnt_check(struct VolumeMgmt *vm, int fatal)
+{
+    int dev, ret;
+    
+    if ( !(vm->flag & NTCAUTION) ) return 0;
+    
+    dev = vm->device;
+
+    fflush(stdout);
+    fflush(stderr);
+    
+    fprintf(stderr, "\n\nReference:  disk \"%s\"  (%d,%d)  %04X\n\n"
+"LILO wants to assign a new Volume ID to this disk drive.  However, changing\n"
+"the Volume ID of a Windows NT, 2000, or XP boot disk is a fatal Windows error.\n"
+"This caution does not apply to Windows 95 or 98, or to NT data disks.\n"
+                               , vm->name, MAJOR(dev), MINOR(dev), dev);
+                                       
+                                       
+    ret = yesno("\nIs the above disk an NT boot disk? ", 1);
+
+    if (ret && fatal) {
+       fprintf(stderr, "Aborting ...\n");
+       exit(0);
+    }
+    
+    return ret;
+}
+
+
+
+#ifdef LCF_MDPRAID
+#define SORT(d) (MAJOR(d)==MAJOR_SD?MKDEV(MAJOR_SD_SORT,MINOR(d)):\
+                MAJOR(d)==MAJOR_MDP?MKDEV(MAJOR_MDP_SORT,MINOR(d)):\
+                MAJOR(d)==MAJOR_EMD?MKDEV(MAJOR_EMD_SORT,MINOR(d)):\
+                MAJOR(d)==MAJOR_HPT370?MKDEV(MAJOR_HPT370_SORT,MINOR(d)):\
+                (d))
+#else
+#define SORT(d) (MAJOR(d)==MAJOR_SD?MKDEV(MAJOR_SD_SORT,MINOR(d)):\
+                MAJOR(d)==MAJOR_EMD?MKDEV(MAJOR_EMD_SORT,MINOR(d)):\
+                MAJOR(d)==MAJOR_HPT370?MKDEV(MAJOR_HPT370_SORT,MINOR(d)):\
+                (d))
+#endif
+
+int pf_hard_disk_scan(void)
+{
+    struct VolumeMgmt vm [MAX_DEVICES];
+static int warned = 0, called = 0;
+    char *line, *next, *name;
+    int major, minor, i, ipart;
+    int dev, mask, bios;
+    unsigned int device;
+    size_t n;
+    DEVICE Dev;
+    DT_ENTRY *walk;
+    struct stat st;
+    int duplicate = 0, invalid = 0, ret = 0, ntcaution = 0;
+    int raidcaution = 0;
+    long codes = 0L;
+
+/* called from  raid_setup  &  from  geo_open */
+/* allow only 1 call */
+    if (called || cfg_get_flag(cf_options,"static-bios-codes")) return ret;
+    called = 1;
+    memset(vm,0,sizeof(vm));   /* for consistency */
+            
+#if 1
+    if (!pp_fd  &&  (pp_fd = fopen(PARTITIONS, "r"))==NULL) {
+#else
+    if ((pp_fd = fopen(PARTITIONS, "r"))==NULL || fetch()) {
+#endif
+       warn("'" PARTITIONS "' does not exist, disk scan bypassed");
+       return 1;
+    }
+
+    n = 0;
+    line = NULL;
+    while (!feof(pp_fd)) {
+       if (line) {
+           free(line);
+           line = NULL;
+           n = 0;
+       }
+       if (getline(&line, &n, pp_fd) <= 0) break;
+
+       major = strtoul(line, &next, 10);
+       if (major==0 || line==next) continue;
+
+        if (is_dm_major(major)) {
+#ifndef LCF_DEVMAPPER
+            warn("device-mapper (%d) referenced in " PARTITIONS ",\n"
+                 "   but LILO is configured without DEVMAPPER option.  Skipping device.", major);
+            continue;
+#endif
+        }
+        else if ((major>=60 && major<=63) || (major>=120 && major<=127) ) {
+            warn(PARTITIONS " references Experimental major device %d.", major);
+        }
+        else if (major==255) {
+            warn(PARTITIONS " references Reserved device 255.");
+            continue;
+        }
+        else if (major>=240 && major<255) {
+            warn(PARTITIONS " references Experimental major device %d.", major);
+        }
+
+       minor = strtoul(next, &name, 10);
+       if (next==name) continue;
+       /* skip */ strtoull(name,&next,10);
+
+       while (isspace(*next)) next++;
+       name = next;
+       while (*name && !isspace(*name)) name++;
+       *name = 0;
+       if (strncmp(DEV_DISK_DIR "/", next, strlen(DEV_DISK_DIR)+1) != 0) name = next-(strlen(DEV_DISK_DIR)+1);
+       else name = next;
+       if (*name=='/') name++;
+       strncpy(name, DEV_DISK_DIR "/", strlen(DEV_DISK_DIR)+1);
+       if (verbose>=5) {
+           printf("pf_hard_disk_scan: (%d,%d) %s\n", major, minor, name);
+       }
+
+       device = MKDEV(major, minor);
+
+       Dev.delete = 0;
+       if (stat(name, &st) < 0) {
+           dev_open(&Dev, device, O_BYPASS);
+           if (!warned) {
+               warn("'" PARTITIONS "' does not match '" DEV_DISK_DIR "' directory structure.\n"
+                               "    Name change: '%s' -> '%s'%s"
+                               ,       name, Dev.name,
+                               slashes(name) > 3 && slashes(Dev.name) < 3 ? "\n"
+                               "    The kernel was compiled with DEVFS_FS, but 'devfs=mount' was omitted\n"
+                               "        as a kernel command-line boot parameter; hence, the '" DEV_DISK_DIR "' directory\n"
+                               "        structure does not reflect DEVFS_FS device names."
+                       :       slashes(name) < 3 && slashes(Dev.name) > 3 ? "\n"
+                               "    The kernel was compiled without DEVFS, but the '" DEV_DISK_DIR "' directory structure\n"
+                               "        implements the DEVFS filesystem."
+                       :
+                               ""
+                               );
+               warned++;
+           }
+           else {
+               warn("Name change: '%s' -> '%s'", name, Dev.name);
+           }
+           name = Dev.name;
+           if (Dev.delete) {
+               warn("'" DEV_DISK_DIR "' directory structure is incomplete; device (%d, %d) is missing.",
+                               major, minor);
+               cache_add(name, device);
+           }
+       }
+       else cache_add(name, device);
+               
+       mask = has_partitions(device);
+       dev = device & mask;    /* dev is the master device */
+       ipart = device & P_MASK(device); /* ipart is the partition number */
+       
+#if 1
+       for (walk=disktab; walk; walk=walk->next) {
+           if (walk->device == dev) {
+               if (walk->heads == 0 /* inaccessible */) {
+                   if (ipart==0 && !identify)
+                       warn("bypassing VolumeID scan of drive flagged INACCESSIBLE:  %s", name);
+                   ipart = -1; /* causes skip below */
+               }
+               break;
+           }
+       }
+#endif
+       if (mask && ipart>0) {
+           int found;
+           int serial;
+          
+           for (found=i=0; i<ndevs && !found; i++) {
+               if (dev==vm[i].device) found = i+1;
+           }
+           if (!found) {
+               DEVICE Dev2;
+               serial = volid_get_set(dev, 0, ID_GET);
+
+#if 0
+/* take care of uninitialized Volume IDs with no fanfare */
+               if (serial==0) {
+                   serial = volid_get_set(dev, new_serial(dev), ID_SET);
+               }
+#endif
+#if BETA_TEST
+               if (verbose>=3) printf("**ndevs=%d\n", ndevs);
+#endif
+               if (ndevs>=MAX_DEVICES) {
+                   die("More than %d hard disks are listed in '" PARTITIONS "'.\n"
+                       "    Disks beyond the %dth must be marked:\n"
+                       "        disk=" DEV_DISK_DIR "/XXXX  inaccessible\n"
+                       "    in the configuration file (" DFL_CONFIG ").\n"
+                       , MAX_DEVICES, MAX_DEVICES);
+               }
+               else
+               {
+                   GEOMETRY geo;
+                   
+                   dev_open(&Dev2,dev,O_BYPASS);
+
+                   vm[ndevs].device = dev;
+
+                   vm[ndevs].sort = SORT(dev);
+                   
+                   vm[ndevs].vol_id.kernel = serial;
+                   
+                   vm[ndevs].name = stralloc(Dev2.name);
+
+                   if (verbose >= 4)
+                       printf("pf:  dev=%04X  id=%08X  name=%s\n", dev, (int)serial, Dev2.name);
+
+                   for (walk = disktab; walk; walk = walk->next) {
+                       if (walk->device == dev) {
+                           bios = walk->bios;
+                           vm[ndevs].dt = walk;        /* record disktab link */
+                           if (bios >= 0x80 && bios <= DEV_MASK) {
+                               vm[ndevs].bios.actual =
+                                       vm[ndevs].bios.user = bios;
+                               bios &= 0x7F;
+                               if (codes & (1L<<bios)) {
+                                   i = ndevs-1;
+                                   bios += 0x80;
+                                   while (vm[i].bios.user != bios) i--;
+                                   die("Disks '%s' and '%s' are both assigned 'bios=0x%02X'",
+                                               vm[ndevs].name, vm[i].name, bios);
+                               }
+                               codes |= 1L << bios;    /* mark BIOS code in use */
+                           } 
+                           else if (bios != -1)
+                               die("Hard disk '%s' bios= specification out of the range [0x80..0x%02X]", Dev2.name, DEV_MASK);
+
+                           break;
+                       }
+                   }
+
+                   dev_close(&Dev2);
+
+                   geo_query_dev(&geo, dev,
+                             MAJOR(dev)!=MAJOR_LOOP
+#ifdef LCF_ATARAID
+                               && MAJOR(dev)!=MAJOR_DM
+#endif
+                                               );
+
+                   vm[ndevs].bios.probe = bios_device(&geo, dev);
+
+                   if (serial_valid(serial, DEV_MASK)) {
+                       for (i=0; i<ndevs; i++) {
+                           if (vm[i].vol_id.kernel==serial) {
+                               duplicate++;
+                               vm[i].flag |= DUPLICATE;
+                               vm[ndevs].flag |= DUPLICATE;    /* mark both of them */
+                           } /* if */
+                       } /* for */
+                   }
+                   else {
+                       vm[ndevs].flag |= INVALID;
+                       invalid++;
+                   }
+                   found = ++ndevs;
+               } /* if (open, lseek, read ) */
+                               
+           } /* if (!found)  */
+
+           if (ipart>0 && ipart<=PART_MAX) {
+               found--;
+               if (part_nowrite(name) & PTW_NTFS) {
+                   vm[found].flag |= NTCAUTION;
+                   vm[found].nt[ipart-1] = NTCAUTION;
+                   ntcaution++;
+                   if (verbose>=4) printf("NT partition: %s %d %s\n",
+                                       vm[found].name, ipart, name);
+               }
+           }
+
+       } /* if (mask && (device & P_MASK(device)) ) */
+
+    } /* while (!feof())  */
+   
+    if (line) free(line);
+    fclose(pp_fd);
+
+
+
+       if (verbose>=5) {
+           int i;
+           for (i=0; i<ndevs; i++)
+               printf("  %04X  %08X  %s\n", vm[i].device, vm[i].vol_id.kernel, vm[i].name);
+       }
+
+    if (verbose>=2) printf("pf_hard_disk_scan: ndevs=%d\n", ndevs);
+
+/* now sort the volumes into canonical order */
+  {
+       int i,j,k;
+       
+       for (j=ndevs-1; j>0; j--)
+       for (i=0; i<j; i++)
+       if (vm[i].sort > vm[i+1].sort) {
+           struct VolumeMgmt temp;
+           temp = vm[i];       
+           vm[i] = vm[i+1];
+           vm[i+1] = temp;
+       }
+
+/* now automatically treat MDP-RAID devices as inaccessible */
+    for (k=0; k<ndevs; k++) {
+#ifdef LCF_MDPRAID
+      if (MAJOR(vm[k].device) == MAJOR_MDP  ||
+          MAJOR(vm[k].device) == MAJOR_EMD   ) {
+
+        if (verbose>=2) printf("MDP-RAID detected,   k=%d\n", k);
+       if (cfg_get_flag(cf_options, "noraid") ) {
+           raidcaution = 1;
+           warn("RAID controller present, with \"noraid\" keyword used.\n"
+               "    Underlying drives individually must be marked INACCESSIBLE." );
+       } else {
+           for (j=0; j<ndevs; j++) {
+               if (j==k) break;        /* skip ourselves */
+
+               if ((i=is_mdp(&vm[j], &vm[k]))<0) {
+                   if (!identify) warn("(MDP-RAID driver) the kernel does not support underlying\n"
+                       "    device inquiries.  Each underlying drive of  %s  must\n"
+                       "    individually be marked INACCESSIBLE.", vm[k].name
+                       );
+                   j=ndevs;    /* terminate loop */
+               }
+               else if (i) {
+                   if (!vm[j].dt) {
+                       walk = alloc_t(DT_ENTRY);
+                       walk->device = vm[j].device;
+                       walk->cylinders = walk->heads = walk->sectors = walk->start = -1;
+                       walk->next = disktab;
+                       vm[j].dt = disktab = walk;
+#if BETA_TEST
+                       if (verbose >= 4) printf("Allocated DT entry for device %04X  ptr=%08lx\n", vm[j].device, (long)walk);
+#endif
+                   }
+
+                   if (vm[j].dt->heads != 0) {
+                       vm[j].dt->heads = 0;
+                       warn("(MDP-RAID) underlying device flagged INACCESSIBLE: %s",
+                               vm[j].name);
+                   }
+                   --ndevs;
+                   warn("bypassing VolumeID check of underlying MDP-RAID drive:\n"
+                       "\t%04X  %08X  %s",
+                               vm[j].device, vm[j].vol_id.kernel, vm[j].name);
+                   for (i=j; i<ndevs; i++) vm[i] = vm[i+1];
+                   if (j < k) k--;
+                   j--;
+               }
+           } /* for j   ... */
+       }
+      }
+#else
+      if (MAJOR(vm[k].device) == MAJOR_EMD  ||
+          MAJOR(vm[k].device) == MAJOR_MDP   ) {
+          raidcaution = 1;
+          warn("MDP-RAID controller present; underlying drives individually\n"
+               "    must be marked INACCESSIBLE." );
+#if BETA_TEST
+{
+       int mdp_fd;
+       DEVICE dev;
+
+       if ((mdp_fd=dev_open(&dev, vm[k].device, O_NOACCESS) ) < 0)
+           die("Unable to open %s",vm[k].name);
+
+       dev_close(&dev);
+}
+#endif
+      }
+#endif
+#ifdef LCF_ATARAID
+      if ( MAJOR(vm[k].device) == MAJOR_DM ) {
+          if (verbose>=2) printf("ATA-RAID detected,   k=%d\n", k);
+          raidcaution = 1;
+          warn("ATA-RAID controller present;\n"
+              "    Underlying drives individually must be marked INACCESSIBLE." );
+      }
+#endif
+    } /* for (k ... */
+  } /* end sort */
+
+       if (verbose>=3) {
+           for (i=0; i<ndevs; i++)
+               printf("  %04X  %08X  %s\n", vm[i].device, vm[i].vol_id.kernel, vm[i].name);
+           printf("Resolve invalid VolumeIDs\n");
+       }
+
+/* now go thru and resolve any invalid VolumeIDs */
+
+    if (invalid)
+    for (i=0; i<ndevs; i++)
+    if (vm[i].flag & INVALID) {
+       if (ndevs>1) winnt_check(&vm[i], 1);
+       else if (vm[i].flag & NTCAUTION) break;
+       
+       dev = vm[i].device;
+       vm[i].vol_id.kernel = volid_get_set(dev, new_serial(dev), ID_SET);
+       vm[i].flag &= ~INVALID;
+    }
+
+       if (verbose>=3)
+           printf("Resolve duplicate VolumeIDs\n");
+    
+/* now check for duplicates */
+
+    while (duplicate) {                /* loop until there are none */
+       int j, k;
+       
+       if (raidcaution) {
+           raidcaution = 0;    /* print comment only once */
+           warn("Duplicated VolumeID's will be overwritten;\n"
+               "   With RAID present, this may defeat all boot redundancy.\n"
+               "   Underlying RAID-1 drives should be marked INACCESSIBLE.\n"
+               "   Check 'man lilo.conf' under 'disk=', 'inaccessible' option."
+               );
+       }
+       duplicate = 0;
+       for (j=ndevs-1; j>0; j--) {
+           for (i=0; i<j; i++) {
+               if (vm[i].vol_id.kernel == vm[j].vol_id.kernel) {
+                   if (vm[i].flag & vm[j].flag & NTCAUTION) {
+                       if (!winnt_check(&vm[j], 0)) k = j;
+                       else winnt_check(&vm[k=i], 1);
+                   }
+                   else if (vm[i].flag & NTCAUTION) k = j;
+                   else if (vm[j].flag & NTCAUTION) k = i;
+                   else k = j;
+                   
+                   dev = vm[k].device;
+                   vm[k].vol_id.kernel = volid_get_set(dev, new_serial(dev), ID_SET);
+                   duplicate++;
+               }
+           }
+       }
+    } /* while (duplicate) */
+
+
+
+       if (verbose>=2) {
+           for (i=0; i<ndevs; i++)
+               printf("  %04X  %08X  %s\n", vm[i].device, vm[i].vol_id.kernel, vm[i].name);
+       }
+
+
+
+    if (verbose>=2) printf("device codes (user assigned pf) = %lX\n", codes);
+
+/* mark those BIOS codes that are already used in the disk=/bios= table */
+
+    for (walk=disktab; walk; walk=walk->next) {
+       if (walk->bios >= 0x80) {   /* eliminate -1 and floppies */
+           if (MAJOR(walk->device)==MAJOR_MD) continue;
+           bios = walk->bios & 0x7F;
+           if (bios >= 8*sizeof(codes) || bios >= MAX_BIOS_DEVICES)
+               die("BIOS code %02X is too big (device %04X)", bios+0x80, walk->device);
+           if (codes & (1L<<bios)) {
+               int j = -1;
+               int k = -1;
+
+               for (i=0; i<ndevs; i++) {
+                   if (vm[i].device == walk->device) j = i;
+                   else if (vm[i].bios.user == bios+0x80) k = i;
+               }
+#if BETA_TEST
+               if (verbose>=3) printf("J=%d  K=%d\n", j, k);
+#endif
+               if (j<0 && k>=0) {
+                   die("Devices %04X and %04X are assigned to BIOS 0x%02X",
+                       vm[k].device, walk->device, bios+0x80);
+               }
+           }
+           codes |= 1L << bios;        
+       }
+    }
+
+    if (verbose>=2) printf("device codes (user assigned) = %lX\n", codes);
+
+    for (i=0; i<ndevs; i++) {
+       bios = vm[i].bios.probe;
+       if (bios >= 0x80) {
+           if (vm[i].bios.actual < 0x80 && !(codes & (1L<<(bios&0x7F)))) {
+               vm[i].bios.actual = bios;
+               bios &= 0x7F;
+               codes |= 1L << bios;
+           }
+       }
+    }
+
+    if (verbose>=2) printf("device codes (BIOS assigned) = %lX\n", codes);
+
+    for (bios=i=0; i<ndevs; i++) {
+       int j;
+       
+       
+       if (vm[i].bios.actual < 0x80) {
+           while ( codes & (1L<<bios) ) bios++;
+           if (bios < MAX_BIOS_DEVICES) {
+               codes |= 1L<<bios;
+               vm[i].bios.actual = 0x80+bios;
+               if (verbose>=3) printf("Filling in '%s' = 0x%02X\n", vm[i].name, bios+0x80);
+           }
+           else vm[i].bios.actual = -1;
+       }
+       if (!vm[i].dt) {
+           walk = alloc_t(DT_ENTRY);
+           walk->device = vm[i].device;
+           walk->cylinders = walk->bios = walk->heads = walk->sectors = walk->start = -1;
+           walk->next = disktab;
+           vm[i].dt = disktab = walk;
+#if BETA_TEST
+           if (verbose >= 4) printf("Allocated DT entry for device %04X  ptr=%08lx\n", vm[i].device, (long)walk);
+#endif
+       }
+       j = vm[i].dt->bios = vm[i].bios.actual;
+       j &= 0x7F;
+
+       if (j < MAX_BIOS_DEVICES) {     
+           serial_no[j] = vm[i].vol_id.kernel;
+           device_code[j] = vm[i].device;
+#if BETA_TEST
+           if (verbose >= 5) {
+               printf("Generated: %02X  %04X  %08X\n", j+0x80, device_code[j], (int)serial_no[j]);
+           }
+#endif
+       }
+       else {
+           vm[i].dt->heads = 0;        /* mark inaccessible */
+           {
+               static int i=0;
+               if (!(i++)) warn("Internal implementation restriction. Boot may occur from the first\n"
+                   "    %d disks only. Disks beyond the %dth will be flagged INACCESSIBLE."
+                   , MAX_BIOS_DEVICES, MAX_BIOS_DEVICES);
+               warn("'disk=%s  inaccessible' is being assumed.  (%04X)",
+               vm[i].name, vm[i].device);
+           }
+       }
+       
+       inited = 1;
+    }
+
+    if (verbose>=2) printf("device codes (canonical) = %lX\n", codes);
+
+    for (bios=8*sizeof(codes)-1; !(codes&(1L<<bios)) && bios>=0; ) bios--;
+
+    if (bios > ndevs)
+       warn("BIOS device code 0x%02X is used (>0x%02X).  It indicates more disks\n"
+                       "  than those represented in '/proc/partitions' having actual partitions.\n"
+                       "  Booting results may be unpredictable.", bios+0x80, ndevs+0x80-1);
+
+
+
+    return ret;
+}
+
diff --git a/src/device.h b/src/device.h
new file mode 100644 (file)
index 0000000..a9623a2
--- /dev/null
@@ -0,0 +1,79 @@
+/* device.h  -  Device access
+
+Copyright 1992-1996 Werner Almesberger.
+Copyright 1999-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+
+#ifndef DEVICE_H
+#define DEVICE_H
+
+#include <sys/stat.h>
+
+
+typedef struct {
+    int fd;
+    struct stat st;
+    char *name;
+    int delete;
+} DEVICE;
+
+
+int dev_open(DEVICE *dev,int number,int flags);
+
+/* Searches /dev for a block device with the specified number. If no device
+   can be found, a temporary device is created. The device is opened with
+   the specified access mode and the file descriptor is returned. If flags
+   are -1, the device is not opened. */
+
+
+
+void dev_close(DEVICE *dev);
+
+/* Closes a device that has previously been opened by dev_open. If the device
+   had to be created, it is removed now. */
+
+
+
+void preload_dev_cache(void);
+
+/* Preloads the device number to name cache. */
+
+
+
+int make_backup(char *backup_file, int force_backup, BOOT_SECTOR *bsect,
+       unsigned int device, char *id);
+
+/* make a backup, returning the timestamp of the backup file */
+
+
+
+unsigned int register_bios(int bios, int device);
+
+/* registers the bios to device association by serial number */
+
+
+void dump_serial_nos(void);
+
+/* debugging dump of the Volume Serial number table */
+
+
+int serial_valid(unsigned int serial, int disk_bios);
+/* determine validity of serial number; liberally if disk_bios==0x80 */
+
+
+int pf_hard_disk_scan(void);
+/* scan /proc/partitions for devices & partitions */
+
+int yesno(char *prompt, int expect);
+/* prompt the user for a yes/no response */
+
+int new_serial(int device);
+/* generate a new volumeID */
+
+#endif
diff --git a/src/disk.S b/src/disk.S
new file mode 100644 (file)
index 0000000..c0c7a4b
--- /dev/null
@@ -0,0 +1,1012 @@
+/*
+; disk.S -- inquire of BIOS and display disk parameters
+;
+Copyright 1999-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+#define DEBUG 0
+#define DELL_DIRTY_HACK
+
+
+SYSSEG =  0x1000       ; DEF_SYSSEG
+SETUPSEG = 0x9020      ; DEF_SETUPSEG
+
+
+               .text
+#if 1
+.globl _main
+_main:
+#endif
+               .globl  zero
+zero:
+
+; we want this to look like a bootable kernel image
+; so we include the following header
+;
+               jmp     begin
+               .ascii  "HdrS"          ; Signature for Setup header
+               .word   0x0201          ; header format version number
+               .word   0,0             ; realmode switch, SETUPSEG
+               .word   SYSSEG          ; SYSSEG -- load at 1000:0000
+               .word   id_string
+               .byte   0               ; type of loader
+               .byte   0               ; flags 0=load low
+               .word   0x200           ; move size
+               dd      0x1000          ; load us here
+               dd      0               ; ramdisk image
+               .word   bs_helper,SETUPSEG      ; kludge???
+               .word   modelist+1024   ; heap end pointer
+;----------end of header------------
+               
+begin:
+                mov     ax,cs
+               cli                     ;make purists happy
+                mov     ss,ax
+                mov     sp,#0x7FFE
+               sti                     ; ***
+                call    start           ;do not separate from the instruction below
+start:          pop     bx              ;this MUST immediately follow the 'call'
+                sub     bx,#start-zero
+                lea     bp,zero
+                sub     bx,bp           ;BX=100h under DOS, BX=0h under BIOS
+                mov     cl,#4
+                sar     bx,cl
+                add     ax,bx
+                mov     ds,ax
+               mov     dx_save,dx      ;save DX we received
+                cld
+#ifdef DELL_DIRTY_HACK
+               mov     ah,#15          ; get video mode
+               int     0x10
+               cbw
+               int     0x10            ; set video mode
+#endif
+                call    say
+                .ascii "\n>>>> Disk Detection and Parameter Display <<<<\n"
+                .ascii  "Version 1.6, Copyright (C) 1999-2005  John Coffman.\n"
+                .ascii  "Re-use and redistribution rights set forth"
+                .ascii  " in the file \"COPYING\".\n\n"
+               .byte   0
+
+                cmp     magic,#0xAA55
+                je      sane            ;check that we got the DS set right
+                call    say
+                .ascii "\n\nCS/DS sanity check failed.\n"
+               .byte   0
+hlti:           hlt
+                jmp      hlti
+;;;    nop     ;spacer
+
+magic:          .word      0xAA55
+dx_save:       .word   0
+
+sane:
+#if 0
+                xor     ax,ax
+                mov     dl,al
+                int     0x13
+                mov     ah,#8
+                int     0x13
+#endif              
+                smsw    ax
+                test    al,#1
+                jnz     v86mode
+                br      realmode
+v86mode:
+                call    say
+                .ascii  "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+                .ascii  "!!! ***  Warning:  DOS is not running in REAL mode  *** !!!\n"
+                .ascii  "!!! ***     Reported results may not be accurate    *** !!!\n"
+                .ascii "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+               .byte   0
+
+               call    pause
+
+realmode:
+                call    say
+                .ascii "There "
+               .byte   0
+                int     0x11            ; get equipment configuration
+                test    al,#1
+                mov     ah,#-1
+                jz      noflop
+                shl     ax,1
+                shl     ax,1
+                and     ah,#3
+                jz      flop1
+noflop:         call    say
+                .ascii  "are "
+               .byte   0
+                jmp     flop2
+flop1:          call    say
+                .ascii  "is "
+               .byte   0
+flop2:          inc     ah
+                mov     nflop,ah
+                mov     al,ah
+                add     al,#0x30
+                call    putc
+                call    say
+                .ascii  " floppy drive"
+               .byte   0
+                mov     al,#'s
+                dec     ah
+                jz      flop3
+                call    putc
+flop3:          inc     ah
+                call    say
+                .ascii  " with BIOS support.\n"
+               .byte   0
+
+; now probe for floppy drives
+
+                mov     dl,#-1
+
+fprobe:         mov     ah,#8
+                inc     dl
+                push    dx
+                xor     cx,cx
+                int     0x13
+                pop     dx
+                jc      fstop
+                or      cx,cx
+                jnz     fprobe
+
+fstop:
+                mov     ah,nflop
+                cmp     ah,dl
+                je      fdisplay
+                call    say
+                .ascii  "But probing has found "
+               .byte   0
+                mov     al,dl
+                add     al,#'0
+                call    putc
+                call    say
+                .ascii  "!!!\n"
+               .byte   0
+                cmp     ah,dl
+                jae     fdisplay
+                xchg    ah,dl
+
+fdisplay:
+                mov     dl,#0            ;start with drive 0x00
+                xor     cx,cx
+                mov     cl,ah
+                jcxz    floppy1
+
+floppy:         call    drive
+                inc     dl
+                loop    floppy
+floppy1:
+                mov     al,#10
+                call    putc
+
+               call    say
+               .ascii  "There is "
+               .byte   0
+               int     0x12            ;get amount of low memory
+;;;      mov ax,#640 ;debug
+               xor     dx,dx
+               call    print
+               call    say
+               .ascii  "K of low memory"
+               .byte   0
+               mov     bx,#640
+               sub     bx,ax
+               jnz     ebda1
+               call    say
+               .ascii  " with no EBDA."
+               .byte   0
+               br      ebda2
+
+ebda1:         push    ax
+               mov     ax,bx
+               xor     bx,bx
+               call    say
+               .ascii  ".    EBDA size = "
+               .byte   0
+               call    dec3
+               call    say
+               .ascii  "K   EBDA starts at 0x"
+               .byte   0
+               pop     ax
+               mov     cl,#6
+               shl     ax,cl
+               call    wout
+               call    say
+               .ascii  "0"
+               .byte   0
+ebda2:
+               call    say
+               .ascii  "\n"
+               .byte   0
+
+; post-floppy pause
+               call    pause
+
+                mov     ah,#0
+                mov     dl,#0x80
+                int     0x13
+                mov     ah,#8
+                int     0x13
+                mov     ah,#0
+                jc      nohard
+                mov     ah,dl
+nohard:         mov     nhard,ah
+                call    say
+                .ascii  "There "
+               .byte   0
+                dec     ah
+                jz      hard1
+                call    say
+                .ascii  "are "
+               .byte   0
+                jmp     hard2
+hard1:          call    say
+                .ascii  "is "
+               .byte   0
+hard2:          inc     ah
+                mov     al,ah
+                add     al,#'0
+                call    putc
+                call    say
+                .ascii  " hard drive"
+               .byte   0
+                mov     al,#'s
+                dec     ah
+                jz      hard3
+                call    putc
+hard3:          inc     ah
+                call    say
+                .ascii  " with BIOS support.\n"
+               .byte   0
+
+; probe for hard drives
+
+                mov     dl,#0x80-1
+
+hprobe:         mov     ah,#8
+                inc     dl
+                push    dx
+                xor     cx,cx
+                int     0x13
+                pop     dx
+                jc      hstop
+                or      cx,cx
+                jnz     hprobe
+
+hstop:
+                and     dl,#0x7f
+                mov     ah,nhard
+                cmp     ah,dl
+                je      hdisplay
+                call    say
+                .ascii  "But probing has found "
+               .byte   0
+                mov     al,dl
+                add     al,#'0
+                call    putc
+                call    say
+                .ascii  "!!!\n"
+               .byte   0
+                cmp     ah,dl
+                jae     hdisplay
+                xchg    ah,dl
+
+hdisplay:
+
+
+
+
+                mov     dl,#0x80         ;start with drive 0x80
+                xor     cx,cx
+                mov     cl,ah
+                jcxz    hdd1
+hard:           call    drive
+                inc     dl
+                loop    hard
+hdd1:
+                test    byte ptr bigflag,#0xFF
+                jz      hdd2
+                br      big
+hdd2:           test    byte ptr bigcyl,#0xFF
+                jz      hdd3
+                br      big2
+hdd3:                
+                call    say
+                .ascii  "\nEither your BIOS does not support EDD"
+               .ascii  " packet calls, or you have no large\n"
+                .ascii  "disks.  You do not need to use LILO with"
+               .ascii  " the 'lba32' global option (or '-L'\n"
+                .ascii  "switch).\n"
+               .byte   0
+                br     exit
+
+
+big:
+                call    say
+                .ascii  "\nYou have "
+               .byte   0
+                cmp     byte bigflag,#1
+                je      noS
+                call    say
+                .ascii  "disks"
+               .byte   0
+                jmp     goOn
+noS:            call    say
+                .ascii  "a disk"
+               .byte   0
+goOn:           call    say
+                .ascii  " bigger than 8.4Gb"
+               .byte   0
+big1c:          call    say
+                .ascii  " with Enhanced BIOS support.\n"
+                .ascii  "Using LILO with the 'lba32' global option"
+               .ascii  " (or '-L' switch) is recommended.\n"
+               .byte   0
+                br     exit
+
+big2:
+                call    say
+                .ascii  "\nYou have "
+               .byte   0
+                cmp     byte bigcyl,#1
+                je      big2a
+                call    say
+                .ascii  "disks"
+               .byte   0
+                jmp     big2b
+big2a:          call    say
+                .ascii  "a disk"
+               .byte   0
+big2b:          call    say
+                .ascii  " with more than 1023 cylinders"
+               .byte   0
+                br      big1c
+
+
+
+nflop:          .byte      0
+nhard:          .byte      0
+bigflag:        .byte      0
+bigcyl:         db      0
+nlimit:         dd     1024*255*63, 0
+
+
+; inquire whether EDD drive BIOS calls are valid
+; Carry clear says NO, Carry set says YES, CX=device bits &
+; SI = pointer to dparam table
+
+inqedd:         push    ax
+                push    bx
+                push    dx
+                push    si
+
+                mov     ah,#0x41
+                mov     bx,#0x55aa
+                int     0x13
+                jc      edd7
+                cmp     bx,#0xaa55
+                jne     edd7
+                test    cl,#7
+                stc
+                jz      edd8
+                lea     si,dparam
+                mov     word (si),#dlth
+;;;    nop     ;spacer
+;;;    nop     ;spacer
+                mov     dh,ah           ;save version number
+                mov     ah,#0x48         ;get drive parameters
+                int     0x13
+                jc      edd7
+                stc
+                pop     ax              ;discard saved SI
+                mov     (si+1),dh       ;save version info
+                jmp     edd9            ;return SI, too
+             
+
+edd7:           xor     cx,cx           ;carry is clear
+edd8:           pop     si
+edd9:           pop     dx
+                pop     bx
+                pop     ax
+                ret
+
+
+; pause for the user to look at the screen
+
+pause:         call    say
+               .ascii  "Hit any key to continue..."
+               .byte   0
+               mov     ah,#0
+               int     0x16
+               call    say
+               .ascii  "\r                           \n"
+               .byte   0
+               ret
+
+; print out the IBM BIOS drive parameters for the drive in DL
+
+drive:          push    bp
+                push    ax
+                push    bx
+                push    cx
+                push    es
+                push    di
+                push    si
+                push    dx
+
+                call    say
+                .ascii  "Drive 0x"
+               .byte   0
+                mov     al,dl
+                call    bout
+                call    say
+                .ascii  "   Cyl:Head:Sec = "
+               .byte   0
+
+                mov     ah,#8
+                int     0x13
+#if DEBUG
+               mov     cx,#0xFAFF
+               mov     dh,#0xFF                ; 0xFE is the max.
+#endif
+                push    cx
+                push    dx
+                rol     cl,1
+                mov     di,#1000
+                rol     cl,1
+                xor     bh,bh
+                and     cl,#3
+                xchg    ch,cl
+                inc     cx
+                mov     ax,cx
+                xor     dx,dx
+                div     di
+                mov     bp,cx
+                or      ax,ax
+                jz      cyl2
+                call    say
+                .ascii  "1"
+               .byte   0
+                mov     bh,#0x80
+cyl2:           xchg    ax,dx
+                call    dec3
+                call    punct
+                pop     dx
+                xor     ax,ax
+                mov     al,dh
+                xor     bh,bh
+                inc     ax
+                call    dec3
+                mov     dx,ax
+                call    punct
+;;;            pop     cx
+;;;            and     cl,#0x3F
+;;;            mov     al,cl
+               pop     ax
+#if 0
+; sectors = [1..63]
+               and     ax,#0x3F
+#else
+;; version 1.6
+;; avoid Davide bug:  Sectors == 0
+               dec     ax
+               and     ax,#0x3F
+               inc     ax      ; now sectors = [1..64]
+;; version 1.6 end
+#endif
+                call    dec3
+                call    say
+                .ascii  " ("
+               .byte   0
+;;;            mul     dl
+               mul     dx
+                mul     bp
+                push    ds
+                pop     es
+                lea     di,ac0
+                push    di
+                stosw
+                mov     ax,dx
+                stosw
+                xor     ax,ax
+                stosw
+                stosw
+                pop     si
+                call    dprint
+                call    say
+                .ascii  " sectors)  -->  "
+               .byte   0
+
+                call    sizeit
+
+                call    say
+                .byte   10,0
+
+                pop     dx
+                push    dx
+                call    inqedd
+                jc      xdd1
+                br      xdd4
+xdd1:
+                call    say
+                .ascii  "   EDD rev "
+               .byte   0
+                mov     al,(si+1)
+                mov     cl,#4
+                mov     ah,al
+                shr     al,cl
+                add     al,#'0
+                call    putc
+                mov     al,#'.
+                call    putc
+                mov     al,ah
+                and     al,#0x0F
+                add     al,#'0
+                call    putc
+
+                call    say
+                .ascii  " geometry = "
+               .byte   0
+                test    byte (si+2),#2
+                jz      xdd2
+                mov     ax,(si+4)
+                mov     dx,(si+6)
+                or      dx,dx
+                jnz     xdd1a
+                cmp     ax,#1024
+                jb      xdd1b
+xdd1a:          inc     byte (bigcyl)
+xdd1b:
+                call    print
+                call    punct
+                mov     ax,(si+8)
+                mov     dx,(si+10)
+                call    print
+                call    punct
+                mov     ax,(si+12)
+                mov     dx,(si+14)
+                call    print
+                call    say
+                .ascii  " "
+               .byte   0
+xdd2:
+                call    say
+                .ascii  "("
+               .byte   0
+                lea     si,(si+16)
+                call    dprint
+                call    say
+                .ascii  " sectors)  -->  "
+               .byte   0
+                mov     ax,(si+6)
+                cmp     ax,nlimit+6
+                jb      xdd3
+                ja      xdd2a
+                mov     ax,(si+4)
+                cmp     ax,nlimit+4
+                jb      xdd3
+                ja      xdd2a
+                mov     ax,(si+2)
+                cmp     ax,nlimit+2
+                jb      xdd3
+                ja      xdd2a
+                mov     ax,(si)
+                cmp     ax,nlimit
+                jb      xdd3
+xdd2a:          inc     byte bigflag
+xdd3:
+                mov     dl,#1
+                call    sizeit
+                call    say
+                .byte   10,0
+
+xdd4:
+
+                pop     dx
+                pop     si
+                pop     di
+                pop     es
+                pop     cx
+                pop     bx
+                pop     ax
+                pop     bp
+                ret
+
+punct:          mov     al,#':
+                call    putc
+                ret
+
+chars:          .ascii  " KMGTxyz"
+
+sizeit:
+                push    ax
+                push    bx
+                push    cx
+                push    dx
+                push    si      
+                push    es
+                push    di
+                
+
+                lea     bx,chars-1
+                mov     di,si
+                push    ds
+                pop     es
+                mov     ax,#512
+                or      dx,dx
+                jz      dpr5            ;handle small disks
+                call    intmul
+                jmp     dpr6
+dpr5:           mov     ax,#2
+                call    intdiv
+                inc     bx
+
+dpr6:           mov     ax,#1000
+                lea     di,ac1
+dpr7:           lea     bx,(bx+1)
+                mov     cx,dx
+                call    intdiv
+                xchg    si,di
+                jnz     dpr7
+
+                mov     si,bx
+                mov     ax,dx
+                xor     bx,bx
+                call    dec3
+                cmp     byte ptr (si),#'K
+                je      dpr8
+                mov     al,#'.
+                call    putc
+                mov     ax,cx
+#if 1
+                mov     bx,#0x800a
+               cmp     ax,#995
+               jae     no_add
+                add     ax,#5
+no_add:
+                div     bl
+                xor     ah,ah
+                div     bl
+                add     al,#'0
+                call    putc
+                xchg    al,ah
+#else
+                mov     bx,#0x8000+100
+                add     ax,#50
+                div     bl
+#endif
+                add     al,#'0
+                call    putc
+dpr8:           mov     al,(si)
+                call    putc
+
+                pop     di
+                pop     es
+                pop     si
+                pop     dx
+                pop     cx
+                pop     bx
+                pop     ax
+                ret
+; print the decimal double word number in DX:AX
+;
+print:          push    ds
+                push    si
+                xor     si,si
+                push    si
+                push    si
+                push    dx
+                push    ax
+                push    ss
+                pop     ds
+                mov     si,sp
+                call    dprint
+                lea     sp,(si+8)
+                pop     si
+                pop     ds
+                ret
+
+
+; print the decimal quad-word number in [DS:SI]
+;
+dprint:         push    ax
+                push    bx
+                push    dx
+                push    es
+                push    di
+                push    ds
+                push    si
+                sub     sp,#8
+                mov     di,sp
+                push    ss
+                pop     es
+                xor     bx,bx
+                mov     ax,#1000
+
+dpr1:           inc     bx
+                call    intdiv
+                mov     si,di
+                push    es
+                pop     ds
+                push    dx
+                jnz     dpr1
+                jmp     dpr3
+
+dpr2:           mov     al,#',
+                call    putc
+dpr3:           pop     ax
+                call    dec3
+                mov     bh,#0x80
+                dec     bl
+                jnz     dpr2
+                
+                lea     sp,(di+8)
+                pop     si
+                pop     ds
+                pop     di
+                pop     es
+                pop     dx
+                pop     bx
+                pop     ax
+                ret
+
+
+; multiply the number in the ac pointed at by [DS:SI] by the AX, putting
+; the result in the ac pointed to by [ES:SI].  Return overflow in AX.
+; SI and DI may be the same
+
+intmul:
+                push    bp
+                push    si
+                push    di
+                push    bx
+                push    cx
+                push    dx
+
+                mov     cx,#4
+                mov     bp,ax
+                xor     dx,dx
+im4:            mov     bx,dx
+                lodsw
+                mul     bp
+                add     ax,bx
+                adc     dx,#0
+;;;    nop     ;spacer
+                stosw
+                loop    im4
+
+                mov     ax,dx
+                pop     dx
+                pop     cx
+                pop     bx
+                pop     di
+                pop     si
+                pop     bp
+                ret
+                
+; divide the ac pointed at by [DS:SI] by the AX, producing a result
+; in [ES:DI], and a remainder in DX; the Z flag reflects the quotient
+; DI may equal SI for in-place division
+
+intdiv:         push    bx
+                push    cx
+                push    bp
+                push    di
+                push    si
+                
+                mov     cx,#4
+                mov     bx,cx
+                dec     bx
+                add     bx,bx
+                lea     si,(si+bx)
+                lea     di,(di+bx)
+                xor     dx,dx
+                xor     bp,bp
+                std
+                mov     bx,ax
+id2:            lodsw
+                div     bx
+                or      bp,ax           ;sets the Z flag
+                stosw
+                loop    id2
+                cld
+                mov     ax,bx
+
+                pop     si
+                pop     di
+                pop     bp
+                pop     cx
+                pop     bx
+                ret
+
+; write the number < 1000 in AX as 3 decimal digits
+; BH flags whether leading zeroes are printed (0x80=yes, 0=no)
+
+dec3:           push    bx
+                push    ax
+                push    cx
+                mov     cx,#2
+                mov     bl,#100
+dec32:          div     bl
+                xor     al,bh
+                jz      dec36
+                xor     al,bh
+                mov     bh,#0x80
+dec34:          add     al,#'0
+                call    putc
+                mov     bh,#0x80
+dec36:          mov     al,ah
+                mov     ah,#0
+                mov     bl,#10
+                dec     cx
+                jg      dec32
+                jz      dec34
+                pop     cx
+                pop     ax
+                pop     bx          
+                ret
+
+; write the <nul> terminated string which follows the call
+; no registers altered
+
+say:            push    bp
+                mov     bp,sp
+                push    ds
+                push    si
+                push    ax
+                mov     si,(bp+2)
+                push    cs
+                pop     ds
+say1:           lodsb
+                or      al,al
+                jz      say2
+                call    putc
+                jmp     say1
+say2:           mov     (bp+2),si
+                pop     ax
+                pop     si
+                pop     ds
+                pop     bp
+                ret
+
+; write the word in AX in hex
+wout:          xchg    ah,al
+               call    bout
+               xchg    ah,al
+               call    bout
+               ret
+
+; write the byte in AL in hex
+bout:           push    ax
+                push    cx
+                push    ax
+                mov     cx,#0x204
+                shr     al,cl
+bout1:          add     al,#'0
+                cmp     al,#'9
+                jbe     bout2
+                add     al,#'A-'0-10
+bout2:          call    putc
+                dec     ch
+                jz      bout4
+                pop     ax
+                and     al,#0xF
+                jmp     bout1
+bout4:          pop     cx
+                pop     ax
+                ret
+
+
+; write the character in AL in teletype mode
+; all registers are preserved
+
+putc:           push    bx
+                push    ax
+                mov     ah,#14
+                xor     bh,bh
+                cmp     al,#10           ;test for new-line
+                jne     putc2
+                mov     al,#13           ;get <cr>
+                int     0x10
+                mov     al,#10
+putc2:          int     0x10
+                pop     ax
+                pop     bx
+                ret
+
+#define LILO_ASM
+#include "lilo.h"
+#include "read.S"
+#include "bdata.h"
+#define BD_VERBOSE
+#include "biosdata.S"
+
+exit:           mov     ax,cs
+                mov     dx,ds
+                cmp     ax,dx
+               jae     bd_test
+exit_dos:       mov     ax,#0x4c00
+                int     0x21
+
+bd_test:
+               call    pause
+                call    say
+                .ascii  "BIOS data collection test.\n"
+               .ascii  "Failure of this test will require booting all Linux\n"
+               .ascii  "kernels with the 'nobd' command-line option.\n"
+                .ascii  "Hit <ESC> to bypass, any other key to continue..."
+               .byte   0
+                mov     ah,#0
+                int     0x16
+               call    say
+               .byte   10,10,0
+               cmp     al,#0x1b        ; <ESC>
+               je      bd_test_skip
+
+#if 1
+               mov     ax,cs
+               mov     bx,#SYSSEG
+               cmp     ax,bx
+               jae     collect
+               mov     es,bx
+               mov     di,#theend-1
+               std
+               lea     cx,(di+1)
+               mov     si,di
+               rep
+                 movsb
+               mov     ss,bx
+               mov     ds,bx
+               cld
+               push    es
+               push    #collect
+               retf
+collect:
+#endif
+
+               mov     dx,dx_save              ; DX passed in on boot
+               call    io_biosdata
+
+               call    say
+               .ascii  "\nALL OKAY\n\n"
+               .byte   0
+
+bd_test_skip:
+                call    say
+                .ascii  "Remove the floppy disk from the drive.\n"
+                .ascii  "Hit any key to reboot..."
+               .byte   0
+                mov     ah,#0
+                int     0x16
+                call    say
+                .byte      10,10,10,0
+bs_helper:      int     0x19                   ;label here for kludge
+
+
+id_string:     .ascii  "Disk.Com"
+               .byte   0
+
+
+ac0:            .word      0,0,0,0
+ac1:            .word      0,0,0,0
+
+dparam:         .word      dlth
+dflags:         .word      0
+dcyl:           dd      0
+dhead:          dd      0
+dsec:           dd      0
+dsecs:          dd      0,0
+ssize:          .word   0
+dptp:           dd      0
+dlthe:
+dlth            =     dlthe-dparam
+modelist:
+
+theend:
diff --git a/src/display4.S b/src/display4.S
new file mode 100644 (file)
index 0000000..7b7244f
--- /dev/null
@@ -0,0 +1,1345 @@
+/*  display4.S is
+
+ Copyright 2001-2005 John Coffman.
+ All rights reserved.
+
+ Licensed under the terms contained in the file 'COPYING' in the 
+ source directory.
+
+*/
+;
+;      Static Name Aliases
+;
+;;        segment _TEXT PARA class=CODE
+       .text
+
+/* the following is set to 1 to test the fallback to TEXT mode */
+#define FAIL   0
+
+       .even           ; 8
+
+_bmp:   dd      0
+_tp:    dd      0
+_state: dw    -1
+_Mode:  dw      0
+_ypitch: dw     0
+_shift:        dw      0
+_mask: dd      0
+_himask: dd    0
+_VesaWindow:   dw      -1
+_seg:  dw      0
+
+
+;
+;       get a single byte in AX (zero extended)
+;       and increment the HUGE pointer _tp
+;
+;       c = *tp++;
+;
+;
+        .even          ;   8
+getbyte:
+        lodsb
+        push    ax
+        cmp     si,#1
+        sbb     ax,ax
+        and     ax,#0x1000
+       add     bp,ax
+        mov     ds,bp
+        pop     ax
+        sub     ah,ah
+        ret
+
+
+        .even          ;   4
+
+d4_getrow4:
+        pusha
+        push    ds
+
+;      rpt = -8                ; bh
+;      repeat = -10            ; bl
+;      skip = -12              ; dh
+;      lp = -4                 ; es:di
+;      c = -6
+;      npix = DX               ; cx
+;      compr = AX
+;       tp was _tp              ; ds:si -- HUGE ptr  [bp:si]
+
+       mov     di,#_line       ;lp
+        push    cs
+        pop     es
+       seg     cs
+          lds     si,[_tp]        ;
+        mov     cx,dx           ;npix
+       cmp     ax,#1           ;compr
+        mov     bp,ds           ;
+       ja      d4_I600
+        je      d4_I601
+d4_FC581:
+        call    getbyte
+        push    ax
+       sar     ax,#4
+        stosb                   ;*lp++
+        pop     ax
+       dec     cx      ;npix
+       and     al,#15  ;000fH
+        stosb                   ;*lp++
+       loop    d4_FC581
+        jmp     d4_I601
+;
+; compr == 2
+;        
+d4_FC590:
+       cmp     cx,#0   ;npix
+       jle     d4_FB591
+        call    getbyte
+       mov     bh,al           ;rpt
+       mov     bl,al           ;repeat
+       or      ax,ax
+       je      d4_L676
+       sub     cx,ax   ;npix
+        call    getbyte
+       jmp     d4_L675
+d4_FC594:
+        push    ax
+       sar     ax,#4
+        stosb                   ;*lp++
+        pop     ax
+       dec     bh      ; 2001/06/23
+       jz      d4_L676 ; 2001/06/23
+        push    ax
+       and     al,#15  ;000fH
+        stosb                   ;*lp++
+        pop     ax
+       dec     bh      ;rpt 2001/06/23
+d4_L675:
+       or      bh,bh   ;rpt
+       jne     d4_FC594
+d4_L676:
+       or      bl,bl   ;repeat
+       jne     d4_FC590
+d4_FB591:
+        jcxz    d4_I600   ;npix
+        call    getbyte
+       mov     bh,al   ;rpt
+       sub     cx,ax   ;npix
+        mov     dh,al
+       inc     dh      ; 2001/06/23
+        and     dh,#2    ;skip
+       jmp     d4_L677
+d4_FC598:
+        call    getbyte
+        push    ax
+       sar     ax,#4
+        stosb                   ;*lp++
+        pop     ax
+       dec     bh      ;rpt 2001/06/23
+       jz      d4_L678 ; 2001/06/23
+       and     al,#15  ;000fH
+        stosb                   ;*lp++
+       dec     bh      ;rpt 2001/06/23
+d4_L677:
+       cmp     bh,#0   ;rpt
+       jne     d4_FC598
+d4_L678:
+       or      dh,dh   ;skip
+       je      d4_I600
+        call    getbyte
+d4_I600:
+       mov     bl,#1   ;repeat
+       cmp     cx,#0   ;npix
+       jg      d4_L676
+        call    getbyte
+        call    getbyte
+;;;     jmp     d4_I601
+
+d4_I601:
+       seg     cs
+          mov     [_tp],si        ;
+       seg     cs
+         mov     [_tp+2],ds      ;
+        pop     ds
+        popa
+       ret     
+
+
+        .even          ;   4
+d4_char10:
+       enter   #6,#0
+        pusha
+        push    ds
+
+;      buf =  0xA000:DI
+;      cgen =  ES:SI
+;      bits =  ax on top of stack
+;      points  (bp-2)
+;      shadow  (bp-4)
+;      mask    (bp-6)
+
+;      sch     (bp+4)  (arg);  DS:BX
+;      y =     BX      (arg)
+;      x =     DX      (arg)
+;      c =     AX      (arg)
+
+        push    WORD #0
+        pop     ds
+        mov    cx,WORD [0x485] ;points
+       xor     ah,ah           ;AL is char to put out
+       mov     WORD (bp-2),cx  ;points
+       imul    ax,cx           ;leave DX alone; 386 form of instruction
+       mov     si,#268 ;010cH  ; int 0x43 -> character bitmaps
+        add    ax,WORD (si)
+        mov    es,WORD (si+2)  ;cgen
+        xchg    si,ax           ;cgen
+
+;  call pixadr -----------------------------------
+       mov     cx,dx           ;x
+       and     cx,#7           ;mask for shift
+       sar     dx,#3           ;x
+       mov     ax,#0x00FF      ;mask
+
+        imul    di,bx,#640/8   ; DI = y * _ypitch
+       ror     ax,cl           ;AL is mask, AH is hi-mask
+       add     di,dx           ; + x
+       mov     WORD (bp-6),ax  ;save mask
+;-------------------------------------------------
+       mov     WORD (bp-4),#0  ;shadow
+        mov     dx,#0x03CE      ;
+       lds     bx,(bp+4)       ;sch
+d4_FC527:
+        seg    es
+         lodsb           ;cgen -> bits
+        push    es
+       sub     ah,ah
+        push    WORD #0xA000
+       ror     ax,cl   ;rotated bits in AX
+        pop     es
+       push    ax      ;save AX rotated bits
+
+       not     ax
+       and     ax,WORD (bp-6)  ;mask complement
+       push    ax
+
+        mov    ah,BYTE (bx+2)  ;sch->bg
+        cmp    BYTE (bx),ah    ;sch->fg
+       pop     ax              ; inserted ****
+       je      d4_I529
+
+       push    ax              ;AH = bits high; AL = bits low
+       mov     ah,al           ;AH = bits low
+       mov     al,#08
+        out     dx,ax
+       mov     ah,BYTE (bx+2)  ;sch->bg
+        seg    es
+         and   BYTE (di),ah    ;buf
+       pop     ax              ; get complemented bits back
+       jcxz    d4_I529
+
+       mov     al,#08          ;AH = ~bits hi, AL = 8
+        out     dx,ax
+       mov     al,BYTE (bx+2)  ;sch->bg
+        seg    es
+         and   BYTE (di+1),al    ;buf
+       
+d4_I529:       ; rotated bits in the stack
+        mov    al,BYTE (bx+4)  ;sch->sh
+        cmp    BYTE (bx),al    ;sch->fg
+       je      d4_I530
+       mov     ax,WORD (bp-4)  ;get shadow
+       rol     ax,#7           ;       
+       push    ax
+       mov     al,#8
+        out     dx,ax
+       mov     ah,BYTE (bx+4)  ;sch->sh
+        seg    es
+         and   BYTE (di),ah
+       pop     ax
+       jcxz    d4_I530
+
+       xchg    ah,al
+       mov     al,#8
+        out     dx,ax
+       mov     ah,BYTE (bx+4)  ;sch->sh
+        seg    es
+         and   BYTE (di+1),ah
+       
+d4_I530:
+       pop     ax              ;rotated bits
+       mov     WORD (bp-4),ax  ; save shadow
+
+       push    ax
+       mov     ah,al
+       mov     al,#8
+        out     dx,ax
+        mov    al,BYTE (bx)    ;sch->fg
+        seg    es
+         and   BYTE (di),al
+       pop     ax
+       jcxz    d4_I531
+
+       mov     al,#8
+        out     dx,ax
+        mov    al,BYTE (bx)    ;sch->fg
+        seg    es
+         and   BYTE (di+1),al
+
+d4_I531:
+        add     di,#640/8        ;buf
+        pop     es
+        dec     WORD (bp-2)
+        jne     d4_FC527
+
+d4_EX519:
+        pop     ds
+        popa
+       leave
+       ret     
+
+
+        .even          ;   4
+_text:
+        push    bp
+        mov     bp,sp
+        push    ds
+
+;      sch = 14
+;      len = 12
+;      cp = 8
+;      ypos = 6
+;      xpos = 4
+        mov     ax,#2
+       call    d4_setstate
+       mov     cx,WORD (bp+12) ;len
+       mov     bx,WORD (bp+6)  ;ypos
+       mov     dx,WORD (bp+4)  ;xpos
+#ifndef PIXADDRESS
+        shl     bx,#4            ;ypos
+        shl     dx,#3            ;xpos
+#endif
+       lds     si,(bp+8)       ;cp
+        jcxz    d4_L672
+       push    WORD (bp+16)
+       push    WORD (bp+14)    ;sch
+d4_FC544:
+        lodsb                   ;*cp
+       seg cs
+         cmp   WORD [_Mode],#0x12
+       jbe     d4_tVga
+       call    d4_char256
+       jmp     d4_tCont
+d4_tVga:
+        call   d4_char10
+d4_tCont:
+       add     dx,#8   ;xpos
+       loop    d4_FC544
+       add     sp,#4
+d4_L672:
+        xor     ax,ax
+       call    d4_setstate
+        pop     ds
+       leave   
+       ret     
+
+#if 0
+        .even          ;   4
+
+_setpalette:
+       push    bp
+       mov     bp,sp
+;      blue = 10
+;      green = 8
+;      red = 6
+;      color = 4
+
+       push    bx
+       mov     bh,bl
+        mov     ax,#0x1000
+        int     0x10
+
+       mov     bx,#0x3fff      ;00ffH
+       mov     al,dh
+       mul     bh
+       div     bl
+       mov     dh,al
+       xor     dl,dl
+
+       mov     al,ch
+       mul     bh
+       div     bl
+       mov     ch,al
+
+       mov     al,cl
+       mul     bh
+       div     bl
+       mov     cl,al
+
+       pop     bx              ;color
+        mov     ax,#0x1010
+        int     0x10
+       leave   
+       ret     
+#endif
+
+
+        .even          ;   4
+d4_putrow4:
+        pusha
+        push    ds
+
+;      mask = -2
+;      lp = -6
+;      tp = -10
+;      vp = -14
+;      vvp = -18
+;      i = -20
+;      nn = -22
+;      x2 = 8
+;      x1 = 6          ; DX
+;      y = 4           ; AX
+        push    ax      ;y
+        push    dx      ;x2-x1+1
+
+;begin pack4
+       push    ds
+        pop     es
+        mov     si,#_line
+       mov     di,si   ;op = lp
+        mov     ah,#640/8        ; npix/8
+d4_FC185:
+       mov     cx,#8
+d4_F187:
+       seg     es
+         lodsb
+        shr     al,#1
+        rcl     bl,#1    ;a
+       shr     al,#1
+        rcl     bh,#1    ;b
+       shr     al,#1
+        rcl     dl,#1    ;c
+       shr     al,#1
+        rcl     dh,#1    ;d
+       loop    d4_F187
+       mov     al,bl   ;a
+        stosb
+       mov     al,bh   ;b
+        stosb
+       mov     al,dl   ;c
+        stosb
+       mov     al,dh   ;d
+        stosb
+        dec     ah
+        jne    d4_FC185
+d4_EX175:
+; end pack4
+
+        pop     bx
+       sar     bx,#3            ;nn
+        pop     di              ;y
+;;     imul    WORD [_ypitch]
+        imul    di,#640/8
+        push    WORD #0xA000
+        pop     es
+       mov     si,#_line       ;lp
+        mov     ax,#0x0102       ;mask
+d4_FC563:
+       mov     dx,#964 ;03c4H
+        out     dx,ax
+        push    di
+        push    si
+        mov     cx,bx           ;nn
+        push    ax                      ;mask
+d4_FC566:
+        lodsb
+       seg     es
+         and   BYTE (di),al
+       add     si,#3   ;tp
+       inc     di      ;vp
+       loop    d4_FC566
+
+        pop     ax              ;mask
+        pop     si
+        pop     di
+        shl     ah,#1
+       inc     si              ;lp
+       test    ah,#15          ;000fH
+       jne     d4_FC563
+
+        pop     ds
+        popa
+       ret     
+
+        .even          ;   4
+d4_setstate:
+        push    ds
+
+        push    cs
+        pop     ds
+#if 0
+       pusha
+       call    wout
+       call    ss1
+       .ascii  " = AX; setstate entered"
+       .byte   10,0
+ss1:   pop     bx
+       call    say
+;;     call    pause
+       popa
+#endif
+       cmp     WORD [_Mode],#0x12
+       ja      d4_SB497                ;setstate is a NOP if VESA
+
+;      new = 4
+       mov     dx,#974 ;03ceH
+       cmp     ax,WORD [_state]
+       je      d4_SB497
+       mov     WORD [_state],ax
+       dec     ax
+       je      d4_SC502
+       dec     ax
+       je      d4_SC503
+
+; state 0
+        push    dx
+       mov     ax,#3842        ;0f02H
+       mov     dx,#964 ;03c4H
+        out     dx,ax
+
+        pop     dx
+       mov     ax,#5    ;0005H
+        out     dx,ax
+
+       mov     ax,#3847        ;0f07H
+        jmp     d4_L669
+
+; state 1
+d4_SC502:
+       mov     ax,#2053        ;0805H
+        jmp     d4_L670
+
+;  state 2
+d4_SC503:
+       mov     ax,#2565        ;0a05H
+d4_L670:
+        out     dx,ax
+       mov     ax,#7
+d4_L669:
+        out     dx,ax
+       mov     ax,#3
+        out     dx,ax
+       mov     ax,#-248        ;ff08H
+        out     dx,ax
+d4_SB497:
+#if 0
+       pusha
+       call    ss2
+       .ascii  "setstate exit"
+       .byte   10,0
+ss2:   pop     bx
+       call    say
+;;     call    pause
+       popa
+#endif
+        pop     ds
+       ret     
+
+        .even          ;   4
+;
+;  _display4:  display the BITMAP
+;
+;  Enter with: ES:BX points to the possible bitmap image
+;              DS==CS
+;
+;  Exit with:
+;      Carry Clear     - bitmap was displayed
+;      AX = 0
+;
+;      Carry Set       - error occurred
+;      AX = 1          "BM" signature not found
+;      AX = 2          not VGA adapter or display
+;      AX = 3          not 640x480x16 bitmap
+;      AX = 4          no VESA support
+;
+_display4:
+; Line 286
+       enter   #22,#0
+       push    si
+       push    di
+
+;      bits = -2
+;      colors = -6
+;      i = -8
+;      disable = -10
+;      color = -14
+;      bmfh = -18
+;      bmh = -22
+;      name = 4
+; Line 296
+       mov     WORD [_bmp],bx  ;store for later
+       mov     WORD [_bmp+2],es
+;;;    les     bx,[_bmp]
+       mov     WORD (bp-18),bx ;bmfh
+       mov     WORD (bp-16),es
+       seg     es
+         cmp   WORD (bx),#19778        ;4d42H
+       jne     d4_I573
+       seg     es
+         cmp   WORD (bx+14+2),#0       ; hi-order part of DWORD
+       jne     d4_I573
+       seg     es
+         cmp   WORD (bx+14),#40        ; Windows/OS2 bitmap header
+       je      d4_I574
+       seg     es
+         cmp   WORD (bx+14),#12        ; OS2 bitmap header
+       je      d4_I574
+; Line 297
+d4_I573:
+        mov     ax,#1
+        stc
+       br      _display4_ret
+
+d4_I574:
+       mov     ax,WORD [_bmp]
+       mov     dx,WORD [_bmp+2]
+       add     ax,#14  ;000eH
+;;     sbb     cx,cx
+;;     and     cx,#0x1000
+;;     add     dx,cx
+       mov     WORD [_tp],ax
+       mov     WORD [_tp+2],dx
+       mov     WORD (bp-22),ax ;bmh
+       mov     WORD (bp-20),dx
+; Line 302
+       mov     es,dx
+       mov     bx,ax
+       seg     es
+         cmp   BYTE (bx),#40           ; Windows
+       je      d4_I575
+
+;  OS2 bitmaps
+       seg     es
+         mov   ax,WORD (bx+8)
+        seg    es
+         mul   WORD (bx+10)
+       mov     WORD (bp-2),ax  ;bits
+; Line 305
+       mov     cx,ax
+       mov     ax,#1
+       shl     ax,cl
+       cwd     
+       mov     WORD (bp-6),ax  ;colors
+; Line 317
+       seg     es
+         cmp   WORD (bx+4),#640        ;0280H
+       jne     d4_I576
+       seg     es
+         cmp   WORD (bx+6),#480        ;01e0H
+       jne     d4_I576
+
+       cmp     cx,#8   ;bits
+       je      d4_Vesa_Setup
+
+       cmp     cx,#4   ;bits
+       jne     d4_I576
+       jmp     d4_I575a
+
+; Windows/OS2 bitmaps
+d4_I575:
+       seg     es
+         mov   ax,WORD (bx+12)
+        seg    es
+         mul   WORD (bx+14)
+       mov     WORD (bp-2),ax  ;bits
+; Line 305
+       mov     cx,ax
+       mov     ax,#1
+       shl     ax,cl
+       cwd     
+       mov     WORD (bp-6),ax  ;colors
+; Line 317
+       seg     es
+;;;      cmp   DWORD (bx+4),#640       ;0280H
+         cmp   WORD (bx+4),#640        ;0280H
+       jne     d4_I576
+       seg     es
+;;;      cmp   DWORD (bx+8),#480       ;01e0H
+         cmp   WORD (bx+8),#480        ;01e0H
+       jne     d4_I576
+
+       cmp     cx,#8   ;bits
+       je      d4_Vesa_Setup
+
+       cmp     cx,#4   ;bits
+       jne     d4_I576
+d4_I575a:
+       mov     WORD [_Mode],#18        ;0012H
+;;     mov     cx,#8
+;;     cwd     
+;;     idiv    cx
+;;     mov     WORD [_ypitch],ax
+; Line 318
+       br      d4_I577
+
+d4_I576:
+; Line 319
+        mov     ax,#3
+        stc
+       br      _display4_ret
+
+
+d4_Vesa_Setup:
+       mov     WORD [_Mode],#0x101     ; 640x480x256
+
+       mov     di,#MAP                 ; ES:DI -> 512 byte buffer
+       mov     DWORD (di),#SIG_VBE2    ; "VBE2"
+       mov     ax,#0x4f00              ; get mode information
+
+       push    es
+       push    ds
+       pop     es                      ; -> communication area
+       int     0x10                    ; video interrupt
+       pop     es
+#if FAIL
+       xor     ax,ax
+#endif
+       cmp     ax,#0x004f
+       jne     d4_I576_4               ; no VESA
+       cmp     DWORD (di),#SIG_VESA    ; "VESA"
+       jne     d4_I576_4
+
+       mov     ax,#0x4f01              ; get mode information
+       mov     cx,[_Mode]
+
+       push    es
+       push    ds
+       pop     es                      ; -> communication area
+       int     0x10                    ; video interrupt
+       pop     es
+
+       cmp     ax,#0x004f
+;;d4_I576_jne:
+       jne     d4_I576_4               ; no VESA
+
+       mov     ax,v_BytesPerScanLine(di)
+       mov     [_ypitch],ax
+       mov     ax,v_WinASegment(di)
+       mov     [_seg],ax
+       mov     cx,v_WinGranularity(di)
+       mov     ax,#9                   ; shift = 9
+d4_J575:
+       jcxz    d4_K575
+       inc     ax                      ; shift++
+       shr     cx,#1
+       jmp     d4_J575
+d4_K575:
+       mov     [_shift],ax
+       xchg    ax,cx                   ; shift to CX
+       mov     eax,#-1
+       shl     eax,cl                  ;
+       not     eax
+       mov     DWORD [_mask],eax
+       not     eax
+       and     eax,#0x00FFFFFF
+       mov     DWORD [_himask],eax     ;
+       test    BYTE v_ModeAttributes(di),#1
+       jz      d4_I576_4
+       mov     al,v_WinAAttributes(di)
+       and     al,#05
+       cmp     al,#05
+       jne     d4_I576_4
+
+;;;    mov     bx,#0x8000
+;;;    mov     WORD (bp-10),bx         ;disable
+;;;    or      bx,[_Mode]
+       mov     bx,[_Mode]
+
+       mov     ax,#0x4f02              ; set video mode
+       int     0x10
+       cmp     ax,#0x004f
+;;;    jne     d4_I576_4
+       je      d4_Line_327
+
+d4_I576_4:
+       mov     ax,#4
+       stc
+       br      _display4_ret
+
+
+; Line 321
+d4_I577:
+; Line 322
+; Line 323
+       mov     bx,#0
+       mov     ax,#6656        ;1a00H
+        int     0x10
+#if FAIL
+       xor     ax,ax
+#endif
+       cmp     al,#26  ;001aH
+       jne     d4_I578
+       cmp     bl,#7
+       je      d4_I579
+       cmp     bl,#8
+       je      d4_I579
+d4_I578:
+        mov     ax,#2
+        stc
+       br      _display4_ret
+; Line 324
+d4_I579:
+       mov     bx,#49  ;0031H
+       mov     ax,#4609        ;1201H
+        int     0x10
+
+;;;    mov     WORD (bp-10),#128       ;0080H  ;disable
+       mov     ax,WORD [_Mode]
+;;;    or      al,#128 ;0080H
+
+        int     0x10
+; Line 327
+d4_Line_327:
+        mov     dx,#480/16
+        mov     bx,#0
+        mov     ax,#0x1124               ;set for 8x16 characters
+        int     0x10
+; Line 331
+;;;    cmp     WORD (bp-10),#0 ;disable
+;;;    je      d4_I580
+       mov     bx,#54  ;0036H
+       mov     ax,#4609        ;1201H
+        int     0x10
+; Line 333
+d4_I580:
+       les     bx,(bp-22)      ;bmh
+       seg     es
+         mov   si,WORD (bx)
+       add     si,WORD [_tp]
+
+       push    ds
+
+       mov     ds,WORD [_tp+2]
+; Line 334
+       xor     bx,bx           ;i
+d4_FC582:
+; Line 335
+       push    bx
+
+       seg cs
+         cmp   [_Mode],#0x12
+       ja      d4_Vesa_Palette
+
+       mov     bh,bl
+        mov     ax,#0x1000
+        int     0x10
+
+d4_Vesa_Palette:
+       mov     bx,#0x3fff      ;00ffH
+
+       lodsb
+       mul     bh
+       div     bl
+       mov     cl,al
+
+       lodsb
+       mul     bh
+       div     bl
+       mov     ch,al
+
+       lodsb
+       mul     bh
+       div     bl
+       mov     dh,al
+       xor     dl,dl
+
+       pop     bx              ;color = i
+        mov     ax,#0x1010
+        int     0x10
+
+; Line 336
+       mov     di,(bp-22)      ;bmh
+         cmp   BYTE (di),#12   ; test for OS/2 bitmap
+       je      d4_F580
+       inc     si
+d4_F580:
+; Line 337
+       inc     bx      ;WORD (bp-8)    ;i
+d4_F581:
+       cmp     WORD (bp-6),bx  ;colors
+       jg      d4_FC582
+
+       pop     ds
+
+; Line 339
+       les     bx,(bp-18)      ;bmfh
+       seg     es
+         mov   ax,WORD (bx+10)
+       seg     es
+         mov   dx,WORD (bx+12)
+       add     ax,WORD [_bmp]
+       adc     dx,#0
+       shl     dx,#12
+       add     dx,WORD [_bmp+2]
+       mov     WORD [_tp],ax
+       mov     WORD [_tp+2],dx
+; Line 340
+        xor     ax,ax
+       call    d4_setstate
+; Line 341
+        mov     ax,#1
+       call    d4_setstate
+; Line 342
+       les     bx,(bp-22)      ;bmh
+;;     seg     es
+;;       mov   ax,WORD (bx+8)          ; 480
+       mov     ax,#480                 ; Windows or OS2
+;;     seg     es
+;;       mov   dx,WORD (bx+4)          ; 640
+       mov     dx,#640                 ; Windows or OS2
+       seg     es
+         cmp   BYTE (bx),#13           ; OS2
+       sbb     cx,cx                   ; OS2 = -1, Win = 0
+       not     cx
+       seg     es
+         and   cx,WORD (bx+16)         ; compression
+
+       mov     bx,cx                   ; compression to BX
+
+       mov     si,#d4_getrow4
+       mov     di,#d4_putrow4
+       cmp     WORD [_Mode],#0x12
+       jbe     d4_FC586
+       mov     si,#d4_getrow8
+       mov     di,#d4_putrow8
+d4_FC586:
+       dec     ax
+        js      d4_FC587
+; Line 343
+        xchg    ax,bx
+;;;    call    d4_getrow4
+       call    si              ;getrow
+; Line 344
+        xchg    ax,bx
+;;;    call    d4_putrow4
+       call    di              ;putrow
+; Line 345
+       jmp     d4_FC586
+
+d4_FC587:
+; Line 346
+       xor     ax,ax                   ; restore state
+       call    d4_setstate
+; Line 348
+
+       mov     bx,#54  ;0036H          ;enable refresh
+       mov     ax,#4608        ;1200H
+        int     0x10
+
+        xor     ax,ax           ;clears the carry
+_display4_ret:
+       pop     di
+       pop     si
+       leave   
+       ret     
+
+        .even          ;   4
+_done4:
+       xor     ax,ax
+       call    d4_setstate     ;restore state
+; Line 356
+; enable default palette loading
+       mov     bx,#49  ;0031H
+       mov     ax,#4608        ;1200H
+        int     0x10
+; Line 357
+       mov     ax,#0x0003       ; set video mode
+        int     0x10
+; Line 359
+       ret     
+
+
+; pixadr8 - pixel address in 256 color mode
+;
+;   Enter with:
+;      AX = y
+;      BX = x
+;
+;   Exit with:
+;      ES:DI = pointer to byte
+;
+d4_pixadr8:
+       push    ax
+       push    cx
+       push    dx
+       push    ds
+
+       push    cs
+       pop     ds
+
+;;     seg cs
+         mul   WORD [_ypitch]
+       add     ax,bx
+       adc     dx,#0
+       mov     di,ax
+;;     seg cs
+         mov   cl,[_shift]
+;;     seg cs
+         and   di,[_mask]
+       shrd    ax,dx,cl
+;;     seg cs
+         cmp   ax,[_VesaWindow]
+       je      d4p8_1
+
+;;     seg cs
+         mov   [_VesaWindow],ax
+       xchg    ax,dx
+       push    bx
+       xor     cx,cx
+       xor     bx,bx
+       mov     ax,#0x4f05
+       int     0x10
+       pop     bx
+d4p8_1:
+;;     seg cs
+         mov   es,[_seg]
+
+       pop     ds
+       pop     dx
+       pop     cx
+       pop     ax
+       ret
+
+
+
+; putrow8
+;
+;   Enter with:
+;      AX = y
+;      BX = compression
+;      DX = npix (640)
+;      DS == CS
+;
+;  Exit with:
+;      ES is trashed
+;      all other registers preserved
+;
+d4_putrow8:
+       pusha
+       mov     si,#_line       ; source
+
+       mov     cx,WORD [_mask] ; mask
+       xor     bx,bx
+       xor     di,di
+d4p8_2:
+       test    di,cx
+       jnz     d4p8_3
+       call    d4_pixadr8
+d4p8_3:
+       inc     bx
+       movsb
+       cmp     bx,dx
+       jb      d4p8_2
+
+       popa
+       ret
+
+
+; getrow8
+;
+;      AX = compression
+;      DX = npix (640)
+;      BX = y
+;
+;
+d4_getrow8:
+       pusha
+       push    ds
+
+       push    cs
+       pop     es
+       mov     di,#_line               ; ES:DI setup
+       lds     si,[_tp]                ; DS:SI is a HUGE pointer
+       mov     bp,ds                   ; also in BP:SI
+
+       test    ax,ax
+       jz      d4_get8_nocompr
+
+; get with compression
+;
+; DX is npix
+; BH is repeat
+; BL is skip
+; CX is rpt
+
+;      repeat = 1;
+       mov     bh,#1
+
+;      while (npix>0) {
+       jmp     d4_get8_99
+d4_get8_1:
+
+;         while (repeat && npix>0) {
+       jmp     d4_get8_30
+d4_get8_10:
+
+;            rpt = GETC(infile);
+       call    getbyte
+       xchg    ax,cx
+
+;            repeat = rpt;
+       mov     bh,cl
+
+;            if (repeat) {
+       test    bh,bh
+       jz      d4_get8_20
+
+;               c = GETC(infile);
+       call    getbyte
+
+;               npix -= rpt;
+       sub     dx,cx
+
+;               while (rpt>0) {
+;                  *lp++ = c;
+;                  rpt--;
+;               }
+       rep
+        stosb
+
+;            }
+d4_get8_20:
+
+;         }    /* end while (repeat && npix>0) */
+d4_get8_30:
+       test    bh,bh           ; repeat
+       jz      d4_get8_40
+       cmp     dx,#0
+       jg      d4_get8_10
+d4_get8_40:
+
+;         if (npix>0) { /* get some enumerated data */
+       cmp     dx,#0
+       jle     d4_get8_95
+
+;            rpt = GETC(infile);
+       call    getbyte
+       xchg    ax,cx
+
+;            npix -= rpt;
+       sub     dx,cx
+
+;            skip = (rpt%2 != 0);
+       mov     bl,cl
+
+;            while (rpt>0) {
+       jcxz    d4_get8_75
+d4_get8_70:
+
+;               c = GETC(infile);
+       call    getbyte
+
+;               *lp++ = c;
+       stosb
+;               rpt--;
+;            }
+       loop    d4_get8_70
+d4_get8_75:
+;            if (skip) c = GETC(infile);
+       shr     bl,#1
+       jnc     d4_get8_80
+       call    getbyte
+d4_get8_80:
+
+;         }
+d4_get8_95:
+
+;         repeat = 1;
+       mov     bh,#1
+
+;      } /* end while (npix>0) */
+d4_get8_99:
+       cmp     dx,#0
+       jg      d4_get8_1
+
+;      GETC(infile);
+;      c=GETC(infile);
+       call    getbyte
+       call    getbyte
+
+       jmp     d4_get8_exit
+
+
+; get with no compression
+;   really just a super movsb with a huge source pointer
+
+d4_get8_nocompr:
+       mov     cx,dx
+d4_get8_nloop:
+       call    getbyte         ; BP==DS is required
+       stosb
+       loop    d4_get8_nloop
+
+d4_get8_exit:
+       seg     cs
+          mov     [_tp],si        ;
+       seg     cs
+         mov     [_tp+2],ds      ;
+
+       pop     ds
+       popa
+       ret
+
+; char256
+;
+;   Enter with:
+;      AL      character to display
+;      BX      ypos
+;      DX      xpos
+;      (bp+4)  far pointer to 
+;
+;   Exit with:
+;      ES is trashed
+;
+;
+;   Stack used:
+;      bp-2    points
+;      bp-4    ypos
+;      bp-6    xpos
+;      bp-8    bits
+;      bp-10   xtem
+;
+;   Variables:
+;      DS:SI   cgen
+;      SI      i
+;      BX      xtem
+;      ES:DI   buf
+;
+d4_char256:
+       enter   #10,#0
+       pusha
+       push    ds
+
+        push    WORD #0
+        pop     ds
+;   points = *(short*)0x00000485UL;     /* 40:85 */
+        mov    cx,WORD [0x485] ;points
+       xor     ah,ah           ;AL is char to put out
+       mov     WORD (bp-2),cx  ;points
+       mov     WORD (bp-4),bx  ;ypos
+       mov     WORD (bp-6),dx  ;xpos
+
+;   cgen = *(char**)(0x43 * 4UL);       /* int 0x43 points to char bitmap */
+;   cgen += (unsigned)c * points;
+       imul    ax,cx           ;leave DX alone; 386 form of instruction
+       mov     si,#268 ;010cH  ; int 0x43 -> character bitmaps
+        add    ax,WORD (si)
+        mov    ds,WORD (si+2)  ;cgen
+        xchg    si,ax           ;cgen  in DS:SI
+
+;   shadow = 0;
+       xor     ch,ch
+       les     di,(bp+4)       ;sch->
+;   fg = sch->fg;
+       seg es
+        mov    cl,(di)
+;   bg = sch->bg;
+       seg es
+         mov   dh,(di+2)
+;   sh = sch->sh;
+       seg es
+         mov   dl,(di+4)
+;
+;   while (points--) {
+d4_char256_10:
+;      int i;
+;
+;      bits = *cgen++;                 ;cgen in DS:SI
+       lodsb
+       mov     WORD (bp-8),ax          ;bits
+       push    si                      ; save SI
+
+;      fore = bits;            ; fore is BL
+       xchg    bx,ax           ; fore is BL
+
+;      xtem = x;
+       mov     ax,WORD (bp-6)
+       mov     WORD (bp-10),ax         ;xtem
+
+;      for (i=8; i; i--) {
+       mov     si,#8                   ;i
+       xor     di,di                   ;buf
+
+d4_char256_20:
+       seg cs
+         test  di,WORD [_mask]
+       jnz     d4_char256_22
+       push    bx
+       mov     ax,WORD (bp-4)  ;ypos
+       mov     bx,WORD (bp-10) ;xtem
+       call    d4_pixadr8      ;buf to ES:DI
+       pop     bx
+d4_char256_22:
+
+;         int color = 0x400;
+       mov     ax,#0x400
+
+;         if (bg != fg) color = bg;
+       cmp     dh,cl           ;bg:fg
+       je      d4_char256_31
+       mov     al,dh           ;color = bg
+       cbw
+d4_char256_31:
+
+;         if ( (shadow&0200) && sh != fg) color = sh;
+       shl     ch,#1           ;shadow
+       jnc     d4_char256_33
+       cmp     dl,cl           ;sh:fg
+       je      d4_char256_33
+       mov     al,dl           ; color = sh
+       cbw
+d4_char256_33:
+
+;         if ( (fore & 0200) ) color = fg;
+       shl     bl,#1
+       jnc     d4_char256_35
+       mov     al,cl           ; color = fg
+       cbw
+
+d4_char256_35:
+
+;         buf = pixadr8(xtem++, y);
+;         if (color<256) *buf = color;
+       inc     ah
+       cmp     ah,#1
+       ja      d4_char256_39
+       seg es
+         mov   BYTE (di),al
+d4_char256_39:
+       inc     di
+       inc     WORD (bp-10)    ;xtem
+
+;         shadow <<= 1;
+;         fore <<= 1;
+;      }
+       dec     si              ;i
+       jnz     d4_char256_20
+
+;      y++;
+       inc     WORD (bp-4)     ;ypos
+
+;      shadow = bits>>1;
+       mov     ch,BYTE (bp-8)
+       shr     ch,#1
+;   }
+       pop     si              ;cgen
+       dec     WORD (bp-2)
+       jnz     d4_char256_10
+
+
+
+d4_char256_exit:
+       pop     ds
+       popa
+       leave
+       ret
+
+
diff --git a/src/dparam.S b/src/dparam.S
new file mode 100644 (file)
index 0000000..e59b706
--- /dev/null
@@ -0,0 +1,103 @@
+#if 0
+;  dparam.S  is
+Copyright 1992 Werner Almesberger */
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+#endif
+
+       .text
+
+       .globl  _main
+       .org    0x100
+
+_main: mov     bl,0x80                 ! NUL-terminate the command line
+       xor     bh,bh
+       mov     0x81(bx),bh
+       mov     bx,#0x81
+aloop: mov     al,(bx)                 ! get the next character
+       inc     bx
+       cmp     al,#32                  ! space ?
+       je      aloop                   ! yes -> skip it
+       cmp     al,#48                  ! '0' ?
+       jne     error                   ! no -> invalid
+       cmpb    (bx),#120               ! 'x' ?
+       je      okay                    ! yes -> okay
+       cmpb    (bx),#88                ! 'X' ?
+       jne     error                   ! no -> invalid
+okay:  cmpb    1(bx),#56               ! '8' ?
+       jne     error                   ! no -> invalid
+       cmpb    3(bx),#0                ! one more digit ?
+       jne     error                   ! no -> invalid
+       mov     dl,2(bx)                ! get the digit
+       sub     dl,#48                  ! convert to a number
+       cmp     dl,#1                   ! valid ?
+       ja      error                   ! no -> error
+       add     dl,#0x80                ! adjust the number
+       mov     ah,#8                   ! get the drive parameters
+       int     0x13
+       or      ah,ah                   ! error ?
+       jnz     derror                  ! yes -> display a message
+       push    cx                      ! save the parameters
+       push    dx
+       mov     al,cl                   ! number of sectors
+       and     al,#0x3f
+       xor     ah,ah
+       call    decout
+       call    space
+       pop     dx                      ! number of heads
+       mov     al,dh
+       inc     al
+       xor     ah,ah
+       call    decout
+       call    space
+       pop     ax                      ! number of cylinders
+       xchg    ah,al
+       mov     cl,#6
+       shr     ah,cl
+       inc     ax
+       call    decout
+       mov     dx,#crlf                ! crlf
+       mov     ah,#9
+       int     0x21
+       ret                             ! done
+
+error: mov     dx,#errmsg              ! display the error message
+       jmp     dispit
+
+derror:        mov     dx,#invdrv              ! display the error message
+       jmp     dispit
+
+space: mov     dx,#spc                 ! display two blanks
+       jmp     dispit
+
+decout:        mov     bx,#decend              ! set the pointer to the end
+declp: xor     dx,dx                   ! divide by 10
+       mov     cx,#10
+       div     cx
+       add     dl,#48                  ! make a digit
+       dec     bx                      ! store digit
+       mov     (bx),dl
+       or      ax,ax                   ! zero ?
+       jnz     declp                   ! no -> go on
+       mov     dx,bx                   ! display the string
+dispit:        mov     ah,#9
+       int     0x21
+       ret                             ! done
+
+errmsg:        .ascii  "usage: dparam 0x80"
+       .byte   13,10
+       .ascii  "   or  dparam 0x81"
+crlf:  .byte   13,10
+       .ascii  "$"
+
+invdrv:        .ascii  "Invalid drive"
+       .byte   13,10
+       .ascii  "$"
+
+spc:   .ascii  "  $"
+
+decbuf:        .byte   0,0,0,0,0
+decend:        .ascii  "$"
diff --git a/src/dump.S b/src/dump.S
new file mode 100644 (file)
index 0000000..8115fc3
--- /dev/null
@@ -0,0 +1,137 @@
+/* dump.S  -  LILO register dumper */
+
+ Copyright 1995-1997 Werner Almesberger.
+ All rights reserved.
+
+ Licensed under the terms contained in the file 'COPYING' in the 
+ source directory.
+
+*/
+
+
+#define LILO_ASM
+#include "lilo.h"
+
+
+       .text
+
+       .globl  _main
+       .org    0
+
+_main: push    sp      ! push all registers
+       push    ss
+       pushf
+       push    es
+       push    ds
+       push    cs
+       push    bp
+       push    di
+       push    si
+       push    dx
+       push    cx
+       push    bx
+       push    ax
+       mov     ax,#BOOTSEG     ! let DS point to where we really are
+       mov     ds,ax
+       mov     bx,#msgs        ! set up loop
+l:     call    say             ! output message
+       cmp     byte ptr (bx),#0 ! at end ?
+       je      back            ! yes -> back to LILO
+       pop     ax              ! get next data word
+       push    bx
+       call    wout            ! output data word
+       pop     bx
+       jmp     l               ! next round
+
+#if 0
+back:  mov     ax,#FIRSTSEG
+       mov     ds,ax
+       mov     word ptr (CODE_START_1),#CODE_START_1+8
+       mov     word ptr (CODE_START_1+2),#FIRSTSEG
+       mov     word ptr (CODE_START_1+4),#CODE_START_1+12
+       mov     byte ptr (CODE_START_1+6),#0xfe
+       mov     es,ax           ! adjust segments
+       mov     ax,#BOOTSEG
+       mov     ds,ax
+       mov     word ptr (10),#0xffff ! no timeout
+       mov     si,#haltnow     ! copy string data
+       mov     di,#CODE_START_1+8
+       mov     cx,#6
+       rep
+       movsb
+       mov     ax,#FIRSTSEG    ! restart LILO
+       jmpi    #GO,FIRSTSEG
+#else
+back:  hlt                     ! stay here
+       jmp     back
+#endif
+
+! Display a NUL-terminated string on the console
+
+say:   mov     al,(bx)         ! get byte
+       inc     bx              ! move pointer
+       or      al,al           ! NUL ?
+       jz      aret            ! yes -> done
+       push    bx              ! save pointer
+       mov     ah,#14          ! display, tty-style
+       xor     bh,bh
+       int     0x10
+       pop     bx
+       jmp     say             ! next one
+
+wout:  push    ax              ! display one word
+       mov     al,ah
+       call    bout
+       pop     ax
+bout:  push    ax              ! display one byte
+       shr     al,#4
+       call    nout
+       pop     ax
+nout:  and     al,#15          ! display one nibble
+       add     al,#48
+       cmp     al,#58
+       jb      nokay
+       add     al,#7
+nokay: xor     bh,bh           ! display on screen
+       mov     ah,#14
+       int     0x10
+aret:  ret
+msgs:  .byte   13,10
+       .ascii  "Register dump:"
+       .byte   13,10,10
+       .ascii  "AX="
+       .byte   0
+       .ascii  " BX="
+       .byte   0
+       .ascii  " CX="
+       .byte   0
+       .ascii  " DX="
+       .byte   0,13,10
+       .ascii  "SI="
+       .byte   0
+       .ascii  " DI="
+       .byte   0
+       .ascii  " BP="
+       .byte   0,13,10
+       .ascii  "CS="
+       .byte   0
+       .ascii  " DS="
+       .byte   0
+       .ascii  " ES="
+       .byte   0,13,10
+       .ascii  "F="
+       .byte   0,13,10
+       .ascii  "SS:SP="
+       .byte   0
+       .ascii  ":"
+       .byte   0,13,10,10
+#if 0
+       .ascii  "Restarting LILO ..."
+#else
+       .ascii  "System halted."
+#endif
+       .byte   13,10,10,0,0
+
+haltnow:.ascii "LILO"                  ! prevent automatic reboot
+       .byte   0
diff --git a/src/edit.c b/src/edit.c
new file mode 100644 (file)
index 0000000..f2d8b93
--- /dev/null
@@ -0,0 +1,902 @@
+/* edit.c -- bitmap file manipulation and editing */
+/*
+Copyright 2002-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/statfs.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+
+#ifdef _SYS_STATFS_H
+#define        _I386_STATFS_H  /* two versions of statfs is not good ... */
+#endif
+
+#include "config.h"
+#include "lilo.h"
+#include "common.h"
+#include "cfg.h"
+#include "temp.h"
+#include "bsect.h"
+#include "bitmap.h"
+#include "edit.h"
+
+
+#define USE_BSECT_PW_INPUT 0           /* use another's input routine */
+#define BMP_CONF ".dat"
+#define BMP_BMP  ".bmp"
+#define NPALETTE 256
+
+/* Luminance of a color 0..255 -- YIQ color model */
+#define Y(c) (((c).red*0.30+(c).green*0.59+(c).blue*0.11)/255)
+#define NORM(x) ((float)(x)/255.0)
+
+static BITMAPFILEHEADER fh;
+static BITMAPHEADER bmh;
+static RGB palette[NPALETTE];
+static int filepos, npal;
+
+static BITMAPLILOHEADER lh0 = {
+       {sizeof(BITMAPLILOHEADER), 0}, "LILO",
+       5*16, 12*8, 1,                  /* row, col, ncol */
+       25, (MAX_IMAGE_NAME+1)*8,       /* maxcol, xpitch */
+       7, 7, 7,                        /* normal text fg, bg, shadow */
+       15, 15, 15,                     /* highlight  fg, bg, shadow  */
+       7, 0, 7,                        /* timer text  fg, bg, shadow */
+       2*16, 64*8,                     /* timer row, col */
+       4, {0, 0, 0}                    /* mincol, reserved[3] */
+               };
+
+
+
+#if USE_BSECT_PW_INPUT
+#define getLine pw_input
+#else
+static char *getLine(void)
+{
+    char *pass;
+    char buf[MAX_TOKEN+1];
+    int i, ch;
+    
+    i = 0;
+    fflush(stdout);
+    while((ch=getchar())!='\n') if (i<MAX_TOKEN) buf[i++]=ch;
+    buf[i]=0;
+    pass = stralloc(buf);
+/*    while (i) buf[--i]=0;    */
+    return pass;
+}
+#endif
+
+
+int get_std_headers(int fd,
+       BITMAPFILEHEADER *fh,
+       BITMAPHEADER *bmh,
+       BITMAPLILOHEADER *lh)
+{
+    short size;
+    BITMAPHEADER2 bmh2;
+    int n, i;
+    
+    lseek(fd, 0, SEEK_SET);
+    if (read(fd, (void*)fh, sizeof(BITMAPFILEHEADER)) !=
+                       sizeof(BITMAPFILEHEADER) )  return -1;
+    if (fh->magic != 0x4D42 /* "BM" */)  return 1;
+    if (read(fd, &size, sizeof(size)) != sizeof(size))   return -1;
+    if (size==sizeof(BITMAPHEADER2)) { /* an OS/2 bitmap */
+       if (read(fd, (void*)&bmh2+sizeof(size), sizeof(BITMAPHEADER2)-sizeof(size))
+               != sizeof(BITMAPHEADER2)-sizeof(size) )   return -1;
+       memset(bmh, 0, sizeof(BITMAPHEADER));
+       bmh->width = bmh2.width;
+       bmh->height = bmh2.height;
+       n = bmh->numBitPlanes = bmh2.numBitPlanes;
+       n *= bmh->numBitsPerPlane = bmh2.numBitsPerPlane;
+       bmh->numColorsUsed = bmh->numImportantColors = 1 << n;
+       bmh->sizeImageData = *(int*)(fh->size) - *(int*)(fh->offsetToBits);
+       bmh->size = sizeof(*bmh);    /* new size!! */
+       n = sizeof(RGB2);
+    }
+    else if (size==sizeof(BITMAPHEADER)) {
+       if (read(fd, (void*)bmh+sizeof(size), sizeof(BITMAPHEADER)-sizeof(size))
+               != sizeof(BITMAPHEADER)-sizeof(size) )   return -1;
+       bmh->size = size;
+       n = sizeof(RGB);
+    }
+    else  return 2;
+
+    *lh = lh0;
+    npal = 1 << (bmh->numBitPlanes * bmh->numBitsPerPlane);
+    colormax = npal - 1;
+    if (npal > nelem(palette) )   return 3;
+    for (i=0; i<npal; i++) {
+       if (read(fd, &palette[i], n) != n)  return -1;
+       if (n==sizeof(RGB2)) palette[i].null = 0;
+    }
+    if (*(int*)(fh->offsetToBits) == sizeof(BITMAPFILEHEADER) +
+               sizeof(BITMAPHEADER) + sizeof(BITMAPLILOHEADER) +
+               npal*sizeof(RGB) )  /* test will fail for OS/2 bitmaps */ {
+      /* get probable BITMAPLILOHEADER */
+       if (read(fd, &size, sizeof(size)) != sizeof(size))  return -1;
+       if (size != sizeof(BITMAPLILOHEADER))   return 4;
+       if (read(fd, (void*)lh+sizeof(size), sizeof(*lh)-sizeof(size)) !=
+               sizeof(*lh)-sizeof(size))  return -1;
+       *(int*)(lh->size) = size;
+       if (strncmp(lh->magic, "LILO", 4) != 0)   return 5;
+    } else { /* there is no BITMAPLILOHEADER present */
+#ifdef STANDALONE
+        printf("No BITMAPLILOHEADER\n");
+#endif
+    }
+
+/* file is left positioned at the start of the bitmap data */
+    filepos = lseek(fd, 0, SEEK_CUR);
+    return 0;
+}
+
+
+int put_std_bmpfile(int fd, int ifd,
+       BITMAPFILEHEADER *fh,
+       BITMAPHEADER *bmh,
+       BITMAPLILOHEADER *lh)
+{
+    int n, total, npalette;
+    char buf[1024];
+    
+    npalette = 1 << (bmh->numBitPlanes * bmh->numBitsPerPlane);
+    write(fd, fh, sizeof(*fh));
+    write(fd, bmh, sizeof(*bmh));
+    write(fd, palette, npalette*sizeof(palette[0]));
+    write(fd, lh, sizeof(*lh));
+    total=0;
+    lseek(ifd, filepos, SEEK_SET);
+    do {
+       n = read(ifd, buf, sizeof(buf));
+       if (n>0) {
+           if (write(fd, buf, n) != n)  return -1;
+           total += n;
+       }
+       else if (n<0)  printf("Error reading input\n");
+    } while (n>0);
+    bmh->sizeImageData = total;
+    *(int*)(fh->offsetToBits) = n = sizeof(BITMAPFILEHEADER) +
+               sizeof(BITMAPHEADER) + sizeof(BITMAPLILOHEADER) +
+               npalette*sizeof(RGB);
+    *(int*)(fh->size) = total + n;
+    lseek(fd, 0, SEEK_SET);
+    write(fd, fh, sizeof(*fh));
+    write(fd, bmh, sizeof(*bmh));
+
+    return 0;
+}
+
+
+#ifndef STANDALONE
+static char *temp_file, *bitmap_file;
+static int ifd, ofd;
+static union {
+          unsigned char buffer[256];
+          MENUTABLE mt;
+          BITMAPLILOHEADER bmlh;
+       } tm;
+static MENUTABLE *menu = &tm.mt;
+static BITMAPLILOHEADER *lh = (void*)tm.buffer + 
+                       ((long)&tm.mt.row - (long)&tm.bmlh.row);
+
+/* a convenience definition */
+#define mn tm.mt
+
+/* timer = 1 if timer is enabled, 0 if timer is disabled */
+#define timer (mn.t_row>=0)
+
+static int yesno(char *query, int def)
+{
+    char *yn;
+    int ans = 2;
+
+    while (ans>1) {    
+       printf("%s (yes or no) [%c]:  ", query, def?'Y':'N');
+       yn = getLine();
+       if (!*yn) ans = def;
+       else if (toupper(*yn) == 'Y') ans = 1;
+       else if (toupper(*yn) == 'N') ans = 0;
+       free(yn);
+    }
+    return ans;
+}
+
+
+static void dat_file_creat(char *bmp)
+{
+    char *datfile;
+    FILE *fdat;
+    
+    datfile = stralloc(bmp);
+    *strrchr(datfile,*(BMP_BMP)) = 0;
+    strcat(datfile, BMP_CONF);
+    if (!(fdat = fopen(datfile, "w"))) pdie("Open .dat file");
+
+    fprintf(fdat,"#\n# generated companion file to:\n#\n");
+    fprintf(fdat,"bitmap = %s\n", bmp);
+    
+    fprintf(fdat,"bmp-table = %d%s,%d%s;%d,%d,%d%s,%d\n",
+       mn.col%8 ? mn.col : mn.col/8+1,
+       mn.col%8 ? "p" : "",
+       mn.row%16 ? mn.row : mn.row/16+1,
+       mn.row%16 ? "p" : "",
+       mn.ncol,
+       mn.maxcol,
+       mn.xpitch%8 ? mn.xpitch : mn.xpitch/8,
+       mn.xpitch%8 ? "p" : "",
+       mn.mincol );
+    
+    fprintf(fdat,"bmp-colors = %d,", mn.fg);
+    if (mn.bg != mn.fg) fprintf(fdat,"%d",mn.bg);
+    putc(',',fdat);
+    if (mn.sh != mn.fg) fprintf(fdat,"%d",mn.sh);
+    putc(';',fdat);
+    fprintf(fdat,"%d,", mn.h_fg);
+    if (mn.h_bg != mn.h_fg) fprintf(fdat,"%d",mn.h_bg);
+    putc(',',fdat);
+    if (mn.h_sh != mn.h_fg) fprintf(fdat,"%d",mn.h_sh);
+    putc('\n',fdat);
+
+    fprintf(fdat,"bmp-timer = ");
+    if (mn.t_row < 0) fprintf(fdat,"none\n");
+    else {
+       fprintf(fdat,"%d%s,%d%s;%d,",
+           mn.t_col%8 ? mn.t_col : mn.t_col/8+1,
+           mn.t_col%8 ? "p" : "",
+           mn.t_row%16 ? mn.t_row : mn.t_row/16+1,
+           mn.t_row%16 ? "p" : "",
+           mn.t_fg );
+       if (mn.t_bg != mn.t_fg) fprintf(fdat,"%d", mn.t_bg);
+       putc(',',fdat);
+       if (mn.t_sh != mn.t_fg) fprintf(fdat,"%d", mn.t_sh);
+       putc('\n',fdat);
+    }
+    fclose(fdat);
+}
+
+static void bmp_file_open(char *bmp)
+{
+    int n;
+
+    bitmap_file = bmp;
+    temp_file = strcat(strcpy(alloc(strlen(bitmap_file)+strlen(MAP_TMP_APP)+1),
+                             bitmap_file),
+                      MAP_TMP_APP);
+    ifd = open(bitmap_file, O_RDONLY);
+    if (ifd<0) pdie("Cannot open bitmap file");
+    ofd = open(temp_file, O_CREAT|O_WRONLY, 0644);
+    if (ofd<0) pdie("Cannot open temporary file");
+    temp_register(temp_file);
+    
+    n = get_std_headers(ifd, &fh, &bmh, lh);
+    if (verbose >= 3) printf("get_std_headers:  returns %d\n", n);
+    
+    if (n<0) die("read file '%s': %s", bitmap_file, strerror(errno));
+    switch (n) {
+       case 1:
+       case 2:
+           die("Not a bitmap file '%s'", bitmap_file);
+       case 3:
+           die("Unsupported bitmap file '%s' (%d bit color)", bitmap_file,
+               bmh.numBitPlanes*bmh.numBitsPerPlane);
+       case 4:
+       case 5:
+           die("Unrecognized auxiliary header in file '%s'", bitmap_file);
+       default:
+           ;
+    }
+}
+
+
+static void bmp_file_close(int update)
+{
+    int n;
+    
+    if (update) n = put_std_bmpfile(ofd, ifd, &fh, &bmh, lh);
+    
+    close(ifd);
+    close(ofd);
+    temp_unregister(temp_file);
+    if (!update || test) {
+       if (verbose < 9) remove(temp_file);
+    } else {
+       n = rename(temp_file, bitmap_file);
+    }
+}
+
+
+static void location(char *what, short x, short y)
+{
+    printf("%sColumn(X): %d%s (chars) or %hdp (pixels)", what, x/8+1, x%8?"+":"", x);
+    printf("   Row(Y): %d%s (chars) or %hdp (pixels)\n", y/16+1, y%16?"+":"", y);
+}
+
+
+static void color(char *what, short fg, short bg, short sh)
+{
+static char sp[] = "   ";
+
+    printf("%sForeground: %hd%sBackground: ", what, fg, sp);
+    if (bg==fg) printf("transparent%s",sp);
+    else printf("%hd%s", bg, sp);
+    printf("Shadow: ");
+    if (sh==fg) printf("none\n");
+    else printf("%hd\n", sh);
+}
+
+
+static void get3colors(char *what, short *color)
+{
+static char *co[] = { "fg", "bg", "sh" };
+static char *op[] = { "", ",transparent", ",none" };
+    int i;
+    int tr, no;
+    unsigned int c;
+    char n[4], *line, *end;
+    int dcol[3];
+
+    for (i=0; i<3; i++) dcol[i] = color[i];    /* save inputs */
+    tr = (dcol[0] == dcol[1]);
+    no = (dcol[0] == dcol[2]);
+    
+    printf("\n");
+    for (i=0; i<3; i++) {
+       sprintf(n, "%hd", dcol[i]);
+       printf("%s text %s color (0..%d%s) [%s]: ", what, co[i], npal-1, op[i],
+               i==1 && tr ? "transparent" :
+               i==2 && no ? "none" : n);
+       line = getLine();
+       if (!*line) c = dcol[i];
+       else if (toupper(*line)=='T' && i==1) c = color[0];
+       else if (toupper(*line)=='N' && i==2) c = color[0];
+       else {
+           c = strtol(line, &end, 0);
+           if (line==end || c>=npal || *end) {
+               c = dcol[i];
+               printf("???\n");
+           }
+       }
+       color[i] = c;
+       free(line);
+       if (i==0) {
+           if (tr) dcol[1]=c;
+           if (no) dcol[2]=c;
+       }
+    }
+}
+
+
+static void number(char *what, short *num, int min, int max)
+{
+    char *line, *end;
+    int val;
+    
+    printf("%s (%d..%d) [%hd]:  ", what, min, max, *num);
+    line = getLine();
+    if (!*line) val = *num;
+    else {
+       val = strtol(line, &end, 0);
+       if (val < min || val > max || *end) {
+           printf("???");
+           val = *num;
+       }
+    }
+    free(line);
+    *num = val;
+}
+
+
+static void getXY(char *what, short *locp, int scale, int abs)
+{
+    char *line, *end;
+    int val;
+    int min = abs ? 1 : MAX_IMAGE_NAME;
+    int minp = min*scale;
+    int max = scale==8 ? 80 : 30;
+    int maxp = (max-abs)*scale;
+    int loc = *locp/scale + abs;
+    char *plus = *locp%scale ? "+" : "";
+    
+    printf("%s (%d..%d) or (%dp..%dp) [%d%s or %dp]: ", what,
+                       min, max, minp, maxp, loc, plus, (int)*locp);
+    
+    line = getLine();
+    if (!*line) val = *locp;
+    else {
+       val = strtol(line, &end, 0);
+       if (line==end || (*end && toupper(*end)!='P')) {
+           val = *locp;
+           printf("???1\n");
+       }
+       if (toupper(*end)!='P') val = (val-1)*scale;
+       if (val > maxp) {
+           val = *locp;
+           printf("???2\n");
+       }
+    }
+    *locp = val;
+    free(line);
+}
+
+
+static void show_timer(void)
+{
+    if (timer) {
+       color("    Timer:  ", mn.t_fg, mn.t_bg, mn.t_sh);
+       location("Timer position:\n  ", mn.t_col, mn.t_row);
+    }
+    else
+    {
+       printf("\n\tThe timer is DISABLED.\n");
+    }
+}
+
+
+static void show_colors(int timopt)
+{
+    color("   Normal:  ", mn.fg, mn.bg, mn.sh);
+    color("Highlight:  ", mn.h_fg, mn.h_bg, mn.h_sh);
+    if (timopt && timer)
+       color("    Timer:  ", mn.t_fg, mn.t_bg, mn.t_sh);
+}
+
+static void show_layout(void)
+{
+    printf("\nTable dimensions:\n");
+    printf("  Number of columns:  %hd\n",  mn.ncol);
+    printf("  Entries per column (number of rows):  %hd\n", mn.maxcol);
+    if (mn.ncol > 1) {
+       printf( "  Column pitch (X-spacing from character 1 of one column to character 1\n"
+               "      of the next column):  %d%s (chars)  %hdp (pixels)\n", mn.xpitch/8,
+               mn.xpitch%8 ? "+" : "", mn.xpitch);
+       printf( "  Spill threshold (number of entries filled-in in the first column\n"
+               "      before entries are made in the second column):  %hd\n", mn.mincol);
+    }
+    location("Table upper left corner:\n  ", mn.col, mn.row);
+}
+
+
+static void edit_timer(void)
+{
+    char *cmd;
+    int editing = 1;
+    
+    do {
+       if (timer) printf("\nTimer colors:\n");
+       show_timer();
+       printf("\nTimer setup:  ");
+       
+       if (timer) printf("C)olors, P)osition, D)isable");
+       else printf("E)nable");
+       
+       printf(", B)ack:  ");
+       
+       cmd = getLine();
+       
+       if (timer) switch(toupper(*cmd)) {
+           case 'C':
+               get3colors("Timer", &mn.t_fg);
+               break;
+           case 'D':
+               while (timer) {
+                   mn.t_row -= 480;
+               }
+               break;
+           case 'P':
+               getXY("\nTimer col", &mn.t_col, 8, 1);
+               getXY("Timer row", &mn.t_row, 16, 1);
+               break;
+           case 'B':
+               editing = 0;
+               break;
+           default:
+               printf("???");
+       }
+       else switch(toupper(*cmd)) {
+           case 'E':
+               while (!timer) {
+                   mn.t_row += 480;
+               }
+               break;
+           case 'B':
+               editing = 0;
+               break;
+           default:
+               printf("???");
+       }
+       free(cmd);
+       printf("\n");
+    } while (editing);
+}
+
+
+static void edit_layout(void)
+{
+    char *cmd;
+    int editing = 1;
+    
+    do {
+       show_layout();
+       
+       printf("\nLayout options:  D)imensions, P)osition, B)ack:  ");
+
+       cmd = getLine();
+       switch(toupper(*cmd)) {
+           case 'D':
+               number("\nNumber of columns", &mn.ncol, 1, 80/MAX_IMAGE_NAME);
+               number("Entries per column", &mn.maxcol, 1, 30);
+               if (mn.ncol > 1) {
+                   getXY("Column pitch", &mn.xpitch, 8, 0);
+                   number("Spill threshold", &mn.mincol, 1, mn.maxcol);
+               }
+               break;
+           case 'P':
+               getXY("\nTable UL column", &mn.col, 8, 1);
+               getXY("Table UL row", &mn.row, 16, 1);
+               break;
+           case 'B':
+               editing = 0;
+               break;
+           default:
+               printf("???");
+       }
+       free(cmd);
+       printf("\n");
+    } while (editing);
+}
+
+
+static void edit_colors(void)
+{
+    char *cmd;
+    int editing = 1;
+    
+    do {
+       printf("\n");
+       show_colors(1);
+       
+       printf("\nText color options:  N)ormal, H)ighlight, ");
+       if (timer) printf("T)imer, ");
+       printf("B)ack:  ");
+
+       cmd = getLine();
+       switch(toupper(*cmd)) {
+           case 'N':
+               get3colors("Normal text", &mn.fg);
+               break;
+           case 'H':
+               get3colors("Highlight text", &mn.h_fg);
+               break;
+           case 'T':
+               if (timer) get3colors("Timer text", &mn.t_fg);
+               else goto bad;
+               break;
+           case 'B':
+               editing = 0;
+               break;
+           default:
+           bad:
+               printf("???");
+       }
+       free(cmd);
+       printf("\n");
+    } while (editing);
+}
+
+
+static void edit_bitmap(char *bitmap_file)
+{
+    char *cmd;
+    int editing = 1;
+    
+    printf("Editing contents of bitmap file:  %s\n", bitmap_file);
+    
+    bmp_file_open(bitmap_file);
+
+    do {
+       show_layout();
+       printf("\nText colors:\n");
+       show_colors(0);
+       show_timer();
+       
+       printf("\nCommands are:  L)ayout, C)olors, T)imer, Q)uit, W)rite:  ");
+       cmd = getLine();
+       switch(toupper(*cmd)) {
+           case 'C':
+               edit_colors();
+               break;
+           case 'L':
+               edit_layout();
+               break;
+           case 'T':
+               edit_timer();
+               break;
+           case 'W':
+               if (yesno("Save companion configuration file?", 0))
+                                               dat_file_creat(bitmap_file);
+               editing = !yesno("Save changes to bitmap file?", 0);
+               if (!editing) {
+                   printf("Writing output file:  %s\n", bitmap_file);
+                   bmp_file_close(!test);  /* update */
+                   if (test) printf("***The bitmap file has not been changed***\n");
+               }
+               break;
+           case 'Q':
+               editing = !yesno("Abandon changes?", 0);
+               if (!editing) bmp_file_close(0);  /* no update */
+               break;
+           default:
+               printf("???");
+       }
+       free(cmd);
+       printf("\n");
+    } while (editing);
+    exit(0);
+}
+
+
+static void transfer_params(char *config_file)
+{
+    int n;
+    char *bitmap_file, *opt;
+    char *cp;
+    int cfd;
+
+    cfg_bitmap_only();         /* disable everything but cf_bitmap */
+    
+    cfd = cfg_open(config_file);
+    if (verbose >= 3) printf("cfg_open returns: %d\n", cfd);
+    n = cfg_parse(cf_bitmap);
+    if (verbose >= 3) printf("cfg_parse returns: %d\n", n);
+    if (n != 0) {
+       die("Illegal token in '%s'", config_file);
+    }
+    if ((bitmap_file = cfg_get_strg(cf_bitmap, "bitmap")) != NULL) {
+       opt = "Using";
+       cp = strrchr(config_file, '/');
+       if (cp && bitmap_file[0] != '/') {
+           *++cp = 0;
+           bitmap_file = strcat(strcpy(alloc(strlen(config_file) + strlen(bitmap_file) + 1),
+                                       config_file),
+                                bitmap_file);
+           *cp = '/';
+       }
+    } else {
+       opt = "Assuming";
+       cp = strrchr(config_file, '.');
+       if (cp) *cp = 0;
+       bitmap_file = alloc(strlen(config_file) + strlen(BMP_BMP) + 1);
+       strcpy(bitmap_file, config_file);
+       strcat(bitmap_file, BMP_BMP);
+       if (cp) *cp = '.';
+    }
+
+    printf("Transfer parameters from '%s' to '%s'", config_file, bitmap_file);
+    if (yesno("?", 0)==0) exit(0);
+
+    if (verbose > 0) printf("%s bitmap file:  %s\n", opt, bitmap_file);
+    
+    bmp_file_open(bitmap_file);
+    
+    bmp_do_table(cfg_get_strg(cf_bitmap, "bmp-table"), menu);
+    bmp_do_colors(cfg_get_strg(cf_bitmap, "bmp-colors"), menu);
+    bmp_do_timer(cfg_get_strg(cf_bitmap, "bmp-timer"), menu);
+    
+    bmp_file_close(1);  /* update */
+    
+    exit(0);
+}
+
+
+void do_bitmap_edit(char *filename)
+{
+    char *bmp = BMP_BMP;
+    char *fn = strrchr(filename, *bmp);
+
+    if (!fn)
+       die ("'%s'/'%s' filename extension required:  %s", BMP_BMP, BMP_CONF, filename);
+
+    if (strcmp(fn, BMP_CONF)==0) transfer_params(filename);
+    if (strcmp(fn, BMP_BMP)==0) edit_bitmap(filename);
+    
+    die("Unknown filename extension:  %s", filename);
+}
+
+#undef mn
+#else  /* STANDALONE */
+
+static RGB vga_palette[16] = {
+/*              B       G       R              */
+       {       000,    000,    000,    0 },    /*  k -- black  */
+       {       170,    000,    000,    0 },    /*  b -- blue   */
+       {       000,    170,    000,    0 },    /*  g -- green  */
+       {       170,    170,    000,    0 },    /*  c -- cyan   */
+
+/*              B       G       R              */
+       {       000,    000,    170,    0 },    /*  r -- red    */
+       {       170,    000,    170,    0 },    /*  m -- magenta */
+       {       000,     85,    170,    0 },    /*  y -- yellow (amber) */
+       {       170,    170,    170,    0 },    /*  w -- white  */
+
+/*              B       G       R              */
+       {        85,     85,     85,    0 },    /*  K -- BLACK (dark grey) */
+       {       255,    000,    000,    0 },    /*  B -- BLUE   */
+       {       000,    255,    000,    0 },    /*  G -- GREEN  */
+       {       255,    255,    000,    0 },    /*  C -- CYAN   */
+
+/*              B       G       R              */
+       {       000,    000,    255,    0 },    /*  R -- RED    */
+       {       255,    000,    255,    0 },    /*  M -- MAGENTA */
+       {       000,    255,    255,    0 },    /*  Y -- YELLOW */
+       {       255,    255,    255,    0 }     /*  W -- WHITE  */
+                       };
+
+FILE* errstd;
+static BITMAPLILOHEADER lh;
+static int idx[16];
+
+static float hue[NPALETTE], y_yiq[NPALETTE], s_hsv[NPALETTE], 
+                       s_hls[NPALETTE], v_hsv[NPALETTE], l_hls[NPALETTE];
+
+void gsort(float array[])
+{
+    int i, j;
+    int n=16;
+    
+    for (j=n-1; j>0; j--) {
+       for (i=0; i<j; i++) {
+           if (array[idx[i]] > array[idx[i+1]]) {
+               int t = idx[i];
+               idx[i] = idx[i+1];
+               idx[i+1] = t;
+           }
+       }
+    }
+}
+
+#define MAX(a,b) (a>b?a:b)
+#define MIN(a,b) (a<b?a:b)
+
+static void compute_arrays(RGB pal[], int n)
+{
+    int i;
+    float r, g, b, max, min, delta;
+    float l, h, mm, hsv, hls;
+    
+    for (i=0; i<n; i++) {
+       idx[i] = i;
+       r = NORM(pal[i].red);
+       g = NORM(pal[i].green);
+       b = NORM(pal[i].blue);
+       
+       max = MAX(r,g);
+       max = MAX(max,b);
+       min = MIN(r,g);
+       min = MIN(min,b);
+       mm = max+min;
+       l = mm * 0.5;
+       delta = max-min;
+       hsv = (max!=0.0 ? delta/max : 0.0);
+       if (delta==0.0) {
+           hls = 0.0;
+           h = -1.0;
+       } else {
+           hls = delta / ( (mm <= 1.0) ? mm: (2.0 - mm) );
+           h = r==max ? (g - b)/delta :
+               g==max ? (b - r)/delta + 2 :
+                        (r - g)/delta + 4;
+           h *= 60;
+           if (h < 0) h += 360;
+       }
+/* compute the YIQ luminance [0..1] */
+       y_yiq[i] = r*0.3 + g*0.59 + b*0.11;
+       
+       l_hls[i] = l;
+       s_hls[i] = hls;
+       s_hsv[i] = hsv;
+       v_hsv[i] = max;
+       hue[i] = h;
+       
+    }  /* for ... */
+}
+
+
+char *Hue(int idx)
+{
+    static char val[8];
+    static const char name[] = "RYGCBM";
+    int i;
+    float h;
+    
+    h = hue[idx];
+    if (h<0) return "";
+    h += 30;
+    i = h/60.0;
+    h -= i*60.0;
+    i %= 6;
+    h -= 30;
+    if (fabs(h)<0.1) { val[0]=name[i]; val[1]=0; }
+    else sprintf(val,"%c%+3.1f", name[i], h);
+    
+    return val;
+}
+
+
+void printline(RGB pal[], int i)
+{
+/*           R   G   B   i     Y      V    S(hsv)   S(hls)   L      H       */
+    printf("(%3d,%3d,%3d)%3d  %6.3f  %6.3f  %6.3f    %6.3f  %6.3f  %+6.1f  %s\n",
+       pal[i].red, pal[i].green, pal[i].blue, i,
+       y_yiq[i], v_hsv[i], s_hsv[i], s_hls[i], l_hls[i], hue[i], Hue(i) );
+}
+
+
+void printpalette(RGB pal[], int n)
+{
+    int i;
+/*           R   G   B   i     Y      V    S(hsv)   S(hls)   L      H       */
+printf("   R   G   B   i     Y       V     S-hsv     S-hls     L       H\n");
+    for (i=0; i<n; i++)  printline(pal, idx[i]);
+    printf("\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+    int ifd;
+    char *outname;
+    int i;
+/*    char *cc = "kbgcrmywKBGCRMYW";  */
+    
+    errstd = stderr;
+    if (argc < 2) {
+        printf("Input file not specified\n");
+       exit(1);
+    }
+    ifd = open(argv[1], O_RDONLY);
+    if (ifd<0) pdie("opening input file");
+    if (argc > 2) die("Too many arguments");
+    if (argc < 3) outname = "out.bmp";
+    else outname = argv[2];
+
+    compute_arrays(vga_palette, 16);
+    printf("\nVGA palette:\n\n\n");
+    printpalette(vga_palette, 16);
+    gsort(y_yiq);
+    printf("\n\nVGA pallette by luminance\n\n\n");
+    printpalette(vga_palette, 16);
+    
+    i = get_std_headers(ifd, &fh, &bmh, &lh);
+    if (i) {
+       printf("Error exit on GET:  %d\n", i);
+       exit(i);
+    }
+    printf("\n\n\nContained palette:\n\n");
+
+    compute_arrays(palette, 16);
+    
+    gsort(y_yiq);
+    printpalette(palette, 16);
+    
+    close(ifd);
+
+    return 0;
+}
+
+#endif /* STANDALONE */
diff --git a/src/edit.h b/src/edit.h
new file mode 100644 (file)
index 0000000..fd85c72
--- /dev/null
@@ -0,0 +1,33 @@
+/* edit.h -- declarations for bitmap file parameter block editing */
+/*
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+
+#ifndef EDIT_H
+#define EDIT_H
+
+#include "common.h"
+#include "bitmap.h"
+#define semi (temp_check(CSOURCE)?"":".")
+
+int get_std_headers(int fd,
+       BITMAPFILEHEADER *fh,
+       BITMAPHEADER *bmh,
+       BITMAPLILOHEADER *lh);
+
+
+int put_std_bmpfile(int fd, int ifd,
+       BITMAPFILEHEADER *fh,
+       BITMAPHEADER *bmh,
+       BITMAPLILOHEADER *lh);
+       
+void do_bitmap_edit(char *bitmap_file);
+       
+#endif
diff --git a/src/first.S b/src/first.S
new file mode 100644 (file)
index 0000000..aabb1a7
--- /dev/null
@@ -0,0 +1,597 @@
+#if 0
+;  first.S  -  LILO first stage boot loader with LBA32 support */
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2005 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+#endif
+#define LILO_ASM
+#include "lilo.h"
+get common.s           /* as86 "include" will bypass the CPP */
+
+#define DEBUG 0
+
+#if VERSION_MINOR>=50
+# define DEBUG_NEW
+
+# undef VIDEO_ENABLE
+# define VIDEO_ENABLE 3
+
+# define VALIDATE !DEBUG       /* adds 0Dh bytes */
+# define SECOND_CHECK !DEBUG   /* adds  5h bytes */
+# define CYL1023 DEBUG         /* subs  8h bytes */
+# define GEOMETRIC !DEBUG      /* adds  1h byte  */
+
+# if DEBUG
+#  define DEBUG_LARGE
+# endif
+#else
+
+# define VALIDATE 1            /* adds 0Dh bytes */
+# define SECOND_CHECK 1                /* adds  5h bytes */
+# define CYL1023 0             /* subs  8h bytes */
+# define GEOMETRIC 1           /* adds  1h byte  */
+#endif
+
+
+!  VIDEO_ENABLE        for those systems that disable the video on boot
+!      = 0             first stage does not enable video
+!      = 1             use get vid mode/set vid mode to enable
+!      = 2             use VGA enable call to enable video
+!                      (cannot use, as code gets too big)
+!      = 3             use direct mode set (mode 3, CGA, EGA, VGA)
+!      = 7             use direct mode set (mode 7, MDA)
+!
+#ifndef VIDEO_ENABLE
+# if VALIDATE==0
+#  define VIDEO_ENABLE 2
+# else
+#  define VIDEO_ENABLE 2
+# endif
+#endif
+
+! do not change the following -- it must correspond to the code in bsect.c
+#define RELOCATABLE -1
+
+
+       .text
+
+       .globl  _main
+
+       .org    0
+
+zero:
+_main: cli                     ! NT 4 blows up if this is missing
+       jmp     start
+
+stage: .byte   STAGE_FIRST
+       .org    4
+reloc:
+#if RELOCATABLE
+       .word   theend-zero     ! size of the code & params
+#else
+       .word   0               ! no size indication
+#endif
+       .org    6
+
+! Boot device parameters. They are set by the installer.
+
+sig:   .ascii  "LILO"
+vers:  .word   VERSION
+mapstamp: .long 0              ! map timestamp
+
+length =  *-sig                ! for the stage 1 vs stage 2 comparison
+
+raid:  .long   0               ! raid sector offset
+tstamp:        .long   0               ! timestamp
+map_serial_no: .long   0       ! volume S/N containing map file
+prompt:        .word   0               ! indicates whether to always enter prompt
+                               ! contains many other flags, too
+
+d_dev: .byte   0x80            ! map file device code
+d_flag:        .byte   0               ! disk addressing flags
+d_addr:        .long   0               ! disk addr of second stage index sector
+
+
+edd_packet     =  0
+;;;    .word   16              ! size of packet
+;;;    .word   1               ! count of bytes to read
+
+edd_addr       =  4
+;;;    .word   map2            ! where to read
+;;;    .word   *-*             ! segment where to read
+
+edd_d_addr     =  8
+;;;    .long   1               ! low address or CX,DX (geometric)
+                               ! start at sector 1 for search in geo mode
+
+;;;    .long   0               ! hi address
+
+#if 0
+!  These locations are referenced as EX_OFF 
+!                                      (they used to be at CODE_START_1)
+ext_si:        .word   0               ! external interface
+ext_es:        .word   0               ! these locations are referenced in second.S
+ext_bx:        .word   0               ! do not disturb the ordering
+ext_dl:        .byte   0               ! second.S will check this magic number
+ext_dh:        .byte   0               ! not referenced, but must align stack
+ext_stack:
+#endif
+       
+/***************************************************/
+!      The following instruction MUST be
+!      first instruction after the CLI/JMP short
+!      at the start of the file; otherwise
+!      the boot sector relocation fails.
+!
+start:
+       mov     ax,#BOOTSEG     ! use DS,ES,SS = 0x07C0
+/***************************************************/
+
+       mov     ss,ax
+       mov     sp,#SETUP_STACKSIZE     ! set the stack for First Stage
+       sti                     ! now it is safe
+
+       push    dx              ! set ext_dl (and ext_dh, which is not used)
+       push    bx              ! WATCH the order of pushes
+       push    es              ! set ext_es
+       push    si              ! set ext_si
+
+#ifdef DEBUG_NEW
+       push    ds
+       push    es      ! just not enough space with debug turned on
+#endif
+
+#define JRC_DS_EQ_SS
+
+       cld                     ! do not forget to do this !!!
+       mov     ds,ax           ! address data area
+       xor     bp,bp           ! shorted addressing
+
+#if VIDEO_ENABLE
+! a BIOS has been found where the video interrupt (0x10) trashes DX
+!   so, we had better be very paranoid about DX
+!
+# if VIDEO_ENABLE==2
+       pusha                   ! protect DX
+# endif
+# if VIDEO_ENABLE > 2
+       mov     ax,#VIDEO_ENABLE        ! set video mode 3 or 7
+# elif VIDEO_ENABLE==1
+       mov     ah,#15          ! get video mode
+       int     0x10
+       cbw
+# else  /* VIDEO_ENABLE==2 */
+       mov     ax,#0x1200      ! enable video (VGA)
+       mov     bl,#0x36        ! (probably a nop on EGA or MDA)
+# endif
+       int     0x10            ! video call
+# if VIDEO_ENABLE==2
+       popa                    ! restore DX
+# endif
+#endif
+
+#if (VIDEO_ENABLE&1) == 0
+       mov     al,#0x0d        ! gimme a CR ...
+       call    display
+; the suspect call for trashing DX on one BIOS:
+       mov     al,#0x0a        ! ... an LF ...
+       call    display
+#endif
+
+#if defined(DEBUG_NEW)
+       mov     ah,dl
+       call    bout            ! code in AH
+#endif
+       mov     al,#0x4c        ! ... an 'L' ...
+       call    display
+
+lagain:
+       pusha                   ! preserve all the registers for restart
+
+       push    ds
+       pop     es              ! use buffer at end of boot sector
+
+       cmp     dl,#EX_DL_MAG   ! possible boot command line (chain.S)
+       jne     boot_in_dl
+       mov     dl,dh           ! code passed in DH instead
+boot_in_dl:
+
+       mov     bx,#map2        ! buffer for volume search
+       mov     dh,[d_dev](bp)  ! map device to DH
+
+#if VALIDATE
+       mov     ax,dx           ! copy device code to AL
+       and     ah,#0x80        ! AH = 00 or 80
+       xor     al,ah           ! hi-bits must be the same
+       js      use_installed
+       cmp     al,#MAX_BIOS_DEVICES    ! limit the device code
+       jae     use_installed   ! jump if DL is not valid
+#endif
+
+! map is on boot device for RAID1, and if so marked; viz.,
+
+       test    byte ptr [prompt](bp),#FLAG_MAP_ON_BOOT
+       jnz     use_boot        ! as passed in from BIOS or MBR loader
+
+use_installed:
+       mov     dl,dh           ! device code to DL
+       mov     esi,[map_serial_no](bp) ! to search for
+       or      esi,esi
+       jz      done_search
+
+       push    dx              ! save flags
+
+       mov     ah,#8           ! get number of hard disks
+       mov     dl,#0x80
+       push    bx              ! paranoia
+       int     0x13
+       pop     bx
+       jc      error
+
+       movzx   cx,dl           ! extend to word in CX
+
+#if GEOMETRIC
+       mov     dx,#0x80-1      ! device 80, flags=0
+#else
+       mov     dx,#LBA32_FLAG*256+0x80-1       ! device 80, flags=LBA32
+#endif
+
+vagain:
+       inc     dx
+       xor     eax,eax
+#if GEOMETRIC
+       inc     ax              ! geometric addressing
+#endif
+       call    disk_read       ! read 
+
+       cmp     esi,[PART_TABLE_OFFSET-6](bx)
+       je      vol_found
+       loop    vagain
+
+       pop     dx              ! restore specified BIOS code
+                               ! AX and DX are identical at this point
+
+vol_found:
+               ! uses value in DX, stack may have extra value
+
+done_search:   
+use_boot:
+       push    bx              ! save map2 for later
+
+       mov     dh,[d_flag](bp) ! get device flags to DH
+       mov     si,#d_addr
+       call    pread           ! increments BX
+
+       mov     ah,#0x99        ! possible error code
+       cmp     dword (bx-4),#EX_MAG_HL ! "LILO"
+       jne     error
+
+       pop     si              ! point at #map2
+
+#if 1
+       push    #SETUP_STACKSIZE/16 + BOOTSEG + SECTOR_SIZE/16*2
+       pop     es
+#else
+       mov     ax,ds           ! get segment
+       add     ax,#SETUP_STACKSIZE/16    !   + SECTOR_SIZE/16*2
+       mov     es,ax
+#endif
+       xor     bx,bx
+
+sload:
+       call    pread           ! read using map at DS:SI
+       jnz     sload           ! into memory at ES:BX (auto increment)
+
+! Verify second stage loader signature
+       
+       mov     si,#sig         ! pointer to signature area
+       mov     di,si
+       mov     cx,#length      ! number of bytes to compare
+       mov     ah,#0x9A        ! possible error code
+       repe
+         cmpsb                 ! check Signature 1 & 2
+       jne     error   ! check Signature 2
+
+#if SECOND_CHECK
+/* it would be nice to re-incorporate this check */
+       mov     al,#STAGE_SECOND        ! do not touch AH (error code)
+       scasb
+       jne     error
+#endif
+
+! Start the second stage loader     DS=location of Params
+
+       push    es              ! segment of second stage
+       push    bp              ! BP==0
+
+       mov     al,#0x49        ! display an 'I'
+       call    display
+
+       retf                    ! Jump to ES:BP
+
+
+
+
+disk_error2:
+       mov     ah,#0x40        ; signal seek error
+
+! no return from error
+error:
+
+#ifndef LCF_NO1STDIAG
+        mov    al,#32          ! display a space
+       call    display0
+
+       call    bout
+#endif
+
+#ifndef DEBUG_LARGE
+       dec     byte [zero](bp)         !  CLI == 0xFA == 250
+       jz      zzz
+
+#ifndef DEBUG_NEW
+       mov     sp,#SETUP_STACKSIZE-4*2-8*2     ! set the stack for First Stage
+#else
+       mov     sp,#SETUP_STACKSIZE-4*2-2*2-8*2 ! set the stack for First Stage
+#endif
+       popa                            ! restore registers for restart
+       jmp     near lagain             ! redo from start
+#endif
+
+
+zzz:
+#ifndef DEBUG_NEW
+       hlt
+#endif
+       jmp     zzz             ! spin; wait for Ctrl-Alt-Del
+
+
+
+
+! packet read routine
+
+disk_read:
+#ifndef JRC_DS_EQ_SS
+       push    ds
+#endif
+       pusha
+
+#ifndef JRC_DS_EQ_SS
+       push    ss
+       pop     ds
+#endif
+
+       push    bp              ! BP==0
+       push    bp              ! BP==0
+
+       push    eax             ! low order disk address
+#ifdef DEBUG_LARGE
+       xchg    ax,dx
+       call    wout
+       xchg    ax,dx
+       call    dout            ! print out disk address
+#endif
+       push    es              ! memory segment ES
+       push    bx              ! memory offset BX
+       push    #1              ! sector count
+       push    #16             ! size of packet = 16 bytes
+       mov     si,sp           ! address of packet  DS:SI
+
+       push    bx
+
+       test    dh,#LINEAR_FLAG|LBA32_FLAG
+       jz      disk_geometric
+       
+       test    dh,#LBA32_FLAG
+       jz      disk_convert    ; it must be LINEAR
+
+       mov     bx,#0x55AA      ;magic number
+       mov     ah,#0x41
+       int     0x13
+       jc      disk_convert
+       cmp     bx,#0xAA55      ;changed?
+       jne     disk_convert
+       test    cl,#EDD_PACKET  ;EDD packet calls supported
+       jnz     disk_edd
+
+disk_convert:
+       push    dx
+       push    es              ! protect on floppies
+       mov     ah,#8           ! get geometry
+       int     0x13
+       pop     es
+disk_error3:                   ! transfer through on CF=1
+       jc      error           ! disk_error12
+
+#if !CYL1023
+       push    cx
+       shr     cl,#6           ;;;;
+       xchg    cl,ch      ;CX is max cylinder number
+       mov     di,cx      ;DI saves it
+       pop     cx
+#endif
+       shr     dx,#8
+       xchg    ax,dx           ;AX <- DX
+       inc     ax              ;AX is number of heads (256 allowed)
+
+; compensate for Davide BIOS bug
+       dec     cx              ; 1..63 -> 0..62;  0->63
+       and     cx,#0x003f      ;CX is number of sectors
+       inc     cx              ; allow Sectors==0 to mean 64
+
+       mul     cx              ; kills DX also
+       xchg    ax,bx           ;save in BX
+
+       mov     ax,[edd_d_addr](si)     ;low part of address
+       mov     dx,[edd_d_addr+2](si)   ;hi part of address
+
+       cmp     dx,bx
+       jae     disk_error2     ;prevent division error
+
+       div     bx              ;AX is cyl, DX is head/sect
+#if CYL1023
+       cmp     ax,#1023
+#else
+       cmp     ax,di
+#endif
+       ja      disk_error2     ;cyl is too big
+
+       shl     ah,#6           ; save hi 2 bits
+       xchg    al,ah
+       xchg    ax,dx
+       div     cl              ;AH = sec-1, AL = head
+       or      dl,ah      ;form Cyl/Sec
+       mov     cx,dx
+       inc     cx              ; sector is 1 based
+
+       pop     dx              ! restore device code
+       mov     dh,al           ! set head#
+       jmp     disk_read2
+
+
+
+disk_edd:
+       mov     ah,#0x42
+disk_int13:
+       pop     bx
+
+       mov     bp,#5
+disk_retry:
+       pusha
+       int     0x13
+#if 0
+       stc
+       mov     ah,#0x9C
+#endif
+       jnc     disk_okay
+
+       dec     bp              ! does not alter CF, already 0
+       jz      disk_error3     ! go to "jc" with CF=1 & ZF=1
+
+       xor     ax,ax           ! reset the disk controller
+       int     0x13
+       popa                    ! reset AX,BX,CX,DX,SI
+       dec     bp              ! fix up BP count
+       jmp     disk_retry
+
+
+disk_geometric:
+       push    eax
+       pop     cx
+       pop     ax
+       mov     dh,ah
+
+disk_read2:
+       mov     ax,#0x201       ;read, count of 1
+       jmp     disk_int13
+
+
+disk_okay:
+; the pusha block is implicitly removed below
+;;;    mov     (si+2*16-1),ah  ! set error code
+;   the error code is never checked
+       lea     sp,(si+16)      ! do not touch carry; 
+       popa
+#ifndef JRC_DS_EQ_SS
+       pop     ds
+#endif
+       ret
+
+
+
+! Pointer Read -- read using pointer in DS:SI
+
+pread:
+       lodsd                   ! get address
+       or      eax,eax
+       jz      done
+       add     eax,[raid](bp)  ! reloc is 0 on non-raid
+       call    disk_read       
+
+       add     bh,#SECTOR_SIZE/256     ! next sector
+done:
+       ret
+
+
+
+
+#if !defined(LCF_NO1STDIAG) || defined(DEBUG_NEW)
+bout:  rol     ax,#4           ! bring hi-nibble to position
+       call    nout
+       rol     ax,#4           ! bring lo-nibble to position
+nout:  and     al,#0x0F        ! display one nibble
+       daa                     ! shorter conversion routine
+       add     al,#0xF0
+       adc     al,#0x40        ! is now a hex char 0..9A..F
+#endif
+; display - write byte in AL to console
+;      preserves all register contents
+; 
+display0:
+#ifndef LCF_NOVGA
+display:
+#endif
+       pusha           ! make sure no register is changed
+       mov     bx,#7           !  BH=0, BL=07
+       mov     ah,#14
+       int     0x10
+       popa            ! restore all the registers
+#ifdef LCF_NOVGA
+display:
+#endif
+       ret
+
+#ifdef DEBUG_LARGE
+
+dout:  pushad
+       ror     eax,#16
+       call    wout
+       ror     eax,#16
+       call    wout
+       mov     al,#0x20        ! space
+       call    display
+       popad
+       ret
+
+wout:  push    ax
+       call    bout    ! put out AH
+       pop     ax
+       push    ax
+       xchg    al,ah
+       call    bout    ! put out AL (now in AH)
+       pop     ax
+       ret
+#endif
+
+theend:
+
+!
+!   If 'first' loads as the MBR, then there must be space for the partition
+!   table.  If 'first' loads as the boot record of some partition, then
+!   the space reserved below is not used.  But we must reserve the area
+!   as a hedge against the first case.
+!
+!
+       .org    MAX_BOOT_SIZE   !
+       .word   0,0,0,0         ! space for NT, DRDOS, and LiLO volume S/N
+
+!      .org    0x1be           ! spot for the partition table
+p_table:
+       .blkb   16
+       .blkb   16
+       .blkb   16
+       .blkb   16
+#ifdef FIRST
+       .org    *-2
+       .long   FIRST           ! boot block check
+#else
+       .word   0xAA55          ! boot block signature
+#endif
+
+! Better be exactly 0x200
+
+map2   equ     *               ! addressed as ES:[map2]
diff --git a/src/geometry.c b/src/geometry.c
new file mode 100644 (file)
index 0000000..006dcc0
--- /dev/null
@@ -0,0 +1,1659 @@
+/* geometry.c  -  Device and file geometry computation */
+/*
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2005 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+/* Patched for linux-2.4.0 - Glibc-2.2 by Sergey Ostrovsky 11/16/2000 */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#ifdef LCF_REISERFS
+#include <sys/statfs.h>
+
+#ifdef _SYS_STATFS_H
+#define        _I386_STATFS_H  /* two versions of statfs is not good ... */
+#endif
+#endif
+
+#include <string.h>
+
+
+#include "config.h"
+#ifdef LCF_DEVMAPPER
+# include <libdevmapper.h>
+#endif
+#include "lilo.h"
+#include "common.h"
+#include "device.h"
+#include "raid.h"
+#include "geometry.h"
+#include "cfg.h"
+#include "md-int.h"
+#include "probe.h"
+
+#ifdef LCF_REISERFS
+#ifndef REISERFS_SUPER_MAGIC
+#define REISERFS_SUPER_MAGIC 0x52654973
+#endif
+
+#if 0
+#ifndef REISERFS_SUPER_MAGIC_STRING
+#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
+#endif
+#endif
+
+#ifndef REISERFS_IOC_UNPACK
+#define REISERFS_IOC_UNPACK            _IOW(0xCD,1,long)
+#endif
+
+#ifndef REISER4_SUPER_MAGIC
+#define REISER4_SUPER_MAGIC  0x52345362
+ /* (*(__u32 *)"R4Sb"); */
+#endif
+#ifndef REISER4_IOC_UNPACK
+#define REISER4_IOC_UNPACK              _IOW(0xCD,1,long)
+#endif
+#endif
+
+#ifdef LCF_DEVMAPPER
+typedef struct _dm_target {
+    struct _dm_target *next;
+    uint64_t start,length,offset;
+    int device;
+} DM_TARGET;
+
+typedef struct _dm_table {
+    struct _dm_table *next;
+    int device;
+    struct _dm_target *target;
+} DM_TABLE;
+
+DM_TABLE *dmtab = NULL;
+int dm_version_nr = 0;
+#endif
+
+int dm_major_list[16];
+int dm_major_nr;
+
+#ifdef LCF_LVM
+struct lv_bmap {
+    __u32 lv_block;
+    dev_t lv_dev;                      /* was __u16, which is wrong */
+};
+
+#ifndef LV_BMAP
+/*     Should the definition be:                                       */
+#define LV_BMAP                                _IOWR(0xfe, 0x30, int)
+/*     As defined in the 2.4 kernels:                                  */
+/*#define LV_BMAP                              _IOWR(0xfe, 0x30, 1)  */
+#endif
+#ifndef LVM_GET_IOP_VERSION
+/*     Should the definition be:                                       */
+#define LVM_GET_IOP_VERSION            _IOR(0xfe, 0x98, unsigned short)
+/*     As defined in the 2.4 kernels:                                  */
+/*#define LVM_GET_IOP_VERSION          _IOR(0xfe, 0x98, 1) */
+#endif
+#endif
+
+#ifdef LCF_EVMS
+struct evms_get_bmap_t {
+    __u64 rsector;
+    __u32 dev;
+    int status;
+};
+
+struct evms_version_t {
+    __u32 major;
+    __u32 minor;
+    __u32 patch;
+};
+
+#ifndef EVMS_GET_BMAP
+#define EVMS_GET_BMAP          _IOWR(MAJOR_EVMS, 0xC7, struct evms_get_bmap_t)
+#endif
+#ifndef EVMS_GET_IOCTL_VERSION
+#define EVMS_GET_IOCTL_VERSION _IOR(MAJOR_EVMS, 0x0, struct evms_version_t)
+#endif
+#endif
+
+#ifndef HDIO_GETGEO
+#define HDIO_GETGEO HDIO_REQ
+#endif
+
+
+typedef struct _st_buf {
+    struct _st_buf *next;
+    struct stat st;
+} ST_BUF;
+
+
+DT_ENTRY *disktab = NULL;
+int old_disktab = 0;
+
+
+void geo_init(char *name)
+{
+    FILE *file = NULL;
+    char line[MAX_LINE+1];
+#ifdef LCF_DEVMAPPER
+    struct dm_task *dmt;
+    char dm_version[32];
+#endif
+    char major_name[32];
+    int major;
+    char *here;
+    DT_ENTRY *entry;
+    int disk_section,items;
+
+    if (name) {
+       if ((file = fopen(name,"r")) == NULL)
+           die("open %s: %s",name,strerror(errno));
+    }
+    if (name || (file = fopen(DFL_DISKTAB,"r")) != NULL) {
+       disk_section = !!disktab;
+       while (fgets(line,MAX_LINE,file)) {
+           here = strchr(line,'\n');
+           if (here) *here = 0;
+           here = strchr(line,'#');
+           if (here) *here = 0;
+           if (strspn(line," \t") != strlen(line)) {
+               entry = alloc_t(DT_ENTRY);
+               items = sscanf(line,"0x%x 0x%x %d %d %d %d",&entry->device,
+                 &entry->bios,&entry->sectors,&entry->heads,&entry->cylinders,
+                 &entry->start);
+               if (items == 5) entry->start = -1;
+               if (items < 5)
+                   die("Invalid line in %s:\n\"%s\"",name ? name : DFL_DISKTAB,
+                     line);
+               entry->next = disktab;
+               disktab = entry;
+               if (disk_section) die("DISKTAB and DISK are mutually exclusive");
+               old_disktab = 1;
+           }
+       }
+       (void) fclose(file);
+    }
+
+    dm_major_nr = 0;
+    file = fopen("/proc/devices", "r");
+    if (!file) return;
+
+    do {
+       if (!fgets(line, (sizeof line)-1, file)) {
+           (void) fclose(file);
+           return;
+       }
+       line[(sizeof line)-1] = 0;
+    } while(strncmp(line, "Block", 5) != 0);
+
+    while(fgets(line, (sizeof line)-1, file)) {
+       if (sscanf(line, "%d %31s\n", &major, major_name) != 2) continue;
+       if (strcmp(major_name, "device-mapper") != 0) continue;
+       dm_major_list[dm_major_nr] = major;
+       if (verbose >= 3) {
+           printf("device-mapper major = %d\n", major);
+       }
+       if (++dm_major_nr > nelem(dm_major_list) ) break;
+    }
+
+    (void) fclose(file);
+
+
+#ifdef LCF_DEVMAPPER
+    /* Suppress error message if the device doesn't exist. It is ugly */
+    struct stat fs;
+
+    if (stat ("/dev/mapper/control", &fs))
+        return;
+
+    if (!(dmt = dm_task_create(DM_DEVICE_VERSION)))
+        return;
+    if (!dm_task_run(dmt))
+        return;
+    if (!dm_task_get_driver_version(dmt, dm_version, sizeof dm_version))
+        return;
+
+    /*
+     * to not confuse returned device number formats %02x:%02x and %d:%d
+     * we assume here that the %02x:%02x format is only found in the ioctl
+     * interface version < 4 (this is really getting ugly...)
+     */
+    dm_version_nr = atoi(dm_version);
+
+    dm_task_destroy(dmt);
+#endif
+}
+
+
+int is_dm_major(int major)
+{
+    int i;
+    
+    for(i=0; i<dm_major_nr; i++) {
+        if (dm_major_list[i] == major) return 1;
+    }
+    return 0;
+}
+
+
+
+void do_partition(void)
+{
+    DT_ENTRY *entry,*walk;
+    struct stat st;
+    char *partition,*start;
+
+    entry = alloc_t(DT_ENTRY);
+    *entry = *disktab;
+    entry->start = -1;
+    partition = cfg_get_strg(cf_partitions,"partition");
+    if (stat(partition,&st) < 0) die("stat %s: %s",partition,strerror(errno));
+    if (!S_ISBLK(st.st_mode) || ((st.st_rdev ^ disktab->device) & D_MASK(st.st_rdev)))
+       die("%s is not a valid partition device",partition);
+    entry->device = st.st_rdev;
+    cfg_init(cf_partition);
+    (void) cfg_parse(cf_partition);
+    start = cfg_get_strg(cf_partition,"start");
+    entry->start = start ? to_number(start) : -1;
+    for (walk = disktab; walk; walk = walk->next)
+       if (entry->device == walk->device)
+           die("Duplicate geometry definition for %s",partition);
+    entry->next = disktab;
+    disktab = entry;
+    cfg_init(cf_partitions);
+}
+
+#if BETA_TEST
+int has_partitions_beta(dev_t dev)
+{
+    int major = MAJOR(dev);
+    
+    if (
+      major == MAJOR_HD || major == MAJOR_IDE2 ||
+      major == MAJOR_IDE3 || major == MAJOR_IDE4 ||
+      major == MAJOR_IDE5 || major == MAJOR_IDE6 ||
+      major == MAJOR_EMD  ||
+      (major >= MAJOR_IDE7 && major <= MAJOR_IDE10) ||
+      major == MAJOR_XT || major == MAJOR_ESDI || major == MAJOR_ACORN
+       ) return 0xFFFFFFC0;    /* 6 bit partition mask */
+      
+    if (
+      major == MAJOR_SD || (major >= MAJOR_SD2 && major <= MAJOR_SD8) ||
+      major == MAJOR_AMI_HYP || major == MAJOR_HPT370 ||
+      (major >= MAJOR_EXPR && major <= MAJOR_EXPR+3) ||
+      (major >= MAJOR_I2O && major <= MAJOR_I2O+7) ||
+      (major >= MAJOR_SMART2 && major <= MAJOR_SMART2+7) ||
+      (major >= MAJOR_CISS && major <= MAJOR_CISS+7) ||
+      major == MAJOR_FTL || major == MAJOR_NFTL || major == MAJOR_DOC ||
+      (major >= MAJOR_SD9 && major <= MAJOR_SD16)
+        ) return 0xFFFFFFF0;   /* 4 bit partition mask */
+
+    if ( major == MAJOR_SATA || major == MAJOR_SATA2
+        )  return 0xFFFFFFE0;  /* 5 bit partition mask */
+
+    if ( major == MAJOR_IBM_iSER ||
+      (major >= MAJOR_DAC960 && major <= MAJOR_DAC960+7) ||
+      (major >= MAJOR_DAC960_8 && major <= MAJOR_DAC960_8+7)
+        )  return 0xFFFFFFF8;  /* 3 bit partition mask */
+
+    return 0;
+}
+#endif
+
+static
+unsigned char max_partno[512] = {
+/*
+  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+*/
+  0,  0,  0, 63,  0,  0,  0,  0, 15,  0,  0,  0,  0, 63,  0,  0,   /*  0x   */
+  0,  0,  0,  0,  0, 63, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+  0, 63, 63,  0, 63,  0,  0,  0,  0,  0,  0,  0, 15,  0,  0,  0,
+#ifndef MAJOR_IDE5
+  7,  7,  7,  7,  7,  7,  7,  7,  0, 63,  0,  0, 15, 15, 15, 15,
+#else
+  7,  7,  7,  7,  7,  7,  7,  7, 63, 63,  0,  0, 15, 15, 15, 15,
+#endif
+
+  0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,   /*  4x   */
+ 15, 15, 15, 15, 15, 15, 15, 15, 63, 63, 63, 63,  0, 15,  0,  0,
+  0,  0,  0,  0, 15, 15,  0,  0, 15, 15, 15, 15, 15, 15, 15, 15,
+  7,  0, 15,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+/*
+  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+*/
+ 15, 15, 15, 15, 15, 15, 15, 15,  7,  7,  7,  7,  7,  7,  7,  7,   /*  8x   */
+  0,  0,  0,  0,  0,  0,  0,  0,  0, 63,  0,  0,  0,  0,  0,  0,
+ 31, 31,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /*  Cx   */
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+/*                                                                
+  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+*/
+};
+
+int has_partitions(dev_t dev)
+{
+   int major = MAJOR(dev);
+   int ret=0;
+   
+   if (major >= nelem(max_partno)) {
+       warn("Major Device (%d) > %d",
+               major, nelem(max_partno)-1);
+   }
+   else if ( (ret=max_partno[major]) )  ret ^= 0xFFFFFFFF;
+   
+   return ret;
+}
+
+
+void do_disk(void)
+{
+    DT_ENTRY *entry,*walk;
+    struct stat st;
+    char *disk,*bios,*sectors,*heads,*cylinders,*maxpart;
+    int major;
+
+    disk = cfg_get_strg(cf_options,"disk");
+    cfg_init(cf_disk);
+    (void) cfg_parse(cf_disk);
+    if (stat(disk,&st) < 0) {
+        if (cfg_get_flag(cf_disk,"inaccessible")) {
+            cfg_unset(cf_options,"disk");
+            return;
+        }
+        die("do_disk: stat %s: %s",disk,strerror(errno));
+    }
+    if (!S_ISBLK(st.st_mode) || 
+       (has_partitions(st.st_rdev) && (MINOR(st.st_rdev) & P_MASK(st.st_rdev))))
+               die(" '%s' is not a whole disk device",disk);
+
+    entry = alloc_t(DT_ENTRY);
+    entry->device = st.st_rdev;
+    major = MAJOR(st.st_rdev);
+    bios = cfg_get_strg(cf_disk,"bios");
+    sectors = cfg_get_strg(cf_disk,"sectors");
+    heads = cfg_get_strg(cf_disk,"heads");
+    cylinders = cfg_get_strg(cf_disk,"cylinders");
+    maxpart = cfg_get_strg(cf_disk,"max-partitions");
+    if (maxpart) {
+      if (major<nelem(max_partno)) {
+       int i = to_number(maxpart);
+       if (max_partno[major] && max_partno[major]!=i) die("Cannot alter 'max-partitions' for known disk  %s", disk);
+       max_partno[major] = i;
+       if (i!=7 && i!=15 && i!=31 && i!=63) die("disk=%s:  illegal value for max-partitions(%d)", disk, i);
+      }
+      else {
+        die("Implementation restriction: max-partitions on major device > %d", nelem(max_partno)-1);
+      }
+    }
+    entry->bios = bios ? to_number(bios) : -1;
+    if (!sectors && !heads) entry->sectors = entry->heads = -1;
+    else if (!(sectors && heads))
+           die("Must specify SECTORS and HEADS together");
+       else {
+           entry->sectors = to_number(sectors);
+           entry->heads = to_number(heads);
+       }
+    if (cfg_get_flag(cf_disk,"inaccessible")) {
+       entry->heads = 0;
+       if (bios) die("INACCESSIBLE and BIOS are mutually exclusive");
+       if ( sectors || heads || cylinders )
+           die("No geometry variables allowed if INACCESSIBLE");
+    }
+    entry->cylinders = cylinders ? to_number(cylinders) : -1;
+    entry->start = 0;
+    for (walk = disktab; walk; walk = walk->next) {
+       if (entry->device == walk->device)
+           die("Duplicate \"disk =\" definition for %s",disk);
+    }
+    entry->next = disktab;
+    disktab = entry;
+    if (verbose >= 6) {
+       printf("do_disk: %s %04X 0x%02X  %d:%d:%d\n",
+               disk, entry->device, entry->bios, entry->cylinders,
+               entry->heads, entry->sectors);
+    }
+    cfg_init(cf_partitions);
+    (void) cfg_parse(cf_partitions);
+    cfg_unset(cf_options,"disk");
+}
+
+
+static int exists(const char *name)
+{
+    struct hd_geometry dummy;
+    int fd,yes;
+    char buff;
+
+    if ((fd = open(name,O_RDWR)) < 0) return 0; /* was O_RDONLY */
+    yes = read(fd,&buff,1) == 1 && ioctl(fd,HDIO_GETGEO,&dummy) >= 0;
+    (void) close(fd);
+    return yes;
+}
+
+
+#if 0
+
+static int scan_last_dev(ST_BUF *next,char *parent,int major,int increment)
+{
+    DIR *dp;
+    struct dirent *dir;
+    char name[PATH_MAX+1];
+    ST_BUF st,*walk;
+    int max,this;
+
+    st.next = next;
+    max = 0;
+    if ((dp = opendir(parent)) == NULL)
+       die("opendir %s: %s",parent,strerror(errno));
+    while ((dir = readdir(dp))) {
+       sprintf(name,"%s/%s",parent,dir->d_name);
+       if (stat(name,&st.st) >= 0) {
+           if (S_ISBLK(st.st.st_mode) && MAJOR(st.st.st_rdev) == major &&
+             (MINOR(st.st.st_rdev) & (increment-1)) == 0) {
+               this = MINOR(st.st.st_rdev)/increment+1;
+               if (this > max && exists(name)) max = this;
+           }
+           if (S_ISDIR(st.st.st_mode) && strcmp(dir->d_name,".") &&
+             strcmp(dir->d_name,"..")) {
+               for (walk = next; walk; walk = walk->next)
+                   if (stat_equal(&walk->st,&st.st)) break;
+               if (!walk) {
+                   this = scan_last_dev(&st,name,major,increment);
+                   if (this > max) max = this;
+               }
+           }
+       }
+    }
+    (void) closedir(dp);
+    return max;
+}
+
+#endif
+
+
+static int last_dev(int major,int increment)
+{
+/*
+ * In version 12 to 18, LILO only relied on scan_last_dev (or last_dev). This
+ * obviously didn't work if entries in /dev were missing. Versions 18 and 19
+ * added the probe loop, which seems to be okay, but which may probe for
+ * invalid minor numbers. The IDE driver objects to that. Since last_dev is
+ * only used to count IDE drives anyway, we try now only the first two devices
+ * and forget about scan_last_dev.
+ */
+    static int cached_major=-1, cached_increment=-1, cached_result=-1;
+    if(major == cached_major && increment == cached_increment)
+        return cached_result;
+    cached_major = major;
+    cached_increment = increment;
+
+    DEVICE dev;
+    int devs;
+
+    for (devs = 0;
+       devs < 2 && dev_open(&dev,MKDEV(major,increment*devs),O_BYPASS);
+           devs++)
+       if (exists(dev.name)) dev_close(&dev);
+        else {
+           dev_close(&dev);
+           break;
+       }
+    cached_result = devs;
+    return devs;
+}
+
+
+#ifdef LCF_LVM
+void lvm_bmap(struct lv_bmap *lbm)
+{
+    DEVICE dev;
+    static int lvmfd = -1;
+    static dev_t last_dev = 0;
+
+    if (lbm->lv_dev != last_dev) {
+       char lvm_char[] = DEV_DIR "/lvm";
+       unsigned short iop;
+
+       if (lvmfd != -1)
+           close(lvmfd);
+
+       if ((lvmfd = open(lvm_char, lbm->lv_dev, O_RDONLY)) < 0)
+           die("can't open LVM char device %s\n", lvm_char);
+
+       if (ioctl(lvmfd, LVM_GET_IOP_VERSION, &iop) < 0)
+           die("LVM_GET_IOP_VERSION failed on %s\n", lvm_char);
+
+       if (iop < 10)
+           die("LVM IOP %d not supported for booting\n", iop);
+       close(lvmfd);
+
+       lvmfd = dev_open(&dev, lbm->lv_dev, O_RDONLY);
+       if (lvmfd < 0)
+           die("can't open LVM block device %#x\n", lbm->lv_dev);
+       last_dev = lbm->lv_dev;
+    }
+    if (ioctl(lvmfd, LV_BMAP, lbm) < 0) {
+       perror(__FUNCTION__);
+       pdie("LV_BMAP error or ioctl unsupported, can't have image in LVM.\n");
+    }
+}
+#endif
+
+
+#ifdef LCF_EVMS
+void evms_bmap(struct evms_get_bmap_t *ebm)
+{                                  
+    DEVICE dev;
+    static int evms_fd = -1;
+    static dev_t evms_last_dev = 0;
+
+    if (ebm->dev != evms_last_dev) {
+        char evms_blk[] = DEV_DIR "/evms/block_device";
+        struct evms_version_t evms_ver;
+
+        /* Open the EVMS device */
+        if (evms_fd != -1)
+            close(evms_fd);
+
+        evms_fd = open(evms_blk, O_RDONLY);
+        if (evms_fd < 0)
+            die("Can't open EVMS block device %s.\n", evms_blk);
+
+        /* Get EVMS ioctl version number. */
+        if (ioctl(evms_fd, EVMS_GET_IOCTL_VERSION, &evms_ver) < 0)
+            die("EVMS_GET_IOCTL_VERSION failed on %s.\n", evms_blk);
+
+        /* Check that the ioctl version is >= 7.1.0 */
+        if (evms_ver.major < 7 ||
+            (evms_ver.major == 7 && evms_ver.minor < 1))
+            die("EVMS ioctl version %d.%d.%d does not support booting.\n",
+                evms_ver.major, evms_ver.minor, evms_ver.patch);
+        close(evms_fd);
+
+        evms_fd = dev_open(&dev, ebm->dev, O_RDONLY);
+        if (evms_fd < 0)
+            die("Can't open EVMS block device %#x\n", ebm->dev);
+        evms_last_dev = ebm->dev;
+    }
+
+    if (ioctl(evms_fd, EVMS_GET_BMAP, ebm) < 0) {
+        perror(__FUNCTION__);
+        pdie("EVMS_GET_BMAP error or ioctl unsupported. Can't have image on EVMS volume.\n");
+    }
+}
+#endif
+
+
+void geo_query_dev(GEOMETRY *geo,int device,int all)
+{
+    DEVICE dev;
+    int fd,get_all,major;
+    struct floppy_struct fdprm;
+    struct hd_geometry hdprm;
+
+    if (verbose>=5) printf("geo_query_dev: device=%04X\n", device);
+#if 0
+/*  Werner's original */
+    get_all = all || MAJOR(device) != MAJOR_FD; */
+#else
+/* simplify the condition -- JRC 2003-06-04 */
+    get_all = all;
+#endif
+    if (!MAJOR(device))
+       die("Trying to map files from unnamed device 0x%04x (NFS/RAID mirror down ?)",device);
+    if (device == MAJMIN_RAM)
+       die("Trying to map files from your RAM disk. "
+         "Please check -r option or ROOT environment variable.");
+    if (get_all) {
+       fd = dev_open(&dev,device,O_NOACCESS);
+    }
+    else {
+       fd = -1; /* pacify GCC */
+       geo->heads = geo->cylinders = geo->sectors = 1;
+       geo->start = 0;
+       geo->device = -1;
+    }
+    switch ((major=MAJOR(device))) {
+       case MAJOR_FD:
+           geo->device = device & 3;
+           if (!get_all) break;
+           if (ioctl(fd,FDGETPRM,&fdprm) < 0)
+               die("geo_query_dev FDGETPRM (dev 0x%04x): %s",device,
+                 strerror(errno));
+           geo->heads = fdprm.head;
+           geo->cylinders = fdprm.track;
+           geo->sectors = fdprm.sect;
+           geo->start = 0;
+           break;
+       case MAJOR_HD:
+       case MAJOR_IDE2:
+       case MAJOR_IDE3:
+       case MAJOR_IDE4:
+#ifdef MAJOR_IDE5
+       case MAJOR_IDE5:
+#endif
+       case MAJOR_IDE6:
+       case MAJOR_IDE7:
+       case MAJOR_IDE8:
+       case MAJOR_IDE9:
+       case MAJOR_IDE10:
+       case MAJOR_ESDI:
+       case MAJOR_XT:
+       case MAJOR_ACORN:
+       MASK63:
+           geo->device = 0x80 + (MINOR(device) >> 6) +
+                   (MAJOR(device) == MAJOR_HD ? 0 : last_dev(MAJOR_HD,64));
+           if (!get_all) break;
+           if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)
+               die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,
+                 strerror(errno));
+           geo->heads = hdprm.heads;
+           geo->cylinders = hdprm.cylinders;
+           geo->sectors = hdprm.sectors;
+           geo->start = hdprm.start;
+           break;
+       case MAJOR_SD:
+       case MAJOR_SD2:
+       case MAJOR_SD3:
+       case MAJOR_SD4:
+       case MAJOR_SD5:
+       case MAJOR_SD6:
+       case MAJOR_SD7:
+       case MAJOR_SD8:
+       MASK15:
+           geo->device = 0x80 + last_dev(MAJOR_HD,64) + (MINOR(device) >> 4);
+           if (!get_all) break;
+           if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)
+               die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,
+                 strerror(errno));
+           if (all && !hdprm.sectors)
+               die("HDIO_REQ not supported for your SCSI controller. Please "
+                 "use a DISK section");
+           geo->heads = hdprm.heads;
+           geo->cylinders = hdprm.cylinders;
+           geo->sectors = hdprm.sectors;
+           geo->start = hdprm.start;
+           break;
+       MASK31:
+           geo->device = 0x80 + last_dev(MAJOR_HD,64) + (MINOR(device) >> 5);
+           if (!get_all) break;
+           if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)
+               die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,
+                 strerror(errno));
+           if (all && !hdprm.sectors)
+               die("HDIO_REQ not supported for your Disk controller. Please "
+                 "use a DISK section");
+           geo->heads = hdprm.heads;
+           geo->cylinders = hdprm.cylinders;
+           geo->sectors = hdprm.sectors;
+           geo->start = hdprm.start;
+           break;
+       case MAJOR_DAC960:
+       case MAJOR_DAC960+1:
+       case MAJOR_DAC960+2:
+       case MAJOR_DAC960+3:
+       case MAJOR_DAC960+4:
+       case MAJOR_DAC960+5:
+       case MAJOR_DAC960+6:
+       case MAJOR_DAC960+7:
+       case MAJOR_IBM_iSER:
+       MASK7:
+           geo->device = 0x80 + last_dev(MAJOR_HD,64) + (MINOR(device) >> 3);
+           if (!get_all) break;
+           if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)
+               die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,
+                 strerror(errno));
+           if (all && !hdprm.sectors)
+               die("HDIO_REQ not supported for your DAC960/IBM controller. "
+                 "Please use a DISK section");
+           geo->heads = hdprm.heads;
+           geo->cylinders = hdprm.cylinders;
+           geo->sectors = hdprm.sectors;
+           geo->start = hdprm.start;
+           break;
+       case MAJOR_AMI_HYP:
+       case MAJOR_HPT370:
+       case MAJOR_EXPR:
+       case MAJOR_EXPR+1:
+       case MAJOR_EXPR+2:
+       case MAJOR_EXPR+3:
+       case MAJOR_FTL:
+       case MAJOR_NFTL:
+       case MAJOR_DOC:
+       case MAJOR_SMART2+0:
+       case MAJOR_SMART2+1:
+       case MAJOR_SMART2+2:
+       case MAJOR_SMART2+3:
+       case MAJOR_SMART2+4:
+       case MAJOR_SMART2+5:
+       case MAJOR_SMART2+6:
+       case MAJOR_SMART2+7:
+       case MAJOR_CISS+0:
+       case MAJOR_CISS+1:
+       case MAJOR_CISS+2:
+       case MAJOR_CISS+3:
+       case MAJOR_CISS+4:
+       case MAJOR_CISS+5:
+       case MAJOR_CISS+6:
+       case MAJOR_CISS+7:
+       case MAJOR_I2O:
+       case MAJOR_I2O+1:
+       case MAJOR_I2O+2:
+       case MAJOR_I2O+3:
+       case MAJOR_I2O+4:
+       case MAJOR_I2O+5:
+       case MAJOR_I2O+6:
+       case MAJOR_I2O+7:
+           geo->device = 0x80 + last_dev(MAJOR_HD,64) + (MINOR(device) >> 4);
+           if (!get_all) break;
+           if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)
+               die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,
+                 strerror(errno));
+           if (all && !hdprm.sectors)
+               die("HDIO_REQ not supported for your Array controller. Please "
+                 "use a DISK section");
+           geo->heads = hdprm.heads;
+           geo->cylinders = hdprm.cylinders;
+           geo->sectors = hdprm.sectors;
+           geo->start = hdprm.start;
+           break;
+
+       default:
+           if (max_partno[major] && major==MAJOR_LOOP) break;
+           if (max_partno[major] == 63)  goto MASK63;
+           if (max_partno[major] == 31)  goto MASK31;
+           if (max_partno[major] == 15)  goto MASK15;
+           if (max_partno[major] == 7)   goto MASK7;
+           
+           if ((MAJOR(device)>=120 && MAJOR(device)<=127)  ||
+               (MAJOR(device)>=240 && MAJOR(device)<=254) )
+               die("Linux experimental device 0x04x needs to be defined.\n"
+                   "Check 'man lilo.conf' under 'disk=' and 'max-partitions='", device);
+           else die("Sorry, don't know how to handle device 0x%04x",device);
+    }
+    if (get_all) dev_close(&dev);
+    if (verbose>=5) printf("exit geo_query_dev\n");
+}
+
+
+int is_first(int device)
+{
+    DT_ENTRY *walk;
+
+    for (walk = disktab; walk; walk = walk->next)
+       if (walk->device == device) break;
+    if (!walk && !old_disktab)
+       for (walk = disktab; walk; walk = walk->next)
+           if (walk->device == (device & D_MASK(device))) break;
+    if (walk && !walk->heads)
+       die("Device 0x%04X: Configured as inaccessible.\n",device);
+    if (walk && walk->bios != -1) return !(walk->bios & 0x7f);
+    switch (MAJOR(device)) {
+       case MAJOR_FD:
+           return !(device & 3);
+
+       case MAJOR_HD:
+           return !(MINOR(device) >> 6);
+
+       case MAJOR_IDE2:
+       case MAJOR_IDE3:
+       case MAJOR_IDE4:
+#ifdef MAJOR_IDE5
+       case MAJOR_IDE5:
+#endif
+       case MAJOR_IDE6:
+       case MAJOR_IDE7:
+       case MAJOR_IDE8:
+       case MAJOR_IDE9:
+       case MAJOR_IDE10:
+       case MAJOR_ESDI:
+       case MAJOR_XT:
+           return MINOR(device) >> 6 ? 0 : !last_dev(MAJOR_HD,64);
+
+       case MAJOR_SD:
+       case MAJOR_SD2:
+       case MAJOR_SD3:
+       case MAJOR_SD4:
+       case MAJOR_SD5:
+       case MAJOR_SD6:
+       case MAJOR_SD7:
+       case MAJOR_SD8:
+       case MAJOR_AMI_HYP:
+       case MAJOR_HPT370:
+       case MAJOR_EXPR+0:
+       case MAJOR_EXPR+1:
+       case MAJOR_EXPR+2:
+       case MAJOR_EXPR+3:
+       case MAJOR_NFTL:
+       case MAJOR_DOC:
+       case MAJOR_SMART2+0:
+       case MAJOR_SMART2+1:
+       case MAJOR_SMART2+2:
+       case MAJOR_SMART2+3:
+       case MAJOR_SMART2+4:
+       case MAJOR_SMART2+5:
+       case MAJOR_SMART2+6:
+       case MAJOR_SMART2+7:
+       case MAJOR_CISS+0:
+       case MAJOR_CISS+1:
+       case MAJOR_CISS+2:
+       case MAJOR_CISS+3:
+       case MAJOR_CISS+4:
+       case MAJOR_CISS+5:
+       case MAJOR_CISS+6:
+       case MAJOR_CISS+7:
+       case MAJOR_I2O:
+       case MAJOR_I2O+1:
+       case MAJOR_I2O+2:
+       case MAJOR_I2O+3:
+       case MAJOR_I2O+4:
+       case MAJOR_I2O+5:
+       case MAJOR_I2O+6:
+       case MAJOR_I2O+7:
+           return MINOR(device) >> 4 ? 0 : !last_dev(MAJOR_HD,64);
+
+       case MAJOR_DAC960:
+       case MAJOR_DAC960+1:
+       case MAJOR_DAC960+2:
+       case MAJOR_DAC960+3:
+       case MAJOR_DAC960+4:
+       case MAJOR_DAC960+5:
+       case MAJOR_DAC960+6:
+       case MAJOR_DAC960+7:
+       case MAJOR_IBM_iSER:
+           return MINOR(device) >> 3 ? 0 : !last_dev(MAJOR_HD,64);
+
+       default:
+           return 1; /* user knows what (s)he's doing ... I hope */
+    }
+}
+
+
+void geo_get(GEOMETRY *geo,int device,int user_device,int all)
+{
+    DT_ENTRY *walk;
+    int inherited,keep_cyls,is_raid=0;
+#ifdef LCF_DEVMAPPER
+    int i;
+
+    for(i = 0; i < dm_major_nr; i++)
+       if (MAJOR(device) == dm_major_list[i])
+           break;
+    while (i < dm_major_nr) {
+       DM_TABLE *dm_table;
+
+       for(dm_table = dmtab; dm_table; dm_table = dm_table->next)
+           if (dm_table->device == device)
+               break;
+
+       if (dm_table) {
+           DM_TARGET *target;
+
+            device = 0;
+           for(target = dm_table->target; target; target = target->next)
+               device = target->device;
+       } else {
+           DEVICE dev;
+           struct dm_task *dmt;
+           void *next = NULL;
+           char dmdev[PATH_MAX+1];
+           char buf[PATH_MAX+1];
+           char *slash;
+           int result;
+
+           dev_open(&dev, device, -1);
+           strncpy(dmdev, dev.name, PATH_MAX);
+           dmdev[PATH_MAX] = 0;
+           do {
+               memset(buf, 0, PATH_MAX + 1);
+               if ((result = readlink(dmdev, buf, PATH_MAX)) < 0 && errno != EINVAL)
+                   die("device-mapper: readlink(\"%s\") failed with: %s",buf,
+                       strerror(errno));
+               if (result >= 0) {
+                   if (buf[0] != '/' && (slash = strrchr(dmdev, '/')) != NULL)
+                       slash++;
+                   else
+                       slash = dmdev;
+                   strncpy(slash, buf, PATH_MAX - (slash-dmdev));
+               }
+               if (realpath(dmdev, buf) == NULL)
+                   die("device-mapper: realpath(\"%s\") failed with: %s",dmdev,
+                       strerror(errno));
+               strncpy(dmdev, buf, PATH_MAX);
+           } while (result >= 0);
+           dmdev[PATH_MAX] = 0;
+
+           if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+               die("device-mapper: dm_task_create(DM_DEVICE_TABLE) failed");
+           slash = strrchr(dmdev, '/');
+               if (slash)
+           slash++;
+               else
+           slash = dmdev;
+           if (!dm_task_set_major(dmt, MAJOR(device)) ||
+               !dm_task_set_minor(dmt, MINOR(device)))
+               die("device-mapper: dm_task_set_major() or dm_task_set_minor() failed");
+           if (!dm_task_run(dmt))
+               die("device-mapper: dm_task_run(DM_DEVICE_TABLE) failed");
+
+           dm_table = alloc_t(DM_TABLE);
+           dm_table->device = device;
+           dm_table->target = NULL;
+           dm_table->next = dmtab;
+           dmtab = dm_table;
+
+           device = 0;
+
+           do {
+               DM_TARGET *target;
+               uint64_t start,length;
+               int major,minor;
+               char *target_type,*params;
+               char *p;
+
+               next = dm_get_next_target(dmt, next, &start, &length,
+                 &target_type, &params);
+
+               if (!target_type) continue;
+
+               if (strcmp(target_type, "linear") != 0)
+                   die("device-mapper: only linear boot device supported");
+
+               target = alloc_t(DM_TARGET);
+               target->start = start;
+               target->length = length;
+               if (dm_version_nr < 4 &&
+                   isxdigit(params[0]) &&
+                   isxdigit(params[1]) &&
+                   params[2] == ':' &&
+                   isxdigit(params[3]) &&
+                   isxdigit(params[4])) { /* old 2.4 format */
+                   if (sscanf(params, "%02x:%02x %"PRIu64, &major, &minor, &target->offset) != 3)
+                       die("device-mapper: parse error in linear params (\"%s\")", params);
+               } else if (isdigit(params[0]) &&
+                          strchr(params, ':')) { /* dm_bdevname/format_dev_t (>= 2.6.0-test4?) format */
+                   if (sscanf(params, "%u:%u %"PRIu64, &major, &minor, &target->offset) != 3)
+                       die("device-mapper: parse error in linear params (\"%s\")", params);
+               } else { /* >= 2.5.69 format, this should go away soon */
+                   struct stat st;
+                   FILE *file;
+
+                   p = strrchr(params, ' ');
+                   if (p == NULL)
+                       die("device-mapper: parse error in linear params (\"%s\")", params);
+                   *p = 0;
+                   sprintf(buf, DEV_DIR "/%s", params);        /* let's hope it's there */
+                   if (stat(buf, &st) == 0) {
+                       if (!S_ISBLK(st.st_mode))
+                           die("device-mapper: %s is not a valid block device", buf);
+                       major = MAJOR(st.st_rdev);
+                       minor = MINOR(st.st_rdev);
+                   } else {                            /* let's try sysfs */
+                       int dev;
+                       sprintf(buf, "/sys/block/%s/dev", params);
+                       file = fopen(buf, "r");
+                       if (!file)
+                           die("device-mapper: \"%s\" could not be opened. /sys mounted?", buf);
+                       if (!fgets(buf, PATH_MAX, file))
+                           die("device-mapper: read error from \"/sys/block/%s/dev\"", params);
+                       if (sscanf(buf, "%u:%u", &major, &minor) != 2) {
+                           if (sscanf(buf, "%x", &dev) != 1)
+                               die("device-mapper: error getting device from \"%s\"", buf);
+                           major = MAJOR(dev);
+                           minor = MINOR(dev);
+                       }
+                       (void) fclose(file);
+                   }
+                   *p = ' ';
+                   if (sscanf(p+1, "%"PRIu64, &target->offset) != 1)
+                       die("device-mapper: parse error in linear params (\"%s\")", params);
+               }
+               target->device = (major << 8) | minor;
+               if (!device)
+                   device = target->device;
+               target->next = dm_table->target;
+               dm_table->target = target;
+           } while(next);
+
+           dm_task_destroy(dmt);
+
+           dev_close(&dev);
+       }
+
+       if (!device)
+           die("device-mapper: Error finding real device");
+       geo->base_dev = device;
+
+       for(i = 0; i < dm_major_nr; i++)
+           if (MAJOR(device) == dm_major_list[i])
+               break;
+    }
+#endif
+
+    if (verbose>=5) printf("geo_get: device %04X, all=%d\n", device, all);
+#ifdef LCF_LVM
+    /*
+     * Find underlying device (PV) for LVM.  It is OK if the underlying PV is
+     * really an MD RAID1 device, because the geometry of the RAID1 device is
+     * exactly the same as the underlying disk, so FIBMAP and LV_BMAP should
+     * return the correct block numbers regardless of MD.
+     *
+     * We do a quick test to see if the LVM LV_BMAP ioctl is working correctly.
+     * It should map the two blocks with the same difference as they were input,
+     * with a constant offset from their original block numbers.  If this is not
+     * the case then LV_BMAP is not working correctly (some widely distributed
+     * kernels did not have working LV_BMAP support, some just oops here).
+     */
+    if (MAJOR(device) == MAJOR_LVM)
+    {
+       struct lv_bmap lbmA, lbmB;
+#define DIFF 255
+
+       lbmA.lv_dev = lbmB.lv_dev = device;
+       lbmA.lv_block = 0;
+       lbmB.lv_block = DIFF;
+
+       lvm_bmap(&lbmA);
+       lvm_bmap(&lbmB);
+       if (lbmB.lv_block - lbmA.lv_block != DIFF)
+           die("This version of LVM does not support boot LVs");
+       device = geo->base_dev = lbmA.lv_dev;
+    }
+#endif
+
+#ifdef LCF_EVMS
+    if (MAJOR(device) == MAJOR_EVMS) {
+        struct evms_get_bmap_t ebm;
+        
+        ebm.rsector = 0;
+        ebm.dev = device;
+        ebm.status = 0;
+        
+        evms_bmap(&ebm);
+        
+        device = geo->base_dev = ebm.dev;
+    }
+#endif
+
+    /* Find underlying device for MD RAID */
+    if (MAJOR(device) == MD_MAJOR) {
+        char mdxxx[16];
+       int md_fd;
+/*     int pass;       */
+       struct md_version md_version_info;
+       md_array_info_t md_array_info;
+       md_disk_info_t md_disk_info;
+       int raid_limit;
+
+       sprintf(mdxxx, DEV_DISK_DIR "/md%d", MINOR(device));
+       if ((md_fd=open(mdxxx,O_NOACCESS)) < 0)
+       {
+           sprintf(mdxxx, DEV_DIR "/md/%d", MINOR(device));
+           if ((md_fd=open(mdxxx,O_NOACCESS)) < 0)
+               die("Unable to open %s", mdxxx);
+       }
+       if (ioctl(md_fd,RAID_VERSION,&md_version_info) < 0)
+           die("Unable to get RAID version on %s", mdxxx);
+       if (md_version_info.major > 0)
+           die("Raid major versions > 0 are not supported");
+       if (md_version_info.minor < 90)
+           die("Raid versions < 0.90 are not supported");
+       
+       if (ioctl(md_fd,GET_ARRAY_INFO,&md_array_info) < 0)
+           die("Unable to get RAID info on %s", mdxxx);
+        if (md_version_info.major != 0 || md_version_info.minor != 90 ||
+            ((md_array_info.major_version != 0 ||
+                md_array_info.minor_version != 90) &&
+             (md_array_info.major_version != 1 ||
+                md_array_info.minor_version != 0))
+            ) {
+            die("Incompatible Raid version information on %s   (RV=%d.%d GAI=%d.%d)",
+                mdxxx,
+                (int)md_version_info.major,
+                (int)md_version_info.minor,
+                (int)md_array_info.major_version,
+                (int)md_array_info.minor_version);
+            }
+       if (md_array_info.level != 1)
+           die("Only RAID1 devices are supported for boot images");
+       raid_limit = md_array_info.raid_disks + md_array_info.spare_disks;
+
+       /* version 22.7 */
+#if 1
+       is_raid = (device==boot_dev_nr);
+       md_disk_info.number = raid_index;
+       if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0)
+           die("GET_DISK_INFO: %s", mdxxx);
+       device = MKDEV(md_disk_info.major, md_disk_info.minor);
+
+#else          /* prior to 22.7 */
+{
+int pass;
+       for (pass = 0; pass < raid_limit; pass++) {
+           md_disk_info.number = pass;
+           if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0)
+#if BETA_TEST
+           {
+               printf("(raid) GET_DISK_INFO: failed for pass=%d\n", pass);
+               continue;
+           }
+#else
+               die("GET_DISK_INFO: %s", mdxxx);
+#endif
+           if (!(md_disk_info.state & (1 << MD_DISK_FAULTY))) {
+#if 1
+               is_raid = (device==boot_dev_nr);
+#else
+/* this change may be in error; the correct comparison is == */
+               is_raid = (device!=boot_dev_nr);
+#endif
+               device = MKDEV(md_disk_info.major, md_disk_info.minor);
+               break;
+           }
+       }
+}
+#endif /* end of code prior to version 22.7 */
+
+       close(md_fd);
+    }
+
+#if BETA_TEST
+       if (verbose>=5) printf("geo_get(2):  device=%04X, all=%d\n", device, all);
+#endif
+
+/* if using hard disk, scan the devices in /proc/partitions */
+    if (has_partitions(device) && all)   pf_hard_disk_scan();
+
+
+
+
+    for (walk = disktab; walk; walk = walk->next)
+       if (walk->device == device) break;
+    inherited = !walk && !old_disktab;
+#if BETA_TEST
+    if (verbose>=5) printf("inherited=%d\n", inherited);
+#endif
+    if (inherited)
+       for (walk = disktab; walk; walk = walk->next)
+           if (walk->device == (device & D_MASK(device))) break;
+#if BETA_TEST
+    if (verbose>=5) printf("walk=%08lx\n", (long)walk);
+#endif
+
+#if 1
+/* add 'all' to conditional below -- JRC 2002-08-20 */
+    if (walk && !walk->heads && all)
+#else
+/* Werner's original conditional */
+    if (walk && !walk->heads)
+#endif
+       die("Device 0x%04X: Configured as inaccessible.\n",device);
+    keep_cyls = !walk || walk->bios == -1 || walk->heads == -1 ||
+      walk->sectors == -1 || inherited || walk->start == -1;
+#if BETA_TEST
+    if (verbose>=5) printf("inherited=%d  keep_cyls=%d\n", inherited, keep_cyls);
+#endif
+
+#if 1
+/* add 'all' to conditional below -- JRC 2002-08-20 */
+    if (keep_cyls && (all || MAJOR(device)==MAJOR_FD) ) {
+#else
+/* Werner's original conditional */
+    if (keep_cyls) {
+#endif
+       geo_query_dev(geo,device,all);
+       
+       if (all) bios_device(geo, device);
+       
+       if ((geo->device & 0x7f) >= bios_max_devs() &&
+         user_device == -1 && (!walk || walk->bios == -1))
+           warn("BIOS drive 0x%02x may not be accessible",
+             geo->device);
+    }
+    if (walk) {
+       if (walk->bios != -1) geo->device = walk->bios;
+       if (walk->heads != -1) geo->heads = walk->heads;
+       if (walk->cylinders != -1 || !keep_cyls)
+           geo->cylinders = walk->cylinders;
+       if (walk->sectors != -1) geo->sectors = walk->sectors;
+       if (walk->start != -1 && !inherited) geo->start = walk->start;
+    }
+    if (user_device != -1) geo->device = user_device;
+    if (!all) {
+       if (verbose > 2)
+           printf("Device 0x%04x: BIOS drive 0x%02x, no geometry.\n",device,
+             geo->device);
+       return;
+    }
+    if (!geo->heads || !geo->cylinders || !geo->sectors)
+       die("Device 0x%04X: Got bad geometry %d/%d/%d\n",device,
+         geo->sectors,geo->heads,geo->cylinders);
+    if (geo->heads > BIOS_MAX_HEADS)
+       die("Device 0x%04X: Maximum number of heads is %d, not %d\n",device,
+         BIOS_MAX_HEADS,geo->heads);
+    if (geo->heads == BIOS_MAX_HEADS)
+       warn("Maximum number of heads = %d (as specified)\n"
+                       "   exceeds standard BIOS maximum of 255.", geo->heads);
+    if (geo->sectors > BIOS_MAX_SECS)
+       die("Device 0x%04X: Maximum number of sectors is %d, not %d\n",
+         device,BIOS_MAX_SECS,geo->sectors);
+    if (geo->sectors == BIOS_MAX_SECS)
+        warn("Maximum number of heads = %d (as specified)\n"
+                        "   exceeds standard BIOS maximum of 63.", geo->sectors);
+    if (!lba32 &&
+      (geo->start+geo->sectors-1)/geo->heads/geo->sectors >= BIOS_MAX_CYLS
+    ) {
+       warn("device 0x%04x exceeds %d cylinder limit.\n"
+        "   Use of the 'lba32' option may help on newer (EDD-BIOS) systems.",
+         device, BIOS_MAX_CYLS);
+    }
+    if (verbose >= 3) {
+       printf("Device 0x%04x: BIOS drive 0x%02x, %d heads, %d cylinders,\n",
+         device,geo->device,geo->heads,geo->cylinders == -1 ? BIOS_MAX_CYLS :
+         geo->cylinders);
+       printf("%15s%d sectors. Partition offset: %d sectors.\n","",
+         geo->sectors,geo->start);
+    }
+    geo->raid = is_raid;
+
+/* make the serial number association */
+    if (!is_raid) register_bios(geo->device, device);
+    else geo->device = md_bios;                /* 22.5.7 add this else */
+    
+    return;
+} /* end of geo_get */
+
+
+int geo_open(GEOMETRY *geo,char *name,int flags)
+{
+    char *here;
+    int user_dev,block_size;
+    struct stat st;
+
+    if ((here = strrchr(name,':')) == NULL) user_dev = -1;
+    else {
+       *here++ = 0;
+        warn("%s:BIOS syntax is no longer supported.\n    Please use a "
+         "DISK section.", name);
+       user_dev = to_number(here);
+    }
+    if ((geo->fd = open(name,flags)) < 0)
+       die("open %s: %s",name,strerror(errno));
+    if (fstat(geo->fd,&st) < 0) die("fstat %s: %s",name,strerror(errno));
+    if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
+       die("%s: neither a reg. file nor a block dev.",name);
+    geo->dev = S_ISREG(st.st_mode) ? st.st_dev : st.st_rdev;
+#if BETA_TEST
+       if (verbose>=4) {
+               printf("geo_open: (%s) st_dev(file)=%04X  st_rdev(blk)=%04X\n",
+               name,
+               (int)st.st_dev,
+               (int)st.st_rdev );
+       }
+#endif
+
+    geo_get(geo, geo->dev, user_dev, 1);
+    geo->file = S_ISREG(st.st_mode) ? st.st_dev : 0;
+    geo->boot = 0;
+#ifndef FIGETBSZ
+    geo->spb = 2;
+#else
+    if (!geo->file) geo->spb = 2;
+    else {
+       if (ioctl(geo->fd,FIGETBSZ,&block_size) < 0) {
+           warn("FIGETBSZ %s: %s",name,strerror(errno));
+           geo->spb = 2;
+       }
+       else {
+           if (!block_size || (block_size & (SECTOR_SIZE-1)))
+               die("Incompatible block size: %d\n",block_size);
+           geo->spb = block_size/SECTOR_SIZE;
+       }
+    }
+#endif
+    return geo->fd;
+}
+
+
+int geo_open_boot(GEOMETRY *geo,char *name)
+{
+    struct stat st;
+
+    if (verbose>=5) printf("geo_open_boot: %s\n", name);
+    if (stat(name,&st) < 0) die("stat %s: %s",name,strerror(errno));
+    if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
+       die("%s: neither a reg. file nor a block dev.",name);
+    geo->dev = S_ISREG(st.st_mode) ? st.st_dev : st.st_rdev;
+#if 1
+    if (MAJOR(geo->dev) == MAJOR_FD) geo->fd = 0;
+    else if ((geo->fd = open(name,O_NOACCESS)) < 0)
+           die("open %s: %s",name,strerror(errno));
+#else
+    if (MAJOR(geo->dev) != MAJOR_FD) {
+       if ((P_MASK(geo->dev) & geo->dev) != 0)
+           die("UNSAFE may be used with floppy or MBR only");
+    }
+    geo->fd = 0;
+#endif
+    geo_get(geo, geo->dev, -1, 0);
+    geo->file = S_ISREG(st.st_mode);
+    geo->raid = 0;
+    geo->boot = 1;
+    geo->spb = 1;
+    return geo->fd;
+}
+
+
+void geo_close(GEOMETRY *geo)
+{
+    if (geo->fd) (void) close(geo->fd);
+    geo->fd = 0;
+}
+
+
+#ifndef FIBMAP
+#define FIBMAP BMAP_IOCTL
+#endif
+
+
+int geo_comp_addr(GEOMETRY *geo,int offset,SECTOR_ADDR *addr)
+{
+    int block,sector;
+    static int linear_warnings = 0;
+
+#if BETA_TEST
+    if (verbose>=6)
+       printf("geo_comp_addr: dev = %x, offset=%d\n",
+               geo->device, offset);
+#endif
+
+#if 0
+    if (linear && lba32)
+       die("'linear' and 'lba32' (-l and -L) are mutually exclusive.");
+#endif
+    if (geo->boot && offset >= SECTOR_SIZE)
+       die("Internal error: sector > 0 after geo_open_boot");
+    block = offset/geo->spb/SECTOR_SIZE;
+    if (geo->file) {
+#ifdef LCF_REISERFS
+           struct statfs buf;
+
+           fstatfs(geo->fd, &buf);
+           if (buf.f_type == REISERFS_SUPER_MAGIC) {
+               if (ioctl (geo->fd, REISERFS_IOC_UNPACK, 1) == ENOSPC)
+                       die("Cannot unpack ReiserFS file");
+               if (verbose > 3) printf("fd %d: REISERFS_IOC_UNPACK\n", geo->fd);
+           }
+        /* Forcing reiser4 to perform tail2extent converstion */
+           if (buf.f_type == REISER4_SUPER_MAGIC) {
+               if (ioctl (geo->fd, REISER4_IOC_UNPACK, 1) != 0)
+                       die("Cannot unpack Reiser4 file");
+               if (verbose > 3) printf("fd %d: REISER4_IOC_UNPACK\n", geo->fd);
+
+           /* 
+               As we may have the situation when extent will be included
+               into transaction, and its item(s) will not be have the real block
+               numbers assigned, we should perform fsync() in order to guarantee,
+               that current atom is flushed and real block numbers assigned to 
+               the extent(s) file was converted in.
+           */
+               if (fdatasync(geo->fd) != 0)
+                   die("Cannot perform fdatasync");
+           
+               if (verbose > 3) printf("fd %d: fdatasync()\n", geo->fd);
+           }
+#endif
+       if (ioctl(geo->fd,FIBMAP,&block) < 0) pdie("ioctl FIBMAP");
+       if (!block) {
+           return 0;
+       }
+    }
+#ifdef LCF_LVM
+    if (MAJOR(geo->dev) == MAJOR_LVM) {
+       struct lv_bmap lbm;
+
+       lbm.lv_dev = geo->dev;
+       lbm.lv_block = block;
+
+       lvm_bmap(&lbm);
+       if (lbm.lv_dev != geo->base_dev)
+           die("LVM boot LV cannot be on multiple PVs\n");
+       block = lbm.lv_block;
+    }
+#endif
+
+#ifdef LCF_EVMS
+    if (MAJOR(geo->dev) == MAJOR_EVMS) {
+        struct evms_get_bmap_t ebm;
+                          
+        ebm.rsector = block * geo->spb;
+        ebm.dev = geo->dev;
+        ebm.status = 0;
+                            
+        evms_bmap(&ebm);
+        if (ebm.dev != geo->base_dev)
+            die("EVMS boot volume cannot be on multiple disks.\n");
+        sector = ebm.rsector + ((offset/SECTOR_SIZE) % geo->spb) + geo->start;
+    }
+    else
+#endif
+    {
+#ifdef LCF_DEVMAPPER 
+       int dev = geo->dev;
+       int i;
+#endif
+       sector = block*geo->spb+((offset/SECTOR_SIZE) % geo->spb);
+#ifdef LCF_DEVMAPPER 
+       for(i = 0; i < dm_major_nr; i++)
+           if (MAJOR(dev) == dm_major_list[i])
+               break;
+       while (i < dm_major_nr) {
+           DM_TABLE *dm_table;
+           DM_TARGET *dm_target;
+
+           for(dm_table = dmtab; dm_table; dm_table = dm_table->next)
+               if (dm_table->device == dev)
+                   break;
+           if (!dm_table)
+               die("device-mapper: Mapped device suddenly lost? (%d)", dev);
+
+           for(dm_target = dm_table->target; dm_target; dm_target = dm_target->next)
+               if (dm_target->start <= sector && sector < (dm_target->start+dm_target->length))
+                   break;
+           if (!dm_target)
+               die("device-mapper: Sector outside mapped device? (%d: %u/%"PRIu64")",
+                   geo->base_dev, sector, (uint64_t)(dm_table->target ?
+                     (dm_table->target->start+dm_table->target->length) : 0));
+
+           dev = dm_target->device;
+           sector = dm_target->offset+(sector-dm_target->start);
+
+           for(i = 0; i < dm_major_nr; i++)
+               if (MAJOR(dev) == dm_major_list[i])
+                   break;
+       }
+
+       if (dev != geo->dev && dev != geo->base_dev)
+           die("device-mapper: mapped boot device cannot be on multiple real devices\n");
+#endif
+       sector += geo->start;
+    }
+
+ /*   DON'T always use CHS addressing on floppies:     JRC   */
+/*    if ((geo->device & 0x80) && (linear || lba32)) { */
+    if ((linear || lba32)) {
+        addr->device = geo->device | (linear ? LINEAR_FLAG : (LBA32_FLAG|LBA32_NOCOUNT))
+#if 0
+                       | (do_md_install && geo->file==boot_dev_nr ? RAID_REL_FLAG : 0);
+#else
+                       | (do_md_install && geo->raid ? RAID_REL_FLAG : 0);
+#endif
+        addr->num_sect = linear ? 1 : (sector >> 24);
+       addr->sector = sector & 0xff;
+       addr->track = (sector >> 8) & 0xff;
+       addr->head = sector >> 16;
+       if (linear) {
+           int cyl = sector;
+           if (geo->sectors>0 && geo->heads>0) {
+               cyl /= geo->sectors;
+               cyl /= geo->heads;
+               if (cyl >= BIOS_MAX_CYLS && linear_warnings++ < 8) {
+                   warn("LINEAR may generate cylinder# above 1023 at boot-time.");
+               }
+           }
+            if (sector/(63*255) >= BIOS_MAX_CYLS)
+               die("Sector address %d too large for LINEAR"
+                                       " (try LBA32 instead).", sector);
+       }
+       if (verbose > 4)
+           printf("fd %d: offset %d -> dev 0x%02x, %s %d\n",
+                        geo->fd, offset, addr->device,
+                        lba32 ? "LBA" : "linear",
+                        sector);
+    }
+    else {
+       addr->device = geo->device;
+       addr->sector = 1;
+       addr->head = 0;
+       if (sector) {
+           if (geo->heads == 0)
+               die("BIOS device 0x%02x is inaccessible", geo->device);
+           addr->sector = (sector % geo->sectors)+1;
+           sector /= geo->sectors;
+           addr->head = sector % geo->heads;
+           sector /= geo->heads;
+       }
+       if (sector >= BIOS_MAX_CYLS)
+           die("geo_comp_addr: Cylinder number is too big (%d > %d)",sector,
+             BIOS_MAX_CYLS-1);
+       if (sector >= geo->cylinders && geo->cylinders != -1)
+           die("geo_comp_addr: Cylinder %d beyond end of media (%d)",sector,
+             geo->cylinders);
+       if (verbose > 4)
+           printf("fd %d: offset %d -> dev 0x%02x, head %d, track %d, sector %d\n",
+             geo->fd,offset,addr->device,addr->head,sector,addr->sector);
+       addr->track = sector & 255;
+       addr->sector |= (sector >> 8) << 6;
+        addr->num_sect = 1;
+    }
+
+    return 1;
+}
+
+
+int geo_find(GEOMETRY *geo,SECTOR_ADDR addr)
+{
+    SECTOR_ADDR here;
+    struct stat st;
+    int i;
+
+#if DEBUG_NEW
+    if (verbose>=2) {
+       printf("Find:  AL=%02x  CX=%04x  DX=%04x  LBA=%d\n", (int)addr.num_sect,
+               addr.sector + (addr.track<<8),
+               addr.device + (addr.head<<8),
+               addr.sector + (addr.track<<8) + (addr.head<<16) +
+               (addr.device&(LBA32_FLAG|LBA32_NOCOUNT)?addr.num_sect<<24:0) );
+    }
+#endif
+    if (fstat(geo->fd,&st) < 0) return 0;
+    geo_get(geo,st.st_dev,-1,1);
+    for (i = 0; i < (st.st_size+SECTOR_SIZE-1)/SECTOR_SIZE; i++)
+       if (geo_comp_addr(geo,i*SECTOR_SIZE,&here))
+           if (here.sector == addr.sector && here.track == addr.track &&
+             here.device == addr.device && here.head == addr.head &&
+             here.num_sect == addr.num_sect ) {
+               if (lseek(geo->fd,i*SECTOR_SIZE,SEEK_SET) < 0) return 0;
+               else return 1;
+           }
+    return 1;
+}
+
+
+#if 0
+int geo_devscan(int device)
+{
+    DT_ENTRY *walk;
+    unsigned int mask, codes = 0;
+    int bios;
+    int maxbios = 0;
+    
+    device &= D_MASK(device);
+
+/* mark those BIOS codes that are already used */
+    for (walk=disktab; walk; walk=walk->next) {
+       if (has_partitions(walk->device) && walk->bios != -1) {
+           bios = walk->bios & 0x7F;
+           if (bios >= 4*sizeof(codes) ) die("BIOS code %02X is too big (device %04X)", bios, device);
+           codes |= 1 << bios; 
+       }
+    }
+
+    bios = -1;
+/* extract BIOS code of master device, or -1 */
+    for (walk=disktab; walk; walk=walk->next) {
+       if (device == walk->device) {
+           bios = walk->bios;
+       }
+    }
+    if (bios > maxbios) maxbios = bios;
+
+/* if device has no BIOS code assigned, assign the next one */
+    if (bios == -1)
+       for (bios=0x80, mask=1; mask; mask<<=1, bios++)
+               if (!(mask&codes)) break;
+    
+    if (bios > DEV_MASK) die("geo_devscan:  ran out of device codes");
+    
+    for (walk=disktab; walk; walk=walk->next) {
+       if (device == walk->device) {
+           if (walk->bios == -1) walk->bios = bios;
+           else bios = walk->bios;
+           break;
+       }
+    }
+    if (bios > maxbios) maxbios = bios;
+    
+    if (verbose >= 2) printf("geo_devscan:  maxbios = %02X\n", maxbios);
+    
+    if (walk) return maxbios;  /* there was an entry in the disktab */
+    
+    walk = alloc_t(DT_ENTRY);
+    walk->device = device;
+    walk->bios = bios;
+    walk->sectors = walk->heads = walk->cylinders = walk->start = -1;
+    walk->next = disktab;
+    disktab = walk;
+    if (verbose>=2)
+       printf("geo_devscan: arbitrary bios assignment  dev=%04X  bios=0x%02X\n",
+                       device, bios);
+
+    for (walk=disktab; walk; walk=walk->next) {
+       if (device == (walk->device & D_MASK(walk->device))) {
+           if (walk->bios != -1) walk->bios = bios;
+       }
+    }
+
+    return maxbios;
+}
+
+#endif
+
diff --git a/src/geometry.h b/src/geometry.h
new file mode 100644 (file)
index 0000000..1bf387f
--- /dev/null
@@ -0,0 +1,177 @@
+/* geometry.h  -  Device and file geometry computation */
+/*
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2005 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+#ifndef GEOMETRY_H
+#define GEOMETRY_H
+
+#define LINUX 1
+
+#if LINUX
+#include <linux/fd.h>
+#include <linux/hdreg.h>
+#else
+struct hd_geometry {
+      unsigned char heads;
+      unsigned char sectors;
+      unsigned short cylinders;
+      unsigned long start;
+};
+
+/* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x030n/0x031n */
+#define HDIO_GETGEO            0x0301  /* get device geometry */
+struct floppy_struct {
+       unsigned int    size,           /* nr of sectors total */
+                       sect,           /* sectors per track */
+                       head,           /* nr of heads */
+                       track,          /* nr of tracks */
+                       stretch;        /* !=0 means double track steps */
+#define FD_STRETCH 1
+#define FD_SWAPSIDES 2
+#define FD_ZEROBASED 4
+
+       unsigned char   gap,            /* gap1 size */
+
+                       rate,           /* data rate. |= 0x40 for perpendicular */
+#define FD_2M 0x4
+#define FD_SIZECODEMASK 0x38
+#define FD_SIZECODE(floppy) (((((floppy)->rate&FD_SIZECODEMASK)>> 3)+ 2) %8)
+#define FD_SECTSIZE(floppy) ( (floppy)->rate & FD_2M ? \
+                            512 : 128 << FD_SIZECODE(floppy) )
+#define FD_PERP 0x40
+
+                       spec1,          /* stepping rate, head unload time */
+                       fmt_gap;        /* gap2 size */
+       const char      * name; /* used only for predefined formats */
+};
+#define FDGETPRM _IOR(2, 0x04, struct floppy_struct)
+#endif
+
+#if 1
+#define MAJOR(dev) (unsigned int)((((dev_t)(dev) >> 8) & 0xfff) | ((unsigned int) ((dev_t)(dev) >> 32) & ~0xfff))
+#define MINOR(dev) (unsigned int)(((dev_t)(dev) & 0xff) | ((unsigned int) ((dev_t)(dev) >> 12) & ~0xff))
+#define MKDEV(major,minor) (((minor & 0xff) | ((major & 0xfff) << 8) \
+         | (((unsigned long long int) (minor & ~0xff)) << 12) \
+         | (((unsigned long long int) (major & ~0xfff)) << 32)))
+#else
+#include <sys/sysmacros.h>
+#ifdef major
+#define MAJOR(dev) major(dev)
+#define MINOR(dev) minor(dev)
+#define MKDEV(maj,min) makedev(maj,min)
+#else
+/* from <linux/kdev_t.h>  */
+/* These are for user-level "dev_t" */
+#define MINORBITS      8
+#define MINORMASK      ((1U << MINORBITS) - 1)
+#error "Should not get here:  MAJOR/MINOR (geometry.h)"
+#define MAJOR(dev)     ((unsigned int) ((dev) >> MINORBITS))
+#define MINOR(dev)     ((unsigned int) ((dev) & MINORMASK))
+#define MKDEV(ma,mi)   (((ma) << MINORBITS) | (mi))
+#endif
+#endif
+
+/*  from <linux/fs.h> */
+#define BMAP_IOCTL 1           /* obsolete - kept for compatibility */
+#define FIBMAP    _IO(0x00,1)  /* bmap access */
+#define FIGETBSZ   _IO(0x00,2) /* get the block size used for bmap */
+
+
+
+typedef struct {
+    int device,heads;
+    int cylinders,sectors;
+    int start; /* partition offset */
+    int spb; /* sectors per block */
+    int fd,file;
+    int boot; /* non-zero after geo_open_boot */
+    int raid; /* file references require raid1 relocation */
+    dev_t dev, base_dev; /* real device if remapping (LVM, etc) */
+} GEOMETRY;
+
+typedef struct _dt_entry {
+    unsigned int device;
+    int bios;
+    int sectors;
+    int heads; /* 0 if inaccessible */
+    int cylinders;
+    int start;
+    struct _dt_entry *next;
+} DT_ENTRY;
+
+extern DT_ENTRY *disktab;
+
+
+/* unsigned char max_partno[256]; */
+/* index by major device number; entries must be 2**n-1 (7,15, or 63) */
+
+
+int has_partitions(dev_t dev);
+/* indicates that the specified device is a block hard disk device */
+/* returns the partition mask or 0 */
+
+
+void geo_init(char *name);
+/* Loads the disk geometry table. */
+
+int is_first(int device);
+/* Returns a non-zero integer if the specified device could be the first (i.e.
+   boot) disk, zero otherwise. */
+
+
+void geo_get(GEOMETRY *geo,int device,int user_device,int all);
+/* Obtains geometry information of the specified device. Sets the BIOS device
+   number to user_device unless -1. If ALL is zero, only the BIOS device number
+   is retrieved and the other geometry information is undefined. */
+
+
+int geo_open(GEOMETRY *geo,char *name,int flags);
+/* Opens the specified file or block device, obtains the necessary geometry
+   information and returns the file descriptor. If the name contains a BIOS
+   device specification (xxx:yyy), it is removed and stored in the geometry
+   descriptor. Returns the file descriptor of the opened object. */
+
+
+int geo_open_boot(GEOMETRY *geo,char *name);
+/* Like get_open, but only the first sector of the device is accessed. This
+   way, no geometry information is needed. */
+
+
+void geo_close(GEOMETRY *geo);
+/* Closes a file or device that has previously been opened by geo_open. */
+
+
+int geo_comp_addr(GEOMETRY *geo,int offset,SECTOR_ADDR *addr);
+/* Determines the address of the disk sector that contains the offset'th
+   byte of the specified file or device. Returns a non-zero value if such
+   a sector exists, zero if it doesn't. */
+
+
+int geo_find(GEOMETRY *geo,SECTOR_ADDR addr);
+/* lseeks in the file associated with GEO for the sector at address ADDR.
+   Returns a non-zero integer on success, zero on failure. */
+
+
+void geo_query_dev(GEOMETRY *geo,int device,int all);
+/* opens the specified device and gets the geometry information.  That
+   information is then stored in *geo */
+
+
+int is_dm_major(int major);
+/* tell whether the specified major device number is one of the
+   device-mapper major devices */
+   
+
+#if 0
+int geo_devscan(int device);
+/* called to fill in a disktab with arbitrary BIOS codes */
+#endif
+
+
+#endif
diff --git a/src/graph.S b/src/graph.S
new file mode 100644 (file)
index 0000000..6bf37db
--- /dev/null
@@ -0,0 +1,58 @@
+#if 0
+; graph.S  is
+Copyright 2000-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+#endif
+
+#ifndef GRAPH_S
+#define GRAPH_S
+
+
+NS     = 179   ; 0xB3
+NSW    = 180
+NSWW   = 181
+NNSSW  = 182
+SSW    = 183
+SWW    = 184   ; 0xB8
+NNSSWW = 185
+NNSS   = 186
+SSWW   = 187
+NNWW   = 188
+NNW    = 189
+NWW    = 190
+SW     = 191
+NE     = 192   ; 0xC0
+NEW    = 193
+SEW    = 194
+NSE    = 195
+EW     = 196
+NSEW   = 197
+NSEE   = 198
+NNSSE  = 199
+NNEE   = 200   ; 0xC8
+SSEE   = 201
+NNEEWW = 202
+SSEEWW = 203
+NNSSEE = 204
+EEWW   = 205
+NNSSEEWW = 206
+NEEWW  = 207
+NNEW   = 208   ; 0xD0
+SEEWW  = 209
+SSEW   = 210
+NNE    = 211
+NEE    = 212
+SEE    = 213
+SSE    = 214
+NNSSEW = 215
+NSEEWW = 216
+NW     = 217
+SE     = 218   ; 0xDA
+
+#endif
+; end of graph.S
+
diff --git a/src/identify.c b/src/identify.c
new file mode 100644 (file)
index 0000000..b26c33e
--- /dev/null
@@ -0,0 +1,135 @@
+/* identify.c  -  Translate label names to kernel paths */
+
+/* 
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "lilo.h"
+#include "common.h"
+#include "cfg.h"
+
+char *identify;
+static char *opt;
+static char *first, *dflt;
+static int idefault;
+
+
+static void do_identify(char *var,char type)
+{
+    char *label,*path,*alias,*initrd,*keytab,*appstr,*dtem,*addappstr;
+    char *rootstr;
+    int root,image, ramdisk, kt, append;
+
+#if 1
+    image = !!strchr(opt,'i');
+    ramdisk = !!strchr(opt,'r');
+    kt = !!strchr(opt,'k');
+    append = !!strchr(opt,'a');
+    root = !!strchr(opt,'R');
+    if (opt && !image && !ramdisk && !kt && !append
+       && !idefault && !root) exit(1);
+/*    if (!opt) image = 1; */
+#else
+    image = ramdisk = 1;
+    printf("do_identify:  opt=\"%s\"\n", opt);
+#endif
+    
+    label = strrchr(path = cfg_get_strg(cf_identify,var),'/');
+    if (label) label++;
+    if (cfg_get_strg(cf_all,"label")) label = cfg_get_strg(cf_all,"label");
+    else if (!label) label = path;
+
+    if (!first) first = stralloc(label);
+    
+    alias = cfg_get_strg(cf_all,"alias");
+    dtem = cfg_get_strg(cf_options,"default");
+
+    if (verbose>=2) printf("identify: dtem=%s  label=%s\n", dtem, label);
+#ifdef LCF_IGNORECASE
+    if (dtem && (!strcasecmp(label,dtem) || (alias && !strcasecmp(alias,dtem)))) {
+#else
+    if (dtem && (!strcmp(label,dtem) || (alias && !strcmp(alias,dtem)))) {
+#endif
+       if (verbose>=2) printf("setting  dflt\n");
+       dflt = dtem;
+    }
+
+    initrd = cfg_get_strg(cf_kernel,"initrd");
+    if (!initrd) initrd = cfg_get_strg(cf_options,"initrd");
+    keytab = cfg_get_strg(cf_options,"keytable");
+    if (!keytab) keytab="us.ktl";
+    appstr = cfg_get_strg(cf_kernel,"append");
+    if (!appstr) appstr = cfg_get_strg(cf_options,"append");
+    addappstr = cfg_get_strg(cf_kernel,"addappend");
+    rootstr = cfg_get_strg(cf_kernel,"root");
+    if (!rootstr) rootstr = cfg_get_strg(cf_options,"root");
+
+#ifdef LCF_IGNORECASE
+    if (!strcasecmp(label,identify) || (alias && !strcasecmp(alias,identify))) {
+#else
+    if (!strcmp(label,identify) || (alias && !strcmp(alias,identify))) {
+#endif
+       if (image) printf("%s\n",path);
+       if (ramdisk) printf("%s\n",initrd?initrd:"No initial ramdisk specified");
+       if (kt) printf("%s\n",keytab);
+       if (append) {
+           if (!appstr && !addappstr)
+               printf("No append= was specified\n");
+           else if ((appstr && !addappstr) || (!appstr && addappstr))
+               printf("%s\n", appstr?appstr:addappstr);
+           else printf("%s %s\n", appstr, addappstr);
+       }
+       if (root) printf("%s\n",rootstr?rootstr:"No root specified");
+       if (idefault) printf("%s\n", dflt ? dflt : first);
+       exit(0);
+    }
+}
+
+
+void id_image(void)
+{
+    cfg_init(cf_image);
+    (void) cfg_parse(cf_image);
+    do_identify("image",'i');
+    cfg_init(cf_identify);
+}
+
+
+void id_other(void)
+{
+    cfg_init(cf_other);
+    cfg_init(cf_kernel);
+    curr_drv_map = curr_prt_map = 0;
+    (void) cfg_parse(cf_other);
+    cfg_init(cf_identify);
+}
+
+
+void identify_image(char *label,char *options)
+{
+    identify = label;
+    opt = options;
+    if (verbose>=2) printf("identify_image: id='%s' opt='%s'\n", label, options);
+    idefault = !!strchr(opt,'D');
+    if (idefault) identify = "";
+    cfg_init(cf_identify);
+    if (cfg_parse(cf_identify)) cfg_error("Syntax error");
+    if (idefault && first) {
+       printf("%s\n", dflt ? dflt : first);
+       exit(0);
+    }
+    die("No image found for \"%s\"",label);
+}
diff --git a/src/identify.h b/src/identify.h
new file mode 100644 (file)
index 0000000..36888f5
--- /dev/null
@@ -0,0 +1,25 @@
+/* identify.h  -  Translate label names to kernel paths
+
+Copyright 1992-1995 Werner Almesberger.
+Copyright 1999-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+
+
+#ifndef IDENTIFY_H
+#define IDENTIFY_H
+
+void identify_image(char *label,char *options);
+
+/* Identifies the image which is referenced by the label. Prints the path name
+   to standard output. If options is non-NULL, the following characters are
+   used to filter the selection: i = traditional image, c = compound image,
+   v = verify that the file exists. An error message is printed to standard
+   error if no appropriate image can be found. */
+
+#endif
diff --git a/src/lilo.c b/src/lilo.c
new file mode 100644 (file)
index 0000000..a4e4522
--- /dev/null
@@ -0,0 +1,1031 @@
+/* lilo.c  -  LILO command-line parameter processing
+ * 
+ * Copyright 1992-1998 Werner Almesberger
+ * Copyright 1999-2007 John Coffman
+ * Copyright 2009-2010 Joachim Wiedorn
+ * All rights reserved.
+ * 
+ * Licensed under the terms contained in the file 'COPYING'
+ * in the source directory.
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <limits.h>
+#include <dirent.h>
+/*#include <asm/page.h>*/
+
+#include "config.h"
+#include "lilo.h"
+#include "common.h"
+#include "cfg.h"
+
+#if !__MSDOS__
+#include "raid.h"
+#include "boot.h"
+#include "device.h"
+#include "flags.i"
+#include "geometry.h"
+#endif /* !__MSDOS__ */
+#include "map.h"
+#if !__MSDOS__
+#include "bsect.h"
+#include "identify.h"
+#include "partition.h"
+#include "probe.h"
+#include "temp.h"
+#include "loader.h"
+#include "md-int.h"
+#include "edit.h"
+#endif /* !__MSDOS__ */
+
+
+char *config_file;             /* actual name of the config file */
+int config_read;               /* readable by other than root */
+FILE *errstd;
+
+static void configuration(void)
+{
+#if VERSION_MINOR>=50 && !__MSDOS__
+{
+               printf(
+               "-DBOOT_PARAMS_1=%d -DBOOT_PARAMS_2=%d  PATH_MAX=%d"
+                 "\n"
+                 ,
+                 (int)sizeof(BOOT_PARAMS_1),
+                 (int)sizeof(BOOT_PARAMS_2),
+                 PATH_MAX
+                    );
+}
+{
+#include "bitmap.h"
+       RGB pal[16];
+       RGB2 pal2[16];
+       
+       printf("\nBMFH=%d BMH=%d BMH2=%d RGB=%d(%d) RGB2=%d(%d) LH=%d\n",
+       (int)sizeof(BITMAPFILEHEADER),
+       (int)sizeof(BITMAPHEADER),
+       (int)sizeof(BITMAPHEADER2),
+       (int)sizeof(RGB),
+       (int)sizeof(pal),
+       (int)sizeof(RGB2),
+       (int)sizeof(pal2),
+       (int)sizeof(BITMAPLILOHEADER) );
+       printf("\nBPB=%d BP_DOS=%d\n",
+               (int)sizeof(BIOS_PARAMETER_BLOCK),
+               (int)sizeof(BOOT_PARAMS_DOS)
+                 );
+}
+#ifdef LCF_FIRST6
+       printf("\nSECTOR_ADDR6=%d\n", (int)sizeof(SECTOR_ADDR6));
+#endif
+
+#endif /* VERSION_MINOR>=50 && !__MSDOS__ */
+
+#if !__MSDOS__
+{
+  unsigned int j;
+  if (verbose>=5) {
+    if (crc(First.data,First.size)) {
+       j = crc(First.data,First.size-4);
+       brev(j);
+       printf("1=0x%x\n", j);
+    }
+    if (crc(Second.data,Second.size)) {
+       j = crc(Second.data,Second.size-4);
+       brev(j);
+       printf("2=0x%x\n", j);
+    }
+    if (crc(Third.data,Third.size)) {
+       j = crc(Third.data,Third.size-4);
+       brev(j);
+       printf("3=0x%x\n", j);
+    }
+    if (crc(Bitmap.data,Bitmap.size)) {
+       j = crc(Bitmap.data,Bitmap.size-4);
+       brev(j);
+       printf("B=0x%x\n", j);
+    }
+    if (crc(Chain.data,Chain.size)) {
+       j = crc(Chain.data,Chain.size-4);
+       brev(j);
+       printf("C=0x%x\n", j);
+    }
+    if (crc(Mbr.data,Mbr.size)) {
+       j = crc(Mbr.data,Mbr.size-4);
+       brev(j);
+       printf("M=0x%x\n", j);
+    }
+    if (crc(Mbr2.data,Mbr2.size)) {
+       j = crc(Mbr2.data,Mbr2.size-4);
+       brev(j);
+       printf("N=0x%x\n\n", j);
+    }
+  }
+}
+
+#if BETA_TEST
+{
+    int i, j, k=0;
+extern int has_partitions_beta(dev_t dev);     /* defined in geometry.c */
+
+
+    printf("\n");
+    for (i=0; i<256; i++) {
+       if ( has_partitions_beta(MKDEV(i,0)) != has_partitions(MKDEV(i,0)) ) {
+           printf("Major device = %d is not configured.\n", i);
+           k ++;
+       }
+    }
+    printf("%sk = %d (should be 0)\n\n", k?"ERROR: ":"", k);
+    for (i=0, j=0; i<40960; i+=17) {
+        dev_t dev;
+        int major, minor;
+        for (k=0; k<81920; k+=19) {
+            dev = MKDEV(i,k);
+            major = MAJOR(dev);
+            minor = MINOR(dev);
+            if (major != i  ||  minor != k) {
+                printf("ERROR: (%d,%d) -> (%d,%d)\n",
+                    i, k, major, minor);
+                j++;
+            }
+        }
+    }
+    if (j==0) printf("MKDEV check passed\n");
+}
+#endif
+
+#if VERSION_MINOR>=50
+{
+       dev_t dev; int i;
+       BOOT_VOLID x;
+       BOOT_SECTOR b;
+       dev = 0xFFF0;
+       i = dev;
+       printf("dev_t is %ssigned size=%d  i=%08X\n", i==0xFFF0 ? "un" : "", (int)sizeof(dev_t), i);
+       printf("size of BOOT_VOLID = %d   BOOT_SECTOR = %d\n", (int)sizeof(x), (int)sizeof(b));
+       printf("Size of MENUTABLE = %d\n", (int)sizeof(MENUTABLE));
+}
+#endif
+               printf("\nCFLAGS = " CFLAGS "\n");
+#if defined(LCF_DEVMAPPER) && defined(HAS_LIBDEVMAPPER_H)
+                printf("With");
+#else
+                printf("Without");
+#endif
+                printf(" device-mapper\n");
+               printf("\nglibc version %d.%d\n", __GLIBC__, __GLIBC_MINOR__);
+               printf("Kernel Headers included from  %d.%d.%d\n",
+                       LINUX_VERSION_CODE>>16,
+                       LINUX_VERSION_CODE>>8 & 255,
+                       LINUX_VERSION_CODE & 255);
+               printf("Maximum Major Device = %d\n", MAJOR(~0UL));
+#endif /* !__MSDOS__ */
+               printf("MAX_IMAGES = %d\t\tc=%d, s=%d, i=%d, "
+                               "l=%d, ll=%d, f=%d, d=%d, ld=%d\n",
+                       MAX_IMAGES, (int)sizeof(char),
+                       (int)sizeof(short), (int)sizeof(int),
+                       (int)sizeof(long), (int)sizeof(
+#if !__MSDOS__
+                       long
+#endif /* !__MSDOS__ */
+                            long),
+                       (int)sizeof(float), (int)sizeof(double),
+                       (int)sizeof(long double)
+                       );
+               printf("IMAGE_DESCR = %d   DESCR_SECTORS = %d\n\n",
+                       (int)sizeof(IMAGE_DESCR), (int)sizeof(DESCR_SECTORS));
+}
+
+#if !__MSDOS__
+
+static void show_other(int fd)
+{
+    BOOT_SECTOR buf[SETUPSECS-1];
+    const unsigned char *drvmap;
+    const unsigned char *prtmap;
+
+    if (read(fd,buf,sizeof(buf)) != sizeof(buf))
+       die("Read on map file failed (access conflict ?) 1");
+    if (!strncmp(buf[0].par_c.signature-4,"LILO",4)) {
+       printf("    Pre-21 signature (0x%02x,0x%02x,0x%02x,0x%02x)\n",
+         buf[0].par_c.signature[0],buf[0].par_c.signature[1],
+         buf[0].par_c.signature[2],buf[0].par_c.signature[3]);
+       return;
+    }
+    if (strncmp(buf[0].par_c.signature,"LILO",4)) {
+       printf("    Bad signature (0x%02x,0x%02x,0x%02x,0x%02x)\n",
+         buf[0].par_c.signature[0],buf[0].par_c.signature[1],
+         buf[0].par_c.signature[2],buf[0].par_c.signature[3]);
+       return;
+    }
+    drvmap = ((unsigned char *) buf+buf[0].par_c.drvmap);
+    prtmap = drvmap+2*(DRVMAP_SIZE+1);
+    while (drvmap[0] && drvmap[1]) {
+       if (drvmap[0]==0xFF && drvmap[1]==0xFF) {
+           if (drvmap[3]==0xFF) printf("    Master-Boot:  This BIOS drive will always appear as 0x80 (or 0x00)\n");
+           else printf("    Boot-As:  This BIOS drive will always appear as 0x%02X\n", drvmap[3]);
+           drvmap += 4;
+       } else {
+           printf("    BIOS drive 0x%02X is mapped to 0x%02X\n",drvmap[0],
+                                               drvmap[1]);
+           drvmap += 2;
+       }
+    }
+    /* fix VERY old bug -- offset of 0 in PT is okay */
+    while (prtmap[0] /*** && prtmap[1] ***/ ) {
+       printf("    BIOS drive 0x%02x, offset 0x%x: 0x%02x -> 0x%02x\n",
+         prtmap[0],prtmap[1]+PART_TABLE_OFFSET,prtmap[2],prtmap[3]);
+       prtmap += 4;
+    }
+}
+#endif /* !__MSDOS__ */
+
+static void show_images(char *map_file)
+{
+#if !__MSDOS__
+    DESCR_SECTORS descrs;
+    BOOT_SECTOR boot;
+    MENUTABLE menu;
+    BOOT_PARAMS_2 param2;
+    GEOMETRY geo;
+    SECTOR_ADDR addr[4];
+    char buffer[SECTOR_SIZE];
+#else /* __MSDOS */
+static DESCR_SECTORS descrs;
+static char buffer[SECTOR_SIZE];
+#endif /*__MSDOS__ */
+    char *name;
+    int fd,image;
+    int tsecs;
+    int tlinear, tlba32;
+    unsigned short flags;
+    time_t Time;
+
+#if !__MSDOS__
+    fd = geo_open(&geo,map_file,O_RDONLY);
+#else  /* __MSDOS__ */
+    if ((fd = open(map_file,O_RDONLY))<=0)
+       die("Cannot open map file: %s", map_file);
+#endif /* __MSDOS__ */
+    if (read(fd,buffer,SECTOR_SIZE) != SECTOR_SIZE)
+       die("read cmdline %s: %s",map_file,strerror(errno));
+    if (read(fd,(char*)&descrs,sizeof(descrs)) != sizeof(descrs))
+       die("read descrs %s: %s",map_file,strerror(errno));
+#if !__MSDOS__
+    if (lseek(fd, SECTOR_SIZE, SEEK_CUR) <= 0) /* skip zero sector */
+       die("lseek over zero sector %s: %s",map_file,strerror(errno));
+    if (read(fd,(char*)&param2,sizeof(param2)) != sizeof(param2))
+       die("read second params %s: %s",map_file,strerror(errno));
+    if (lseek(fd, - sizeof(menu), SEEK_END) <= 0)
+       die("lseek keytable %s: %s",map_file,strerror(errno));
+    if (read(fd,(char*)&menu,sizeof(menu)) != sizeof(menu))
+       die("read keytable %s: %s",map_file,strerror(errno));
+    tlba32  = (descrs.d.descr[0].start.device & LBA32_FLAG) != 0;
+    tlinear = !tlba32 && (descrs.d.descr[0].start.device & LINEAR_FLAG);
+    if (tlinear != linear  ||  tlba32 != lba32) {
+        printf("Warning: mapfile created with %s option\n",
+              tlinear?"linear":tlba32?"lba32":"no linear/lba32");
+        linear = tlinear;  lba32 = tlba32;
+    }
+    if (verbose) {
+       bsect_read(cfg_get_strg(cf_options,"boot"),&boot);
+#if 1
+       if (boot.par_1.cli != 0xFA) {   /* relocation happened */
+           int len, offset=0;
+           if (boot.sector[0] == 0xEB)         /* jmp short */
+               offset = boot.sector[1]+2;
+           else if (boot.sector[0] == 0xE9)    /* jmp near */
+               offset = *(short*)&boot.sector[1] + 3;
+           else die("Cannot undo boot sector relocation.");
+           len = SECTOR_SIZE - offset;
+           memmove(&boot, &boot.sector[offset], len);
+           if (boot.par_1.cli != 0xFA)
+               die("Cannot recognize boot sector.");
+       }
+#endif
+#if 1
+        Time = boot.par_1.map_stamp;
+       printf("Installed:  %s\n", ctime(&Time));
+#else
+       printf("Installed:  %s\n", ctime((time_t*)&boot.par_1.map_stamp));
+#endif
+       printf("Global settings:\n");
+       tsecs = (param2.delay*2197+3999)/4000;
+       printf("  Delay before booting: %d.%d seconds\n",tsecs/10,tsecs % 10);
+       if (param2.timeout == 0xffff) printf("  No command-line timeout\n");
+       else {
+           tsecs = (param2.timeout*2197+3999)/4000;
+           printf("  Command-line timeout: %d.%d seconds\n",tsecs/10,
+             tsecs % 10);
+       }
+       printf("  %snattended booting\n", param2.flag2&FLAG2_UNATTENDED ? "U" : "No u");
+       printf("  %sPC/AT keyboard hardware prescence check\n", param2.flag2&FLAG2_NOKBD ? "" : "No ");
+       if (boot.par_1.prompt & FLAG_PROMPT) printf("  Always enter boot prompt\n");
+       else printf("  Enter boot prompt only on demand\n");
+       printf("  Boot-time BIOS data%s saved\n",
+               boot.par_1.prompt & FLAG_NOBD ? " NOT" : "");
+       printf("  Boot-time BIOS data auto-suppress write%s bypassed\n",
+               boot.par_1.prompt & FLAG_BD_OKAY ? "" : " NOT");
+       printf("  Large memory (>15M) is%s used to load initial ramdisk\n", 
+               boot.par_1.prompt & FLAG_LARGEMEM ? "" : " NOT");
+       printf("  %sRAID installation\n",
+               boot.par_1.prompt & FLAG_RAID ? "" : "Non-");
+       printf("  Boot device %s be used for the Map file\n",
+               boot.par_1.prompt & FLAG_MAP_ON_BOOT ? "WILL" : "will not");
+       if (!param2.port) printf("  Serial line access is disabled\n");
+       else printf("  Boot prompt can be accessed from COM%d\n",
+             param2.port);
+       if (!param2.msg_len) printf("  No message for boot prompt\n");
+       else if (!cfg_get_strg(cf_options,"bitmap"))
+           printf("  Boot prompt message is %d bytes\n",param2.msg_len);
+       else printf("  Bitmap file is %d paragraphs (%d bytes)\n",
+                       param2.msg_len, 16*param2.msg_len);
+/* 22.6.2 begin */
+       if (*(unsigned short *) buffer != DC_MAGIC /* || !buffer[2] */)
+/* 22.6.2 end */
+           printf("  No default boot command line\n");
+       else printf("  Default boot command line: \"%s\"\n",buffer+2);
+       if (verbose>=3) {
+           printf("Serial numbers %08X\n", menu.serial_no[0]);
+       }
+       printf("Images:\n");
+    }
+/* 22.7 begin */
+    else       /* verbose==0 */
+#endif /* !__MSDOS__ */
+    {
+       if (*(unsigned short *) buffer == DC_MAGIC)
+           printf("Default boot command line: \"%s\"\n",buffer+2);
+    }
+/* 22.7 end */
+    for (image = 0; image < MAX_IMAGES; image++) {
+       if (*(name = descrs.d.descr[image].name)) {
+#if __MSDOS__
+           printf("%s\n", name
+#else /* !__MSDOS__ */
+           printf("%s%-" SA(MAX_IMAGE_NAME) "s %s%s%s",verbose > 0 ? "  " : "",name,
+             image ? "" : "*",
+#ifdef LCF_VIRTUAL
+             descrs.d.descr[image].flags & FLAG_VMDEFAULT ? "@" :
+#endif
+             "",
+#ifdef LCF_NOKEYBOARD
+             descrs.d.descr[image].flags & FLAG_NOKBDEFAULT ? "&" :
+#endif
+             ""
+#endif /* !__MSDOS__ */
+             );
+#if !__MSDOS__
+           if (verbose >= 2) {
+               if (descrs.d.descr[image].start.device & (LINEAR_FLAG|LBA32_FLAG)) {
+                  unsigned int sector;
+                  sector = (descrs.d.descr[image].start.device & LBA32_FLAG)
+                     && (descrs.d.descr[image].start.device & LBA32_NOCOUNT)
+                       ? descrs.d.descr[image].start.num_sect : 0;
+                  sector = (sector<<8)+descrs.d.descr[image].start.head;
+                  sector = (sector<<8)+descrs.d.descr[image].start.track;
+                  sector = (sector<<8)+descrs.d.descr[image].start.sector;
+                  printf(" <dev=0x%02x,%s=%d>",
+                    descrs.d.descr[image].start.device&DEV_MASK,
+                    descrs.d.descr[image].start.device&LBA32_FLAG ? "lba32" : "linear",
+                    sector);
+               }
+               else { /*  CHS addressing */
+                   printf(" <dev=0x%02x,hd=%d,cyl=%d,sct=%d>",
+                     descrs.d.descr[image].start.device,
+                     descrs.d.descr[image].start.head,
+                     descrs.d.descr[image].start.track,
+                     descrs.d.descr[image].start.sector);
+               }
+           }
+           printf("\n");
+           if (verbose >= 1) {
+               flags = descrs.d.descr[image].flags;
+#ifdef LCF_VIRTUAL
+               if (flags & FLAG_VMDISABLE)
+                   printf("    Virtual Boot is disabled\n");
+               if (flags & FLAG_VMWARN)
+                   printf("    Warn on Virtual boot\n");
+#endif         
+#ifdef LCF_NOKEYBOARD
+               if (flags & FLAG_NOKBDISABLE)
+                   printf("    NoKeyboard Boot is disabled\n");
+#endif         
+               if ( !(flags & FLAG_PASSWORD) )
+                   printf("    No password\n");
+               else printf("    Password is required for %s\n",flags &
+                     FLAG_RESTR ? "specifying options" : "booting this image");
+               printf("    Boot command-line %s be locked\n",flags &
+                 FLAG_LOCK ? "WILL" : "won't");
+               printf("    %single-key activation\n",flags & FLAG_SINGLE ?
+                 "S" : "No s");
+               if (flags & FLAG_KERNEL) {
+#ifdef NORMAL_VGA
+                   if (!(flags & FLAG_VGA))
+                      printf("    VGA mode is taken from boot image\n");
+                   else {
+                       printf("    VGA mode: ");
+                       switch (descrs.d.descr[image].vga_mode) {
+                           case NORMAL_VGA:
+                               printf("NORMAL\n");
+                               break;
+                           case EXTENDED_VGA:
+                               printf("EXTENDED\n");
+                               break;
+                           case ASK_VGA:
+                               printf("ASK\n");
+                               break;
+                           default:
+                               printf("%d (0x%04x)\n",
+                                 descrs.d.descr[image].vga_mode,
+                                 descrs.d.descr[image].vga_mode);
+                       }
+                   }
+#endif
+                   if (!(flags & FLAG_LOADHI))
+                       printf("    Kernel is loaded \"low\"\n");
+                   else printf("    Kernel is loaded \"high\"\n");
+                   if (!*(unsigned int *) descrs.d.descr[image].rd_size)
+                       printf("    No initial RAM disk\n");
+                   else printf("    Initial RAM disk is %d bytes\n",
+                         *(unsigned int *) descrs.d.descr[image].rd_size);
+                   if (flags & FLAG_TOOBIG)
+                       printf("       and is too big to fit between 4M-15M\n");
+               }
+               if (!geo_find(&geo,descrs.d.descr[image].start)) {
+                   printf("    Map sector not found\n");
+                   continue;
+               }
+               if (read(fd,addr,4*sizeof(SECTOR_ADDR)) !=
+                 4*sizeof(SECTOR_ADDR))
+                       die("Read on map file failed (access conflict ?) 2");
+               if (!geo_find(&geo,addr[0]))
+                   printf("    Fallback sector not found\n");
+               else {
+                   if (read(fd,buffer,SECTOR_SIZE) != SECTOR_SIZE)
+                       die("Read on map file failed (access conflict ?) 3");
+                   if (*(unsigned short *) buffer != DC_MAGIC)
+                       printf("    No fallback\n");
+                   else printf("    Fallback: \"%s\"\n",buffer+2);
+               }
+#define OTHER 0
+#if OTHER
+               if (flags & FLAG_KERNEL)
+#endif
+                   if (!geo_find(&geo,addr[1]))
+                       printf("    Options sector not found\n");
+                   else {
+                       if (read(fd,buffer,SECTOR_SIZE) != SECTOR_SIZE)
+                           die("Read on map file failed (access conflict ?) 4");
+                       if (*buffer) printf("    Options: \"%s\"\n",buffer);
+                       else printf("    No options\n");
+                   }
+#if OTHER
+               else {
+#else
+               if (!(flags & FLAG_KERNEL)) {
+#endif
+                   if (geo_find(&geo,addr[3])) show_other(fd);
+                   else printf("    Image data not found\n");
+               }
+           }
+#endif /*  !__MSDOS__ */
+       } /* if */
+    } /* for */
+#undef OTHER
+    (void) close(fd);
+#if !__MSDOS__
+    if (descrs.l.checksum ==
+         crc32(descrs.sector, sizeof(descrs.l.sector), CRC_POLY1) )
+#endif /* !__MSDOS__ */
+               exit(0);
+#if !__MSDOS__
+    fflush(stdout);
+    fprintf(errstd,"Checksum error\n");
+    exit(1);
+#endif /* !__MSDOS__ */
+}
+
+
+static void usage(char *name)
+{
+    char *here;
+
+#if !__MSDOS__
+    here = strrchr(name,'/');
+#else /* __MSDOS__ */
+    here = strrchr(name,'\\');
+#endif /* __MSDOS__ */
+    if (here) name = here+1;
+    fprintf(errstd,"usage: %s [ -C config_file ] -q [ -m map_file ] "
+      "[ -v N | -v ... ]\n",name);
+#if !__MSDOS__
+    fprintf(errstd,"%7s%s [ -C config_file ] [ -b boot_device ] [ -c ] "
+      "[ -g | -l | -L ]\n","",name);
+    fprintf(errstd,"%12s[ -F ] [ -i boot_loader ] [ -m map_file ] [ -d delay ]\n","");
+    fprintf(errstd,"%12s[ -v N | -v ... ] [ -t ] [ -s save_file | -S save_file ]\n",
+      "");
+    fprintf(errstd,"%12s[ -p ][ -P fix | -P ignore ] [ -r root_dir ] [ -w | -w+ ]\n","");
+#endif /* !__MSDOS__ */
+    fprintf(errstd,"%7s%s [ -C config_file ] [ -m map_file ] "
+      "-R [ word ... ]\n","",name);
+#if !__MSDOS__
+    fprintf(errstd,"%7s%s [ -C config_file ] -I name [ options ]\n","",name);
+    fprintf(errstd,"%7s%s [ -C config_file ] [ -s save_file ] "
+      "-u | -U [ boot_device ]\n","",name);
+    fprintf(errstd,"%7s%s -A /dev/XXX [ N ]\t\tinquire/activate a partition\n","",name);
+    fprintf(errstd,"%7s%s -M /dev/XXX [ mbr | ext ]\tinstall master boot record\n","",name);
+    fprintf(errstd,"%7s%s -T help \t\t\tlist additional options\n", "", name);
+    fprintf(errstd,"%7s%s -X\t\t\t\tinternal compile-time options\n", "", name);
+#endif /* !__MSDOS__ */
+    fprintf(errstd,"%7s%s -V [ -v ]\t\t\tversion information\n\n","",name);
+    exit(1);
+}
+
+
+int main(int argc,char **argv)
+{
+    char *name,*reboot_arg,*ident_opt,*new_root;
+    char *tell_param, *uninst_dev, *param, *act1, *act2, ch;
+static char *bitmap_file;
+    int more,version,uninstall,validate,activate,instmbr,geom;
+    int fd, temp=0, tell_early=0;
+    int raid_offset;
+#if !__MSDOS__
+    struct stat st;
+#endif /* !__MSDOS__ */
+
+    errstd = stderr;
+#if VERSION_MINOR>=50
+    if (sizeof(MENUTABLE)!=256) die("MENUTABLE is not 256 bytes (common.h)");
+#if !__MSDOS__
+    cfg_alpha_check();
+#endif /* !__MSDOS__ */
+#endif
+    config_file = DFL_CONFIG;
+    act1 = act2 = tell_param = 
+           reboot_arg = identify = ident_opt = new_root = uninst_dev = NULL;
+    do_md_install = zflag =
+           version = uninstall = validate = activate = instmbr = 0;
+    verbose = -1;
+#if !__MSDOS__
+    name = *argv;
+#else  /* __MSDOS__ */
+    name = "lilo";
+#endif /* __MSDOS__ */
+    argc--;
+
+#if !__MSDOS__    
+    if (atexit( (void(*)(void)) sync)) die("atexit(sync)");
+    if (atexit( (void(*)(void)) purge)) die("atexit(purge)");
+#endif /* !__MSDOS__ */
+    
+    cfg_init(cf_options);
+    while (argc && **++argv == '-') {
+       argc--;
+      /* first those options with a mandatory parameter */
+      /* Notably absent are "RuUvw" */
+       if (strchr("AbBCdDEfiImMPrsSTxZ", ch=(*argv)[1])) {
+           if ((*argv)[2]) param = (*argv)+2;
+           else {
+               param = *++argv;
+               if(argc-- <= 0) usage(name);
+           }
+       } else { 
+           param = NULL;
+           if (strchr("cFglLpqtVXz", ch)       /* those with no args */
+               && (*argv)[2]) usage(name);
+       }
+#if 0
+fprintf(errstd,"argc=%d, *argv=%s, ch=%c param=%s\n", argc, *argv, ch, param);
+#endif
+       switch (ch) {
+#if !__MSDOS__
+           case 'A':
+               activate = 1;
+               act1 = param;
+               if (argc && argv[1][0] != '-') {
+                   act2 = *++argv;
+                   argc--;
+               }
+               break;
+           case 'b':
+               cfg_set(cf_options,"boot",param,NULL);
+               break;
+           case 'B':
+               cfg_set(cf_options,"bitmap",param,NULL);
+               break;
+           case 'c':
+               cfg_set(cf_options,"compact",NULL,NULL);
+               compact = 1;
+               break;
+#endif /* !__MSDOS */
+           case 'C':
+               config_file = param;
+               break;
+#if !__MSDOS__
+           case 'd':
+               cfg_set(cf_options,"delay",param,NULL);
+               break;
+           case 'D':
+               cfg_set(cf_options,"default",param,NULL);
+               break;
+           case 'E':
+               eflag=1;
+               bitmap_file = param;
+               break;
+           case 'f':
+               cfg_set(cf_options,"disktab",param,NULL);
+               break;
+           case 'F':
+               force_fs=1;
+               break;
+           case 'g':
+               geometric |= AD_GEOMETRIC;
+               break;
+           case 'H':
+               force_raid=1;
+               break;
+           case 'i':
+               cfg_set(cf_options,"install",param,NULL);
+               break;
+           case 'I':
+               identify = param;
+               if (argc && *argv[1] != '-') {
+                   ident_opt = *++argv;
+                   argc--;
+               } else {
+                   ident_opt = "i";
+               }
+               break;
+           case 'l':
+               geometric |= AD_LINEAR;
+               break;
+           case 'L':
+               geometric |= AD_LBA32;
+               break;
+#endif /* !__MSDOS__ */
+           case 'm':
+               cfg_set(cf_options,"map",param,NULL);
+               break;
+#if !__MSDOS__
+           case 'M':
+               instmbr = 1;
+               act1 = param;
+#if !defined LCF_BUILTIN       || 1
+               if (argc && argv[1][0] != '-') {
+                   act2 = *++argv;
+                   argc--;
+               }
+#endif
+               break;
+           case 'p':
+               passw = 1;      /* force re-gen of password file */
+               break;
+           case 'P':
+               if ((act1=strchr(param,'='))) {
+                   *act1++ = 0;        /* null terminate */
+                   cfg_set(cf_options,param,act1,NULL);
+               }
+               else if (!strcasecmp(param,"fix"))
+                   cfg_set(cf_options,"fix-table",NULL,NULL);
+               else if (!strcasecmp(param,"ignore"))
+                   cfg_set(cf_options,"ignore-table",NULL,NULL);
+               else if (!strcasecmp(param,"x"))
+                   extended_pt = 1;
+               else
+                   cfg_set(cf_options,param,NULL,NULL);
+               break;
+#endif /* !__MSDOS__ */
+           case 'q':
+               query = 1;
+               break;
+#if !__MSDOS__
+           case 'r':
+               new_root = param;
+               break;
+#endif /* !__MSDOS__ */
+           case 'R':
+               if (*(param = (*argv)+2)) argc++;
+               else if (argc) param = *++argv;
+               else reboot_arg = "";
+               
+               while (argc) {
+                       if (!reboot_arg)
+                           *(reboot_arg = alloc(strlen(param)+1)) = 0;
+                       else {
+                           param = *++argv;
+                           strcat(reboot_arg = ralloc(reboot_arg,
+                               strlen(reboot_arg)+strlen(param)+2)," ");
+                       }
+                       strcat(reboot_arg, param);
+                       argc--;
+                   }
+#if 0
+fprintf(errstd,"REBOOT=\"%s\"\n", reboot_arg);             
+#endif
+               break;
+#if !__MSDOS__
+           case 's':
+               cfg_set(cf_options,"backup",param,NULL);
+               break;
+           case 'S':
+               cfg_set(cf_options,"force-backup",param,NULL);
+               break;
+           case 't':
+               test = 1;
+               break;
+           case 'T':
+               tell_param = param;
+               break;
+           case 'u':
+               validate = 1;
+               /* fall through */
+           case 'U':   /* argument to -u or -U is optional */
+               uninstall = 1;
+               if ((*argv)[2]) param = (*argv)+2;
+               else if (argc && argv[1][0] != '-') {
+                   param = *++argv;
+                   argc--;
+               }
+               uninst_dev = param;
+               break;
+#endif /* !__MSDOS__ */
+           case 'v':
+               if ((*argv)[2]) param = (*argv)+2;
+               else if (argc && argv[1][0]>='0' && argv[1][0]<='9') {
+                   param = *++argv;
+                   argc--;
+               }
+               if (param) 
+                   verbose = to_number(param);
+               else
+                   if (verbose<0) verbose = 1;
+                   else verbose++;
+               if (verbose) errstd = stdout;
+               break;
+           case 'V':
+               version = 1;
+               break;
+#if !__MSDOS__
+           case 'w':
+               cfg_set(cf_options,"nowarn",NULL,NULL);
+               nowarn = 1;
+               if ( (*argv)[2] == '+' ) nowarn = -1;
+               break;
+           case 'x':
+               cfg_set(cf_options,RAID_EXTRA_BOOT,param,NULL);
+               break;
+#endif /* !__MSDOS__ */
+           case 'X':
+               configuration();
+               exit(0);
+#if !__MSDOS__
+           case 'z':
+               zflag++;        /* force zero of MBR 8-byte area */
+               break;
+           case 'Z':
+               cfg_set(cf_options,"bios-passes-dl",param,NULL);
+               break;
+#endif /* !__MSDOS__ */
+           default:
+               usage(name);
+       }
+    }
+    if (argc) usage(name);
+#if !__MSDOS__
+    if (!new_root) new_root = getenv("ROOT");
+    if (new_root && *new_root) {
+       pp_fd = fopen(PARTITIONS, "r");
+       if (chroot(new_root) < 0) die("chroot %s: %s",new_root,strerror(errno));
+       if (chdir("/dev") < 0)
+               warn("root at %s has no /dev directory", new_root);
+       if (chdir("/") < 0) die("chdir /: %s",strerror(errno));
+    }
+    if (atexit(temp_remove)) die("atexit() failed");
+    if (version+activate+instmbr+(tell_param!=NULL) > 1) usage(name);
+    if (activate) do_activate(act1, act2);
+#endif /* !__MSDOS__ */
+    if (verbose > 0 || version) {
+       printf("LILO version %d.%d%s%s", VERSION_MAJOR, VERSION_MINOR,
+             VERSION_EDIT, test ? " (test mode)" : "");
+       if (version && verbose<=0) {
+           printf("\n");
+           return 0;
+       }
+       printf("\n * Copyright (C) 1992-1998 Werner Almesberger  (until v20)\n"
+                       " * Copyright (C) 1999-2007 John Coffman  (until v22)\n"
+                       " * Copyright (C) 2009-2010 Joachim Wiedorn  (since v23)\n"
+                       "This program comes with ABSOLUTELY NO WARRANTY. This is free software \n"
+                       "distributed under the BSD License (3-clause). Details can be found in \n"
+                       "the file COPYING, which is distributed with this software.\n"
+              );
+        if (verbose>0) {
+#if !__MSDOS__
+#include <sys/utsname.h>
+           struct utsname buf;
+#endif
+            printf("Released %s%s and compiled at %s on %s%s\n",
+               VERSION_DATE, comma ? "," : "", __TIME__, __DATE__, semi);
+#if !__MSDOS__
+           if (verbose>=2 && uname(&buf)==0) {
+               printf("Running %s kernel %s on %s\n",
+                       buf.sysname, buf.release, buf.machine);
+           }
+#endif
+       }
+        printf("\n");
+        if (version) {
+            if (verbose>=2) configuration();
+            return 0;
+        }
+    }
+
+    if (verbose > 0) errstd = stdout;
+#if !__MSDOS__
+    preload_types();
+    if (geometric & (geometric-1))
+       die ("Only one of '-g', '-l', or '-L' may be specified");
+
+    if (tell_param) tell_early = strcasecmp(tell_param, "chrul")
+                               && strcasecmp(tell_param, "ebda");
+    if (eflag) do_bitmap_edit(bitmap_file);
+    if (tell_param && tell_early) probe_tell(tell_param);
+    if (instmbr) do_install_mbr(act1, act2);
+#endif /* !__MSDOS__ */    
+
+    fd = cfg_open(config_file);
+    more = fd<0 ? 0 : cfg_parse(cf_options);
+    
+#if !__MSDOS__
+    temp = cfg_get_flag(cf_options,"nowarn");
+    if (nowarn < 0) nowarn = 0;
+    else nowarn = temp;
+/* All warnings appear if very verbose modes used */
+    if (verbose>=3) nowarn = 0;
+#endif /* !__MSDOS__ */
+
+    if (verbose>=6) printf("main: cfg_parse returns %d\n", more);
+
+#if !__MSDOS__
+    if (tell_param && !tell_early) probe_tell(tell_param);
+
+    if (fstat(fd,&st) < 0)
+           die("fstat %s: %s", config_file, strerror(errno) );
+
+    if (S_ISREG(st.st_mode)) {
+        if (st.st_uid)
+            warn("%s should be owned by root", config_file);
+        else if (st.st_mode & (S_IWGRP | S_IWOTH))
+           warn("%s should be writable only for root", config_file);
+        config_read = !!(st.st_mode & (S_IRGRP | S_IROTH));
+    }
+
+    if (!cfg_get_flag(cf_options,"nodevcache"))  preload_dev_cache();
+    
+    if (verbose<0 && cfg_get_strg(cf_options,"verbose"))
+       verbose = to_number(cfg_get_strg(cf_options,"verbose"));
+    if (verbose<0) verbose = 0;
+    if (verbose) errstd = stdout;
+
+    compact = cfg_get_flag(cf_options,"compact");
+    geom = cfg_get_flag(cf_options,"geometric");
+    linear = cfg_get_flag(cf_options,"linear");
+    lba32  = cfg_get_flag(cf_options,"lba32");
+    
+    if (geom+linear+lba32 > 1)
+       die("May specify only one of GEOMETRIC, LINEAR or LBA32");
+    if (geometric) {
+       if (geom+linear+lba32 > 0)  
+           warn("Ignoring entry '%s'", geom ? "geometric" :
+                     linear ? "linear" : "lba32");
+       geom = linear = lba32 = 0;
+       if (geometric==AD_LBA32) lba32 = 1;
+       else if (geometric==AD_LINEAR) linear = 1;
+       else if (geometric==AD_GEOMETRIC) geom = 1;
+    }    
+    if (geom+linear+lba32 == 0) {
+       warn("LBA32 addressing assumed");
+       lba32 = 1;
+    }
+    if (linear) warn(
+       "LINEAR is deprecated in favor of LBA32:  LINEAR specifies 24-bit\n"
+       "  disk addresses below the 1024 cylinder limit; LBA32 specifies 32-bit disk\n"
+       "  addresses not subject to cylinder limits on systems with EDD-BIOS extensions;\n"
+       "  use LINEAR only if you are aware of its limitations.");
+    
+    if (identify) identify_image(identify,ident_opt);
+
+    if (uninstall)
+       bsect_uninstall(uninst_dev ? uninst_dev : cfg_get_strg(cf_options,
+             "boot"),cfg_get_strg(cf_options,"backup"),validate);
+#endif /* !__MSDOS__ */
+
+    if (reboot_arg) {
+       map_patch_first(cfg_get_strg(cf_options,"map") ? cfg_get_strg(
+             cf_options,"map") : MAP_FILE, reboot_arg);
+       exit(0);
+    }
+
+#if !__MSDOS__
+    if ( (param = cfg_get_strg(cf_options,"bios-passes-dl")) ) {
+       if (strchr("YyTt1", *param)) bios_passes_dl = DL_GOOD;
+       if (strchr("NnFf0", *param)) bios_passes_dl = DL_BAD;
+    }
+    if (bios_passes_dl == DL_NOT_SET)  check_bios();   /* in probe.c */
+
+    if (compact && (linear || lba32) && verbose>=4)
+       warn("COMPACT may conflict with %s on some "
+               "systems", lba32 ? "LBA32" : "LINEAR");
+
+    geo_init(cfg_get_strg(cf_options,"disktab"));
+#endif /* !__MSDOS__ */
+    if (query)
+       show_images(!cfg_get_strg(cf_options,"map") ? MAP_FILE :
+             cfg_get_strg(cf_options,"map"));
+
+#if !__MSDOS__
+/*************************************************/
+/*  Doing a real install (may be test mode)      */
+/*************************************************/
+
+/* test for a RAID installation */
+       raid_offset = raid_setup();
+       if (verbose >= 2) {
+           printf("raid_setup returns offset = %08X  ndisk = %d\n", raid_offset, ndisk);
+           dump_serial_nos();    
+       }
+
+       if (verbose >=2 && do_md_install)
+           printf("raid flags: at bsect_open  0x%02X\n", raid_flags);
+
+       bsect_open(
+               cfg_get_strg(cf_options,"boot"),
+               cfg_get_strg(cf_options,"map") ?
+                       cfg_get_strg(cf_options,"map") : MAP_FILE,
+               cfg_get_strg(cf_options,"install"),
+               cfg_get_strg(cf_options,"delay") ?
+                       timer_number(cfg_get_strg(cf_options,"delay")) : 0,
+               cfg_get_strg(cf_options,"timeout") ?
+                       timer_number(cfg_get_strg(cf_options,"timeout")) : -1,
+               raid_offset );
+       if (more) {
+           cfg_init(cf_top);
+           if (cfg_parse(cf_top)) cfg_error("Syntax error");
+       }
+       
+       temp = bsect_number();
+       if (temp==0) die("No images have been defined.");
+       else if (temp<0) die("Default image doesn't exist.");
+
+#ifdef LCF_VIRTUAL
+       check_vmdefault();
+#endif
+#ifdef LCF_NOKEYBOARD
+       check_nokbdefault();
+#endif
+       check_fallback();
+       check_unattended();
+       
+       if (verbose>=2) dump_serial_nos();
+       if (do_md_install) raid_final();
+       else if (!test) {
+           char *cp;
+           
+           if (verbose) printf("Writing boot sector.\n");
+
+           cp = cfg_get_strg(cf_options,"force-backup");
+           if (cp) bsect_update(cp,1,0);
+           else bsect_update(cfg_get_strg(cf_options,"backup"),0,0);
+
+       } 
+       else {
+           bsect_cancel();
+           if (passw)
+               printf("The password crc file has *NOT* been updated.\n");
+
+           printf("The boot sector and the map file have *NOT* been "
+             "altered.\n");
+       }
+       if (verbose>=4) dump_serial_nos();
+       if (warnings) {
+           if (warnings>1)
+               printf("%d warnings were ", warnings);
+            else printf("One warning was ");
+            printf("%sed.\n", nowarn ? "suppress" : "issu");
+       }
+#else  /* __MSDOS__ */
+       die("No option switches specified:  -q, -R, or -V");
+#endif /* __MSDOS__ */
+       
+    return 0;
+}
diff --git a/src/lilo.h b/src/lilo.h
new file mode 100644 (file)
index 0000000..1f1ef7d
--- /dev/null
@@ -0,0 +1,498 @@
+/* lilo.h  -  LILO constants
+
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2006 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+
+/* This file is also included by the boot loader assembler code. Put
+   everything that isn't legal C syntax or isn't swallowed by the
+   preprocessor into #ifdef LILO_ASM ... #endif */
+
+#ifndef LILO_H
+#define LILO_H
+
+#if !__MSDOS__
+#define INT4 int
+#else
+#define INT4 long
+#endif /* !__MSDOS__ */
+
+/* This is the stuff to check the configuration:
+ */
+#if defined(LCF_READONLY) && defined(LCF_REWRITE_TABLE)
+#error "Incompatible Makefile options: READONLY and REWRITE_TABLE"
+#endif
+#ifdef LCF_LARGE_EBDA
+#error "Configuration option '-DLARGE_EBDA' is deprecated"
+#endif
+
+/*
+ * Starting with 2.1.something, Linux kernels put VGA constants and segment
+ * definitions into asm/boot.h instead of linux/config.h
+ */
+
+#if 0
+
+#ifdef HAS_BOOT_H
+#include <asm/boot.h>
+#else
+#include <linux/config.h>
+#endif
+
+#else
+
+/* Don't touch these, unless you really know what you're doing. */
+#define DEF_INITSEG    0x9000
+#define DEF_SYSSEG     0x1000
+#define DEF_SETUPSEG   0x9020
+#define DEF_SYSSIZE    0x7F00
+
+/* Internal svga startup constants */
+#define NORMAL_VGA     0xffff          /* 80x25 mode */
+#define EXTENDED_VGA   0xfffe          /* 80x50 mode */
+#define ASK_VGA                0xfffd          /* ask for it at bootup */
+
+#endif
+
+#if defined(HAS_VERSION_H) && !__MSDOS__
+#include <linux/version.h>
+#endif /* !__MSDOS__ */
+
+#ifndef LINUX_VERSION_CODE
+#define LINUX_VERSION_CODE 0
+#endif
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+#define nelem(a) (sizeof(a)/sizeof((a)[0]))
+#define S2(x) #x
+#define SA(x) S2(x)
+
+#include "version.h"
+#define VERSION 256*VERSION_MINOR+VERSION_MAJOR
+#if VERSION_MINOR >= 50
+# define BETA_TEST 1
+#else
+# define BETA_TEST 0
+#endif
+
+/* definitions for pf_hard_disk_scan in device.c  */
+#ifdef DEBUG_PARTITIONS
+#define PARTITIONS "./devfs_partitions"
+#else
+#define PARTITIONS "/proc/partitions"
+#endif
+
+
+/* the known major device numbers */
+#define MAJMIN_RAM     0x101 /* RAM disk */
+#ifdef LCF_MDPRAID
+#define MAJOR_MDP_SORT  1 /* Convert MAJOR_MDP to this for sorting */
+#endif
+#define MAJOR_EMD_SORT  2 /* Convert MAJOR_EMD to this for sorting */
+#define MAJOR_HPT370_SORT  2 /* Convert MAJOR_HPT370 to this for sorting */
+#define MAJOR_FD       2 /* floppy disks */
+#define MAJOR_HD       3 /* IDE-type hard disks */
+#define MAJOR_LOOP     7 /* Loopback devices 0-15 */
+#define MAJOR_SD       8 /* SCSI disks 0-15 */
+#define MAJOR_MD       9 /* multi-disk RAID sets */
+#define MAJOR_XT       13 /* XT-type hard disks */
+#define MAJOR_ACORN    21 /* Acorn MFM controller */
+#define MAJOR_IDE2     22 /* IDE on second interface */
+#define MAJOR_IDE3     33 /* IDE on third interface */
+#define MAJOR_IDE4     34 /* IDE on fourth interface */
+#define MAJOR_ESDI     36 /* PS/2 ESDI drives */
+#define MAJOR_FTL      44 /* Flash Transition Layer on Memory Technology Device */
+#define MAJOR_PP       45 /* Parallel Port IDE drive */
+#define MAJOR_PPFD     47 /* Parallel Port floppy drive */
+#define MAJOR_DAC960   48 /* First Mylex DAC960 PCI RAID controller */
+#if !BETA_TEST || 1
+#define MAJOR_IDE5     56 /* IDE on fifth interface */
+#endif
+#define MAJOR_IDE6     57 /* IDE on sixth interface */
+#define MAJOR_LVM      58 /* Logical Volume Manager block device */
+#define MAJOR_EXPR     60 /* Experimental devices 60..63 */
+/*#define MAJOR_FL     62 / M-Systems Disk-On-Chip 2000 ***experimental*** */
+
+#define MAJOR_SD_SORT  64 /*** MAJOR_SD converted to this for sorting ***/
+#define MAJOR_SD2      65 /* SCSI disks 16-31 */
+#define MAJOR_SD3      66 /* SCSI disks 32-47 */
+#define MAJOR_SD4      67 /* SCSI disks 48-63 */
+#define MAJOR_SD5      68 /* SCSI disks 64-79 */
+#define MAJOR_SD6      69 /* SCSI disks 80-95 */
+#define MAJOR_SD7      70 /* SCSI disks 96-111 */
+#define MAJOR_SD8      71 /* SCSI disks 112-127 */
+#define MAJOR_SMART2   72 /* First Compaq Smart/2 Major 72-79 */
+#define MAJOR_I2O      80  /* First I2O block device 80-87 */
+#define MAJOR_IDE7     88 /* IDE on seventh interface */
+#define MAJOR_IDE8     89 /* IDE on eighth interface */
+#define MAJOR_IDE9     90 /* IDE on ninth interface */
+#define MAJOR_IDE10    91 /* IDE on tenth interface */
+#define MAJOR_PPDD     92 /* PPDD encrypted disks - not supported */
+#define MAJOR_NFTL     93 /* NAND Flash Translation Layer (Disk-On-Chip) */
+#define MAJOR_DOC      100 /* Disk-On-Chip driver */
+#define MAJOR_AMI_HYP  101 /* AMI Hyper Disk RAID controller */
+#define MAJOR_CISS     104 /* First CCISS Major 104-111 */
+#define MAJOR_IBM_iSER 112 /* IBM iSeries virtual disk */
+#define MAJOR_HPT370   114 /* HPT370 controller */
+#define MAJOR_EVMS     117 /* Enterprise Volume Management System */
+#define MAJOR_SD9      128 /* SCSI disks 129     */
+#define MAJOR_SD16     135 /* SCSI disks    -255 */
+#define MAJOR_DAC960_8 136 /* Ninth Mylex DAC960 PCI RAID controller */
+#define MAJOR_EMD      153 /* Enhanced multi-disk RAID sets */
+#define MAJOR_SATA     160 /* Carmel SATA Disk on first 8-port controller */
+#define MAJOR_SATA2    161 /* Carmel SATA Disk on 2nd 8-port controller */
+/* don't use the following */
+#define MAJOR_MDP      254 /* Enhanced multi-disk RAID sets [experimental?] */
+
+#define MAX_TOKEN      1023 /* max device Token length */
+#define MAX_IMAGE_NAME 15 /* maximum name length (w/o terminating NUL) */
+#define MAX_DESCR_SECTORS  12  /* upper limit on MAX_DESCR_SECS */
+
+#ifdef LCF_PASS160
+#undef SHS_PASSWORDS
+#define SHS_PASSWORDS          /* use this one if SHS passwords are in use */
+#define MAX_PW_CRC     5       /* max # of longwords in password digest */
+#define PW_FILE_SUFFIX ".shs"          /* suffix for the file that saves password digest */
+#else
+#define CRC_PASSWORDS          /* use this one if CRC passwords are in use */
+#define MAX_PW_CRC     2       /* max # of CRC-32's in password */
+#define PW_FILE_SUFFIX ".crc"          /* suffix for the file that saves password CRC's */
+#endif
+
+#ifdef LCF_DSECS
+#define MAX_DESCR_SECS LCF_DSECS
+#else
+#define MAX_DESCR_SECS 2       /* maximum # of descriptor sectors */
+#endif
+#if MAX_DESCR_SECS > MAX_DESCR_SECTORS
+#error "Maximum DSECS=x exceeded."
+#endif
+#define MAX_IMAGES      ((int)((SECTOR_SIZE*MAX_DESCR_SECS-sizeof(INT4)-1)/sizeof(IMAGE_DESCR)))
+                         /* maximum number of images */
+
+#define COMMAND_LINE_SIZE      512     /* CL_LENGTH */
+#define SECTOR_SIZE    512 /* disk sector size */
+#ifndef BLOCK_SIZE /* may also come from linux/fs.h */
+#define BLOCK_SIZE     1024 /* disk block size */
+#endif
+
+#define PARTITION_ENTRY           16   /* size of one partition entry */
+#define PARTITION_ENTRIES  4    /* number of partition entries */
+#define PART_TABLE_SIZE    (PARTITION_ENTRY*PARTITION_ENTRIES)
+#define PART_TABLE_OFFSET  0x1be /* offset in the master boot sector */
+#define PART_ACT_ENT_OFF   0   /* offset in entry for active flag */
+#define PART_TYPE_ENT_OFF  4   /* offset in entry for partition type */
+
+#define P_MASK(x) ((~has_partitions(x))&0xFFFFFFFF)
+#define D_MASK(x) (has_partitions(x))
+#define PART_MAX PARTITION_ENTRIES /* biggest primary partition number */
+#define PART_MAX_MAX   63      /* max. partition number (on IDE disks) */
+
+#define MAX_BOOT_SIZE  0x1b6   /* (leave some space for NT's and DR DOS' dirty
+                                  hacks) scream if the boot sector gets any
+                                  bigger -- (22.5 - we now use those hacks) */
+
+#define BOOT_SIGNATURE 0xAA55  /* boot signature */
+#define BOOT_SIG_OFFSET        510     /* boot signature offset */
+#define MAGIC_SERIAL   0xC9CF  /* LILO installed serial number */
+#define PRIME          271     /* prime number used for serial no generation */
+#define SMALL_PRIME     17     /* another prime, but a small one */
+#if VERSION_MINOR>90
+#define MAX_BIOS_DEVICES  2    /* max hard disk devices used by BIOS */
+#define MAX_DEVICES    4       /* max hard disk devices, total */
+#else
+#define MAX_BIOS_DEVICES  16   /* max hard disk devices used by BIOS */
+#define MAX_DEVICES    64      /* max hard disk devices, total */
+#endif
+#define MAX_RAID       30      /* max number of RAID disks in a set */
+#if 0
+#define MAX_RAID_DEVICES  6    /* max raid devices reported to second.S */
+#else
+#define MAX_RAID_DEVICES MAX_DESCR_SECTORS-MAX_DESCR_SECS+6    /* max raid devices reported to second.S */
+#endif
+
+#define PART_LINUX_MINIX  0x81 /* Linux/MINIX partition */
+#define PART_LINUX_SWAP          0x82  /* Linux swap partition */
+#define PART_LINUX_NATIVE 0x83 /* Linux native (file system) */
+#define PART_DOS_EXTD    5     /* DOS Extended partition */
+#define PART_WIN_EXTD_LBA 0xF  /* Win95/98 Extended partition */
+#define PART_LINUX_EXTD   0x85 /* Linux Extended partition */
+#define PART_LINUX_LVM    0x8E /* Linux LVM partition */
+#define PART_OS2_BOOTMGR  0xA  /* OS/2 Boot Manager */
+
+#define PART_DOS12       1     /* DOS 12 bit FAT partition type */
+#define PART_DOS16_SMALL  4    /* DOS 16 bit FAT partition type, < 32 MB */
+#define PART_DOS16_BIG   6     /* DOS 16 bit FAT partition type, >= 32 MB */
+#define PART_HPFS        7     /* OS/2 High Performance File System */
+#define PART_NTFS        7     /* WinNT File System */
+#define PART_FAT32       0xB   /* Win95/98 FAT32 partition on small disk */
+#define PART_FAT32_LBA   0xC   /* Win95/98 FAT32 partition on large disk */
+#define PART_FAT16_LBA   0xE   /* Win95/98 FAT16 partition on large disk */
+#define PART_INVALID     98    /* invalid partition type */
+
+#define HIDDEN_OFF     0x10    /* type offset to hide partition (OS/2 BM) */
+#define PART_HDOS12    (PART_DOS12+HIDDEN_OFF)
+#define PART_HDOS16_SMALL (PART_DOS16_SMALL+HIDDEN_OFF)
+#define PART_HDOS16_BIG        (PART_DOS16_BIG+HIDDEN_OFF)
+
+#define STAGE_FIRST    1       /* first stage loader code */
+#define STAGE_SECOND   2       /* second stage loader code */
+#define        STAGE_CHAIN     0x10    /* chain loader code */
+#define STAGE_DRIVE_MAP        0x11    /* chain loader drive mapper */
+#define STAGE_MBR      0x12    /* mbr loader */
+#define STAGE_MBR2     0x13    /* mbr2 loader (extended) */
+#define STAGE_FLAG_SERIAL  0x0100      /* boot loader supports serial i/o */
+#define STAGE_FLAG_MENU        0x0200  /* boot loader supports menu interface */
+#define STAGE_FLAG_BMP4        0x0400  /* boot loader supports 640x480x4 bitmaps */
+
+#define SETUPSECS      4       /* nr of setup sectors */
+#define VSS_NUM                497     /* address where variable setup size is
+                                  stored */
+#define VGA_SET                506     /* address of initial kernel VGA mode */
+#define MAX_SETUPSECS  31      /* maximum number of sectors in kernel
+                                  setup code (+ bootsect) */
+#define MAX_KERNEL_SECS        1024    /* absolute maximum kernel size */
+#define SPECIAL_SECTORS        2       /* special sectors (don't compact) at beginning
+                                  of map sections */
+#define SPECIAL_BOOTSECT 1     /* INITSEG bootsect.S bootloader at beginning
+                                  of all kernels, ahead of SETUPSECS */
+
+#define LINEAR_FLAG    0x40    /* mark linear address */
+#define LBA32_FLAG      0x20    /* mark lba 32-bit address */
+#define LBA32_NOCOUNT   0x40    /* mark address with count absent */
+#define RAID_REL_FLAG  0x10    /* mark address raid-relocatable */
+/*
+ *     FLAG    Description
+ *
+ *     0x00     pure geometric addressing (C:H:S)
+ *     0x40     Linear address (24-bits) converted to CHS at boot-time
+ *     0x60     LBA32 address (32-bits), count=1, sets the high nibble!!
+ *     0x20     LBA32 address (24-bits) + (8-bit) high nibble (implied)
+ *
+*/
+#define DEV_MASK_EXP   0x80+MAX_BIOS_DEVICES-1
+#define DEV_MASK       (DEV_MASK_EXP)
+
+#define        EX_OFF          SETUP_STACKSIZE-8+SSDIFF /* external parameter block */
+#define EX_DL_MAG      0xfe    /* magic number in DL */
+#define EX_MAG_L       0x494c  /* magic number at ES:SI, "LI" */
+#define EX_MAG_H       0x4f4c  /* magic number at ES:SI+2, "LO" */
+#define EX_MAG_HL      0x4f4c494c  /* "LILO" */
+#define EX_MAG_STRING  "LILO"  /* magic signature string as as string */
+
+#define BIOS_MAX_DEVS  2       /* BIOS devices (2 fd, 2 hd) */
+#define BIOS_MAX_HEADS  256    /* 8 bits head number; really 255 */
+                       /* but must account for oddball BIOS's that allow 256 */
+#define BIOS_MAX_CYLS   1024   /* 10 bits cylinder number */
+#define BIOS_MAX_SECS   64     /* 6 bits sector number (really 63) */
+
+/* these are the boot record flags in the "prompt" variable */
+#define FLAG_PROMPT    1       /* always issue boot: prompt */
+#define FLAG_RAID      2       /* one boot record of many */
+#define FLAG_RAID_DEFEAT  4    /* defeat finding this RAID boot record */
+#if 0
+#define FLAG_RAID_NOWRITE 8    /* defeat RAID writeback of command line */
+#endif
+#define FLAG_NOBD      16      /* defeat BIOS data collection at boot time */
+#define FLAG_LARGEMEM  32      /* BIOS has MoveExtMemBlk support for 386 */
+#define FLAG_MAP_ON_BOOT 64    /* map file is on the boot device */
+#define FLAG_BD_OKAY   128     /* BIOS data collection known to work */
+#ifdef FLAG_RAID_NOWRITE
+#define FLAG_SAVE (~(FLAG_RAID|FLAG_RAID_DEFEAT|FLAG_RAID_NOWRITE))  /* All but raid flags */
+#else
+#define FLAG_SAVE (~(FLAG_RAID|FLAG_RAID_DEFEAT))  /* All but raid flags */
+#endif
+
+/* these are the second-stage specific flags */
+#define FLAG2_EL_TORITO  2     /* El Torito format bootable CD */
+#define FLAG2_UNATTENDED 4     /* Unattended booting option */
+#define FLAG2_VIRTUAL   8      /* vmdefault, vmdisable, vmwarn used */
+#define FLAG2_NOKBD    16      /* nokbdefault, nokbdisable used */
+
+/* these are the descriptor flags */
+#define FLAG_VGA       1       /* override VGA mode */
+#define FLAG_RESTR     2       /* restrict additional parameters */
+#define FLAG_LOCK      4       /* lock on target */
+#define FLAG_MODKRN    8       /* modern kernel with high memory support */
+#define FLAG_KERNEL    16      /* image is a kernel */
+#define FLAG_TOOBIG    32      /* initrd so big that kernel could be overwritten */
+#define FLAG_FALLBACK  64      /* fallback command line exists */
+#define FLAG_PASSWORD  128     /* this image requires a password */
+#define FLAG_LOADHI    256     /* this kernel loads high (>=1Mb) */
+#ifdef LCF_VIRTUAL
+#define FLAG_VMDISABLE 512     /* unable to boot if virtual */
+#define FLAG_VMWARN    1024    /* warn on virtual boot */
+#define FLAG_VMDEFAULT 2048    /* this is the default vitual load */
+#endif
+#define FLAG_SINGLE    4096    /* single key activation */
+#define FLAG_RETAIN    0x2000  /* retain BMP screen on boot */
+#ifdef LCF_NOKEYBOARD
+#define FLAG_NOKBDEFAULT 0x4000        /* this is the default with no keyboard */
+#define FLAG_NOKBDISABLE 0x8000        /* unable to boot if no keyboard */
+#endif
+
+#define VGA_NOCOVR     0x8000  /* VGA setting not overridden on command line */
+
+#define SER_DFL_PRM    0xa3    /* default serial parameters: 2400n8 */
+
+#define DC_MAGIC       0xf4f2  /* magic number of default cmd. line sector */
+#define DC_MGOFF       0x6b6d  /* magic number for disabled line */
+
+#define MAX_MESSAGE    65535   /* maximum message length */
+#define MAX_MENU_TITLE 37      /* maximum MENU title length */
+
+#define NEW_HDR_SIG    "HdrS"  /* setup header signature */
+#define NEW_HDR_VERSION        0x200   /* header version number */
+#define NEW2_HDR_VERSION 0x202 /* new cmdline protocol */
+#define NEW3_HDR_VERSION 0X203 /* defines CL_RAMDISK_MAX */
+#define LOADER_VERSION 0x02    /* loader version, for SETUP_HDR.loader */
+#define LFLAG_HIGH     1       /* SETUP_HDR.flags */
+#define LFLAG_USE_HEAP 0x80
+
+#define PRTMAP_SIZE    32      /* number of partition type mappings */
+#define DRVMAP_SIZE    24      /* number of drive mappings */
+
+#define CRC_POLY1 0x04c11db7
+#define CRC_POLY2 0x23a55379
+#define CRC_POLY3 0x049f21c7
+#define CRC_POLY4 0x1c632927
+#define CRC_POLY5 0xA3139383
+
+#define PROBE_SIGNATURE        "LiLo"  /* signature placed in low memory */
+#define PROBESEG 0x60          /* must be in first 4k page in memory */
+#define EDD_LTH            30          /* length of the EDD return structure (max) */
+#define EDD_PACKET  01         /* packet calls are supported */
+#define EDD_LOCK    02         /* removable media may be locked */
+#define EDD_SUBSET  04         /* EDD call supported */
+
+
+
+#ifdef LILO_ASM
+BOOTSEG   = 0x07C0                     ! original address of boot-sector
+PARTS_LOAD= 0x0600                     ! partition sector load address
+PARTS_SCR = 0x0800                     ! ditto, for non-boot partitions
+PART_TABLE= 0x07BE                     ! partition table
+
+INITSEG   = DEF_INITSEG                        ! we move boot here - out of the way
+SETUPSEG  = DEF_SETUPSEG               ! setup starts here
+SYSSEG    = DEF_SYSSEG                 ! system loaded at 0x10000 (65536).
+
+MAX_DESCR_SECS_asm = MAX_DESCR_SECS    ! **
+MAX_DESCR_SECTORS_asm = MAX_DESCR_SECTORS ! **
+MAX_IMAGE_NAME_asm = MAX_IMAGE_NAME    ! **
+MAX_PW_CRC_asm = MAX_PW_CRC            ! **
+SECTOR_SIZE_asm = SECTOR_SIZE          ! **
+MAX_MENU_TITLE_asm = MAX_MENU_TITLE    ! **
+MAX_BIOS_DEVICES_asm = MAX_BIOS_DEVICES        ! **
+MAX_RAID_DEVICES_asm = MAX_RAID_DEVICES        ! **
+DEV_MASK_asm = DEV_MASK_EXP            ! **
+
+
+STACKSEG  = 0x9000          ! MUST == INITSEG for kernel 2.0.36 (and others?)
+SETUP_STACKSIZE = 2048         ! stacksize for kernel setup.S
+
+#else
+#define BOOTSEG 0x07c0                 /* for probe.c  */
+#endif
+
+#define FIRSTSEG BOOTSEG
+
+#ifdef LILO_ASM
+
+STACK    = 2048                ! amount of stack space to reserve
+SSDIFF = 0
+
+BOOTSECT  = 0x200              ! kernel bootsect.S
+
+#define SETUP_STACK_DYN  PARMLINE
+#define SLA_SIZE_DYN  SETUP_STACK_DYN-SETUP_STACKSIZE-BOOTSECT
+
+KBBEG     = 0x41A                      ! beginning of keyboard buffer
+KBEND    = 0x41C                       ! end of keyboard buffer
+KBLOW    = 0x1e
+KBHIGH   = 0x3e
+
+!
+!  Memory layout
+!
+! 0x007BE-0x007FD    64 B    partition table
+! 0x07C00-0x07DFF   0.5 kB   HD/FD boot load address
+! 0x10000-0x8FFFF 512.0 kB   kernel (zImage)
+! 0x90000-0x901FF   0.5 kB   kernel floppy boot sector (bootsect.S)
+! 0x90200-0x967FF  25.5 kB   kernel setup code (setup.S) and heap
+! 0x96800-0x969FF   0.5 kB   LILO stack
+! 0x96A00-0x96BFF   0.5 kB   LILO first stage loader
+! 0x96C00-0x985FF   6.5 kB   LILO second stage loader
+! 0x98600-0x987FF   0.5 kB   file map load area
+! 0x98800-0x98BFF     1 kB   descriptor table load area
+! 0x98C00-0x98DFF   0.5 kB   default command line load area
+! 0x98E00-0x98FFF   0.5 kB   keyboard translation table load area
+! 0x99000-0x991FF   0.5 kB   parameter line construction area
+! 0x99200-0x9FFFF  27.5 kB   Extended BIOS Data Area
+
+! when LILO has loaded the kernel, and control is transfered to
+! the kernel setup.S code at 0x9020:0000
+!
+! 0x007BE-0x007FD    64 B    partition table
+! 0x07C00-0x07DFF   0.5 kB   HD/FD boot load address
+! 0x10000-0x8FFFF 512.0 kB   kernel (zImage)
+! 0x90000-0x901FF   0.5 kB   kernel floppy boot sector (bootsect.S)
+! 0x90200-0x967FF  25.5 kB   kernel setup code (setup.S) and heap
+! 0x96800-0x987FF   8.0 kB   additional heap space
+! 0x98800-0x98FFF   2.0 kB   stack created for (setup.S)
+! 0x99000-0x991FF   0.5 kB   parameter line for kernel
+! 0x99200-0x9FFFF  27.5 kB   Extended BIOS Data Area
+
+CL_MAGIC_ADDR  = 0x20                  ! command line magic number
+CL_MAGIC       = 0xa33f                ! very unusual command sequence
+CL_OFFSET      = 0x22                  ! command line offset
+CL_LENGTH      = COMMAND_LINE_SIZE     ! maximum length = 256-1
+
+! 0x90020-0x90021     2 by   command line magic number
+! 0x90022-0x90023     2 by   command line offset
+
+CL_HEADER_ID   = 0x202                 ! "HdrS"
+CL_HDRS_VERSION        = 0x206                 ! 0x0201=old;  0x0202=new
+NEW_VERSION    = NEW2_HDR_VERSION      ! 0x0202 for new cmdline protocol
+CL_POINTER     = 0x228                 ! new pointer is dword address
+CL_RAMDISK_MAX = CL_POINTER+4          ! ramdisk_max; header version 0x0203
+
+
+#endif
+
+/* Bug fix needed for some S-ATA controllers with the Silicon Image
+   3112 or 3114 chipsets.  Early versions of the SI BIOS do not properly
+   update the low memory size in the BIOS Data Area at 40h:13h when
+   they allocate space in the Extended BIOS Data Area (EBDA).
+*/
+#ifdef LCF_BUG_SI_EBDA
+# define EBDA_EXTRA LCF_BUG_SI_EBDA
+#else
+# define EBDA_EXTRA 0
+#endif
+
+
+/* the following configuration variable are now  required
+   don't compile without them ...
+ */
+
+#ifndef LCF_UNIFY
+# define LCF_UNIFY
+#endif
+#ifndef LCF_BUILTIN
+# define LCF_BUILTIN
+#endif
+#ifndef LCF_FIRST6
+# define LCF_FIRST6
+#endif
+
+#endif
+
diff --git a/src/loader.h b/src/loader.h
new file mode 100644 (file)
index 0000000..5bfc861
--- /dev/null
@@ -0,0 +1,21 @@
+/* loader.h */
+/*
+Copyright 2002-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+#include "common.h"
+
+extern BUILTIN_FILE First;
+extern BUILTIN_FILE Second;
+extern BUILTIN_FILE Third;
+extern BUILTIN_FILE Bitmap;
+extern BUILTIN_FILE Mbr;
+extern BUILTIN_FILE Mbr2;
+extern BUILTIN_FILE Chain;
+extern BUILTIN_FILE Os2_d;
+
+/* end loader.h */
diff --git a/src/map.c b/src/map.c
new file mode 100644 (file)
index 0000000..c583c0d
--- /dev/null
+++ b/src/map.c
@@ -0,0 +1,479 @@
+/* map.c  -  Map file creation */
+/*
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2005 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "lilo.h"
+#include "common.h"
+#if !__MSDOS__
+#include "geometry.h"
+#endif /* !__MSDOS__ */
+#include "map.h"
+
+#if !__MSDOS__
+typedef struct _map_entry {
+    SECTOR_ADDR addr;
+    struct _map_entry *next;
+} MAP_ENTRY;
+
+
+static MAP_ENTRY *map,*last;
+static SECTOR_ADDR zero_addr;
+static int map_file;
+#endif /* !__MSDOS__ */
+
+void map_patch_first(char *name,char *str)
+{
+    DESCR_SECTORS descrs;
+    int fd,size,image;
+    unsigned short magic;
+    char *start,*end;
+
+    if (strlen(str) >= SECTOR_SIZE-2)
+       die("map_patch_first: String is too long");
+    if ((fd = open(name,O_RDWR)) < 0) die("open %s: %s",name,strerror(errno));
+    if (lseek(fd,(off_t)SECTOR_SIZE,SEEK_SET) < 0) die("lseek %s: %s",name,strerror(errno));
+    if (read(fd,(char *) &descrs,sizeof(descrs)) != sizeof(descrs))
+       die("read %s: %s",name,strerror(errno));
+    for (start = str; *start && *start == ' '; start++);
+    if (*start) {
+       for (end = start; *end && *end != ' '; end++);
+       if (*end) *end = 0;
+       else end = NULL;
+       for (image = 0; image < MAX_IMAGES; image++)
+#ifdef LCF_IGNORECASE
+           if (!strcasecmp(descrs.d.descr[image].name,start)) break;
+#else
+           if (!strcmp(descrs.d.descr[image].name,start)) break;
+#endif
+       if (image == MAX_IMAGES) die("No image \"%s\" is defined",start);
+       if (end) *end = ' ';
+    }
+    if (lseek(fd,(off_t)0,SEEK_SET) < 0) die("lseek %s: %s",name,strerror(errno));
+    magic = *str ? DC_MAGIC : 0;
+    if ((size = write(fd,(char *) &magic,2)) < 0)
+       die("write %s: %s",name,strerror(errno));
+    if (size != 2) die("map_patch_first: Bad write ?!?");
+    if ((size = write(fd,str,strlen(str)+1)) < 0)
+       die("write %s: %s",name,strerror(errno));
+    if (size != strlen(str)+1) die("map_patch_first: Bad write ?!?");
+    if (close(fd) < 0) die("close %s: %s",name,strerror(errno));
+}
+
+#if !__MSDOS__
+
+static GEOMETRY map_geo;
+
+void map_create(char *name)
+{
+    char buffer[SECTOR_SIZE];
+    int fd, i;
+
+    if ((fd = creat(name,0600)) < 0) die("creat %s: %s",name,strerror(errno));
+    (void) close(fd);
+    memset(buffer,0,SECTOR_SIZE);
+    *(unsigned short *) buffer = DC_MGOFF;
+    map_file = geo_open(&map_geo,name,O_RDWR);
+    bios_map = map_geo.device; /* set device code of map file */
+    if (do_md_install) {
+       struct stat st;
+       if(fstat(map_file,&st)) die("map_create: cannot fstat map file");
+       if (verbose >= 2)
+           printf("map_create:  boot=%04X  map=%04X\n", 
+                                       boot_dev_nr, (int)st.st_dev);
+       if (boot_dev_nr != st.st_dev  &&  extra != X_MBR_ONLY) {
+           die("map file must be on the boot RAID partition");
+       }
+    }
+
+/* write default command line, descriptor table, zero sector */
+
+    for (i=0; i<MAX_DESCR_SECS+2; i++) {
+       if (write(map_file,buffer,SECTOR_SIZE) != SECTOR_SIZE)
+           die("write %s: %s",name,strerror(errno));
+       *(unsigned short *) buffer = 0;
+    }
+    if (!geo_comp_addr(&map_geo,SECTOR_SIZE*(MAX_DESCR_SECS+1),&zero_addr))
+       die("Hole found in map file (zero sector)");
+}
+
+
+void map_descrs(DESCR_SECTORS *descr, SECTOR_ADDR* addr, SECTOR_ADDR* dflcmd)
+{
+    struct stat st;
+    int i, pos;
+    off_t last;
+
+    descr->l.checksum =
+                crc32(descr->sector, sizeof((*descr).l.sector), CRC_POLY1);
+
+    last = lseek(map_file, 0L, SEEK_END);      /* save final position */
+    pos = SECTOR_SIZE;
+    if (lseek(map_file, pos, SEEK_SET) < 0) pdie("lseek map file");
+    if (write(map_file,(char *) descr, SECTOR_SIZE*MAX_DESCR_SECS) != SECTOR_SIZE*MAX_DESCR_SECS)
+       pdie("write map file");
+
+    for (i=0; i<MAX_DESCR_SECS; i++) {
+       if (!geo_comp_addr(&map_geo,pos,addr))
+           die("Hole found in map file (descr. sector %d)", i);
+       addr++;
+       pos += SECTOR_SIZE;
+    }
+
+    if (!geo_comp_addr(&map_geo,0,dflcmd))
+       die("Hole found in map file (default command line)");
+
+    if (verbose >= 2) {
+       if (fstat(map_file,&st) < 0) pdie("fstat map file");
+       printf("Map file size: %d bytes.\n",(int) st.st_size);
+    }
+    if (last!=lseek(map_file, last, SEEK_SET)) pdie("lseek map file to end");
+}
+
+
+void map_close(BOOT_PARAMS_2 *param2, off_t here)
+{
+    if (param2) {
+       if (lseek(map_file, here, SEEK_SET) != here)
+           die("map_close: lseek");
+       if (write(map_file,(void*)param2,sizeof(BOOT_PARAMS_2))!=sizeof(BOOT_PARAMS_2))
+           die("map_close: write");
+    }
+    geo_close(&map_geo);
+}
+
+
+void map_register(SECTOR_ADDR *addr)
+{
+    MAP_ENTRY *new;
+
+    new = alloc_t(MAP_ENTRY);
+    new->addr = *addr;
+    new->next = NULL;
+    if (last) last->next = new;
+    else map = new;
+    last = new;
+}
+
+
+void map_add_sector(void *sector)
+{
+    int here;
+    SECTOR_ADDR addr;
+
+    if ((here = lseek(map_file,0L,SEEK_CUR)) < 0) pdie("lseek map file");
+    if (write(map_file,sector,SECTOR_SIZE) != SECTOR_SIZE)
+       pdie("write map file");
+    if (!geo_comp_addr(&map_geo,here,&addr))
+       die("Hole found in map file (app. sector)");
+    map_register(&addr);
+}
+
+
+void map_begin_section(void)
+{
+    map = last = NULL;
+}
+
+
+void map_add(GEOMETRY *geo,int from,int num_sect)
+{
+    int count;
+    SECTOR_ADDR addr;
+
+    for (count = 0; count < num_sect; count++) {
+       if (geo_comp_addr(geo,SECTOR_SIZE*(count+from),&addr))
+           map_register(&addr);
+       else {
+           map_register(&zero_addr);
+           if (verbose > 3) printf("Covering hole at sector %d.\n",count);
+       }
+    }
+}
+
+
+void map_add_zero(void)
+{
+    map_register(&zero_addr);
+}
+
+
+static void map_compact(int dont_compact)
+{
+    MAP_ENTRY *walk,*next;
+    int count, removed, offset, adj, hinib, noffset, maxcount;
+
+    removed = 0;
+    hinib = 257;
+    maxcount = lba32 ? 127 : 128;  /* JRC: max LBA transfer is 127 sectors,
+             per the EDD spec, v1.1, not 128 (unfortunately) */
+/* JRC: for testing the hinib save: */
+#ifdef DEBUG
+       maxcount = lba32 ? 3 : maxcount;
+#endif
+    walk = map;
+    for (count = 0; walk && count < dont_compact; count++) walk = walk->next;
+    offset = 0;
+    noffset = 0;
+    while (walk && walk->next) {
+       adj = ((walk->addr.device ^ walk->next->addr.device) & ~LBA32_NOCOUNT) == 0;
+        if (adj && (walk->addr.device & LBA32_FLAG)) {
+           if ((walk->addr.device & LBA32_NOCOUNT)==0) {
+               if ( (adj = (hinib==walk->next->addr.num_sect)) ) {
+                   walk->next->addr.num_sect = 1;
+                   walk->next->addr.device &= ~LBA32_NOCOUNT;
+               }
+           }
+           else {
+               adj = 0;
+               hinib = walk->addr.num_sect;
+               if ((walk->next->addr.device&LBA32_NOCOUNT) &&
+                   (walk->next->addr.num_sect == hinib)) {
+                  walk->next->addr.num_sect = 1;
+                  walk->next->addr.device &= ~LBA32_NOCOUNT;
+               }
+           }
+       }
+       if (adj && walk->addr.device & (LINEAR_FLAG|LBA32_FLAG))
+           adj = ((walk->addr.head << 16) | (walk->addr.track << 8) |
+             walk->addr.sector)+walk->addr.num_sect == ((walk->next->addr.head
+             << 16) | (walk->next->addr.track << 8) | walk->next->addr.sector);
+       else adj = adj && walk->addr.track == walk->next->addr.track &&
+             walk->addr.head == walk->next->addr.head &&
+             walk->addr.sector+walk->addr.num_sect == walk->next->addr.sector;
+       noffset += SECTOR_SIZE;
+       adj = adj && (offset>>16 == noffset>>16) &&
+                    (walk->addr.num_sect < maxcount);    
+       if (!adj) {
+           offset = noffset;
+           walk = walk->next;
+       }
+       else {
+           walk->addr.num_sect++;
+           next = walk->next->next;
+           free(walk->next);
+           removed++;
+           walk->next = next;
+       }
+    }
+    if (verbose > 1)
+       printf("Compaction removed %d BIOS call%s.\n",removed,removed == 1 ?
+         "" : "s");
+}
+
+
+static void map_alloc_page(int offset,SECTOR_ADDR *addr)
+{
+    int here;
+
+    if ((here = lseek(map_file,offset,SEEK_CUR)) < 0) pdie("lseek map file");
+    if (write(map_file,"",1) != 1) pdie("write map file");
+    if (fdatasync(map_file)) pdie("fdatasync map file");
+    if (!geo_comp_addr(&map_geo,here,addr))
+       die("Hole found in map file (alloc_page)");
+    if (lseek(map_file,-offset-1,SEEK_CUR) < 0) pdie("lseek map file");
+}
+
+
+int map_end_section(SECTOR_ADDR *addr,int dont_compact)
+{
+    int first,offset,sectors;
+    char buffer[SECTOR_SIZE];
+    MAP_ENTRY *walk,*next;
+    int hinib;
+
+    first = 1;
+    memset(buffer,0,SECTOR_SIZE);
+    offset = sectors = 0;
+    if (compact) map_compact(dont_compact);
+    if (!map) die("Empty map section");
+    hinib = 0;
+    for (walk = map; walk; walk = next) {
+       next = walk->next;
+       if (verbose > 3) {
+           if ((walk->addr.device&LBA32_FLAG) && (walk->addr.device&LBA32_NOCOUNT)) hinib = walk->addr.num_sect;
+           printf("  Mapped AL=0x%02x CX=0x%04x DX=0x%04x",walk->addr.num_sect,
+             (walk->addr.track << 8) | walk->addr.sector,(walk->addr.head << 8)
+             | walk->addr.device);
+           if (linear||lba32)
+               printf(", %s=%d",
+                 lba32 ? "LBA" : "linear",
+                 (walk->addr.head << 16) | (walk->addr.track << 8) | walk->addr.sector | hinib<<24);
+           printf("\n");
+       }
+       if (first) {
+           first = 0;
+           map_alloc_page(0,addr);
+       }
+       if (offset+sizeof(SECTOR_ADDR)*2 > SECTOR_SIZE) {
+           map_alloc_page(SECTOR_SIZE,(SECTOR_ADDR *) (buffer+offset));
+           if (write(map_file,buffer,SECTOR_SIZE) != SECTOR_SIZE)
+               pdie("write map file");
+           memset(buffer,0,SECTOR_SIZE);
+           offset = 0;
+       }
+       memcpy(buffer+offset,&walk->addr,sizeof(SECTOR_ADDR));
+       offset += sizeof(SECTOR_ADDR);
+       sectors += (walk->addr.device&LBA32_FLAG) && (walk->addr.device&LBA32_NOCOUNT)
+               ? 1 : walk->addr.num_sect;
+       free(walk);
+    }
+    if (offset)
+       if (write(map_file,buffer,SECTOR_SIZE) != SECTOR_SIZE)
+           pdie("write map file");
+    return sectors;
+}
+
+#ifdef LCF_FIRST6
+static int sa6_from_sa(SECTOR_ADDR6 *sa6, SECTOR_ADDR *sa)
+{
+    static unsigned char hinib = 0;
+    int count;
+    int flags;
+    int sector;
+    
+    sa6->device = sa->device & DEV_MASK;
+    flags = sa6->flags = sa->device & ~DEV_MASK;
+    count = sa->num_sect;
+    
+    if ((flags & (LBA32_FLAG|LINEAR_FLAG)) == 0) {
+/* pure geometric addressing */
+       sector = *(unsigned int*)&(sa->sector);
+    }
+    else {
+       if (flags & LBA32_FLAG) {
+/* pure lba32 addressing */
+           if (flags & LBA32_NOCOUNT) {
+               hinib = count;
+               count = 1;
+           }
+       sector = hinib;
+       } /* linear addressing */
+       else  sector = 0;
+
+       sector = ((sector<<8 | sa->head)<<8 | sa->track)<<8 | sa->sector;
+    }
+    sa6->sector = sector;
+    
+    return sector;
+}
+
+#endif
+
+
+#ifdef LCF_FIRST6
+int map_write(SECTOR_ADDR *list,int max_len,int terminate,int sa6)
+#else
+int map_write(SECTOR_ADDR *list,int max_len,int terminate)
+#endif
+{
+    MAP_ENTRY *walk,*next;
+    int sectors;
+#ifdef LCF_FIRST6
+    SECTOR_ADDR6 sa6tem, *list6 = (void*)list;
+    unsigned int *list4 = (void*)list;
+#endif
+
+    sectors = 0;
+    for (walk = map; walk; walk = next) {
+       next = walk->next;
+       if (--max_len < (terminate ? 1 : 0)) die("Map segment is too big.");
+#ifdef LCF_FIRST6
+       if (sa6) {
+           (void)sa6_from_sa(&sa6tem, &(walk->addr));
+           if (sa6==2) *list4++ = sa6tem.sector;
+           else *list6++ = sa6tem;
+       }
+       else
+#endif
+       *list++ = walk->addr;
+
+       free(walk);
+       sectors++;
+    }
+    
+    if (terminate) {
+#ifdef LCF_FIRST6
+       if (sa6==2) *list4 = 0;
+       else if (sa6) memset(list6, 0, sizeof(SECTOR_ADDR6));
+       else
+#endif
+       memset(list,0,sizeof(SECTOR_ADDR));
+    }  
+
+    return sectors;
+}
+
+
+off_t map_insert_file(GEOMETRY *geo, int skip, int sectors)
+{
+    off_t here;
+    int count, i;
+    char buff[SECTOR_SIZE];
+    
+    if (verbose>0) printf("Calling map_insert_file\n");
+    if (lseek(geo->fd, (off_t)skip*SECTOR_SIZE, SEEK_SET)<0)
+       pdie("map_insert_file: file seek");
+    here = lseek(map_file, 0, SEEK_CUR);
+
+    for (i=0; i<sectors; i++) {
+       count = read(geo->fd, buff, SECTOR_SIZE);
+       if (count<0) pdie("map_insert_file: file read");
+       if (count<SECTOR_SIZE) memset(buff+count, 0, SECTOR_SIZE-count);
+       count = write(map_file, buff, SECTOR_SIZE);
+       if (count<=0) pdie("map_insert_file: map write");
+    }
+
+    if ((here % SECTOR_SIZE) != 0) die("Map file positioning error");
+    map_add(&map_geo, here/SECTOR_SIZE, sectors);
+    
+    return here;
+}
+
+off_t map_insert_data(unsigned char *data, int size)
+{
+    off_t here;
+    int count, sectors = 0;
+    char buff[SECTOR_SIZE];
+    
+    if (verbose>0) printf("Calling map_insert_data\n");
+    here = lseek(map_file, 0, SEEK_CUR);
+
+    while (size) {
+       if (size>SECTOR_SIZE) count=SECTOR_SIZE;
+       else count=size;
+       
+       memcpy(buff, data, count);
+       data += count;
+       size -= count;
+       sectors++;
+       
+       if (count<SECTOR_SIZE) memset(buff+count, 0, SECTOR_SIZE-count);
+       
+       count = write(map_file, buff, SECTOR_SIZE);
+       if (count<=0) pdie("map_insert_data: map write");
+    }
+
+    if ((here % SECTOR_SIZE) != 0) die("Map file positioning error");
+    map_add(&map_geo, here/SECTOR_SIZE, sectors);
+    
+    return here;
+}
+
+#endif /* !__MSDOS__ */
+
diff --git a/src/map.h b/src/map.h
new file mode 100644 (file)
index 0000000..67dd442
--- /dev/null
+++ b/src/map.h
@@ -0,0 +1,78 @@
+/* map.h  -  Map file creation */
+/*
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+#ifndef MAP_H
+#define MAP_H
+
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+
+void map_patch_first(char *name,char *str);
+/* Puts str into the first sector of a map file. */
+
+void map_create(char *name);
+/* Create and initialize the specified map file. */
+
+void map_descrs(DESCR_SECTORS *descr, SECTOR_ADDR* addr, SECTOR_ADDR* dflcmd);
+/* Updates map file with descriptors & default command line */
+
+void map_close(BOOT_PARAMS_2 *param2, off_t here);
+/* closes the map file, write second stage parameters */
+
+void map_add_sector(void *sector);
+/* Adds the specified sector to the map file and registers it in the map
+   section. */
+
+void map_begin_section(void);
+/* Begins a map section. Note: maps can also be written to memory with 
+   map_write. Thus, the map routines can be used even without map_create. */
+
+void map_add(GEOMETRY *geo,int from,int num_sect);
+/* Adds pointers to sectors from the specified file to the map file, starting
+   "from" sectors from the beginning. */
+
+void map_add_zero(void);
+/* Adds a zero-filled sector to the current section. */
+
+int map_end_section(SECTOR_ADDR *addr,int dont_compact);
+/* Writes a map section to the map file and returns the address of the first
+   sector of that section. The first DONT_COMPACT sectors are never compacted.
+   Returns the number of sectors that have been mapped. */
+
+#ifdef LCF_FIRST6
+int map_write(SECTOR_ADDR *list,int max_len,int terminate,int sa6);
+#else
+int map_write(SECTOR_ADDR *list,int max_len,int terminate);
+#endif
+/* Writes a map section to an array. If terminate is non-zero, a terminating
+   zero entry is written. If the section (including the terminating zero entry)
+   exceeds max_len sectors, map_write dies. */
+
+off_t map_insert_file(GEOMETRY *geo, int skip, int sectors);
+/* Copies a file (second stage loader, usually) into the map file, skipping
+   'skip' sectors at the beginning, and writing 'sectors' sectors.  The 
+   sectors are added to the current map section. */
+   
+off_t map_insert_data(unsigned char *data, int size);
+/* Copies data from an internal array into the map file.  The sectors
+   are added to the current map section */
+
+   
+#endif
diff --git a/src/mapper.S b/src/mapper.S
new file mode 100644 (file)
index 0000000..993b23d
--- /dev/null
@@ -0,0 +1,183 @@
+;  mapper.S  -  LILO chain loader subroutine
+;
+; Copyright 2003-2004 John Coffman.
+; All rights reserved.
+;
+; Licensed under the terms contained in the file 'COPYING' in the 
+; source directory.
+;
+; Check for presence of existing drive mapper
+;
+;      Enter with  DS == CS,  SS == 0000         (chain loader)
+;      Enter with  DS == CS == ES,  SS != 0000   (second stage)
+;
+;      If a previous drive mapper exists, ES:DI points at the  drvmap
+;              and ZF=0        (DI != 0)
+;
+;      If no recognizable drive map exists, DI == 0  and  ZF==1
+;              ES is indeterminate
+;
+;
+;
+is_prev_mapper:
+       push    cx
+       push    si
+
+#ifndef CHAIN_LOADER
+       push    #0
+       pop     es
+       seg es
+#else
+       seg ss
+#endif
+         les   di,[4*0x13]     ; vector to int 0x13
+       or      di,di
+       jnz     is_p_no_mapper  ; our mappers start at offset 0
+
+       mov     di,es
+       cmp     di,#0xA000      ; start of system reserved locations
+       jae     is_p_no_mapper
+       cmp     di,#0x0060      ; VERY conservative
+       jb      is_p_no_mapper
+
+; first test for new mapper
+       xor     di,di
+       mov     cx,#new13_length
+       mov     si,#new13
+       repe
+         cmpsb
+       jne     is_p_try_old
+
+; found new (v.22) mapper
+       seg es
+         mov   di,[new13_drvmap_offset]
+#if defined CHAIN_LOADER && defined DEBUG_NEW
+       mov     si,#msg_new
+       call    say
+#endif
+       jmp     is_prev_ret
+
+is_p_try_old:
+       xor     di,di
+       mov     cx,#new13_old_length
+       mov     si,#new13_old
+       repe
+         cmpsb
+       jne     is_p_no_mapper
+
+; likely old (<=v.21) mapper
+       seg es
+         mov   di,(di) 
+       cmp     di,#new13_old_min_offs  ; validate the range of values
+       jb      is_p_no_mapper
+       cmp     di,#new13_old_max_offs  ; validate the range of values
+#if defined CHAIN_LOADER && defined DEBUG_NEW
+       ja      is_p_no_mapper
+       mov     si,#msg_old
+       call    say
+       jmp     is_prev_ret
+#else
+       jbe     is_prev_ret
+#endif
+
+is_p_no_mapper:
+       xor     di,di           ; set DI = 0, ZF=1
+is_prev_ret:
+       or      di,di           ; set ZF by DI
+       pop     si
+       pop     cx
+       ret
+
+
+/* LILO version 21 (and maybe earlier) drive map header signature code */
+new13_old:
+       push    ax              ! save AX (contains function code in AH)
+       push    bp              ! need BP to mess with stack
+       mov     bp,sp
+       pushf                   ! push flags (to act like interrupt)
+       push    si
+       mov     si,#drvmap-new13
+
+new13_old_drvmap_offs  =       * - new13_old - 2
+new13_old_length       =       new13_old_drvmap_offs
+new13_old_min_offs     =       0x46    ; min seen in old code is 0x49
+new13_old_max_offs     =       0x50    ; maxed out at  21.7.5 at 0x4d
+
+       .even                   ! this is very important
+
+new13: push    ax              ! save AX (contains function code in AH)
+       push    bp              ! need BP to mess with stack
+       mov     bp,sp
+       jmp     new13a          ! make space for signature
+
+       .org    new13+6
+       .ascii  "LILO"
+       .word   STAGE_DRIVE_MAP
+new13_length           =       *-new13         ; max compare length
+       .word   VERSION
+new13_drvmap_offset    =       * - new13
+       .word   drvmap-new13    ! relative pointer to drive map
+new13a:
+#ifdef CHAIN_LOADER
+       ! Stack layout:
+       !
+       !   +8  INT flags
+       !   +6  INT CS
+       !   +4  INT IP
+       !   +2  AX
+       ! BP+0 BP
+       pushf                   ! push flags (to act like interrupt)
+       push    si
+       mov     si,#drvmap-new13
+mapfl: seg     cs              ! get next entry
+        mov    ax,(si)         ! do not depend on DIRECTION flag
+       lea     si,(si+2)       ! **
+       or      ax,ax           ! at end ?
+       jz      nomap           ! yes -> do not map
+       cmp     dl,al           ! match ?
+       jne     mapfl           ! no -> continue
+       mov     dl,ah           ! map drive
+nomap: pop     si              ! restore SI
+       mov     8(bp),ax        ! overwrite old flags (to remember mapping)
+       mov     ax,2(bp)        ! restore AX
+       mov     bp,(bp)         ! restore BP
+old13of        =       *+1
+old13sg        =       *+3
+       callf   0,0
+
+       push    bp              ! save BP again
+       mov     bp,sp
+       ! New stack layout:
+       !
+       !   +10 mapping (was flags)
+       !   +8  INT CS
+       !   +6  INT IP
+       !   +4  AX
+       !   +2  obsolete BP
+       ! BP+0  BP
+       xchg    ax,4(bp)        ! save AX and get command
+       pushf                   ! fix driver number, if necessary
+       cmp     ah,#8 ! do not fix
+       je      done13
+       cmp     ah,#0x15 ! do not fix
+       je      done13
+       mov     ax,10(bp)       ! no mapping ?
+       or      ax,ax
+       jz      done13
+       mov     dl,al           ! fix mapping
+done13:        mov     ax,4(bp)        ! restore AX
+       pop     10(bp)          ! restore flags
+       pop     bp              ! get BP
+       add     sp,#4           ! fix SP
+       iret                    ! done
+       
+       .even
+drvmap:        .blkw   DRVMAP_SIZE+1
+
+new13end:
+#endif
+#ifdef SECOND_STAGE_LOADER
+drvmap:
+#endif
+
+/* end of mapper.S  */
diff --git a/src/mbr.S b/src/mbr.S
new file mode 100644 (file)
index 0000000..2602847
--- /dev/null
+++ b/src/mbr.S
@@ -0,0 +1,498 @@
+;  mbr.S -- Master Boot Record to boot first partition marked active
+;
+; Copyright 2002-2004 John Coffman.
+; All rights reserved.
+;
+; Licensed under the terms contained in the file 'COPYING' in the 
+; source directory.
+;
+
+/* set to 1 for debugging output */
+#define DEBUG 0
+
+#define SEARCH 1               /* turn on search for device code */
+#define CYL1023 0              /* 1==compare to 1023 / 0==fn8 cyl #    */
+#define PASS_PARAMS 1          /* 1==pass lilo parameters */
+#define BYPASS18 0             /* bypass int 18h exit */
+
+#ifdef MBX
+# define EXT_PART 1            /* search extended partitions, too */
+/*# define VIDEO_ENABLE                / we just have no space for this */
+# define VIDEO_ENABLE          /* we now do have space for this */
+#else
+# define EXT_PART 0            /* search primary partition only */
+# define VIDEO_ENABLE
+#endif
+
+DELAY  = 12                    /* tenths of a second */
+
+#if DEBUG
+STEP   = 1                     /* delay is in seconds if DEBUG */
+# ifdef VIDEO_ENABLE
+/*#  undef VIDEO_ENABLE*/
+# endif
+#else
+STEP   = 10                    /* delay is in deciseconds if not DEBUG */
+#endif
+
+#define LILO_ASM
+#include "lilo.h"
+
+
+       .text
+
+       .globl  _main
+
+       .org    PARTS_LOAD
+
+zero:
+_main: cli                     ! NT 4 blows up if this is missing
+       jmp     start
+
+#if EXT_PART
+stage: .byte   STAGE_MBR2      ! search extended partitions, too
+#else
+stage: .byte   STAGE_MBR       ! search primary parition only
+#endif
+
+       .org    PARTS_LOAD+6
+sig:   .ascii  "LILO"          ! signature
+vers:  .word   VERSION
+
+! the disk I/O packet  DS:SI uses it
+packet:        .word   16              ! size of packet
+       .word   1               ! count of sectors to transfer
+addr:  .word   BOOTSEG*16      ! address offset to transfer to
+       .word   0               ! address segment to transfer to
+daddr: .long   0               ! low order disk address
+       .long   0               ! high order disk address
+! end of packet
+
+
+       
+#if DEBUG
+#if !SEARCH
+dout:  push    ax              ! save low half
+       shr     eax,#16
+       call    wout            ! put out high word
+       pop     ax
+wout:  push    ax
+       xchg    ah,al           ! put out AH first
+       call    bout
+       pop     ax              ! restore AL
+#endif
+bout:  push    ax              ! convert & output hex byte in AL
+       shr     al,#4           ! high nibble
+       call    nout
+       pop     ax              ! low nibble
+nout:  and     al,#0x0F        ! write the nibble in low half of AL
+       daa                     ! convert to upper case hex character
+       add     al,#0xF0        ! **
+       adc     al,#0x40        ! **
+cout:  push    bx              ! write character to the console
+       mov     ah,#0x0E        ! video BIOS function 14
+       mov     bh,#0
+       int     0x10            ! video interrupt
+       pop     bx
+       ret
+#endif
+
+say:   pop     si              ! get CS:SI pointer to character string
+say1:  lodsb                   ! but DS==CS, so this works
+       or      al,al           ! NUL terminated?
+       jz      say9
+#if DEBUG
+       call    cout
+#else
+       mov     ah,#0x0E        ! in-line character write routine
+       mov     bx,#07          ! write to page 0
+       int     0x10            ! video interrupt
+#endif
+       jmp     say1
+say9:
+#if DEBUG
+       jmp     si              ! return from "say:"
+#endif
+stop:
+#if DEBUG
+       hlt                     ! wait for interrupt
+       jmp     stop            ! loop back after interrupt
+#else
+#if BYPASS18
+       xor     eax,eax         ! EXPERIMENTAL code
+       mov     [daddr],eax     ! zero the disk address
+       inc     dx              ! try the next device code
+       call    disk_read       ! read sector 0
+       jmpi    (addr)
+#else
+       mov     cx,#DELAY*16/STEP  ! delay DELAY/10 seconds, DX doesn't matter
+
+       mov     ah,#0x86
+       int     0x15            ! delay call
+
+       int     0x18            ! exit to BIOS
+
+#endif /* BYPASS18 */
+#endif /* DEBUG */
+
+start:
+       xor     ax,ax                   ! all addressing from 0000:0000
+       mov     ss,ax                   ! set up the stack
+       mov     sp,#BOOTSEG*16          ! #0x7C00
+       sti                             ! enable interrupts
+#if PASS_PARAMS
+       mov     cx,sp
+       push    es
+       push    bx
+       push    si
+       push    dx
+       mov     si,cx
+#else
+       mov     si,sp                   ! from here 0000:7C000
+#endif
+       cld                             ! clear direction flag (UP)
+       mov     ds,ax                   ! DS=0
+       mov     es,ax                   ! ES=0
+       mov     di,#PARTS_LOAD          ! move to here 0000:0600
+       mov     cx,#SECTOR_SIZE/2       ! one sector worth
+       rep
+         movsw                         ! move words
+       jmpi    go,0                    ! intersegment jump 0:go
+go:
+#ifdef VIDEO_ENABLE
+       pusha                   ! certain video cards trash DX
+#if 0
+       mov     al,[0x449]              ! get video mode
+       cbw
+#else
+       mov     ax,#0x1200      ! enable video (VGA)
+       mov     bl,#0x36        ! (probably a nop on EGA or MDA)
+#endif
+       int     0x10            ! 
+
+       popa                    ! DX must be protected from rogue video cards
+#endif
+
+#if SEARCH
+       mov     edi,[serial_no]         ! serial number to look for
+       or      edi,edi
+       jz      use_boot
+
+       mov     ah,#8           ! get number of hard drives
+       mov     dl,#0x80
+       int     0x13
+       movzx   cx,dl
+
+       xchg    ax,dx           ! save device code in AX
+       mov     dx,#0x80        ! device 80
+
+vagain:
+       call    disk_read       
+
+       cmp     edi,[BOOTSEG*16+PART_TABLE_OFFSET-6]
+       je      vol_found
+       inc     dx              ! try next device
+       loop    vagain
+
+       xchg    ax,dx           ! try what we were passed
+
+vol_found:
+use_boot:
+
+#endif
+
+#if DEBUG
+       call    say                     ! debugging dump of DL
+       .ascii  "DL="
+       .byte   0
+       mov     ax,dx
+       call    bout                    ! write the byte in AL
+#if !SEARCH
+       mov     al,#0x20
+       call    cout
+       mov     eax,[serial_no]         ! serial number to look for
+       call    dout
+#endif
+       call    say
+       .byte   13,10,0
+#endif 
+       mov     si,#p_table             ! scan the partition table 
+#if EXT_PART
+       xor     edi,edi                 ! BASE = 0
+#endif
+       mov     cx,#4                   ! 4 entries
+find_active:
+#if EXT_PART
+       call    is_ext                  ! test for extended
+#endif
+       test    byte ptr (si),#0x80     ! test hi-bit
+       mov     bp,si                   ! save possible ptr
+       js      one_found               ! found Active if sign bit set
+       add     si,#16                  ! move to next entry
+       loop    find_active             ! & loop back
+
+#if EXT_PART
+/* no primary partition was marked active */
+       xchg    edi,ebp                 ! EBP = base, EDI = second
+       xor     edi,edi
+
+/* extended partitions exist, search them */
+ext_search:
+       add     edi,ebp                 ! second += base
+       mov     [daddr],edi
+       call    disk_read
+       mov     si,#BOOTSEG*16+PART_TABLE_OFFSET        ! pt[0]
+       test    byte ptr (si),#0x80     ! test hi-bit
+       js      boot_si                 ! one to boot if set
+       add     si,#16                  ! pt[1]
+       call    is_ext                  ! will set EDI
+       jz      ext_search
+#endif
+
+       call    say                     ! comment & quit
+#if DEBUG
+       .ascii  "nPa"
+#else
+       .ascii  "No partition active"
+#endif
+       .byte   13,10,0
+#if DEBUG
+stop1: br      stop
+#endif
+
+
+#if !EXT_PART
+find_more:                             ! check for more that one partition
+#if EXT_PART
+       call    is_ext                  ! continue check for extended part.
+#endif
+       test    byte ptr (si),#0x80     ! with active bit set
+       jns     one_found
+       call    say                     ! oops, a second partition is active
+#if DEBUG
+       .ascii  "iPT"
+#else
+       .ascii  "Invalid PT"
+#endif
+       .byte   13,10,0                 ! comment & quit
+#if DEBUG
+       jmp     stop1
+#endif
+
+one_found:                             ! one partition is active
+       add     si,#16                  ! go on & test others
+       loop    find_more               ! continue the loop
+
+; BP points at the only active partition
+
+       mov     si,bp           ; now SI points at active partition
+#else
+one_found:
+#endif /* !EXT_PART */
+
+boot_si:
+       mov     eax,(si+8)      ; get partition start
+#if EXT_PART
+       add     [daddr],eax     ; set disk address
+#else
+       mov     [daddr],eax     ; set disk address
+#endif
+       call    disk_read       ; read sector
+
+boot_it:
+;;;    seg     es                      ! DS==ES, so don't need prefix
+       cmp     word ptr [BOOTSEG*16+BOOT_SIG_OFFSET],#0xAA55   ! look for boot signature
+       jne     no_boot                 ! not bootable if no sig.
+
+#ifdef LCF_COHERENT
+       mov     (si),dl         ; move into partition table
+#endif
+       xor     ax,ax           ; signal no disk error
+#if DEBUG
+       pusha
+       call    say
+       .ascii  "B:"
+       .byte   13,10,0
+
+       mov     cx,#DELAY*16/STEP/2  ! delay DELAY/10 seconds, DX doesn't matter
+
+       mov     ah,#0x86
+       int     0x15            ! delay call
+       popa
+#endif
+#if PASS_PARAMS
+       pop     ax              ! check for possible params
+       cmp     al,#0xFE        !
+       jne     no_params
+       mov     ah,dl
+       pop     si
+       pop     bx
+       pop     es
+       xchg    ax,dx
+no_params:
+#endif
+       jmpi    (addr)
+
+
+no_boot: call  say
+#if DEBUG
+       .ascii  "nBs"
+#else
+#if EXT_PART
+;;;    .ascii  "No 0xAA55 in partition"
+       .ascii  "No boot sig. in partition"
+#else
+       .ascii  "No boot signature in partition"
+#endif
+#endif
+       .byte   13,10,0
+#if DEBUG
+       jmp     stop1
+#endif
+
+! packet read routine
+disk_read:
+       pusha
+       mov     bp,#12          ! retry count
+
+disk_retry:
+       mov     si,#packet
+       mov     bx,#0x55AA      ;magic number
+       mov     ah,#0x41
+       int     0x13
+       jc      disk_convert
+       cmp     bx,#0xAA55      ;changed?
+       jne     disk_convert
+       test    cl,#EDD_PACKET  ;EDD packet calls supported
+       jz      disk_convert
+
+       mov     ah,#0x42
+       jmp     disk_int13
+
+
+disk_convert:
+       push    dx
+       mov     ah,#8           ! get geometry
+       int     0x13
+       jc      disk_error12
+
+#if !CYL1023
+       push    cx
+       shr     cl,#6           ;;;;
+       xchg    cl,ch      ;CX is max cylinder number
+       mov     di,cx      ;DI saves it
+       pop     cx
+#endif
+       shr     dx,#8
+       xchg    ax,dx           ;AX <- DX
+       inc     ax              ;AX is number of heads (256 allowed)
+
+       and     cx,#0x003f      ;CX is number of sectors
+       mul     cx              ; kills DX also
+       xchg    ax,bx           ;save in BX
+
+       mov     ax,[daddr]      ;low part of address
+       mov     dx,[daddr+2]    ;hi part of address
+       
+       cmp     dx,bx
+       jae     disk_error2     ;prevent division error
+       div     bx              ;AX is cyl, DX is head/sect
+#if CYL1023
+       cmp     ax,#1023
+#else
+       cmp     ax,di
+#endif
+       ja      disk_error2     ;cyl is too big
+
+       shl     ah,#6           ; save hi 2 bits
+       xchg    al,ah
+       xchg    ax,dx
+       div     cl              ;AH = sec-1, AL = head
+       or      dl,ah      ;form Cyl/Sec
+       mov     cx,dx
+       inc     cx              ; sector is 1 based
+
+       pop     dx              ! restore device code
+       mov     dh,al           ! set head#
+       mov     ax,#0x201       ;read, count of 1
+
+disk_int13:
+       les     bx,[addr-packet](si)    ! for both reads
+       int     0x13
+       jc      disk_error1
+disk_ret:
+       popa
+       ret
+
+
+disk_error2:
+       mov     ah,#0x40        ; signal seek error
+disk_error12:
+       pop     dx
+disk_error1:
+       dec     bp
+       jz      disk_error0
+
+;;     mov     ah,#0x0D        ! reset fixed disk controller
+       xor     ah,ah
+       int     0x13
+       jmp     disk_retry
+
+disk_error0:
+disk_error:
+#if DEBUG
+       xchg    al,ah           ; error code to AL
+       call    bout
+       call    say
+       .ascii  "=dRe"
+#else
+       call    say             ; something is wrong with the disk read
+       .ascii  "Disk read error"
+#endif
+       .byte   13,10,0
+#if DEBUG
+       br      stop
+#endif
+
+
+
+#if EXT_PART
+/* return ZF=1 if SI -> extended partition and set EDI */
+is_ext:
+       mov     al,(si+4)               ; get partition type
+       cmp     al,#PART_DOS_EXTD
+       jz      is_extd
+       cmp     al,#PART_WIN_EXTD_LBA
+       jz      is_extd
+       cmp     al,#PART_LINUX_EXTD
+       jnz     is_extr
+is_extd:
+       mov     edi,(si+8)              ; get start to edi
+is_extr:
+       ret
+#endif
+
+theend1:       /* better be at or below 07B6 */
+
+       .org    PARTS_LOAD+MAX_BOOT_SIZE
+       .word   0
+serial_no:     .blkb   4       ! volume serial number
+       .blkb   2
+
+!!!    .org    0x1be           ! spot for the partition table
+p_table:
+       .blkb   16              ! the partition table is filled in
+       .blkb   16              ! when this Master Boot Record is installed
+       .blkb   16              ! just leave space
+       .blkb   16              ! here
+#if defined MBX
+       .org    *-2
+       .long   MBX             ! boot block signature check
+#elif defined MBR
+       .org    *-2
+       .long   MBR             ! boot block signature check
+#else
+       .word   0xAA55          ! boot block signature goes here
+#endif
+
+theend:        ! must be 0000:0800
diff --git a/src/md-int.h b/src/md-int.h
new file mode 100644 (file)
index 0000000..f6bbbec
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+   md.h : Multiple Devices driver for Linux
+          Copyright (C) 1994-96 Marc ZYNGIER
+         <zyngier@ufr-info-p7.ibp.fr> or
+         <maz@gloups.fdn.fr>
+         
+   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, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#ifndef MD_INT_H
+#define MD_INT_H
+
+/* don't include the kernel RAID header! */
+#define _MD_H
+
+typedef unsigned int md_u32;
+typedef unsigned short md_u16;
+typedef unsigned char md_u8;
+
+/*#include <linux/major.h>*/
+#include <sys/ioctl.h>
+
+#define MD_MAJOR MAJOR_MD
+
+/*
+ * Different major versions are not compatible.
+ * Different minor versions are only downward compatible.
+ * Different patchlevel versions are downward and upward compatible.
+ */
+
+struct md_version {
+       md_u32 major;
+       md_u32 minor;
+       md_u32 patchlevel;
+};
+
+/*
+ * default readahead
+ */
+#define MD_READAHEAD   (256 * 1024)
+
+/* These are the ioctls for md versions < 0.50 */
+#define REGISTER_MD_DEV                _IO (MD_MAJOR, 1)
+#define START_MD               _IO (MD_MAJOR, 2)
+#define STOP_MD                _IO (MD_MAJOR, 3)
+
+/* status */
+#define RAID_VERSION            _IOR (MD_MAJOR, 0x10, struct md_version)
+#define GET_ARRAY_INFO          _IOR (MD_MAJOR, 0x11, md_array_info_t)
+#define GET_DISK_INFO           _IOR (MD_MAJOR, 0x12, md_disk_info_t)
+#define PRINT_RAID_DEBUG        _IO (MD_MAJOR, 0x13)
+
+/* configuration */
+#define CLEAR_ARRAY             _IO (MD_MAJOR, 0x20)
+#define ADD_NEW_DISK            _IOW (MD_MAJOR, 0x21, md_disk_info_t)
+#define HOT_REMOVE_DISK         _IO (MD_MAJOR, 0x22)
+#define SET_ARRAY_INFO          _IOW (MD_MAJOR, 0x23, md_array_info_t)
+#define SET_DISK_INFO           _IO (MD_MAJOR, 0x24)
+#define WRITE_RAID_INFO         _IO (MD_MAJOR, 0x25)
+#define UNPROTECT_ARRAY         _IO (MD_MAJOR, 0x26)
+#define PROTECT_ARRAY           _IO (MD_MAJOR, 0x27)
+#define HOT_ADD_DISK            _IO (MD_MAJOR, 0x28)
+
+/* usage */
+#define RUN_ARRAY               _IOW (MD_MAJOR, 0x30, struct md_param)
+#define START_ARRAY             _IO (MD_MAJOR, 0x31)
+#define STOP_ARRAY              _IO (MD_MAJOR, 0x32)
+#define STOP_ARRAY_RO           _IO (MD_MAJOR, 0x33)
+#define RESTART_ARRAY_RW        _IO (MD_MAJOR, 0x34)
+
+
+/* for raid < 0.50 only */
+#define MD_PERSONALITY_SHIFT   16
+
+#define MD_RESERVED       0UL
+#define LINEAR            1UL
+#define STRIPED           2UL
+#define RAID0             STRIPED
+#define RAID1             3UL
+#define RAID5             4UL
+#define TRANSLUCENT       5UL
+#define LVM               6UL
+#define MAX_PERSONALITY   7UL
+
+/*
+ * MD superblock.
+ *
+ * The MD superblock maintains some statistics on each MD configuration.
+ * Each real device in the MD set contains it near the end of the device.
+ * Some of the ideas are copied from the ext2fs implementation.
+ *
+ * We currently use 4096 bytes as follows:
+ *
+ *     word offset     function
+ *
+ *        0  -    31   Constant generic MD device information.
+ *        32  -    63   Generic state information.
+ *       64  -   127   Personality specific information.
+ *      128  -   511   12 32-words descriptors of the disks in the raid set.
+ *      512  -   911   Reserved.
+ *      912  -  1023   Disk specific descriptor.
+ */
+
+/*
+ * If x is the real device size in bytes, we return an apparent size of:
+ *
+ *     y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
+ *
+ * and place the 4kB superblock at offset y.
+ */
+#define MD_RESERVED_BYTES              (64 * 1024)
+#define MD_RESERVED_SECTORS            (MD_RESERVED_BYTES / 512)
+#define MD_RESERVED_BLOCKS             (MD_RESERVED_BYTES / BLOCK_SIZE)
+
+#define MD_NEW_SIZE_SECTORS(x)         ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
+#define MD_NEW_SIZE_BLOCKS(x)          ((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS)
+
+#define MD_SB_BYTES                    4096
+#define MD_SB_WORDS                    (MD_SB_BYTES / 4)
+#define MD_SB_BLOCKS                   (MD_SB_BYTES / BLOCK_SIZE)
+#define MD_SB_SECTORS                  (MD_SB_BYTES / 512)
+
+/*
+ * The following are counted in 32-bit words
+ */
+#define        MD_SB_GENERIC_OFFSET            0
+#define MD_SB_PERSONALITY_OFFSET       64
+#define MD_SB_DISKS_OFFSET             128
+#define MD_SB_DESCRIPTOR_OFFSET                992
+
+#define MD_SB_GENERIC_CONSTANT_WORDS   32
+#define MD_SB_GENERIC_STATE_WORDS      32
+#define MD_SB_GENERIC_WORDS            (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
+#define MD_SB_PERSONALITY_WORDS                64
+#define MD_SB_DISKS_WORDS              384
+#define MD_SB_DESCRIPTOR_WORDS         32
+#define MD_SB_RESERVED_WORDS           (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
+#define MD_SB_EQUAL_WORDS              (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
+#define MD_SB_DISKS                    (MD_SB_DISKS_WORDS / MD_SB_DESCRIPTOR_WORDS)
+
+/*
+ * Device "operational" state bits
+ */
+#define MD_DISK_FAULTY         0 /* disk is faulty / operational */
+#define MD_DISK_ACTIVE         1 /* disk is running or spare disk */
+#define MD_DISK_SYNC           2 /* disk is in sync with the raid set */
+
+typedef struct md_device_descriptor_s {
+       md_u32 number;          /* 0 Device number in the entire set          */
+       md_u32 major;           /* 1 Device major number                      */
+       md_u32 minor;           /* 2 Device minor number                      */
+       md_u32 raid_disk;       /* 3 The role of the device in the raid set   */
+       md_u32 state;           /* 4 Operational state                        */
+       md_u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
+} md_descriptor_t;
+
+#define MD_SB_MAGIC            0xa92b4efc
+
+/*
+ * Superblock state bits
+ */
+#define MD_SB_CLEAN            0
+#define MD_SB_ERRORS           1
+
+typedef struct md_superblock_s {
+       /*
+        * Constant generic information
+        */
+       md_u32 md_magic;                /*  0 MD identifier                           */
+       md_u32 major_version;   /*  1 major version to which the set conforms */
+       md_u32 minor_version;   /*  2 minor version ...                       */
+       md_u32 patch_version;   /*  3 patchlevel version ...                  */
+       md_u32 gvalid_words;    /*  4 Number of used words in this section    */
+       md_u32 set_magic;       /*  5 Raid set identifier                     */
+       md_u32 ctime;           /*  6 Creation time                           */
+       md_u32 level;           /*  7 Raid personality                        */
+       md_u32 size;            /*  8 Apparent size of each individual disk   */
+       md_u32 nr_disks;        /*  9 total disks in the raid set             */
+       md_u32 raid_disks;      /* 10 disks in a fully functional raid set    */
+       md_u32 md_minor;        /* 11 preferred MD minor device number        */
+       md_u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 12];
+
+       /*
+        * Generic state information
+        */
+       md_u32 utime;           /*  0 Superblock update time                  */
+       md_u32 state;           /*  1 State bits (clean, ...)                 */
+       md_u32 active_disks;    /*  2 Number of currently active disks        */
+       md_u32 working_disks;   /*  3 Number of working disks                 */
+       md_u32 failed_disks;    /*  4 Number of failed disks                  */
+       md_u32 spare_disks;     /*  5 Number of spare disks                   */
+       md_u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 6];
+
+       /*
+        * Personality information
+        */
+       md_u32 layout;          /*  0 the array's physical layout             */
+       md_u32 chunk_size;      /*  1 chunk size in bytes                     */
+       md_u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 2];
+
+       /*
+        * Disks information
+        */
+       md_descriptor_t disks[MD_SB_DISKS];
+
+       /*
+        * Reserved
+        */
+       md_u32 reserved[MD_SB_RESERVED_WORDS];
+
+       /*
+        * Active descriptor
+        */
+       md_descriptor_t descriptor;
+
+} md_superblock_t;
+
+/*
+ * options passed in raidstart:
+ */
+
+#define MAX_CHUNK_SIZE (4096*1024)
+
+struct md_param
+{
+       int                     personality;    /* 1,2,3,4 */
+       int                     chunk_size;     /* in bytes */
+       int                     max_fault;      /* unused for now */
+};
+
+typedef struct md_array_info_s {
+       /*
+        * Generic constant information
+        */
+       md_u32 major_version;
+       md_u32 minor_version;
+       md_u32 patch_version;
+       md_u32 ctime;
+       md_u32 level;
+       md_u32 size;
+       md_u32 nr_disks;
+       md_u32 raid_disks;
+       md_u32 md_minor;
+       md_u32 not_persistent;
+
+       /*
+        * Generic state information
+        */
+       md_u32 utime;           /*  0 Superblock update time                  */
+       md_u32 state;           /*  1 State bits (clean, ...)                 */
+       md_u32 active_disks;    /*  2 Number of currently active disks        */
+       md_u32 working_disks;   /*  3 Number of working disks                 */
+       md_u32 failed_disks;    /*  4 Number of failed disks                  */
+       md_u32 spare_disks;     /*  5 Number of spare disks                   */
+
+       /*
+        * Personality information
+        */
+       md_u32 layout;          /*  0 the array's physical layout             */
+       md_u32 chunk_size;      /*  1 chunk size in bytes                     */
+
+} md_array_info_t;
+
+typedef struct md_disk_info_s {
+       /*
+        * configuration/status of one particular disk
+        */
+       md_u32 number;
+       md_u32 major;
+       md_u32 minor;
+       md_u32 raid_disk;
+       md_u32 state;
+
+} md_disk_info_t;
+
+
+/*
+ * Supported RAID5 algorithms
+ */
+#define RAID5_ALGORITHM_LEFT_ASYMMETRIC                0
+#define RAID5_ALGORITHM_RIGHT_ASYMMETRIC       1
+#define RAID5_ALGORITHM_LEFT_SYMMETRIC         2
+#define RAID5_ALGORITHM_RIGHT_SYMMETRIC                3
+
+#endif
diff --git a/src/menu.S b/src/menu.S
new file mode 100644 (file)
index 0000000..c0d371b
--- /dev/null
@@ -0,0 +1,382 @@
+#if 0
+; menu.S  is
+Copyright 2000-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+#endif
+#define PAGE0
+;
+; mn_init:
+;      enter with nothing
+;
+;      return with:
+;              AH = #columns
+;              AL = video mode
+;              BH = active page
+;              CH = rows-1
+;              CL = cols-1
+;
+;      side effects:
+;              If video mode 7 (MDA) is detected, the default attributes
+;              are modified to those suitable for monochrome
+;
+mn_init:
+       mov     ah,#0x0f
+       int     0x10            ; AH=cols, AL=mode, BH=page
+       mov     ch,#0x18
+       cmp     al,#7
+       je      mn_imono        ; MDA does not use 40:84
+       push    ds
+       push    #0x40
+       pop     ds
+       mov     ch,[0x84]       ; get rows-1
+       pop     ds
+mn_imono:
+       mov     cl,ah
+       dec     cl              ; CL=cols-1
+#ifndef PAGE0
+       mov     [mn_page],bh    ; save page
+#endif
+       mov     [mn_max_row_col],cx     ; save max screen coord.
+       cmp     al,#7           ; test for monochrome
+       jne     mn_init9
+       push    dword [mn_at_mono]      ; move 4 bytes
+       pop     dword [mn_attrib]
+mn_init9:
+       ret
+
+; mn_getcursor:
+;      exit with:
+;              DX = current cursor position
+;
+mn_getcursor:
+       push    ax
+       push    bx
+       push    cx
+       mov     ah,#3
+#ifndef PAGE0
+       mov     bh,[mn_page]
+#else
+       xor     bh,bh
+#endif
+       int     0x10
+       pop     cx
+       pop     bx
+       pop     ax
+       ret
+
+; mn_setcursor:
+;
+;      enter with:
+;              DX = row/col for cursor
+;
+mn_setcursor:
+       push    ax
+       push    bx
+       mov     ah,#2
+#ifndef PAGE0
+       mov     bh,[mn_page]
+#else
+       xor     bh,bh
+#endif
+       int     0x10
+       pop     bx
+       pop     ax
+       ret
+
+; mn_cursoroff:
+;
+mn_cursoroff:
+       push    dx
+       mov     dx,[mn_max_row_col]
+       inc     dh
+       xor     dl,dl
+       call    mn_setcursor
+       pop     dx
+       ret
+
+; mn_rdcha:  read character and attribute
+;      enter with:
+;              DX = row/col
+;
+;      exit with:
+;              AH = attribute
+;              AL = character
+;
+mn_rdcha:
+       push    bx
+       mov     ah,#2           ;set cursor position
+#ifndef PAGE0
+       mov     bh,[mn_page]
+#else
+       xor     bh,bh
+#endif
+       int     0x10
+       mov     ah,#8           ; read char and attr
+       int     0x10
+       pop     bx
+       ret
+
+; mn_wrcha:  write character and attribute
+;      enter with:
+;              AH = attribute
+;              AL = character
+;              DX = row/col
+;      
+mn_wrcha:
+       push    cx
+       push    bx
+       push    ax
+       mov     ah,#2
+#ifndef PAGE0
+       mov     bh,[mn_page]
+#else
+       xor     bh,bh
+#endif
+       int     0x10    ; set cursor position
+       pop     ax
+       push    ax
+       mov     bl,ah
+       mov     cx,#1
+       mov     ah,#9
+       int     0x10
+       pop     ax
+       pop     bx
+       pop     cx
+       ret
+
+; mn_wrstra:  write string with attribute
+;      enter with:
+;              AL = attribute
+;              DS:BX points at string
+;              DX = row/col of start
+;
+mn_wrstra:
+       push    ax
+       push    bx
+       push    dx
+       mov     ah,al
+mn_wrs1:
+       mov     al,(bx)
+       inc     bx
+       or      al,al
+       jz      mn_wrs9
+       call    mn_wrcha
+       inc     dl
+       jmp     mn_wrs1
+mn_wrs9:
+       pop     dx
+       pop     bx
+       pop     ax
+       ret
+       
+; mn_drawbox:
+;      enter with:
+;              AL =    0 no border
+;                      1 single border
+;                      2 double border
+;                      3 single top/bot, double sides
+;                      4 double top/bot, single sides
+;         (if hi-bit of AL is set, expand box by 1 in horizontal)
+;              BH = attribute for area
+;              CX = row/col of upper left
+;              DX = delta row/delta col
+;
+mn_drawbox:
+       push    dx
+       push    cx
+       push    ax
+       or      al,al
+       jns     mn_dr01
+       dec     cl
+       inc     dl
+       inc     dl
+mn_dr01:
+       mov     ax,#0x0600
+       add     dx,cx
+       int     0x10
+       pop     ax
+       pop     cx
+       pop     dx
+       test    al,#0x7F
+       jz      mn_dr9
+
+       push    ax
+       push    si
+       and     ax,#0x7F
+       mov     si,ax
+       shl     si,#3
+       lea     si,[mn_box-8](si)
+
+       mov     ah,[mn_at_border]
+       xchg    dx,cx
+
+       push    cx
+
+       lodsb
+mn_dr1:        call    mn_wrcha
+       inc     dl
+       dec     cl
+       mov     al,(si)
+       jnz     mn_dr1
+
+       inc     si
+       lodsb
+mn_dr2:        call    mn_wrcha
+       inc     dh
+       dec     ch
+       mov     al,(si)
+       jnz     mn_dr2
+
+       pop     cx
+       push    cx
+       inc     si
+       lodsb
+mn_dr3:        call    mn_wrcha
+       dec     dl
+       dec     cl
+       mov     al,(si)
+       jnz     mn_dr3
+
+       inc     si
+       lodsb
+mn_dr4:        call    mn_wrcha
+       dec     dh
+       dec     ch
+       mov     al,(si)
+       jnz     mn_dr4
+
+       pop     cx
+       xchg    cx,dx
+       
+       pop     si
+       pop     ax
+
+mn_dr9:        ret
+
+; mn_vline:  vertical line
+;
+;      enter with:
+;              AL = 1 (single line), 2 (double line)
+;              CX = row/col to start
+;              DH = delta Y
+;
+mn_vline:
+       pusha
+       cbw
+       mov     si,ax
+       mov     bl,[mn_ver-1](si)
+       shl     si,#3
+       lea     si,[mn_vint-8](si)
+       mov     di,#0x100
+       xchg    cx,dx
+       mov     cl,ch
+       jmp     mn_line00       ; join common code
+
+
+
+; mn_hline:  horizontal line
+;
+;      enter with:
+;              AL = 1 (single line), 2 (double line)
+;              CX = row/col to start
+;              DL = delta X
+;
+mn_hline:
+       pusha
+       cbw
+       mov     si,ax
+       mov     bl,[mn_hor-1](si)       ; BL is char to write
+       shl     si,#3
+       lea     si,[mn_hint-8](si)      ; SI is intersect table
+       mov     di,#1
+       xchg    cx,dx
+; do the beginning of the line
+mn_line00:
+       call    mn_rdcha
+       mov     ah,bl           ; AH is char to write
+       cmp     al,(si)         ; know intersect?
+       jne     mn_line01
+       mov     ah,[1](si)
+mn_line01:
+       cmp     al,[4](si)
+       jne     mn_line02
+       mov     ah,[5](si)
+mn_line02:
+       mov     al,ah
+       mov     ah,[mn_at_border]
+       call    mn_wrcha
+       add     dx,di
+       dec     cl
+       jz      mn_line20
+
+mn_line10:             ;do the central part of the line
+       call    mn_rdcha
+       mov     ah,bl
+       cmp     al,(si)
+       jne     mn_line11
+       mov     ah,[2](si)
+mn_line11:
+       cmp     al,[4](si)
+       jne     mn_line12
+       mov     ah,[6](si)
+mn_line12:
+       mov     al,ah
+       mov     ah,[mn_at_border]
+       call    mn_wrcha
+       add     dx,di
+       dec     cl
+       jnz     mn_line10
+
+mn_line20:             ;do the end of the line
+       call    mn_rdcha
+       mov     ah,bl
+       cmp     al,(si)
+       jne     mn_line21
+       mov     ah,[3](si)
+mn_line21:
+       cmp     al,[4](si)
+       jne     mn_line22
+       mov     ah,[7](si)
+mn_line22:
+       mov     al,ah
+       mov     ah,[mn_at_border]
+       call    mn_wrcha
+
+       popa
+       ret
+
+mn_box:        db      SE,EW,SW,NS,NW,EW,NE,NS
+       db      SSEE,EEWW,SSWW,NNSS,NNWW,EEWW,NNEE,NNSS
+       db      SSE,EW,SSW,NNSS,NNW,EW,NNE,NNSS
+       db      SEE,EEWW,SWW,NS,NWW,EEWW,NEE,NS
+
+mn_hor:        db      EW,EEWW
+mn_hint:  db   NS,NSE,NSEW,NSW
+       db      NNSS,NNSSE,NNSSEW,NNSSW
+       db      NS,NSEE,NSEEWW,NSWW
+       db      NNSS,NNSSEE,NNSSEEWW,NNSSWW
+
+mn_ver:        db      NS,NNSS
+mn_vint:  db   EW,SEW,NSEW,NEW
+       db      EEWW,SEEWW,NSEEWW,NEEWW
+       db      EW,SSEW,NNSSEW,NNEW
+       db      EEWW,SSEEWW,NNSSEEWW,NNEEWW
+
+mn_attrib:
+mn_at_text:    db      0x47
+mn_at_hilite:  db      0x71
+mn_at_border:  db      0x47
+mn_at_title:   db      0x4E
+
+mn_at_mono:    db      0x07,0x70,0x07,0x0F
+#ifndef PAGE0
+mn_page:       db      0
+#endif
+mn_max_row_col: dw     0
+
+; end of menu.S
+
diff --git a/src/partition.c b/src/partition.c
new file mode 100644 (file)
index 0000000..da26fc2
--- /dev/null
@@ -0,0 +1,826 @@
+/* partition.c  -  Partition table handling */
+/*
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2005 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <time.h>
+#include <dirent.h>
+#include "config.h"
+#include "lilo.h"
+#include "common.h"
+#include "cfg.h"
+#include "device.h"
+#include "geometry.h"
+#include "partition.h"
+#include "boot.h"
+#include "loader.h"
+
+#if __GLIBC__ < 2 || __GLIBC_MINOR__ < 1
+#if defined(_syscall5) && defined(__NR__llseek)
+       
+       _syscall5(int,  _llseek,  unsigned int,  fd, unsigned int, hi,
+           unsigned int, lo, lloff_t *, res, unsigned int, wh);
+       int _llseek(unsigned int fd,  unsigned  int  offset_high,
+           unsigned  int  offset_low,  lloff_t * result, unsigned int whence);
+
+       lloff_t lseek64(unsigned int fd, lloff_t offs, unsigned int whence)
+       { lloff_t res;
+                  return _llseek(fd, offs>>32, offs, &res, whence) < 0  ?
+                                (lloff_t)(-1) : res;
+       }
+
+#else
+/* last ditch attempt on small disks, and very old systems */
+# warning "*****************************************"
+# warning "***** no 64 bit lseek is available ******"
+# warning "***** using 23 bit sector addresses *****"
+# warning "*****************************************"
+# define lseek64 lseek
+#endif
+#endif
+
+static
+int anywhere(void *buf, char *str)
+{
+    int k, n;
+    void *s;
+    
+    k = strlen(str);
+    n = SECTOR_SIZE-k;
+    s = memchr(buf, *str, n);
+    while(s) {
+       if (!strncmp(s, str, k)) return 1;
+       s++;
+       n = SECTOR_SIZE - k - (int)(s-buf);
+       s = memchr(s, *str, n);
+    }
+    return 0;
+}
+
+
+
+/* identify partitions which would be destroyed if the boot block
+   is overwritten:
+   
+   known problems occur for:
+       XFS
+       NTFS
+       DOS FAT (relocation will fix)
+
+*/
+int part_nowrite(char* device)
+{
+    int fd;
+    BOOT_SECTOR bs;
+    
+    int ret=PTW_OKAY;  /* say ok, unless we recognize a problem partition */
+if ( !(do_md_install && extra==X_MBR_ONLY) ) {
+    if ((fd = open(device, O_RDONLY)) < 0) pdie("part_nowrite check:");
+    if (read(fd, bs.sector, sizeof(bs)) != SECTOR_SIZE) pdie("part_nowrite: read:");
+    
+/* check for XFS */
+    if (!strncmp("XFSB", (char*)bs.sector, 4)) ret=PTW_XFS;
+    
+/* check for NTFS */
+    else if (  !strncmp("NTFS", bs.par_d.system, 4)
+               || anywhere(bs.sector,"NTLDR")  ) ret=PTW_NTFS;
+
+/* check for HPFS */
+    else if (  !strncmp("OS2", bs.par_d.system, 3)
+               || anywhere(bs.sector,"OS2LDR")  ) ret=PTW_OS2;
+
+/* check for DOS FAT */
+    else if (
+       (bs.par_d.bpb.media_descriptor >= 0xF8 || bs.par_d.bpb.media_descriptor == 0xF0)
+       && *(short*)bs.par_d.bpb.bytes_per_sector == SECTOR_SIZE
+       && (bs.par_d.bpb.number_of_FATs==1 || bs.par_d.bpb.number_of_FATs==2)
+    /* sectors_per_cluster is a power of 2, meaning only 1 bit is on */
+       && bs.par_d.bpb.sectors_per_cluster
+       && (bs.par_d.bpb.sectors_per_cluster & (bs.par_d.bpb.sectors_per_cluster-1))==0
+                               ) {
+               ret=PTW_DOS;
+#if 0
+/* this, it turns out is from Windows 98, so no caution here on NT */
+               if (anywhere(bs.sector,"WINBOOT SYS")) ret+=PTW_NTFS;
+#endif
+    }
+    
+/* check for SWAP -- last check, as 'bs' is overwritten */
+    else if (*(int*)bs.sector == 0xFFFFFFFEU) {
+       if (lseek(fd, (PAGE_SIZE)-SECTOR_SIZE, SEEK_SET) != (PAGE_SIZE)-SECTOR_SIZE)
+           pdie("part_nowrite lseek:");
+       if (SECTOR_SIZE != read(fd, bs.sector, sizeof(bs)) ) pdie("part_nowrite swap check:");
+       if (!strncmp((char*)bs.sector+SECTOR_SIZE-10,"SWAPSPACE2",10)
+           || !strncmp((char*)bs.sector+SECTOR_SIZE-10,"SWAP-SPACE",10) ) ret=PTW_SWAP;
+    }
+
+/* didn't recognize the superblock type, so assume it is okay */    
+    else ret=PTW_OKAY;
+    
+    close(fd);
+
+} /* raid install with X_MBR_ONLY in use */
+    if (verbose>=6) printf("part_nowrite: %d\n", ret);    
+    
+    return ret;
+}
+
+
+void part_verify(int dev_nr,int type)
+{
+    GEOMETRY geo;
+    DEVICE dev;
+    char backup_file[PATH_MAX+1];
+    int fd, bck_file, part, size, lin_3d, cyl;
+    unsigned int second, base;
+    struct partition part_table[PART_MAX];
+    int mask, i, pe, Linux, dos, mbr;
+    unsigned short boot_sig;
+    BOOT_PARAMS_1 bs;
+    
+    if (!has_partitions(dev_nr) || !(mask = P_MASK(dev_nr)) || !(dev_nr & mask)
+#if 0
+     || (dev_nr & mask) > PART_MAX
+#endif
+       ) return;
+
+    if (verbose >= 4) printf("part_verify:  dev_nr=%04x, type=%d\n", dev_nr, type);
+    geo_get(&geo,dev_nr & ~mask,-1,1);
+    fd = dev_open(&dev,dev_nr & ~mask,cfg_get_flag(cf_options,"fix-table")
+      && !test ? O_RDWR : O_RDONLY);
+    part = (pe = dev_nr & mask)-1;
+#if 1
+    if (type) {
+       if (lseek(fd, 0L, SEEK_SET) != 0 ||
+           read(fd, &bs, sizeof(bs)) != sizeof(bs) ) pdie("bs read");
+       if (*(int*)bs.signature==EX_MAG_HL) mbr = bs.stage;
+       else mbr = STAGE_MBR;
+    } else mbr = STAGE_MBR;
+#endif
+    if (lseek(fd, PART_TABLE_OFFSET, SEEK_SET) < 0) pdie("lseek partition table");
+    if (!(size = read(fd,(char *) part_table, sizeof(struct partition)*
+      PART_MAX))) die("Short read on partition table");
+    if (size < 0) pdie("read partition table");
+    if ( read(fd, &boot_sig, sizeof(boot_sig)) != sizeof(boot_sig)  ||
+       boot_sig != BOOT_SIGNATURE ) die("read boot signature failed");
+
+    if (verbose>=5) printf("part_verify:  part#=%d\n", pe);
+
+    second=base=0;
+    for (i=0; i<PART_MAX; i++) {
+       if (is_extd_part(part_table[i].sys_ind)) {
+           if (!base) base = part_table[i].start_sect;
+           else die("invalid partition table: second extended partition found");
+       }
+    }
+    i=5;
+    while (i<=pe && base) {
+        if (lseek64(fd, LLSECTORSIZE*(base+second) + PART_TABLE_OFFSET, SEEK_SET) < 0)
+            die("secondary lseek64 failed");
+       if (read(fd, part_table, sizeof(part_table)) != sizeof(part_table)) die("secondary read pt failed");
+       if ( read(fd, &boot_sig, sizeof(boot_sig)) != sizeof(boot_sig)  ||
+           boot_sig != BOOT_SIGNATURE ) die("read second boot signature failed");
+        if (is_extd_part(part_table[1].sys_ind)) second=part_table[1].start_sect;
+        else base = 0;
+        i++;
+        part=0;
+    }
+#if 1
+    if (type && pe>0 && pe<=(mbr==STAGE_MBR2?63:PART_MAX)
+            && !(part_table[part].boot_ind&0x80) )
+       warn("Partition %d on %s is not marked Active.",
+               pe, dev.name);
+#endif
+    i = part_table[part].sys_ind;
+
+    Linux =   i == PART_LINUX_MINIX ||
+             i == PART_LINUX_NATIVE ||
+             i == PART_LINUX_LVM ||
+             is_extd_part(i);
+
+    i &= ~HIDDEN_OFF;
+    dos =     i == PART_DOS12 ||
+             i == PART_DOS16_SMALL ||
+             i == PART_DOS16_BIG ||
+             i == PART_FAT32 ||
+             i == PART_FAT32_LBA ||
+             i == PART_FAT16_LBA ||
+             i == PART_NTFS ||
+             i == PART_OS2_BOOTMGR ;
+
+    if (type && !Linux) {
+       warn("partition type 0x%02X"" on device 0x%04X is a dangerous place for\n"
+             "    a boot sector.%s",
+                       part_table[part].sys_ind, dev_nr,
+       dos ? "  A DOS/Windows/OS2 system may be rendered unbootable."
+               "\n  The backup copy of this boot sector should be retained."
+               : "" );
+#if 0
+       if (!dos && !cfg_get_flag(cf_options,"ignore-table"))
+           die("You may proceed by using either '-P ignore' or 'ignore-table'");
+#else
+       if (!yesno("\nProceed? ", 0)) exit(0);
+#endif
+    }
+    cyl = part_table[part].cyl+((part_table[part].sector >> 6) << 8);
+    lin_3d = (part_table[part].sector & 63)-1+(part_table[part].head+
+      cyl*geo.heads)*geo.sectors;
+    if (pe <= PART_MAX &&
+           (lin_3d > part_table[part].start_sect || (lin_3d <
+           part_table[part].start_sect && cyl != BIOS_MAX_CYLS-1)) ) {
+       warn("Device 0x%04X: Inconsistent partition table, %d%s entry",
+         dev_nr & ~mask,part+1,!part ? "st" : part == 1 ? "nd" : part ==
+         2 ? "rd" : "th");
+        if (!nowarn)
+       fprintf(errstd,"  CHS address in PT:  %d:%d:%d  -->  LBA (%d)\n",
+               cyl,
+               part_table[part].head,
+               part_table[part].sector & 63,
+               lin_3d);
+       cyl = part_table[part].start_sect/geo.sectors/geo.heads;
+        if (!nowarn)
+       fprintf(errstd,"  LBA address in PT:  %d  -->  CHS (%d:%d:%d)\n",
+               part_table[part].start_sect,
+               cyl,
+               part_table[part].head = (part_table[part].start_sect/geo.sectors) % geo.heads,
+               part_table[part].sector = (part_table[part].start_sect % geo.sectors)+1
+               );
+       if (cyl >= BIOS_MAX_CYLS) cyl = BIOS_MAX_CYLS-1;
+       part_table[part].sector |= (cyl >> 8)<<6;
+       part_table[part].cyl = cyl & 0xff;
+       if (!cfg_get_flag(cf_options,"fix-table") && !cfg_get_flag(cf_options,
+         "ignore-table")) die("Either FIX-TABLE or IGNORE-TABLE must be specified\n"
+                       "If not sure, first try IGNORE-TABLE (-P ignore)");
+       if (test || cfg_get_flag(cf_options,"ignore-table")) {
+           warn("The partition table is *NOT* being adjusted.");
+       } else {
+           sprintf(backup_file,BACKUP_DIR "/part.%04X",dev_nr & ~mask);
+           if ((bck_file = creat(backup_file,0644)) < 0)
+               die("creat %s: %s",backup_file,strerror(errno));
+           if (!(size = write(bck_file,(char *) part_table,
+             sizeof(struct partition)*PART_MAX)))
+               die("Short write on %s",backup_file);
+           if (size < 0) pdie(backup_file);
+           if (close(bck_file) < 0)
+               die("close %s: %s",backup_file,strerror(errno));
+           if (verbose > 0)
+               printf("Backup copy of partition table in %s\n",backup_file);
+           printf("Writing modified partition table to device 0x%04X\n",
+             dev_nr & ~mask);
+           if (lseek(fd,PART_TABLE_OFFSET,SEEK_SET) < 0)
+               pdie("lseek partition table");
+           if (!(size = write(fd,(char *) part_table,sizeof(struct partition)*
+             PART_MAX))) die("Short write on partition table");
+           if (size < 0) pdie("write partition table");
+       }
+    }
+    dev_close(&dev);
+}
+
+
+CHANGE_RULE *change_rules = NULL;
+
+
+void do_cr_reset(void)
+{
+    CHANGE_RULE *next;
+
+    while (change_rules) {
+       next = change_rules->next;
+       free((char *) change_rules->type);
+       free(change_rules);
+       change_rules = next;
+    }
+}
+
+
+static unsigned char cvt_byte(const char *s)
+{
+    char *end;
+    unsigned int value;
+
+    value = strtoul(s,&end,0);
+    if (value > 255 || *end) cfg_error("\"%s\" is not a byte value",s);
+    return value;
+}
+
+
+static void add_type(const char *type,int normal,int hidden)
+{
+    CHANGE_RULE *rule;
+
+    for (rule = change_rules; rule; rule = rule->next)
+       if (!strcasecmp(rule->type,type))
+           die("Duplicate type name: \"%s\"",type);
+    rule = alloc_t(CHANGE_RULE);
+    rule->type = stralloc(type);
+    rule->normal = normal == -1 ? hidden ^ HIDDEN_OFF : normal;
+    rule->hidden = hidden == -1 ? normal ^ HIDDEN_OFF : hidden;
+    rule->next = change_rules;
+    change_rules = rule;
+}
+
+
+void do_cr_type(void)
+{
+    const char *normal,*hidden;
+
+    cfg_init(cf_change_rule);
+    (void) cfg_parse(cf_change_rule);
+    normal = cfg_get_strg(cf_change_rule,"normal");
+    hidden = cfg_get_strg(cf_change_rule,"hidden");
+    if (normal)
+       add_type(cfg_get_strg(cf_change_rules,"type"),cvt_byte(normal),
+         hidden ? cvt_byte(hidden) : -1);
+    else {
+       if (!hidden)
+           cfg_error("At least one of NORMAL and HIDDEN must be present");
+       add_type(cfg_get_strg(cf_change_rules,"type"),cvt_byte(hidden),-1);
+    }
+    cfg_unset(cf_change_rules,"type");
+}
+
+
+void do_cr(void)
+{
+    cfg_init(cf_change_rules);
+    (void) cfg_parse(cf_change_rules);
+}
+
+
+#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
+
+/*
+ * Rule format:
+ *
+ * +------+------+------+------+
+ * |drive |offset|expect| set  |
+ * +------+------+------+------+
+ *     0      1      2      3
+ */
+
+static void add_rule(unsigned char bios,unsigned char offset,
+  unsigned char expect,unsigned char set)
+{
+    int i;
+
+    if (curr_prt_map == PRTMAP_SIZE)
+       cfg_error("Too many change rules (more than %s)",PRTMAP_SIZE);
+    if (verbose >= 3)
+       printf("  Adding rule: disk 0x%02x, offset 0x%x, 0x%02x -> 0x%02x\n",
+           bios,PART_TABLE_OFFSET+offset,expect,set);
+    prt_map[curr_prt_map] = (set << 24) | (expect << 16) | (offset << 8) | bios;
+    for (i = 0; i < curr_prt_map; i++) {
+       if (prt_map[i] == prt_map[curr_prt_map])
+         die("Repeated rule: disk 0x%02x, offset 0x%x, 0x%02x -> 0x%02x",
+           bios,PART_TABLE_OFFSET+offset,expect,set);
+       if ((prt_map[i] & 0xffff) == ((offset << 8) | bios) &&
+         (prt_map[i] >> 24) == expect)
+           die("Redundant rule: disk 0x%02x, offset 0x%x: 0x%02x -> 0x%02x "
+             "-> 0x%02x",bios,PART_TABLE_OFFSET+offset,
+            (prt_map[i] >> 16) & 0xff,expect,set);
+    }
+    curr_prt_map++;
+}
+
+#endif
+
+
+static int has_partition;
+
+static CHANGE_RULE *may_change(unsigned char sys_ind)
+{
+    CHANGE_RULE *cr = change_rules;
+    
+    while (cr) {
+        if (cr->normal == sys_ind || cr->hidden == sys_ind) return cr;
+        cr = cr->next;
+    }
+    return NULL;
+}
+
+
+void do_cr_auto(void)
+{
+    GEOMETRY geo;
+    struct stat st;
+    char *table, *table2, *other;
+    int partition, pfd, i, j;
+    struct partition part_table[PART_MAX];
+
+    if (autoauto) has_partition = 0;
+    other = identify ? cfg_get_strg(cf_identify, "other")
+                    : cfg_get_strg(cf_top, "other");
+    if (verbose > 4) printf("do_cr_auto: other=%s has_partition=%d\n",
+        other, has_partition);
+#if 0
+    i = other[strlen(other)-1] - '0';
+    if (i>PART_MAX || i<1) return;
+#endif
+    table = cfg_get_strg(cf_other,"table");
+    table2 = boot_mbr(other, 1);       /* get possible default */
+    if (!table) table = table2;
+    
+    if (!table && autoauto) return;
+    if (table && autoauto && !table2) cfg_error("TABLE may not be specified");
+   
+    if (has_partition) cfg_error("AUTOMATIC must be before PARTITION");
+    if (!table) cfg_error("TABLE must be set to use AUTOMATIC");
+    /*    
+     */
+    if (stat(table,&st) < 0) die("stat %s: %s",table,strerror(errno));
+    geo_get(&geo,st.st_rdev & D_MASK(st.st_rdev),-1,1);
+    partition = st.st_rdev & P_MASK(st.st_rdev);
+    if (!S_ISBLK(st.st_mode) || partition)
+       cfg_error("\"%s\" doesn't contain a primary partition table",table);
+    pfd = open(table, O_RDONLY);
+    if (pfd<0) die("Cannot open %s", table);
+    if (lseek(pfd, PART_TABLE_OFFSET, SEEK_SET)!=PART_TABLE_OFFSET)
+       die("Cannot seek to partition table of %s", table);
+    if (read(pfd, part_table, sizeof(part_table))!=sizeof(part_table))
+       die("Cannot read Partition Table of %s", table);
+    close(pfd);
+    partition = other[strlen(other)-1] - '0';
+    if (verbose > 3) printf("partition = %d\n", partition);
+    for (j=i=0; i<PART_MAX; i++)
+       if (may_change(part_table[i].sys_ind)) j++;
+
+    if (j>1)
+#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
+    for (i=0; i<PART_MAX; i++) {
+       CHANGE_RULE *cr;
+       if ((cr=may_change(part_table[i].sys_ind))) {
+           j = i*PARTITION_ENTRY + PART_TYPE_ENT_OFF;
+           if (autoauto) {
+               warn("CHANGE AUTOMATIC assumed after \"other=%s\"", other);
+               autoauto = 0;  /* suppress further warnings */
+           }    
+           if (i == partition-1)
+               add_rule(geo.device, j, cr->hidden, cr->normal);
+           else
+               add_rule(geo.device, j, cr->normal, cr->hidden);
+       }
+    }
+#else
+    warn("This LILO is compiled without REWRITE_TABLE;\n"
+       "   unable to generate CHANGE/AUTOMATIC change-rules");
+#endif
+}
+
+
+
+void do_cr_part(void)
+{
+    GEOMETRY geo;
+    struct stat st;
+    char *tmp;
+    int partition,part_base;
+
+    tmp = cfg_get_strg(cf_change,"partition");
+    if (stat(tmp,&st) < 0) die("stat %s: %s",tmp,strerror(errno));
+    geo_get(&geo,st.st_rdev & D_MASK(st.st_rdev),-1,1);
+    partition = st.st_rdev & P_MASK(st.st_rdev);
+    if (!S_ISBLK(st.st_mode) || !partition || partition > PART_MAX)
+       cfg_error("\"%s\" isn't a primary partition",tmp);
+    part_base = (partition-1)*PARTITION_ENTRY;
+    has_partition = 1;   
+    cfg_init(cf_change_dsc);
+    (void) cfg_parse(cf_change_dsc);
+    tmp = cfg_get_strg(cf_change_dsc,"set");
+    if (tmp) {
+#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
+       CHANGE_RULE *walk;
+       char *here;
+       int hidden;
+
+       here = (void*)NULL;     /* quiet GCC */
+       hidden = 0;             /* quiet GCC */
+       if (strlen(tmp) < 7 || !(here = strrchr(tmp,'_')) ||
+         ((hidden = strcasecmp(here+1,"normal")) &&
+         strcasecmp(here+1,"hidden")))
+           cfg_error("Type name must end with _normal or _hidden");
+       *here = 0;
+       for (walk = change_rules; walk; walk = walk->next)
+           if (!strcasecmp(walk->type,tmp)) break;
+       if (!walk) cfg_error("Unrecognized type name");
+       add_rule(geo.device,part_base+PART_TYPE_ENT_OFF,hidden ? walk->normal :
+         walk->hidden,hidden ? walk->hidden : walk->normal);
+#else
+       die("This LILO is compiled without REWRITE_TABLE and doesn't support "
+         "the SET option");
+#endif
+    }
+    if (cfg_get_flag(cf_change_dsc,"activate")) {
+#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
+       add_rule(geo.device,part_base+PART_ACT_ENT_OFF,0x00,0x80);
+       if (cfg_get_flag(cf_change_dsc,"deactivate"))
+           cfg_error("ACTIVATE and DEACTIVATE are incompatible");
+#else
+       die("This LILO is compiled without REWRITE_TABLE and doesn't support "
+         "the ACTIVATE option");
+#endif
+    }
+    if (cfg_get_flag(cf_change_dsc,"deactivate"))
+#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY)
+       add_rule(geo.device,part_base+PART_ACT_ENT_OFF,0x80,0x00);
+#else
+       die("This LILO is compiled without REWRITE_TABLE and doesn't support "
+         "the DEACTIVATE option");
+#endif
+    cfg_unset(cf_change,"partition");
+}
+
+
+void do_change(void)
+{
+    cfg_init(cf_change);
+    has_partition = 0;
+    (void) cfg_parse(cf_change);
+}
+
+
+void preload_types(void)
+{
+#if 0 /* don't know if it makes sense to add these too */
+    add_type("Netware", 0x64, 0x74);
+    add_type("OS2_BM", 0x0a, 0x1a);
+#endif
+    add_type("OS2_HPFS", 0x07, 0x17);
+
+    add_type("FAT16_lba", PART_FAT16_LBA, -1);
+    add_type("FAT32_lba", PART_FAT32_LBA, -1);
+    add_type("FAT32", PART_FAT32, -1);
+    add_type("NTFS", PART_NTFS, -1);
+    add_type("DOS16_big", PART_DOS16_BIG, -1);
+    add_type("DOS16_small", PART_DOS16_SMALL, -1);
+    add_type("DOS12", PART_DOS12, -1);
+}
+
+
+
+#define PART_BEGIN     0x1be
+#define PART_NUM       4
+#define PART_SIZE      16
+#define PART_ACTIVE    0x80
+#define PART_INACTIVE  0
+
+
+void do_activate(char *part, char *which)
+{
+#if 1
+    int part_max, count, number, fd;
+    struct partition pt [PART_MAX_MAX+1];
+    long long daddr [PART_MAX_MAX+1];
+    int modify=0;
+    
+    part_max = read_partitions(part, extended_pt ? PART_MAX_MAX : 0,
+                                       NULL, pt, daddr);
+/*    printf("part_max=%d\n", part_max); */
+    if (!which) {      /* one argument: display active partition */
+       for (count=0; count < part_max; count++) {
+           if (pt[count].boot_ind) {
+               printf("%s%d\n",part,count+1);
+               exit(0);
+           }
+       }
+       printf("No active partition found on %s\n",part);
+       exit(0);
+    }
+    number = to_number(which);
+    if (number < 0 || number > part_max)
+       die("%s: not a valid partition number (1-%d)",which,part_max);
+
+    if (number && !pt[number-1].sys_ind) die("Cannot activate an empty partition");
+    number--;  /* we are zero-based from here on */
+
+    if ((fd = open(part, O_RDWR)) < 0)
+       die("open %s: %s",part,strerror(errno));
+    for (count=0; count<part_max; count++) {
+       unsigned char flag = count==number ? PART_ACTIVE : PART_INACTIVE;
+       if (pt[count].sys_ind && pt[count].boot_ind != flag) {
+           pt[count].boot_ind = flag;
+           printf("pt[%d] -> %2x\n", count+1, (int)flag);
+           if (lseek64(fd, daddr[count], SEEK_SET) < 0) die("PT lseek64 failed");
+           if (!test)
+           if (write(fd, &pt[count], sizeof(pt[0])) != sizeof(pt[0]) )
+               die("PT write failure");
+           modify++;
+       }
+    }
+    close(fd);
+    if (modify)
+       printf("The partition table has%s been updated.\n", test ? " *NOT*" : "");
+    else
+       printf("No partition table modifications are needed.\n");
+#else
+    struct stat st;
+    int fd,number,count;
+    unsigned char flag, ptype;
+
+    if ((fd = open(part, !which ? O_RDONLY : O_RDWR)) < 0)
+       die("open %s: %s",part,strerror(errno));
+    if (fstat(fd,&st) < 0) die("stat %s: %s",part,strerror(errno));
+    if (!S_ISBLK(st.st_mode)) die("%s: not a block device",part);
+    if (verbose >= 1) {
+       printf("st.st_dev = %04X, st.st_rdev = %04X\n",
+                                       (int)st.st_dev, (int)st.st_rdev);
+    }
+    if ((st.st_rdev & has_partitions(st.st_rdev)) != st.st_rdev)
+        die("%s is not a master device with a primary partition table", part);
+    if (!which) {      /* one argument: display active partition */
+       for (count = 1; count <= PART_NUM; count++) {
+           if (lseek(fd,PART_BEGIN+(count-1)*PART_SIZE,SEEK_SET) < 0)
+               die("lseek: %s",strerror(errno));
+           if (read(fd,&flag,1) != 1) die("read: %s",strerror(errno));
+           if (flag == PART_ACTIVE) {
+               printf("%s%d\n",part,count);
+               exit(0);
+           }
+       }
+       die("No active partition found on %s",part);
+    }
+    number = to_number(which);
+    if (number < 0 || number > 4)
+       die("%s: not a valid partition number (1-4)",which);
+    for (count = 1; count <= PART_NUM; count++) {
+       if (lseek(fd,PART_BEGIN+(count-1)*PART_SIZE+4,SEEK_SET) < 0)
+           die("lseek: %s",strerror(errno));
+       if (read(fd,&ptype,1) != 1) die("read: %s",strerror(errno));
+       if (count == number && ptype==0) die("Cannot activate an empty partition");
+    }
+    if (test) {
+        printf("The partition table of  %s  has *NOT* been updated\n",part);
+    }
+    else for (count = 1; count <= PART_NUM; count++) {
+       if (lseek(fd,PART_BEGIN+(count-1)*PART_SIZE,SEEK_SET) < 0)
+           die("lseek: %s",strerror(errno));
+       flag = count == number ? PART_ACTIVE : PART_INACTIVE;
+       if (write(fd,&flag,1) != 1) die("write: %s",strerror(errno));
+    }
+#endif
+    exit(0);
+}
+
+
+void do_install_mbr(char *part, char *what)
+{
+    int fd, i;
+#ifndef LCF_BUILTIN
+    int nfd;
+#endif
+    struct stat st;
+    BOOT_SECTOR buf;
+    char *cp;
+    
+    if (!what) what = DFL_MBR;
+    extended_pt |= !!strchr(what,'x') || !!strchr(what,'X') || !!strchr(what,'2');
+    if ((fd=open(part,O_RDWR)) < 0) die("Cannot open %s: %s", part,strerror(errno));
+    if (fstat(fd,&st) < 0) die("stat: %s : %s", part,strerror(errno));
+    if (!S_ISBLK(st.st_mode) && !force_fs) die("%s not a block device",part);
+    if (st.st_rdev != (st.st_rdev & has_partitions(st.st_rdev)))
+       die("%s is not a master device with a primary parition table",part);
+    if (read(fd,&buf,SECTOR_SIZE) != SECTOR_SIZE) die("read %s: %s",part, strerror(errno));
+
+    cp = cfg_get_strg(cf_options,"force-backup");
+    i = (cp!=NULL);
+    if (!cp) cp = cfg_get_strg(cf_options,"backup");
+    make_backup(cp, i, &buf, st.st_rdev, part);
+    
+#ifndef LCF_BUILTIN    
+    if ((nfd=open(what,O_RDONLY)) < 0) die("Cannot open %s: %s",what,strerror(errno));
+    if (read(nfd,buf,MAX_BOOT_SIZE) != MAX_BOOT_SIZE) die("read %s: %s",what,strerror(errno));
+#else
+    memcpy(&buf, extended_pt ? Mbr2.data : Mbr.data, MAX_BOOT_SIZE);
+#endif    
+    buf.boot.boot_ind = BOOT_SIGNATURE;
+    if (zflag) {
+        buf.boot.mbz =
+        buf.boot.marker =
+        buf.boot.volume_id = 0;
+#if BETA_TEST || 1
+        if ((cp=cfg_get_strg(cf_options,RAID_EXTRA_BOOT))) {
+           buf.boot.volume_id = strtoul(cp, NULL, 16);
+        }
+#endif
+    } else if (buf.boot.volume_id == 0) {
+#if 0
+       i = st.st_rdev;
+       i %= PRIME;             /* modulo a prime number; eg, 2551, 9091 */
+       i += SMALL_PRIME;
+        srand(time(NULL));     /* seed the random number generator */
+        while (i--) rand();
+        *(int*)&buf[PART_TABLE_OFFSET - 6] = rand();  /* insert serial number */
+        if (*(short*)&buf[PART_TABLE_OFFSET - 2] == 0)
+            *(short*)&buf[PART_TABLE_OFFSET - 2] = MAGIC_SERIAL;
+#else
+       buf.boot.volume_id = new_serial(st.st_rdev);
+       buf.boot.marker = MAGIC_SERIAL;
+#endif
+    }
+    
+    if (lseek(fd,0,SEEK_SET) != 0) die("seek %s; %s", part, strerror(errno));
+    if (!test) {
+       if (write(fd,&buf,SECTOR_SIZE) != SECTOR_SIZE)
+               die("write %s: %s",part,strerror(errno));
+    }
+    close(fd);
+#ifndef LCF_BUILTIN
+    close(nfd);
+#endif
+    printf("The Master Boot Record of  %s  has %sbeen updated.\n", part, test ? "*NOT* " : "");
+    exit(0);
+}
+
+
+
+/* partition table read */
+int read_partitions(char *part, int max, int *volid,
+               struct partition *p, long long *where)
+{
+    int fd, i;
+    unsigned int second, base;
+    unsigned short boot_sig;
+    struct partition pt[PART_MAX];
+    BOOT_PARAMS_1 hdr;
+    struct stat st;
+    long long daddr;
+
+    if ((fd=open(part,O_RDONLY))<0) die("Cannot open '%s'", part);
+    if (fstat(fd,&st)<0) die("Cannot fstat '%s'", part);
+    if (!S_ISBLK(st.st_mode)) die("Not a block device '%s'", part);
+    i = st.st_rdev;
+    if (!has_partitions(i) || (P_MASK(i)&i) )
+       die("Not a device with partitions '%s'", part);
+
+    if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) die("read header");
+    if (!strncmp(hdr.signature, "LILO", 4) && hdr.stage == STAGE_MBR2 &&
+       max == 0) max = PART_MAX_MAX;
+    else if (max == 0) max = PART_MAX;
+    if (lseek(fd, PART_TABLE_OFFSET, SEEK_SET)<0) die("lseek failed");
+    if (read(fd, pt, sizeof(pt)) != sizeof(pt)) die("read pt failed");
+    if ( read(fd, &boot_sig, sizeof(boot_sig)) != sizeof(boot_sig)  ||
+       boot_sig != BOOT_SIGNATURE ) die("read boot signature failed");
+    if (volid) {
+       if (lseek(fd, MAX_BOOT_SIZE+2, SEEK_SET)<0) die("lseek vol-ID failed");
+       if (read(fd, volid, sizeof(*volid)) != sizeof(*volid))
+           die("read vol-ID failed");
+/*     printf(" vol-ID: %08X\n", second);      */
+    }
+/*    printf("%s\n", phead); */
+    second=base=0;
+    if (max>=4)
+    for (i=0; i<PART_MAX; i++) {
+/*     print_pt(i+1, pt[i]); */
+       if (is_extd_part(pt[i].sys_ind)) {
+           if (!base) base = pt[i].start_sect;
+           else die("invalid partition table: second extended partition found");
+       }
+       if (where) *where++ = PART_TABLE_OFFSET + i*sizeof(*p);
+       *p++ = pt[i];
+    }
+
+    max -= (i=4);
+    
+    if (max>0)
+    while (base) {
+       daddr = LLSECTORSIZE*(base+second) + PART_TABLE_OFFSET;
+        if (lseek64(fd, daddr, SEEK_SET) < 0)
+            die("secondary lseek64 failed");
+       if (read(fd, pt, sizeof(pt)) != sizeof(pt)) die("secondary read pt failed");
+       if ( read(fd, &boot_sig, sizeof(boot_sig)) != sizeof(boot_sig)  ||
+           boot_sig != BOOT_SIGNATURE ) die("read second boot signature failed");
+/*     print_pt(i++, pt[0]); */
+        if (is_extd_part(pt[1].sys_ind)) second=pt[1].start_sect;
+        else base = 0;
+        if (max-- > 0) {
+           *p++ = pt[0];
+           if (where) *where++ = daddr;
+           i++;
+        }
+    }
+    if (max > 0) {
+       p->sys_ind = 0;
+       if (where) *where = 0;
+    }
+        
+    close(fd);
+    
+    return i;
+}
+
diff --git a/src/partition.h b/src/partition.h
new file mode 100644 (file)
index 0000000..23b8b7c
--- /dev/null
@@ -0,0 +1,88 @@
+/* partition.h  -  Partition table handling */
+
+/*
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+
+#ifndef PARTITION_H
+#define PARTITION_H
+
+#include <unistd.h>
+#include <linux/unistd.h>
+
+typedef struct _change_rule {
+    const char *type;
+    unsigned char normal;
+    unsigned char hidden;
+    struct _change_rule *next;
+} CHANGE_RULE;
+
+enum {PTW_OKAY=0, PTW_DOS=1, PTW_OS2=2, PTW_SWAP, PTW_XFS,
+               PTW_mask=7, PTW_NTFS=8};
+
+
+#define LLSECTORSIZE ((long long)SECTOR_SIZE)
+
+#if __GLIBC__ < 2 || __GLIBC_MINOR__ < 1
+typedef long long lloff_t;
+
+#ifdef _syscall5
+       lloff_t lseek64(unsigned int fd, lloff_t offs, unsigned int whence);
+#endif
+#endif
+
+struct partition {
+       unsigned char boot_ind;         /* 0x80 - active */
+       unsigned char head;             /* starting head */
+       unsigned char sector;           /* starting sector */
+       unsigned char cyl;              /* starting cylinder */
+       unsigned char sys_ind;          /* What partition type */
+       unsigned char end_head;         /* end head */
+       unsigned char end_sector;       /* end sector */
+       unsigned char end_cyl;          /* end cylinder */
+       unsigned int start_sect;        /* starting sector counting from 0 */
+       unsigned int nr_sects;          /* nr of sectors in partition */
+};
+
+
+int part_nowrite(char* device);
+/* identify partitions which would be destroyed if the boot block
+   is overwritten:
+   
+   known problems occur for:
+       XFS
+       NTFS
+       DOS FAT (relocation will fix)
+*/
+
+#define is_extd_part(x) ((x)==PART_DOS_EXTD||(x)==PART_WIN_EXTD_LBA||(x)==PART_LINUX_EXTD)
+
+void part_verify(int dev_nr,int type);
+/* Verify the partition table of the disk of which dev_nr is a partition. May
+   also try to "fix" a partition table. Fail on non-Linux partitions if the
+   TYPE flag is non-zero (unless IGNORE-TABLE is set too). */
+
+void do_cr_auto(void);
+/* do automatic change-rules */
+
+void preload_types(void);
+/* Preload some partition types for convenience */
+
+void do_activate(char *where, char *which);
+/* Activate the specified partition */
+
+void do_install_mbr(char *where, char *what);
+/* Install a new MBR (Master Boot Record) */
+
+int read_partitions(char *part, int max, int *volid,
+               struct partition *p, long long *where);
+/* read all partitions & partition tables */
+
+#endif
diff --git a/src/probe.c b/src/probe.c
new file mode 100644 (file)
index 0000000..90a579d
--- /dev/null
@@ -0,0 +1,1193 @@
+/* probe.c -- BIOS probes */
+/*
+Copyright 1999-2006 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+/*#define DEBUG_PROBE*/
+#define BITMAP 0       /* change to 1 when do_bitmap is filled in */
+#define VOLID  1       /* change to 1 when do_volid is filled in */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "config.h"
+#include "lilo.h"
+#include "common.h"
+#include "device.h"
+#include "geometry.h"
+#include "partition.h"
+#include "bsect.h"
+#include "bdata.h"
+#include "probe.h"
+
+
+#ifdef LCF_BDATA
+#if BD_MAX_FLOPPY > 4
+#error "too many floppies in  bdata.h"
+#endif
+#if BD_MAX_HARD > 16
+#error "too many hard disks in  bdata.h"
+#endif
+#if BD_GET_VIDEO > 3
+#error "video get level set too high in  bdata.h"
+#endif
+#endif
+
+
+static union Buf {
+   unsigned char b[5*SECTOR_SIZE];
+   struct {
+      short checksum[2];       /* prevent alignment on *4 boundary */
+      char signature[4];
+      short version;
+      short length;
+      unsigned char disk;      /* device code of last good disk */
+      unsigned char vid, mflp, mhrd;
+      short floppy;            /* byte offset to floppy data    */
+      short hard;              /* byte offset to hard disk data */
+      short partitions;                /* byte offset to partition info */
+      video_t v;
+      floppy_t f[4];
+      hard_t d;
+/*      edd_t edd; */
+   } s4;
+   struct {
+      short checksum[2];       /* prevent alignment on *4 boundary */
+      char signature[4];
+      short version;
+      short length;
+      unsigned char disk;      /* device code of last good disk */
+      unsigned char vid, mflp, mhrd;
+      short floppy;            /* byte offset to floppy data    */
+      short hard;              /* byte offset to hard disk data */
+      short partitions;                /* byte offset to partition info */
+/* version 5 additions */
+      short equipment;         /* byte offset to the equipment information */
+      short video;             /* byte offset to the video information */
+   } s5;
+} buf;
+
+static equip_t *eq;
+static video_t1 *v1;
+static video_t2 *v2;
+static video_t25 *v25; /* extension for PROBE_VERSION 5 */
+static video_t3 *v3;
+
+static int video_36_bug;
+static int buf_valid = -1;
+static hard_t *hdp[16+1] =             /* pointers to all the hard disks */
+       {       NULL, NULL, NULL, NULL, 
+               NULL, NULL, NULL, NULL, 
+               NULL, NULL, NULL, NULL, 
+               NULL, NULL, NULL, NULL,  NULL   };
+static char warned[16];
+
+static void do_ebda(void);
+static void do_cr_pr(void);
+static void do_help(void);
+static void do_geom(char *bios);
+static void do_geom_all(void);
+static void do_table(char *part);
+static void do_video(void);
+static void do_bios(void);
+#if BITMAP
+static void do_bitmap(char *file);
+#endif
+#if VOLID
+static void do_volid(void);
+#endif
+static char dev[] = "<device>";
+
+extern CHANGE_RULE *change_rules;      /* defined in partition.c */
+
+
+
+static
+struct Probes {
+       char *cmd;
+       void (*prc)();
+       char *str;
+       char *help;
+       }
+       list[] = {
+{ "help",  do_help,  NULL,  "Print list of -T(ell) options"    },
+{ "bios",  do_bios,  NULL,  "State of DL as passed to boot loader"  },
+#if BITMAP
+{ "bitmap=",do_bitmap,"<file>", "Display .bmp file X,Y/color/timer information"},
+#endif
+{ "ChRul", do_cr_pr, NULL,  "List partition change-rules"  },
+{ "EBDA",  do_ebda,  NULL,  "Extended BIOS Data Area information" },
+{ "geom=", do_geom,  "<bios>", "Geometry CHS data for BIOS code 0x80, etc." },
+{ "geom" , do_geom_all, NULL, "Geometry for all BIOS drives" },
+{ "table=", do_table, dev, "Partition table information for " DEV_DISK_DIR "/hda, etc."},
+{ "video", do_video, NULL,  "Graphic mode information" },
+#if VOLID
+{ "vol-ID", do_volid, NULL, "Volume ID check for uniqueness"},
+#endif
+{ NULL,    NULL,     NULL,   NULL}
+       };
+
+
+static struct partitions {
+       char *name;
+       unsigned char type;
+       unsigned char hide;
+       } ptab [] = {           /* Not complete, by any means */
+
+    { "DOS12", PART_DOS12, HIDDEN_OFF },
+    { "DOS16_small", PART_DOS16_SMALL, HIDDEN_OFF },
+    { "DOS16_big", PART_DOS16_BIG, HIDDEN_OFF },
+    { "NTFS or OS2_HPFS", PART_NTFS, HIDDEN_OFF },     /* same as HPFS; keep these two together */
+/*  { "HPFS", PART_HPFS, HIDDEN_OFF }, */      /* same as NTFS */
+    { "FAT32", PART_FAT32, HIDDEN_OFF },
+    { "FAT32_lba", PART_FAT32_LBA, HIDDEN_OFF },
+    { "FAT16_lba", PART_FAT16_LBA, HIDDEN_OFF },
+    { "OS/2 BootMgr", PART_OS2_BOOTMGR, 0 },
+    { "DOS extended", PART_DOS_EXTD, 0 },
+    { "WIN extended", PART_WIN_EXTD_LBA, 0 },
+    { "Linux ext'd", PART_LINUX_EXTD, 0 },
+    { "Linux Swap", PART_LINUX_SWAP, 0 },
+    { "Linux Native", PART_LINUX_NATIVE, 0 },
+    { "Minix", PART_LINUX_MINIX, 0 },
+    { "Linux RAID", 0xfd, 0 },
+    { NULL, 0, 0 }   };
+
+static char phead[] = "\t\t Type  Boot      Start           End      Sector    #sectors";
+static int dirty = -1; /* buffer is unread */
+
+/* load the low memory bios data area */
+/*  0 = no error, !0 = error on get */
+int fetch(void)
+{
+    int fd;
+    int got, get;
+    int at = 0, seek = PROBESEG*16;
+    
+    if (buf_valid>=0) return buf_valid;
+    
+    if ((fd=open(DEV_DIR "/mem", O_RDONLY)) < 0) return buf_valid=1;
+    at = lseek(fd, seek, SEEK_SET);
+    if (at != seek) return buf_valid=1;
+    get = sizeof(buf.b);
+    if (read(fd, &buf.b, get) != get) return buf_valid=1;
+    close(fd);
+    dirty = 0; /* buffer is unmodified */
+    
+    if (strncmp(buf.s5.signature, PROBE_SIGNATURE,4)) return buf_valid=2;
+/*    got = buf.s5.version; */ /* quiet GCC */
+    if (buf.s5.version < 3 ||
+        buf.s5.version > (short)(PROBE_VERSION)) return buf_valid=3;
+    got = buf.s5.length;
+    if (got > sizeof(buf.b) || got < sizeof(buf.s4)) return buf_valid=4;
+    if (*(int*)buf.s5.checksum != crc32((unsigned char*)&buf.s5 + 4, got-4, CRC_POLY1))
+       return buf_valid=5;
+
+    if (buf.s5.version == 4) {
+       eq = (void*)&buf.s4.v.equipment;
+       v1 = (void*)&buf.s4.v.vid0F;
+       if (buf.s4.vid > 1) v2 = (void*)&buf.s4.v.vid12;
+       if (buf.s4.vid > 2) v3 = (void*)&buf.s4.v.vid4F00;
+    }
+    if (buf.s5.version >= 5) {
+       eq = (void*)&buf.b[buf.s5.equipment];
+       v1 = (void*)&buf.b[buf.s5.video];
+       if (buf.s5.vid > 1) {
+           v2 = (void*)v1 + sizeof(*v1);
+           v25 = (void*)v2 + sizeof(*v2);
+       }
+       if (buf.s5.vid > 2) v3 = (void*)v25 + sizeof(*v25);
+    }
+#if BETA_TEST
+       if (verbose>=5) printf("fetch: good return\n");
+#endif    
+    return buf_valid=0;
+}
+
+
+int purge(void)
+{
+    int i, fd;
+    int seek = PROBESEG*16;
+    
+    if (verbose>=6) printf("purge: called\n");
+#if 0
+    if (verbose>=6) {fetch(); dirty=1;}                /* test of checksumming */
+#endif
+    if (dirty <= 0) return 0;          /* nothing to purge */
+    
+    if ((i=fetch())) return i; /* return error from fetch */
+    
+    i = buf.s5.length;
+    *(int*)buf.s5.checksum = crc32((unsigned char*)&buf.s5 + 4, i-4, CRC_POLY1);
+    
+    if ((fd=open(DEV_DIR "/mem", O_WRONLY)) < 0) pdie("purge: can't open " DEV_DIR "/mem");
+    if (lseek(fd, seek, SEEK_SET) != seek) pdie("purge: ");
+    i = sizeof(buf.b);
+    if (write(fd, &buf.b, i) != i) pdie("purge: ");
+    close(fd);
+    
+    if (verbose>=6) printf("purge: successful write\n");
+    
+    return dirty = 0;                  /* buffer is unmodified */
+}
+
+
+static int notice(int needed)
+{
+    int f = fetch();
+    
+    if (f || buf.s5.version < needed) {
+       printf( f==1 ?  "Only 'root' may do this.\n\n" :
+#if 0
+               "This information request requires that you previously booted your system\n"
+               "using LILO version %s or later.  These versions of the LILO boot\n"
+               "loader provide the BIOS data check information in low memory.  A boot floppy\n"
+               "constructed with 'mkrescue' may help.\n\n",
+#endif
+               "The information you requested is not available.\n\n"
+               "Booting your system with LILO version %s or later would provide the re-\n"
+               "quested information as part of the BIOS data check.  Please install a more\n"
+               "recent version of LILO on your hard disk, or create a bootable rescue floppy\n"
+               "or rescue CD with the 'mkrescue' command.\n\n",
+               
+               needed==4 ? "22.0" :
+               needed==5 ? "22.5.1" :
+               needed==6 ? "22.5.7" :
+               SA(VERSION_MAJOR) "." SA(VERSION_MINOR) VERSION_EDIT  );
+       return 1;
+    }
+    return 0;
+}
+
+
+/* print out the help page for -T flag */
+static void do_help(void)
+{
+    struct Probes *pr;
+    
+    printf("usage:");
+    for (pr=list; pr->cmd; pr++) {
+       printf("\tlilo -T %s%s\t%s\n", 
+                       pr->cmd, 
+                       pr->str ? pr->str : "        ",
+                       pr->help);
+    }
+#ifdef DEBUG_PROBE
+    printf("    In some cases, the '-v' flag will produce more output.\n");
+    printf("sizeof(video_t) = %d  sizeof(floppy_t) = %d  sizeof(hard_t) = %d\n"
+           "sizeof(edd_t) = %d  sizeof(buf.s) = %d\n",
+            sizeof(video_t),  sizeof(floppy_t), sizeof(hard_t), sizeof(edd_t),
+            sizeof(buf.s5) );
+       
+    printf("fetch returns %d\n", fetch());            
+#endif
+}
+
+/* diagnostic output */
+static void show_geom(char *who, int cyl, int head, int sect)
+{
+   if (nowarn) return;
+   fprintf(errstd, "    %s: %d cylinders, %d heads, %d sectors\n", who, cyl, head, sect);
+}
+
+
+/* get the old BIOS disk geometry */
+static int get_geom(unsigned int drive, struct disk_geom *geom)
+{
+    hard_t *hd;
+    floppy_t *fd;
+    int i;
+    struct partition *pt_base;
+    unsigned int total;
+    int sec_err = 0;
+    int hd_err = 0;
+
+#if 0
+    if((i=fetch())) {
+        printf("No drive geometry information is available.\n\n");
+        exit(0);
+    }
+#else
+    if (notice(4)) exit(0);
+#endif
+#ifdef DEBUG_PROBE
+       printf("get_geom: drive = 0x%02X\n", drive);
+       fflush(stdout);
+#endif
+    if (drive >= 0 && drive < buf.s5.mflp) {
+       fd = (floppy_t*)&buf.b[buf.s5.floppy] + drive;
+       hd = (hard_t*)fd;
+    }
+    else if (drive == 0x80) {
+       hdp[drive-0x80] = hd = (hard_t*)&buf.b[buf.s5.hard];
+    }    
+    else if (drive >= 0x81 && drive < 0x80+buf.s5.mhrd) {
+       if (drive > buf.s5.disk) return 1;
+       if (!hdp[drive-0x80]) {
+           i = get_geom(drive-1, geom);
+#ifdef DEBUG_PROBE
+               printf("get_geom recursive return = %d  AH=0x%02X\n", i, i-1);
+               fflush(stdout);
+#endif
+           if (i) return i;
+       }
+       hd = hdp[drive-0x80];
+    } else return 1;
+#ifdef DEBUG_PROBE
+       printf("get_geom:  hd = %08X\n", (int)hd);
+       fflush(stdout);
+#endif
+    
+    memset(geom, 0, sizeof(*geom));
+
+
+    if (drive >= 0x80)
+        hdp[drive-0x80 + 1] = (void*)hd + sizeof(hard_t);              /* simplest increment, but may be wrong */
+    
+    /* regs.eax = 0x1500;           check drive type */
+    /* regs.edx = drive;                       */
+
+#ifdef DEBUG_PROBE
+       printf("get_geom: int13, fn=15\n");
+       fflush(stdout);
+#endif
+   
+   if (hd->fn15.flags & 1)   return 1; /* carry was set */
+   geom->type = hd->fn15.ah;
+   if (geom->type == 0) return 1;
+   if (geom->type == 3)
+     geom->n_total_blocks = ((int)hd->fn15.cx << 16) + hd->fn15.dx;
+   
+   /* regs.eax = 0x0800;               */
+   /* regs.edx = drive;                        */
+   
+#ifdef DEBUG_PROBE
+       printf("get_geom: int13, fn=08\n");
+       fflush(stdout);
+#endif
+   
+   if (hd->fn08.flags&1 || hd->fn08.ah || hd->fn08.cx==0)
+     return 1 + hd->fn08.ah;
+   
+   if (!(i = hd->fn08.cx & 0x3F))  i = 64;     /* BIOS bug if 0 */
+   geom->n_sect = i;
+   
+   i *=
+   geom->n_head = ((hd->fn08.dx>>8)&0xFF)+1;
+   i *=
+   geom->n_cyl  = (((hd->fn08.cx>>8)&0xFF)|((hd->fn08.cx&0xC0)<<2))+1;
+   if (i > geom->n_total_blocks) geom->n_total_blocks = i;
+   geom->n_disks = hd->fn08.dx & 0xFF;
+   geom->pt = NULL;
+
+   hd_err = (geom->n_head > 255);
+   sec_err = (geom->n_sect > 63);
+   
+   if (drive < 4)  return 0;
+   
+   pt_base = NULL;
+   if (buf.s5.disk) {
+       pt_base = (struct partition *)&buf.b[buf.s5.partitions];
+   }
+   if (pt_base && drive <= (int)buf.s5.disk) {
+#if 0
+                               geom->pt = &pt_base[(drive&15)*4];
+#else
+       void *p = (void*)pt_base;
+       int i = buf.s5.version >= 4 ? 8 : 0;
+       
+       p += (drive & 15) * (PART_TABLE_SIZE + i) + i;
+       geom->pt = (struct partition *)p;
+       if (i) geom->serial_no = *(int*)(p-6);
+#endif
+   }
+
+#ifdef DEBUG_PROBE
+   printf("get_geom:  PT->%08X  S/N=%08X\n", (int)geom->pt, geom->serial_no);
+#endif
+      
+   /* regs.eax = 0x4100;      check EDD extensions present */
+   /* regs.edx = drive;                                */
+   /* regs.ebx = 0x55AA;                       */
+#ifdef DEBUG_PROBE
+       printf("get_geom: int13, fn=41\n");
+       fflush(stdout);
+#endif
+   if ((hd->fn41.flags&1)==0 && (hd->fn41.bx)==(unsigned short)0xAA55) {
+      geom->EDD_flags = hd->fn41.cx;
+      geom->EDD_rev = hd->fn41.ah;
+   }
+   
+   if (((geom->EDD_flags) & EDD_SUBSET) || buf.s5.version >= 6) {
+      edd_t *dp;
+
+      dp = (edd_t*)hdp[drive-0x80 + 1];
+#ifdef DEBUG_PROBE
+       printf("get_geom:  EDD  dp = %08X\n", (int)dp);
+       fflush(stdout);
+#endif
+    /* update the pointer to the next drive */
+      hdp[drive-0x80 + 1] = (void*)dp + sizeof(edd_t);
+
+      /* regs.eax = 0x4800;            */
+      /* regs.edx = drive;             */
+      
+#ifdef DEBUG_PROBE
+       printf("get_geom: int13, fn=48\n");
+       fflush(stdout);
+#endif
+
+       if ((dp->reg.flags&1) == 0 && dp->reg.ah == 0) {
+
+             if ((dp->info) & EDD_PARAM_GEOM_VALID) {
+                if ((geom->n_sect != dp->sectors || geom->n_head != dp->heads) &&
+                               ((verbose>0 && !lba32) || verbose>=4) && 
+                               !(warned[drive-0x80]&1) ) {
+                       warn("Int 0x13 function 8 and function 0x48 return different\n"
+                                      "head/sector geometries for BIOS drive 0x%02X", drive);
+                       show_geom("fn 08", geom->n_cyl, geom->n_head, geom->n_sect);
+                       show_geom("fn 48", dp->cylinders, dp->heads, dp->sectors);
+                       warned[drive-0x80] |= 1;
+                   }
+
+       /* prefer to return the fn 8 geometry */
+#if 0
+                geom->n_cyl  = dp->cylinders;
+                geom->n_head = dp->heads;
+                geom->n_sect = dp->sectors;
+#endif
+                total = dp->sectors;
+                total *= dp->heads;
+                total *= dp->cylinders;
+                if (total > geom->n_total_blocks) geom->n_total_blocks = total;
+       
+             }
+             if (dp->total_sectors > geom->n_total_blocks)
+                       geom->n_total_blocks = dp->total_sectors;
+       }
+    }
+    if (!(warned[drive-0x80]&4)) {
+       if (hd_err) warn("LILO is compensating for a BIOS bug: (drive 0x%02X) heads > 255",
+                           drive);
+       if (sec_err) {
+           warn("LILO will try to compensate for a BIOS bug: (drive 0x%02X) sectors > 63",
+                           drive);
+           if ((geom->EDD_flags & EDD_PACKET) && !lba32)
+               die("LBA32 addressing should be used, not %s", linear ? "LINEAR" : "GEOMETRIC");
+           if (!(geom->EDD_flags & EDD_PACKET)   &&   !(lba32 | linear) )
+               warn("Drive 0x%02X may not be usable at boot-time.", drive);
+       }
+       warned[drive-0x80] |= 4;
+    }
+   
+   return 0;
+}
+
+
+/* get the conventional memory size in Kb */
+static int get_conv_mem(void)
+{
+#if 0
+    if(fetch()) {
+        printf("No memory information is available.\n\n");
+        exit(0);
+    }
+#else
+    if (notice(4)) exit(0);
+#endif
+    return (int)eq->mem;
+}
+
+
+/* print the conventional memory size */
+static void do_ebda(void)
+{
+    int m, n, init;
+    static char EBDA[]="Extended BIOS Data Area (EBDA)";
+    
+    m = get_conv_mem() - EBDA_EXTRA;
+#if EBDA_EXTRA
+    printf("*** BUGFIX - reported EBDA is increased by %dK - BUGFIX ***\n",
+       EBDA_EXTRA);
+#endif
+    if (m==640) printf("    no %s\n", EBDA);
+    else printf("    %s = %dK\n", EBDA, 640-m);
+    printf("    Conventional Memory = %dK    0x%06X\n", m, m<<10);
+    m <<= 10;
+    m -= 0x200;
+    n = (select_loader()->size + SECTOR_SIZE - 1) / SECTOR_SIZE;
+    n = m - (n+4+MAX_DESCR_SECS+(COMMAND_LINE_SIZE>256))*SECTOR_SIZE;
+    init = (n - (MAX_SETUPSECS+1)*SECTOR_SIZE)>>4;
+    if (init > DEF_INITSEG) init = DEF_INITSEG;
+    printf("\n");
+
+    printf("    The First stage loader boots at:  0x%08X  (0000:%04X)\n",
+                       FIRSTSEG<<4, FIRSTSEG<<4);
+    printf("    The Second stage loader runs at:  0x%08X  (%04X:%04X)\n",
+                       n, n>>4, n&15);
+    printf("    The kernel cmdline is passed at:  0x%08X  (%04X:%04X)\n",
+                       m, init, m-(init<<4));
+
+}
+
+static char *number(unsigned int n)
+{
+    unsigned int k = 1000000000UL;     /* 10^9 */
+    static char s[16];
+    char *cp = s;
+    
+    while (n<k && k>1) k /= 1000UL;
+    sprintf(cp,"%u",n/k);
+    n %= k;
+    k /= 1000UL;
+    while (k) {
+       while (*++cp) ;
+       sprintf(cp,",%03u",n/k);
+       n %= k;
+       k /= 1000UL;
+    }
+    return s;
+}
+
+
+/* print the CHS geometry information for the specified disk */
+static void print_geom(int dr, struct disk_geom geom)
+{
+    char ch_ser[24] = { 0 };
+    char *sz = "KMGT";
+    char *sp = sz;
+    unsigned int n, m=0;
+
+#ifdef DEBUG_PROBE
+    if (!dr) geom.n_total_blocks = 4000000000UL;       /* 2.09Tb */
+#endif
+
+    if (geom.serial_no) sprintf(ch_ser, "vol-ID: %08X", geom.serial_no);
+    printf("    bios=0x%02x, cylinders=%d, heads=%d, sectors=%d\t%s\n", 
+       dr, geom.n_cyl, geom.n_head, geom.n_sect, ch_ser);
+    n = geom.n_total_blocks/2;
+    while (n > 999999) { n/=1000UL; n*=1024UL; n/=1000UL; sp++; }
+    if (n > 999) {
+       m = (n%1000UL)/10;
+       n /= 1000UL;
+       sp++;
+    }
+    if (m) printf("\t(%3u.%02u%cb", n, m, *sp);
+    else printf("\t(%3u%cb", n, *sp);
+    
+    printf("%14s sectors)", number(geom.n_total_blocks));
+    if (geom.EDD_flags & EDD_PACKET) {
+/*     printf("\tEDD packet calls allowed");   */
+       printf("\tLBA32 supported (EDD bios)");
+    } else printf("\tC:H:S supported (PC bios)");
+    printf("\n");
+}
+
+
+/* print disk drive geometry for all drives */
+static void do_geom_all(void)
+{
+   int d, hd, dr;
+   struct disk_geom geom;
+   
+   for (hd=0; hd<0x81; hd+=0x80)
+   for (d=0; d<16; d++) {
+      dr = d+hd;
+      if (get_geom(dr, &geom)==0) {
+         if (dr==0x80) printf("\nBIOS reports %d hard drive%s\n", (int) geom.n_disks,
+                                      (int)geom.n_disks==1 ? "" : "s");
+        print_geom(dr, geom);
+      }
+   }
+}
+
+
+/* print disk drive geometry information for a particular drive */
+static void do_geom(char *bios)
+{
+    int dr;
+    struct disk_geom geom;
+
+    dr = to_number(bios);
+    if (get_geom(dr, &geom)==0) print_geom(dr, geom);
+    else printf("Unrecognized BIOS device code 0x%02x\n", dr);
+    
+}
+
+
+/* print an individual partition table entry */
+static void print_pt(int index, struct partition pt)
+{
+    char bt[4], *ty, start[32], end[32], type[8];
+    char x;
+    int i;
+    
+    for (x=i=0; i<sizeof(pt); i++) x |= ((char*)&pt)[i];
+    if (!x) {
+       printf("%4d\t\t\t     ** empty **\n", index);
+       return;
+    }
+    strcpy(bt,"   ");
+    sprintf(type, "0x%02x", (int)pt.sys_ind);
+    sprintf(start, "%4d:%d:%d",
+       (int)pt.cyl+((pt.sector&0xC0)<<2),
+       (int)pt.head,
+       (int)pt.sector & 0x3f );
+    sprintf(end, "%4d:%d:%d",
+       (int)pt.end_cyl+((pt.end_sector&0xC0)<<2),
+       (int)pt.end_head,
+       (int)pt.end_sector & 0x3f );
+    ty = type;
+    if (pt.boot_ind==0x80) bt[1]='*';
+    else if (pt.boot_ind==0) ; /* do nothing */
+    else {
+       sprintf(bt+1,"%02x", (int)pt.boot_ind);
+    }
+    for (i=0; ptab[i].name; i++) {
+       if (ptab[i].type == pt.sys_ind) {
+           ty = ptab[i].name;
+           break;
+       } else if ((ptab[i].type|ptab[i].hide) == pt.sys_ind) {
+           bt[0] = 'H';
+           ty = ptab[i].name;
+           break;
+       }
+    }
+    printf("%4d%18s%5s%11s%14s%12u%12u\n", index, ty, bt,
+       start, end, pt.start_sect, pt.nr_sects);
+}
+
+
+/* partition table display */
+static void do_table(char *part)
+{
+    struct partition pt [PART_MAX_MAX+1];
+    int volid;
+    long long where[PART_MAX_MAX+1];
+    int i,j;
+    int extd = (extended_pt || verbose>0);
+    
+    j = read_partitions(part, extd ? nelem(pt)-1 : 0, &volid, pt, verbose>=5 ? where : NULL);
+    extd |= j>PART_MAX;
+    printf(" vol-ID: %08X\n\n%s\n", (int)volid, phead);
+    for (i=0; i<PART_MAX; i++) {
+       print_pt(i+1, pt[i]);
+    }
+    i=4;
+    if (extd)
+    while (pt[i].sys_ind) {
+       print_pt(i+1, pt[i]);
+       i++;
+    }
+    if (verbose>=5) {
+       printf("\n");
+       for (i=0; i<j; i++) printf("%4d%20lld%12d\n", i+1, where[i], (int)(where[i]/SECTOR_SIZE));
+    }
+}
+
+
+/* list partition change-rules */
+static void do_cr_pr(void)
+{
+    CHANGE_RULE *cr;
+    
+    cr = change_rules;
+    printf("\t\tType Normal Hidden\n");
+    if (!cr) printf("\t **** no change-rules defined ****\n");
+    while (cr) {
+       printf ("%20s  0x%02x  0x%02x\n", cr->type, (int)cr->normal, (int)cr->hidden);
+       cr = cr->next;
+    }
+}
+
+static int egamem;
+static int mode, col, row, page;
+/*
+enum {VIDEO_UNKNOWN, VIDEO_MDA, VIDEO_CGA, VIDEO_EGA, VIDEO_MCGA,
+       VIDEO_VGA, VIDEO_VESA, VIDEO_VESA_800};
+ */
+
+int get_video(void)    /* return -1 on error, or adapter type [0..7] */
+{
+    int adapter = 0;    /* 0=unknown, 1=MDA,HGC, 2=CGA, 3=EGA, 4=MCGA, 5=VGA,
+                                        6=VESA (640), 7=VESA (800) */
+    int okay = 1;
+    int monitor;
+        
+    if(fetch()) return -1;
+
+    if ((okay=buf.s5.vid)) {
+    /* get current video mode */
+    /* reg.eax = 0x0F00;               */
+       if (verbose >= 6)
+           printf("get video mode\n");
+       mode = v1->vid0F.al;
+       col = v1->vid0F.ah;
+       page = v1->vid0F.bh;
+       row = v1->vid0F.bl + 1;
+       if (mode==7) {
+           adapter=1;
+           row = 25;
+           okay = 0;
+       } else if (col<80) {
+           adapter=2;
+           okay=0;
+       } else adapter=2;       /* at least CGA */
+    }
+    if (okay>=2) {
+    /* determine video adapter type */
+    /*    reg.eax = 0x1200;      call valid on EGA/VGA */
+    /*    reg.ebx = 0xFF10;                            */
+       if (verbose >= 6)
+           printf("determine adapter type\n");
+       if ((unsigned)(monitor = v2->vid12.bh) <= 1U)  {
+           adapter = 3; /* at least EGA */
+           egamem = v2->vid12.bl;
+       }
+       else {
+           okay = 0;
+       }
+    }
+    if (okay>=2) {
+       /* check for VGA */
+       /* reg.eax = 0x1A00;       get display combination */
+       if (verbose >= 6)
+           printf("get display combination\n");
+       if ( v2->vid1A.al==0x1A ) {
+           monitor = (v2->vid1A.bx >> ((verbose>=9)*8) ) & 0xFF;
+           switch (monitor) {
+             case 1:
+               adapter = 1;
+               break;
+             case 2:
+               adapter = 2;
+               break;
+             case 7:
+             case 8:
+               adapter = 5;    /* VGA */
+               break;
+             case 0xA:
+             case 0xB:
+             case 0xC:
+               adapter = 4;    /* MCGA */
+               break;
+             default:
+               okay = 0;
+               break;
+           }
+       } else {
+           okay = 0;
+       }
+    }
+    if (okay>=3 && adapter==5) {
+       /* check for BIOS bug (trashing DX) */
+       if (v25 && verbose >= 6)
+           printf("check Enable Screen Refresh\n");
+       if (v25) {
+           video_36_bug = 2;   /* mark implemented */
+           
+           if ((v25->vid36.ax & 0xFF) != 0x12)  video_36_bug = 1;
+           else {
+               if (v25->vid36.cx != 0x1234 || v25->vid36.bp != 0x4321)
+                   video_36_bug |= 4;
+               if (v25->vid36.dx != 0x5680) video_36_bug |= 8;
+           }
+       }
+       
+       /* check for VESA extensions */
+       if (verbose >= 6)
+           printf("check VESA present\n");
+           
+       if ((v3->vid4F00.ax == 0x4f) && strncmp("VESA", v3->vid4F00.sig, 4)==0)  adapter++;
+       
+       if (adapter > 5) {
+           /* reg.eax = 0x4f01;
+              reg.ecx = 0x0101;           640x480x256 */
+           if ((v3->vid101.ax == 0x4f) && (v3->vid101.bits & 0x19) == 0x19) adapter ++;
+           else adapter--;
+       }
+       if (adapter > 6) {
+           /* reg.eax = 0x4f01;
+              reg.ecx = 0x0103;           800x600x256 */
+           if ((v3->vid103.ax == 0x4f) && (v3->vid103.bits & 0x19) == 0x19) ;
+           else adapter--;
+       }
+    }
+    if (verbose>=2)
+       printf ("mode = 0x%02x,  columns = %d,  rows = %d,  page = %d\n",
+                      mode, col, row, page);
+    
+    return adapter;
+}
+
+/* print VGA/VESA mode information */
+void do_video(void)
+{
+static char *display[] = { "unknown", "MDA", "CGA", "EGA", 
+               "MCGA", "VGA", "VGA/VESA", "VGA/VESA" };
+    int adapter; /* 0=unknown, 1=MDA,HGC, 2=CGA, 3=EGA, 4=MCGA, 5=VGA,
+                        6=VESA (640), 7=VESA (800) */
+
+    if (notice(4)) exit(0);
+    
+    adapter = get_video();
+#if 0
+    if(adapter<0) {
+        printf("No video mode information is available.\n");
+        return;
+    }
+#endif
+    printf("%s adapter:\n\n", display[adapter]);
+    if (adapter < 3 || (adapter == 3 && egamem < 1) ) {
+        printf("No graphic modes are supported\n");
+    } else {
+       if (adapter != 4)
+           printf("    640x350x16    mode 0x0010\n");
+       if (adapter >= 5) {
+           printf("    640x480x16    mode 0x0012\n\n");
+           printf("    320x200x256   mode 0x0013\n");
+       }
+       if (adapter >= 6)
+           printf("    640x480x256   mode 0x0101\n");
+       if (adapter >= 7)
+           printf("    800x600x256   mode 0x0103\n");
+    }
+    if (video_36_bug && (verbose>0 || (video_36_bug&(8+4)))) {
+     /* setting video_36_bug is a side effect of get_video */
+       printf("\nEnable Screen Refresh %s.\n",
+           (video_36_bug & 4) ? "bugs are present" :
+           (video_36_bug & 8) ? "bug is present" :
+           (video_36_bug == 1) ? "is not supported" : "is supported");
+    }
+}
+
+/* entry from lilo.c for the '-T' (tell) switch */
+void probe_tell (char *cmd)
+{
+    struct Probes *pr = list;
+    int n;
+    char *arg;
+    
+    if (!(verbose>0)) printf("\n");
+    for (; pr->cmd; pr++) {
+       n = strlen(pr->cmd);
+       arg = NULL;
+       if (pr->cmd[n-1] == '=') arg = cmd+n;
+       if (!strncasecmp(cmd, pr->cmd, n)) {
+           pr->prc(arg);
+           printf("\n");
+           exit(0);
+       }
+    }
+    printf("Unrecognized option to '-T' flag\n");
+    do_help();
+    printf("\n");
+    exit(1);
+}
+
+
+int bios_max_devs(void)
+{
+    struct disk_geom geom;
+    int i;
+    
+    if (!fetch() && !get_geom(0x80, &geom)) {
+       i = (buf.s5.disk & 0x7f) + 1;
+       if (geom.n_disks == i) return i;
+    }
+    return BIOS_MAX_DEVS;    
+}
+
+#ifdef DEBUG_PROBE
+static void dump_pt(unsigned char *pt)
+{
+    int i, j;
+    for (j=0; j<4; j++) {
+       for (i=0; i<16; i++) {
+           printf(" %02X", (int)(*pt++));
+       }
+       printf("\n");
+    }
+    printf("\n");
+}
+#endif
+
+/* 
+ *  return the bios device code of the disk, based on the geometry
+ *     match with the probe data
+ *   side effect is to place the device code in geo->device
+ * return -1 if indeterminate
+ */
+int bios_device(GEOMETRY *geo, int device)
+{
+    int bios1, bios, match, fd;
+    int bios2, snmatch;
+    int mbios[BD_MAX_HARD];
+    struct disk_geom bdata;
+    DEVICE dev;
+    unsigned char part[PART_TABLE_SIZE];
+    unsigned char extra[8];
+    int serial;
+    
+        
+    if (fetch()) return -1;
+    
+    if (verbose>=5) printf("bios_dev:  device %04X\n", device);
+#ifdef DEBUG_PROBE
+       fflush(stdout);
+#endif    
+    if (!has_partitions(device)) return -1;
+        
+    match = 0;
+    bios1 = -1;                /* signal error */
+    for (bios=0x80; bios<=buf.s5.disk; bios++) {
+       mbios[bios-0x80] = 0;
+       if (get_geom(bios, &bdata)) break;
+       if (geo->cylinders == bdata.n_cyl &&
+           geo->heads == bdata.n_head &&
+           geo->sectors == bdata.n_sect) {
+               match++;
+               mbios[bios-0x80] = bios1 = bios;
+       }
+    }
+    if (match == 1) {
+       if (verbose>=5) printf("bios_dev: match on geometry alone (0x%02X)\n",
+               bios1);
+       return (geo->device = bios1);
+    }
+
+    device &= D_MASK(device);  /* mask to primary device */
+    fd = dev_open(&dev,device,O_RDONLY);
+    if (verbose>=5) printf("bios_dev:  masked device %04X, which is %s\n", 
+                       device, dev.name);
+    if (lseek(fd, PART_TABLE_OFFSET-8, SEEK_SET)!=PART_TABLE_OFFSET-8)
+       die("bios_device: seek to partition table - 8");
+    if (read(fd,extra,sizeof(extra))!= sizeof(extra))
+       die("bios_device: read partition table - 8");
+    serial = *(int*)(extra+2);
+    if (lseek(fd, PART_TABLE_OFFSET, SEEK_SET)!=PART_TABLE_OFFSET)
+       die("bios_device: seek to partition table");
+    if (read(fd,part,sizeof(part))!= sizeof(part))
+       die("bios_device: read partition table");
+    dev_close(&dev);
+
+#ifdef DEBUG_PROBE
+    if (verbose>=5) {
+        printf("serial number = %08X\n", serial);
+        dump_pt(part);
+    }
+#endif
+
+    if (verbose>=5) printf("bios_dev: geometry check found %d matches\n", match);
+    
+    snmatch = match = 0;
+    bios2 = bios1 = -1;
+
+ /* 'bios' is set leaving the 'for' above */
+    while (--bios >= 0x80) {
+       get_geom(bios, &bdata);
+       if (verbose>=5) {
+               printf("bios_dev: (0x%02X)  vol-ID=%08X  *PT=%08lX\n",
+                       bios, bdata.serial_no, (long)bdata.pt);
+#ifdef DEBUG_PROBE
+               dump_pt((void*)bdata.pt);
+#endif
+       }
+       if ( !memcmp(part,bdata.pt,sizeof(part)) ) {
+           match++;
+           bios1 = bios;
+       }
+       if ( bdata.serial_no && serial==bdata.serial_no ) {
+           snmatch++;
+           bios2 = bios;
+       }
+    }
+    if (verbose>=5) printf("bios_dev: PT match found %d match%s (0x%02X)\n",
+               match, match==1 ? "" : "es", bios1&255);
+    if (match != 1) {
+       match = snmatch;
+       bios1 = bios2;
+       if (verbose>=5) printf("bios_dev: S/N match found %d match%s (0x%02X)\n",
+               match, match==1 ? "" : "es", bios1);
+    }
+
+    if (match == 1) {
+       get_geom(bios1, &bdata);
+       if (  (geo->sectors && geo->sectors!=bdata.n_sect)  ||
+              (geo->heads && geo->heads!=bdata.n_head)  )  {
+           unsigned int nblocks = geo->cylinders * geo->heads * geo->sectors;
+
+           if (!(lba32 | linear) && !(warned[bios1-0x80]&2) ) {
+               warn("Kernel & BIOS return differing head/sector geometries for device 0x%02X", bios1);
+               show_geom("Kernel", geo->cylinders, geo->heads, geo->sectors);
+               show_geom("  BIOS", bdata.n_cyl, bdata.n_head, bdata.n_sect);
+               warned[bios1-0x80] |= 2;
+           }
+#if 1
+           geo->sectors = bdata.n_sect;
+           geo->heads = bdata.n_head;
+           if (bdata.n_total_blocks > nblocks) nblocks = bdata.n_total_blocks;
+           /* If this is a buggy BIOS, make sure to avoid a division by zero */
+           if (bdata.n_head*bdata.n_sect > 0) 
+               geo->cylinders = nblocks / (bdata.n_head*bdata.n_sect);
+           else
+               geo->cylinders = nblocks;
+#endif
+       }
+       return (geo->device = bios1);
+    }
+
+    return -1;
+}
+
+
+#if BITMAP
+static void do_bitmap(char *file)
+{
+    printf("Color, Positioning, and Timer information for file:  %s\n", file);
+    printf("...<unimplemented>...\n");
+}
+#endif
+
+static unsigned char dl,dh;
+
+static int get_bios(void)
+{
+    if (fetch() || buf.s5.version<5) return -1;
+#if BETA_TEST
+       if (verbose>=5) printf("get_bios 1\n");
+#endif
+    dl = eq->boot_dx;
+#if BETA_TEST
+       if (verbose>=5) printf("get_bios 2\n");
+#endif
+    dh = eq->boot_dx >> 8;
+    
+    return eq->boot_dx;
+}
+
+
+void check_bios(void)
+{
+#if BETA_TEST
+       if (verbose>=5) printf("check_bios 1\n");
+#endif
+    if (bios_passes_dl == DL_NOT_SET) {
+       bios_passes_dl = DL_UNKNOWN;
+       
+       if (get_bios() < 0) return;
+#if BETA_TEST
+       if (verbose>=5) printf("check_bios 2\n");
+#endif
+       if (dl==0xFE) {
+           if ( !((dh>=0x80 && dh<=DEV_MASK) || dh==0) )
+               bios_passes_dl = DL_BAD;
+       }
+       else if ( dl>=0x80 && dl<=DEV_MASK ) bios_passes_dl = DL_MAYBE;
+       else if ( dl > 0 ) bios_passes_dl = DL_BAD;
+    }
+    /* already set, leave alone */
+#if BETA_TEST
+       if (verbose>=5) printf("check_bios 3  bios_passes_dl=%d\n", (int)bios_passes_dl);
+#endif
+}
+
+
+void do_bios(void)
+{
+    int code=1;
+    
+static char *ord[] =
+{ "first", "second", "3rd", "4th", "5th", "6th", "7th", "8th",
+  "9th", "10th", "11th", "12th", "13th", "14th", "15th", "16th" };
+    
+    notice(5);
+    if (get_bios() < 0)
+       printf("No information available on the state of DL at boot.\n");
+    else
+    {
+       printf("BIOS provided boot device is 0x%02x  (DX=0x%04X).\n",
+               code=(dl==0xFE ? dh : dl), eq->boot_dx);
+       bios_passes_dl = DL_NOT_SET;
+       check_bios();
+    }
+    printf("\nUnless overridden, 'bios-passes-dl = %s' will be assumed.",
+       bios_passes_dl == DL_BAD ? "no" :
+       bios_passes_dl == DL_MAYBE ? "maybe" :
+       bios_passes_dl == DL_GOOD ? "yes" : "unknown" );
+    if (bios_passes_dl > DL_BAD) {
+       char *cp = NULL;
+       char *cn = NULL;
+
+       if (code>=0 && code<2) { cp="floppy"; cn=ord[code]; }
+       if (code>=0x80 && code<=0x8f) { cp="hard"; cn=ord[code&15]; }
+       if (cp)
+       printf("  If you\nactually booted from the %s %s drive, then this assumption is okay.",
+               cn, cp);
+#if 0
+       if (bios_passes_dl == DL_MAYBE)
+           printf("\nIf the BIOS always gets DL set correctly, you might consider specifying\n"
+                  "  'bios_passes_dl = yes' or '-Z1'.\n");
+#endif
+    }
+    printf("\n");
+}
+
+#if VOLID
+static void do_volid(void)
+{
+    int bios, n, i, k, sv, nv, unique;
+    struct disk_geom geom;
+    unsigned int serial[MAX_BIOS_DEVICES];
+    int uniq[MAX_BIOS_DEVICES], valid[MAX_BIOS_DEVICES];
+
+    if (notice(4)) exit(0);
+    
+    printf("\n  BIOS     Volume ID\n\n");
+    unique = 1;
+    nv = n = 0;
+    for (bios=0x80; bios<0x80+MAX_BIOS_DEVICES && !get_geom(bios, &geom); bios++) {
+       int uq = 1;
+       i = bios - 0x80;
+#if 0
+       if (i==0 || i==2) geom.serial_no = 0;
+       if (i==4) geom.serial_no = serial[2];
+#endif
+
+       serial[i] = geom.serial_no;
+       valid[i] = sv = serial_valid(geom.serial_no, bios);
+       nv |= !sv;
+       if (sv) for (k=0; k<i; k++) uq &= (geom.serial_no != serial[k]);
+       uniq[i] = uq;
+       unique &= uq;
+       n++;
+
+       printf("  0x%02X     %08X %s%s\n", i+0x80, serial[i],
+               uq ? "" : "*", sv ? "" : "-");
+    }
+
+    printf("\nVolume ID's are%s unique.\n", unique ? " all" : " NOT");
+    if (nv)
+       printf("   '-' marks an invalid Volume ID which will be automatically updated\n"
+               "\tthe next time  /sbin/lilo  is executed.\n");
+    if (!unique)
+       printf("   '*' marks a volume ID which is duplicated.  Duplicated ID's must be\n"
+               "\tresolved before installing a new boot loader.  The volume ID may\n"
+               "\tbe cleared using the '-z' and '-M' switches.\n"
+               );
+    printf("\n");
+}
+#endif
+
diff --git a/src/probe.h b/src/probe.h
new file mode 100644 (file)
index 0000000..c384c4f
--- /dev/null
@@ -0,0 +1,241 @@
+/* probe.h  -- definitions for the LILO probe utility
+
+Copyright 1999-2005 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+#ifndef __PROBE_H_
+#define __PROBE_H_
+
+
+
+struct disk_geom {
+   unsigned int n_total_blocks;
+   int n_sect;
+   int n_head;
+   int n_cyl;
+   char type;
+   char EDD_flags;
+   char EDD_rev;
+   char n_disks;
+   struct partition *pt;
+   int serial_no;              /* added at PROBE_VERSION==4 */
+};
+
+#if 0
+/* structure used by int 0x13, AH=0x48 */
+
+struct disk_param {
+   short size;
+   short flags;
+   unsigned int n_cyl;
+   unsigned int n_head;
+   unsigned int n_sect;
+   long long n_sectors;
+   short n_byte;
+   unsigned int edd_config_ptr;
+};
+#endif
+
+
+#define EDD_DMA_BOUNDARY_TRANSP  01
+#define EDD_PARAM_GEOM_VALID     02
+
+
+/* the following structures are created by the biosdata.S codes */
+
+typedef
+struct Equip {
+   unsigned short equipment;
+   unsigned short mem;
+#if PROBE_VERSION >= 5
+   unsigned short boot_dx;
+#endif
+} equip_t;
+
+
+/* BD_GET_VIDEO >= 1 */
+typedef
+struct Video1 {
+   struct {
+      unsigned char  al;
+      unsigned char  ah;
+      unsigned char  bl;
+      unsigned char  bh;
+   } vid0F;
+} video_t1;
+
+
+/* BD_GET_VIDEO >= 2  */
+typedef
+struct Video2 {
+   struct {
+      unsigned short ax;
+      unsigned char  bl;
+      unsigned char  bh;
+   } vid12;
+   struct {
+      unsigned char  al;
+      unsigned char  ah;
+      unsigned short bx;
+   } vid1A;
+} video_t2;
+
+/* BD_GET_VIDEO >=2 extension for PROBE_VERSION 5 */
+typedef
+struct Video25 {
+   struct {
+      unsigned short ax;
+      unsigned short cx;
+      unsigned short dx;
+      unsigned short bp;
+   } vid36;
+} video_t25;
+
+
+/* BD_GET_VIDEO >= 3  */
+typedef
+struct Video3 {
+   struct {
+      unsigned short ax;
+               char  sig[4];
+   } vid4F00;
+   struct {
+      unsigned short ax;
+      unsigned short bits;
+   } vid101;
+   struct {
+      unsigned short ax;
+      unsigned short bits;
+   } vid103;
+} video_t3;
+
+
+typedef
+struct Video {
+   unsigned short equipment;
+   unsigned short mem;
+
+/* BD_GET_VIDEO >= 1 */
+   struct {
+      unsigned char  al;
+      unsigned char  ah;
+      unsigned char  bl;
+      unsigned char  bh;
+   } vid0F;
+
+/* BD_GET_VIDEO >= 2  */
+   struct {
+      unsigned short ax;
+      unsigned char  bl;
+      unsigned char  bh;
+   } vid12;
+   struct {
+      unsigned char  al;
+      unsigned char  ah;
+      unsigned short bx;
+   } vid1A;
+
+
+/* BD_GET_VIDEO >= 3  */
+   struct {
+      unsigned short ax;
+      unsigned char  sig[4];
+   } vid4F00;
+   struct {
+      unsigned short ax;
+      unsigned short bits;
+   } vid101;
+   struct {
+      unsigned short ax;
+      unsigned short bits;
+   } vid103;
+} video_t;
+
+
+typedef
+struct Floppy {
+   struct {
+      unsigned char  ah;               /* AL and AH were swapped */
+      unsigned char  flags;
+      unsigned short dx;
+      unsigned short cx;
+   } fn15;
+   struct {
+      unsigned char  ah;               /* AL and AH were swapped */
+      unsigned char  flags;
+      unsigned short cx;
+      unsigned short dx;
+      unsigned short di;
+      unsigned short es;
+   } fn08;
+} floppy_t;
+
+
+typedef
+struct Hard {
+   struct {
+      unsigned char  ah;               /* AL and AH were swapped */
+      unsigned char  flags;
+      unsigned short dx;
+      unsigned short cx;
+   } fn15;
+   struct {
+      unsigned char  ah;               /* AL and AH were swapped */
+      unsigned char  flags;
+      unsigned short cx;
+      unsigned short dx;
+   } fn08;
+   struct {
+      unsigned char  ah;               /* AL and AH were swapped */
+      unsigned char  flags;
+      unsigned short bx;
+      unsigned short cx;
+   } fn41;
+} hard_t;
+
+typedef
+struct Fn48 {
+   unsigned char  ah;          /* AL and AH were swapped */
+   unsigned char  flags;
+} fn48_t;
+
+typedef
+struct Edd {
+   unsigned short size;                        /* 26 or 30 */
+   unsigned short info;
+   unsigned int  cylinders;
+   unsigned int  heads;
+   unsigned int  sectors;
+   long long      total_sectors;
+   unsigned short sector_size;
+
+   unsigned short offset,
+                 segment;
+           fn48_t reg;         /* AH & flags returned from the call */
+} edd_t;                               /* struct is 26; but may be 30 in mem */
+
+/* the video adapter types */
+enum {VIDEO_UNKNOWN, VIDEO_MDA, VIDEO_CGA, VIDEO_EGA, VIDEO_MCGA,
+       VIDEO_VGA, VIDEO_VESA, VIDEO_VESA_800};
+
+int fetch(void);
+
+int purge(void);
+
+void probe_tell (char *cmd);
+
+int bios_max_devs(void);
+
+int bios_device(GEOMETRY *geo, int device);
+
+int get_video(void);   /* return -1 on error, or adapter type [0..7] */
+
+void check_bios(void); /* set up bios_passes_dl */
+
+#endif
+/* end probe.h */
diff --git a/src/pseudo.S b/src/pseudo.S
new file mode 100644 (file)
index 0000000..ceda00d
--- /dev/null
@@ -0,0 +1,71 @@
+; pseudo.S -- produce a pseudo kernel header
+;
+;      This file is useful for booting arbitrary binary images
+;      at      0x1000:0000
+;
+; Copyright 2002-2005 John Coffman.
+; All rights reserved.
+; 
+; Licensed under the terms contained in the file 'COPYING' in the 
+; source directory.
+;
+
+#define DEBUG 0
+#define DELL_DIRTY_HACK
+
+
+SYSSEG =  0x1000       ; DEF_SYSSEG
+SETUPSEG = 0x9020      ; DEF_SETUPSEG
+
+CL_MAGIC_ADDR  = 0x20                  ! command line magic number
+CL_MAGIC       = 0xa33f                ! very unusual command sequence
+CL_OFFSET      = 0x22                  ! command line offset
+CL_LENGTH      = 256                   ! maximum length
+
+               .text
+#if 0
+.globl _main
+_main:
+#endif
+               .globl  zero
+zero:
+
+; we want this to look like a bootable kernel image
+; so we include the following header
+;
+               jmp     begin
+               .ascii  "HdrS"          ; looks like a real kernel
+               .word   0x0200          ; header format version number
+               .word   0,0             ; realmode switch, SETUPSEG
+               .word   SYSSEG          ; SYSSEG -- load at 1000:0000
+               .word   id_string
+               .byte   0               ; type of loader
+               .byte   0               ; flags 0=load low
+               .word   2*512           ; move size: 2 sectors
+               dd      0x10000         ; load us here
+               dd      0               ; ramdisk image
+               dd      0               ; ramdisk size
+               .word   bs_helper,SETUPSEG      ; kludge???
+;;             .word   modelist+1024   ; heap end pointer
+;----------end of header------------
+               
+begin:
+       xor     di,di
+       cmp     word ptr [CL_MAGIC_ADDR],#CL_MAGIC
+       jne     gotoit
+       mov     di,[CL_OFFSET]
+gotoit:
+       jmpi    0000,SYSSEG                     ; jmp to 0x1000:0000
+
+
+bs_helper:      int     0x19                   ;label here for kludge
+
+
+id_string:     .ascii  "pseudo.b"
+               .byte   0
+
+               .blkb   zero+512-*
+
+modelist:
+
+theend:
diff --git a/src/raid.c b/src/raid.c
new file mode 100644 (file)
index 0000000..6a1a640
--- /dev/null
@@ -0,0 +1,644 @@
+/* raid.c  -  The RAID-1 hooks for LILO */
+/*
+Copyright 2001-2005 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+/*#include <asm/page.h>*/
+
+#include "config.h"
+#include "lilo.h"
+#include "common.h"
+#include "raid.h"
+#include "boot.h"
+#include "device.h"
+#include "geometry.h"
+#include "bsect.h"
+#include "cfg.h"
+#include "partition.h"
+#include "md-int.h"
+
+static int lowest;
+static DT_ENTRY *md_disk;
+static DT_ENTRY *disk;
+static unsigned int raid_base, raid_offset[MAX_RAID];
+static char *raid_mbr[MAX_RAID];
+static int raid_device[MAX_RAID+1];
+static int raid_bios[MAX_RAID+1];
+static int device;
+enum {MD_NULL=0, MD_PARALLEL, MD_MIXED, MD_SKEWED};
+int do_md_install, ndisk, md_bios;
+static char *raid_list[MAX_RAID];
+static int list_index[MAX_RAID];
+static int nlist, faulty;
+static int autocount;
+static char *boot;
+
+#define IS_COVERED    0x1000
+#define TO_BE_COVERED 0x2000
+#define COVERED   (IS_COVERED|TO_BE_COVERED)
+
+static int is_primary(int device)
+{
+    int mask;
+    
+    mask = has_partitions(device);
+    if (!mask) die("is_primary:  Not a valid device  0x%04X", device);
+    mask = device & ~mask;
+    return (mask && mask<=PART_MAX);
+}
+
+
+
+static int master(int device)
+{
+    int mask;
+    
+    if (MAJOR(device) == MAJOR_FD) return device;
+    
+    mask = has_partitions(device);
+    if (!mask) die("master:  Not a valid device  0x%04X", device);
+    return device & mask;
+}
+
+
+static int is_accessible(int device)
+{
+    int mask;
+    
+    mask = has_partitions(device);
+    if (!mask) die("is_accessible:  Not a valid device  0x%04X", device);
+    mask = device & ~mask;
+    return (mask<=PART_MAX);
+}
+
+
+int raid_setup(void)
+{
+    int pass, mask;
+    struct stat st;
+    int md_fd;
+    struct md_version md_version_info;
+    md_disk_info_t md_disk_info;
+    md_array_info_t md_array_info;
+    GEOMETRY geo;
+    DEVICE dev;
+    char *extrap;
+    int raid_offset_set, all_pri_eq, pri_index;
+    int pri_offset;
+    int raid_limit;
+    
+    if (!(boot=cfg_get_strg(cf_options,"boot"))) {
+       boot = "/";
+#if 0
+      warn("RAID1 install implied by omitted 'boot='");
+#endif
+    }
+    if (stat(boot,&st)<0) die("raid_setup: stat(\"%s\")", boot);
+
+    if (verbose>=5)
+       printf("raid_setup: dev=%04X  rdev=%04X\n",
+                               (int)st.st_dev, (int)st.st_rdev);
+
+#if BETA_TEST
+       fflush(stdout);
+#endif
+
+    if ( MAJOR(st.st_rdev) != MAJOR_MD ) {     /* not raid */
+       if (cfg_get_strg(cf_options, RAID_EXTRA_BOOT))
+           die("Not a RAID install, '" RAID_EXTRA_BOOT "=' not allowed");
+       return 0;
+    }
+    else {     /* It is a RAID installation */
+
+       if (!nowarn && boot[0]=='/' && !boot[1])
+          warn("RAID1 install implied by 'boot=/'\n");
+          
+/* scan the devices in /proc/partitions */
+       pf_hard_disk_scan();
+
+
+       if ((md_fd=dev_open(&dev, st.st_rdev, O_NOACCESS) ) < 0)
+           die("Unable to open %s",boot);
+       boot = stralloc(dev.name);
+       if (fstat(md_fd,&st) < 0)
+           die("Unable to stat %s",boot);
+       if (!S_ISBLK(st.st_mode))
+           die("%s is not a block device",boot);
+
+       boot_dev_nr = st.st_rdev;       /* set this very early */
+
+       if (ioctl(md_fd,RAID_VERSION,&md_version_info) < 0)
+           die("Unable to get RAID version on %s", boot);
+        if (verbose >= 4) printf("RAID_VERSION = %d.%d\n",
+                (int)md_version_info.major,
+                (int)md_version_info.minor);
+       if (md_version_info.major > 0)
+           die("Raid major versions > 0 are not supported");
+       if (md_version_info.minor < 90)
+           die("Raid versions < 0.90 are not supported");
+       
+       if (ioctl(md_fd,GET_ARRAY_INFO,&md_array_info) < 0)
+           die("Unable to get RAID info on %s",boot);
+        if (verbose >= 4) printf("GET_ARRAY_INFO version = %d.%d\n",
+                (int)md_array_info.major_version,
+                (int)md_array_info.minor_version);
+        if (md_version_info.major != 0 || md_version_info.minor != 90 ||
+            ((md_array_info.major_version != 0 ||
+                md_array_info.minor_version != 90) &&
+             (md_array_info.major_version != 1 ||
+                md_array_info.minor_version != 0))
+            ) {
+            die("Incompatible Raid version information on %s   (RV=%d.%d GAI=%d.%d)",
+                boot,
+                (int)md_version_info.major,
+                (int)md_version_info.minor,
+                (int)md_array_info.major_version,
+                (int)md_array_info.minor_version);
+           }
+       if (md_array_info.level != 1)
+           die("Only RAID1 devices are supported as boot devices");
+       if (!linear && !lba32) {
+           lba32 = 1;
+           if (!nowarn)
+               warn("RAID install requires LBA32 or LINEAR;"
+                       " LBA32 assumed.\n");
+       }
+       extrap = cfg_get_strg(cf_options, RAID_EXTRA_BOOT);
+       extra = !extrap ? X_AUTO :
+               !strcasecmp(extrap,"none") ? X_NONE :
+               !strcasecmp(extrap,"auto") ? X_AUTO :
+               !strcasecmp(extrap,"mbr-only") ? X_MBR_ONLY :
+               !strcasecmp(extrap,"mbr") ? X_MBR :
+                   X_SPEC;
+       
+       do_md_install = MD_PARALLEL;
+
+       all_pri_eq = 1;
+       raid_offset_set = pri_index = pri_offset = 0;
+       raid_flags = FLAG_RAID;
+       md_bios = 0xFF;                 /* we want to find the minimum */
+       ndisk = 0;                      /* count the number of disks on-line */
+       nlist = 0;
+       faulty = 0;
+       
+       device = MKDEV(MD_MAJOR, md_array_info.md_minor);
+       
+    /* search the disk table for a definition */
+       md_disk = disktab;
+       while (md_disk && md_disk->device != device)
+           md_disk = md_disk->next;
+           
+       if (!md_disk) {
+           md_disk = alloc_t(DT_ENTRY);
+           md_disk->device = MKDEV(MD_MAJOR, md_array_info.md_minor);
+           md_disk->bios = -1; /* use the default */
+           md_disk->next = disktab;
+           disktab = md_disk;
+       }
+
+       if (verbose >= 2) {
+          printf("RAID info:  nr=%d, raid=%d, active=%d, working=%d, failed=%d, spare=%d\n",
+               md_array_info.nr_disks,
+               md_array_info.raid_disks,
+               md_array_info.active_disks,
+               md_array_info.working_disks,
+               md_array_info.failed_disks,
+               md_array_info.spare_disks );
+       }
+
+    /* scan through all the RAID devices */
+       raid_limit = md_array_info.raid_disks;
+       if (md_array_info.active_disks < md_array_info.raid_disks) {
+           if (!force_raid) die("Not all RAID-1 disks are active; use '-H' to install to active disks only");
+           else {
+               warn("Partial RAID-1 install on active disks only; booting is not failsafe\n");
+               raid_limit = md_array_info.raid_disks;
+           }
+       }
+       raid_index = 0;
+       for (pass=0; pass < raid_limit; pass++) {
+           DEVICE dev;
+           int disk_fd;
+           char new_name[MAX_TOKEN+1];
+           char *np;
+           
+           md_disk_info.number = pass;
+           if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0)
+#if 1
+               die("raid: GET_DISK_INFO: %s, pass=%d", strerror(errno), pass);
+#else
+               {
+               printf("raid: GET_DISK_INFO: %s, pass=%d\n", strerror(errno), pass);
+               continue;
+               }
+#endif
+           device = MKDEV(md_disk_info.major, md_disk_info.minor);
+            if(verbose>=3) printf("md: RAIDset device %d = 0x%04X\n", pass, device);       
+           if (device == 0) { /* empty slot left over from recovery process */
+               faulty++;
+               warn("Faulty disk in RAID-1 array; boot with caution!!");
+               continue;
+           }
+           disk_fd = dev_open(&dev,device,O_NOACCESS);
+           if (md_disk_info.state & (1 << MD_DISK_FAULTY)) {
+               printf("disk %s marked as faulty, skipping\n",dev.name);
+               faulty++;
+               continue;
+           }
+           geo_get(&geo, device, -1, 1);
+           disk = alloc_t(DT_ENTRY);
+           if (verbose>=3)
+               printf("RAID scan: geo_get: returns geo->device = 0x%02X"
+                     " for device %04X\n", geo.device, device);
+             
+           disk->bios = geo.device;    /* will be overwritten */
+           disk->device = device;
+             /* used to mask above with 0xFFF0; forces MBR; sloppy, mask may be: 0xFFF8 */
+           disk->sectors = geo.sectors;
+           disk->heads = geo.heads;
+           disk->cylinders = geo.cylinders;
+           disk->start = geo.start;
+           if (ndisk==0) {
+               raid_base = geo.start;
+               raid_index = pass;
+           }
+           raid_offset[ndisk] = geo.start - raid_base;
+           raid_device[ndisk] = device;
+
+           if (raid_offset[ndisk]) {
+               do_md_install = MD_SKEWED;       /* flag non-zero raid_offset */
+           }
+
+           if (all_pri_eq && is_primary(device)) {
+               if (raid_offset_set) {
+                   all_pri_eq &= (pri_offset == raid_offset[ndisk]);
+               } else {
+                   pri_offset = raid_offset[ndisk];
+                   raid_offset_set = 1;
+                   pri_index = ndisk;
+               }
+           }
+
+#if 1
+           if (geo.device < md_bios) { /* OLD: use smallest device code */
+#else
+           if (ndisk==0) {     /* NEW: use the device code of the first device */
+#endif
+               md_bios = geo.device;   /* find smallest device code, period */
+               lowest = ndisk;         /* record where */
+           }
+           raid_bios[ndisk] = geo.device;  /* record device code */
+
+           disk->next = disktab;
+           disktab = disk;
+
+           if (verbose >= 3 && do_md_install) {
+               printf("disk->start = %d\t\traid_offset = %d (%08X)\n",
+                  disk->start, (int)raid_offset[ndisk], (int)raid_offset[ndisk]);
+           }
+       
+       /* derive the MBR name, which may be needed later */
+           strncpy(new_name,dev.name,MAX_TOKEN);
+           new_name[MAX_TOKEN] = '\0';
+           np = boot_mbr(dev.name, 0);
+           if (!np) np = stralloc(new_name);
+           raid_mbr[ndisk] = np;
+
+           if (ndisk==0) {     /* use the first disk geometry */
+               md_disk->sectors = geo.sectors;
+               md_disk->heads = geo.heads;
+               md_disk->cylinders = geo.cylinders;
+               md_disk->start = geo.start;
+           }
+           
+           ndisk++;  /* count the disk */
+       }  /* for (pass=...    */
+
+       dev_close(&dev);
+       raid_bios[ndisk] = 0;           /* mark the end */
+       raid_device[ndisk] = 0;
+
+       all_pri_eq &= raid_offset_set;
+       if (all_pri_eq && do_md_install == MD_SKEWED) {
+           do_md_install = MD_MIXED;
+       }
+       else pri_index = lowest;
+
+       autocount = 0;
+       /* check that all devices have an accessible block for writeback info */
+       for (pass=0; pass < ndisk; pass++) {
+           if (extra == X_MBR_ONLY || extra == X_MBR)
+               raid_bios[pass] |= TO_BE_COVERED;
+
+           if (extra == X_AUTO /*&& raid_bios[pass] != 0x80*/) {
+               if (do_md_install == MD_SKEWED)  {
+                   raid_bios[pass] |= TO_BE_COVERED;
+                   autocount++;
+               }
+               if (do_md_install == MD_MIXED) {
+                   if (is_primary(raid_device[pass])) raid_bios[pass] |= IS_COVERED;
+                   else  {
+                       raid_bios[pass] |= TO_BE_COVERED;
+                       autocount++;
+                   }
+               }
+           }
+           if (extra != X_MBR)
+           if ((do_md_install == MD_PARALLEL && is_accessible(raid_device[pass]))
+               || (do_md_install == MD_MIXED && pri_offset == raid_offset[pass]
+                       && is_primary(raid_device[pass]))
+               )    
+               raid_bios[pass] |= IS_COVERED;
+       }
+               
+       nlist = 0;
+       if (extra==X_SPEC) {
+           char *next, *scan;
+           
+           scan = next = extrap;
+           while (next && *next) {
+               scan = next;
+               while (isspace(*scan)) scan++;  /* deblank the line */
+               next = strchr(scan, ',');       /* find the separator */
+               if (next) *next++ = 0;          /* NUL terminate  scan */
+                   
+               if ((md_fd=open(scan,O_NOACCESS)) < 0)
+                   die("Unable to open %s", scan);
+               if (fstat(md_fd,&st) < 0)
+                   die("Unable to stat %s",scan);
+               if (!S_ISBLK(st.st_mode))
+                   die("%s (%04X) not a block device", scan, (int)st.st_rdev);
+               if (verbose>=4) printf("RAID list: %s is device 0x%04X\n",
+                               scan, (int)st.st_rdev);         
+               close(md_fd);
+               
+               list_index[nlist] = ndisk;  /* raid_bios==0 here */
+               for (pass=0; pass < ndisk; pass++) {
+                   if (master(st.st_rdev) == master(raid_device[pass])) {
+                       list_index[nlist] = pass;
+                       if (st.st_rdev == raid_device[pass])
+                           die("Cannot write to a partition within a RAID set:  %s", scan);
+                       else if (is_accessible(st.st_rdev))
+                           raid_bios[pass] |= IS_COVERED;
+                       break;
+                   }
+               }
+               if (list_index[nlist] == ndisk) {
+#ifdef FLAG_RAID_NOWRITE
+                   raid_flags |= FLAG_RAID_NOWRITE;  /* disk is outside RAID set */
+#endif
+                   if (!nowarn) printf("Warning: device outside of RAID set  %s  0x%04X\n", 
+                                               scan, (int)st.st_rdev);
+               }
+               raid_list[nlist++] = stralloc(scan);
+           }
+           
+       }
+       
+               
+    /* if the install is to MBRs, then change the boot= name */
+       if (extra == X_MBR_ONLY) {
+#if 0
+           if (cfg_get_strg(cf_options,"boot")) cfg_unset(cf_options,"boot");
+           cfg_set(cf_options, "boot", (boot=raid_mbr[0]), NULL);
+#endif
+       }
+       else {  /* if skewed install, disable mdX boot records as 
+                                                       source of writeback info */
+           if (do_md_install == MD_SKEWED) raid_flags |= FLAG_RAID_DEFEAT
+#ifdef FLAG_RAID_NOWRITE
+                       | (extra == X_NONE ? FLAG_RAID_NOWRITE : 0)
+#endif
+                       ;
+       }
+
+       mask = 1;
+       for (pass=0; pass < ndisk; pass++) {
+           mask &= !!(raid_bios[pass] & COVERED);
+       }
+#ifdef FLAG_RAID_NOWRITE
+       if (!mask) {
+           raid_flags |= FLAG_RAID_NOWRITE;
+       }
+
+       if (raid_flags & FLAG_RAID_NOWRITE) {
+           warn("FLAG_RAID_NOWRITE has been set.");
+       }
+#endif
+
+    /* if the disk= bios= did not specify the bios, then this is the default */
+       if (md_disk->bios < 0) {
+           md_disk->bios = md_bios;
+       }
+       md_bios = md_disk->bios;
+       if (md_disk->bios < 0x80 || md_disk->bios > DEV_MASK)
+          die("Unusual RAID bios device code: 0x%02X", md_disk->bios);
+#if 0
+/* Assigning all disks the same bios code is OBSOLETE in 22.5.6 */
+       disk = disktab;
+       for (pass=0; pass < ndisk; pass++) {
+           disk->bios = md_disk->bios;   /* all disks in the array are */
+           disk = disk->next;            /*  assigned the same bios code */
+       }
+#endif
+       if (verbose) {
+           printf(
+              "Using BIOS device code 0x%02X for RAID boot blocks\n",
+                                           md_disk->bios);
+       }
+
+#if 0
+       if ( mask &&  ( extra == X_NONE ||
+                       (extra == X_AUTO  &&  autocount == 0) ) )  {
+           if (bios_passes_dl > DL_BAD) bios_passes_dl = DL_GOOD;
+       }
+#endif
+       
+       if (bios_passes_dl==DL_GOOD  &&  !(extra == X_MBR_ONLY || extra == X_MBR))
+           warn("Boot sector on  %s  will depend upon the BIOS device code\n"
+               "  passed in the DL register being accurate.  Install Master Boot Records\n"
+               "  with the 'lilo -M' command, and activate the RAID1 partitions with the\n"
+               "  'lilo -A' command.",
+               boot );
+       
+       return raid_offset[pri_index];
+    }  /* IF (test for a raid installation */
+}  /* int raid_setup(void) */
+
+
+
+void raid_final(void)
+{
+    int pass, force = 0;
+    char *cp = NULL;
+    int mask = FLAG_SAVE;
+
+
+    if (bios_passes_dl < DL_GOOD) mask &= ~FLAG_MAP_ON_BOOT;
+    
+    if (test) /* do nothing */;
+    else if ((cp=cfg_get_strg(cf_options,"force-backup"))) force=1;
+    else cp=cfg_get_strg(cf_options,"backup");
+           
+    if (verbose>=2) {
+       printf("do_md_install: %s\n", do_md_install == MD_PARALLEL ? "MD_PARALLEL" :
+               do_md_install == MD_MIXED ? "MD_MIXED" :
+               do_md_install == MD_SKEWED ? "MD_SKEWED" : "unknown");
+       for (pass=0; pass<ndisk; pass++)
+           printf("  offset %08X  %s\n", raid_offset[pass], raid_mbr[pass]);
+    }
+               
+    if (extra == X_MBR_ONLY) {    
+        pass = 0;
+        while (pass < ndisk) {
+#ifndef LCF_UNIFY
+# error "Bios Translation algorithms require '-DUNIFY' in Makefile"
+#endif
+           if (pass==0 && test) {
+               bsect_cancel();
+               if (passw) printf("The password crc file has *NOT* been updated.\n");
+               printf("The map file has *NOT* been altered.\n");
+           }
+
+           if (!test) {
+               bsect_raid_update(raid_mbr[pass], raid_offset[pass],
+                       cp, force, pass ? pass : -1, mask );
+           }
+
+           printf("The Master boot "
+               "record of  %s  has%s been updated.\n",
+                       raid_mbr[pass],
+                       test ? " *NOT*" : "" );
+           pass++;
+        }
+    } 
+    else {     /*  extra != X_MBR_ONLY   */
+        
+#ifdef FLAG_RAID_DEFEAT
+       raid_flags &= ~FLAG_RAID_DEFEAT;    /* change won't affect /dev/mdX */
+#endif
+       {
+         if (test) {
+           bsect_cancel();
+           if (passw) printf("The password crc file has *NOT* been updated.\n");
+           printf("The map file has *NOT* been updated.\n");
+         }
+         else {
+       /* write out the /dev/mdX boot records */           
+           bsect_raid_update(boot, 0L, cp, force, 0, FLAG_SAVE);
+         }
+           printf("The boot record of  %s  has%s been updated.\n", 
+                       boot,
+                       test ? " *NOT*" : "");
+       }
+
+       if (extra == X_NONE ||
+               (extra == X_AUTO  &&  autocount == 0) ) return;
+
+       if (extra == X_SPEC)
+       for (pass = 0; pass < nlist; pass++) {
+           int index;
+
+           if (raid_bios[list_index[pass]] & 0xFF) {
+               index = list_index[pass];       /* within RAID set */
+           }
+           else {  /* not in the RAID set */
+#ifdef FLAG_RAID_DEFEAT
+               raid_flags |= FLAG_RAID_DEFEAT;  /* make outsider invisible */
+#endif
+               index = lowest;
+           }
+
+           if (verbose>=3) printf("Specified partition:  %s  raid offset = %08X\n",
+                                       raid_list[pass], raid_offset[index]);
+
+           if (!test)
+               bsect_raid_update(raid_list[pass], raid_offset[index], cp, force, 1, mask);
+           
+           printf("The boot record of  %s  has%s been updated.\n",
+                       raid_list[pass], (test ? " *NOT*" : ""));
+
+#ifdef FLAG_RAID_DEFEAT
+           raid_flags &= ~FLAG_RAID_DEFEAT; /* restore DEFEAT flag to 0 */
+#endif
+       }
+       else {          /* extra = X_AUTO or X_MBR*/
+           for (pass = 0; pass < ndisk; pass++) {
+               if (!(raid_bios[pass] & IS_COVERED)) {
+                   if ((raid_bios[pass] & 0xFF) != 0x80  || extra == X_MBR) {
+                       if (!test)
+                           bsect_raid_update(raid_mbr[pass], raid_offset[pass],
+                                                       cp, force, 1, mask);
+                       printf("The Master boot record of  %s  has%s been updated.\n",
+                                       raid_mbr[pass], (test ? " *NOT*" : ""));
+                   } else {
+                       warn("%splicit AUTO does not allow updating the Master Boot Record\n"
+                               "  of '%s' on BIOS device code 0x80, the System Master Boot Record.\n"
+                               "  You must explicitly specify updating of this boot sector with\n"
+                               "  '-x %s' or 'raid-extra-boot = %s' in the\n"
+                               "  configuration file.",
+                                cfg_get_strg(cf_options, RAID_EXTRA_BOOT) ? "Ex" : "Im",
+                               raid_mbr[pass],
+                               raid_mbr[pass],
+                               raid_mbr[pass] 
+                               );
+                   }
+               }
+           }
+       }
+    }
+
+
+#ifdef FLAG_RAID_NOWRITE
+    if (raid_flags & FLAG_RAID_NOWRITE) {
+       warn("FLAG_RAID_NOWRITE has been set.%s", verbose>=1 ?
+               "\n  The boot loader will be unable to update the stored command line;\n"
+               "  'lock' and 'fallback' are not operable; the 'lilo -R' boot command\n"
+               "  line will be locked." : "" );
+    }
+#endif
+
+}
+
+/* form the mask of the raid bios codes and the list of offsets */
+/* this information goes into the MENUTABLE passed to the loader */
+int raid_mask(int *offsets)
+{
+    int mask = 0;
+    int i, j;
+    int offset[MAX_BIOS_DEVICES];
+    
+    if (ndisk > MAX_RAID_DEVICES)
+       die("More than %d active RAID1 disks", MAX_RAID_DEVICES);
+       
+    memset(offset, 0, sizeof(offset));
+    for (i=0; i<ndisk; i++) {
+       offset[j = raid_bios[i] & (DEV_MASK & 0x7F) ] = raid_offset[i];
+       mask |= 1<<j;
+    }
+    for (i=0; i<nelem(offset); i++) {
+       if ( (mask>>i) & 1 ) *offsets++ = offset[i];
+       if (do_md_install && verbose>=3) printf("RAID offset entry %d  0x%08X\n", offset[i], offset[i]);
+    }
+    
+    if (verbose>=2) printf("RAID device mask 0x%04X\n", mask);
+    
+    return mask;
+}
+
+
diff --git a/src/raid.h b/src/raid.h
new file mode 100644 (file)
index 0000000..e233bac
--- /dev/null
@@ -0,0 +1,19 @@
+/* raid.h  -  The RAID-1 hooks for LILO */
+/*
+Copyright 2001-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+int do_md_install, ndisk, md_bios;
+
+int raid_setup(void);
+void raid_final(void);
+
+/* form the mask of the raid bios codes and the list of offsets */
+/* this information goes into the MENUTABLE passed to the loader */
+int raid_mask(int *offsets);
+
diff --git a/src/read.S b/src/read.S
new file mode 100644 (file)
index 0000000..c55eac2
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+;  read.S  is
+Copyright 1999-2006 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+#define NEW_WRITE 1
+;
+; lba_read:      read using LBA
+;
+;  Enter with:
+;       AL      actual count of blocks to transfer
+;       DL      device (0x00=A:, 0x80=C:, 0x81=D:) and LINEAR/LBA32 flags
+;       ES:BX   buffer pointer
+;       DI:CX   LBA to read
+;
+;  Exit with:
+;       No Error:  carry clear
+;       CX      count of blocks read
+;       ES:BX   unchanged
+;       DX      unchanged
+;       AH      error status if CF=1
+;       DI      trashed
+;
+
+lba_read:       push    si              ;save some registers
+#ifndef JRC_NOCOMPACT
+                push    bx
+                push    dx
+                xor     ah,ah           ;convert count to word
+                push    ax
+#endif
+                push    cx              ;gotta ask about 32-bit addressing 
+                push    bx
+#ifndef JRC_FLAGS_IN_DH
+               mov     dh,dl           ;use BL for flag test
+#endif
+               and     dl,#DEV_MASK_asm    ;remove spurious flags (0x8F)
+#ifndef JRC_MBR
+               test    dh,#LBA32_FLAG
+               jz      no_lba          ;linear will never use EDD calls
+#endif
+#ifndef JRC_NOCOMPACT
+               cmp     al,#127         ;test for LINEAR transfer too big
+               ja      no_lba          ; for LBA mode (127 is max)
+                push    ax
+#endif
+                mov     bx,#0x55AA      ;magic number
+                mov     ah,#0x41        ;function call
+                int     0x13
+#ifndef JRC_NOCOMPACT
+                pop     ax
+#endif
+                jc      no_lba
+                cmp     bx,#0xAA55      ;magic return
+                jne     no_lba
+                test    cl,#EDD_PACKET  ;packet calls supported?
+                jz      no_lba
+
+
+; LBA mode is to be used
+
+lba_avail:
+                pop     bx
+                pop     cx
+
+#ifndef JRC_NOCOMPACT
+                pop     ax
+                push    ax
+#endif
+#ifndef JRC_DS_EQ_SS
+                push    ds              ;save DS
+#endif
+               push    dword #0                ;  0L is pushed
+                push    di              ;LBA hi word
+                push    cx              ;    lo word
+                push    es              ;ES:BX
+                push    bx
+#ifndef JRC_NOCOMPACT
+                push    ax
+#else
+                push    #1             ;count always 1
+#endif
+                push    #16            ;size of parameter area  ;#
+                                       ;actually pushes a word
+                mov     si,sp          ;DS:SI is param block pointer
+#ifndef JRC_DS_EQ_SS
+                push    ss
+                pop     ds              ;DS:SI points at param block
+#endif
+#ifndef JRC_NOCOMPACT
+                mov     ax,#0x4200      ;read function -- must be AX
+                                       ; as AL has meaning on WRITE
+                call    dsk_do_rw
+#else
+;;;            mov     ax,#0x4200      ;read function
+               mov     ah,#0x42        ;read only -- AL matters not
+                int     0x13
+#endif
+                lea     sp,word ptr (si+16)      ;use lea so flags are not changed
+#ifndef JRC_DS_EQ_SS
+                pop     ds              ;restore DS
+#endif
+                jmp     lba_read_exit1
+
+
+
+no_lba:
+                pop     bx
+                pop     cx
+
+
+lba_small:                      ;must get the disk geometry
+#ifndef JRC_NOCOMPACT
+lba_more_small:
+                push    bx
+                push    di
+                push    cx
+                push    ax
+#endif
+                push    bx
+                push    dx
+                push    di
+                push    cx
+
+                push    es
+                mov     ah,#8          ; DL is set to device
+#ifndef JRC_NOCOMPACT
+                call    dsk_do_int13
+#else
+                int     0x13
+#endif
+                pop     es
+                jc      lba_geom_error
+
+                push    cx
+                shr     cl,#6          ;;;;
+                xchg    cl,ch           ;CX is max cylinder number
+                mov     di,cx           ;DI saves it
+                pop     cx
+
+               shr     dx,#8
+               xchg    ax,dx           ;AX <- DX
+               inc     ax              ;AX is number of heads (256 allowed)
+
+; compensate for Davide BIOS bug
+               dec     cx              ; 1..63 -> 0..62;  0->63
+               and     cx,#0x003f      ;CX is number of sectors
+               inc     cx              ; allow Sectors==0 to mean 64
+
+                mul     cx             ; kills DX
+                xchg    ax,si           ;save in SI
+
+                pop     ax              ;was CX
+                pop     dx              ;was DI
+                cmp     dx,si
+                jae     lba_geom_error2  ;prevent division error
+                div     si              ;AX is cyl, DX is head/sect
+                cmp     ax,di
+                ja      lba_geom_error2  ;cyl is too big
+
+                shl     ah,#6          ;;;;
+                xchg    al,ah
+                xchg    ax,dx
+                div     cl              ;AH = sec-1, AL = head
+#ifndef JRC_NOCOMPACT
+                sub     cl,ah           ;CX = max count possible
+                mov     si,cx           ;save in SI
+#endif
+                inc     ah
+                add     dl,ah           ;form Cyl/Sec
+                mov     cx,dx
+                pop     dx              ;get device
+                pop     bx
+                xchg    al,dh           ;
+
+#ifndef JRC_NOCOMPACT
+                pop     ax              ;restore the count
+                push    ax              ;keep in the stack
+                cmp     ax,si           ;
+                jb      lba_cntltmax
+                mov     ax,si           ;smaller is in AX
+lba_cntltmax:   push    ax
+                mov     ah,#2           ;READ
+                call    dsk_do_rw
+#else
+                mov     ax,#0x201       ;read, count of 1
+                int     0x13
+#endif
+        ; carry is set or clear
+#ifndef JRC_NOCOMPACT
+                pop     bx              ;actual count read (was AX)
+                pop     si              ;count remaining
+                pop     cx
+                pop     di
+                jc      lba_read_exit_e
+                add     cx,bx           ;update lba address
+                adc     di,#0           ;the # was omitted in rev 3
+                xchg    ax,bx
+                pop     bx              ;buffer address
+                add     bh,al           ;update ES:BX
+                add     bh,al           ;LILO has already checked for seg update
+                xchg    si,ax
+                sub     ax,si           ;AX is remaining count after transfer
+                jnz     lba_more_small
+                         ; after the sub yields 0, the carry is clear
+#endif
+lba_read_exit1:        jmp     lba_read_exit
+
+#ifndef JRC_NOCOMPACT
+
+#ifndef LCF_READONLY
+
+#if NEW_WRITE
+
+dsk_do_rw:     or      ah,#0           ; 0=read, 1=write, 2=read-only test
+dsk_wrflag     equ     *-1             ; byte data area is the immediate
+
+#else
+dsk_wrflag:     .byte   0               ; 0=read, 1=write, 2=read-only test
+
+dsk_do_rw:
+                seg     cs
+                or     ah,dsk_wrflag
+#endif
+
+#else
+#if DEBUG_NEW
+dsk_wrflag:     .byte   0               ; 0=read, 1=write, 2=read-only test
+#endif
+dsk_do_rw:
+#endif
+
+dsk_do_int13:
+                push    bp
+                mov     bp,#5           ;number of tries
+dsk_do_int13a:  pusha
+                int     0x13
+                jnc     dsk_io_exit
+                dec     bp              ;does not affect the carry
+                jz      dsk_io_exit
+                xor     ax,ax           ;reset disk controllers
+                int     0x13
+                popa
+                dec     bp
+                jmp     dsk_do_int13a
+
+dsk_io_exit:    mov     bp,sp           ;do not touch any flags
+                lea     sp,(bp+16)      ;an ADD would touch flags
+                pop     bp              ;do not touch any flags
+                ret
+#endif
+lba_geom_error:
+                pop     cx
+                pop     di
+                jmp     lba_g3
+lba_geom_error2:
+                mov     ah,#0x40         ;seek failure error code
+lba_g3:         pop     dx
+                pop     bx
+#ifndef JRC_NOCOMPACT
+                pop     cx              ;was AX
+                pop     cx
+                pop     di
+lba_read_exit_e:
+                pop     bx
+#endif
+                stc
+lba_read_exit:
+#ifndef JRC_NOCOMPACT
+                pop     cx              ;return count in CX
+                pop     dx
+                pop     bx
+#endif
+                pop     si
+#ifndef JRC_NORETURN
+                ret
+#endif
diff --git a/src/second.S b/src/second.S
new file mode 100644 (file)
index 0000000..bec0b7b
--- /dev/null
@@ -0,0 +1,4183 @@
+#if 0
+/* second.S  -  LILO second stage boot loader */
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2006 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+#endif
+
+/*#define DEBUG*/
+#define REG_DUMP 1
+/*#define DELL_DIRTY_HACK*/
+#define PIXADDRESS
+#define MEMORY_CHECK
+#define RETAIN
+#define DNAME 1
+
+#define LILO_ASM
+#include "lilo.h"
+get common.s           /* as86 "include" will bypass the CPP */
+
+#define MAP Map
+#define MAP2 Map2
+#define DFLCMD Dflcmd
+#define DESCR Descr
+#define KEYTABLE Keytable
+#define PARMLINE Parmline
+
+#define DEBUG_INITRD 0
+
+#ifdef DEBUG
+#define DEBUG_NEW 1
+#else
+#if VERSION_MINOR<50
+#define DEBUG_NEW 0
+#else
+#define DEBUG_NEW 1
+#ifndef MEMORY_CHECK
+#define MEMORY_CHECK
+#endif
+#endif         /* VERSION_MINOR */
+#endif         /* DEBUG */
+
+/* The following is set to 1 to enable map file writing */
+#if DEBUG_NEW
+# define WR_ENABLE 2
+# if VERSION_MINOR>=90
+#  undef WR_ENABLE
+#  define WR_ENABLE 1
+# endif
+#else
+# define WR_ENABLE 1
+#endif
+
+
+#if DEBUG_NEW==0 && !(WR_ENABLE&1)
+#error "Retail version should have WR_ENABLE=1"
+#endif
+
+/* if compiling READONLY, then WR_ENABLE should never be used */
+#ifdef LCF_READONLY
+# undef WR_ENABLE
+#endif
+
+#if    ! NO_FS
+#if DEBUG_NEW
+#define CHECK_FS_VERBOSE 0
+#define BEG_FS call fs_check
+#else
+#define BEG_FS
+#endif
+#define SEG_FS seg fs
+#define END_FS
+#else
+#define BEG_FS db 0x1e,0x2e,0x8e,0x1e,0x02,0x00
+/*     push ds; \
+       seg cs; \
+       mov     ds,firstseg */
+#define SEG_FS
+#define END_FS pop ds
+#endif
+
+/* get rid of the following to revert to old int 0x15/fn 0x88 mem scheme */
+#define HIGHMEM_MAX 0x38000000
+
+LOADSEG        = SYSSEG                ; max kernel = 1024 sectors
+
+#define UI_MAGIC 0xff          /* take input from keyboard */
+
+#ifdef MENU
+STAGE_MENU     =       STAGE_FLAG_MENU
+X=MENU
+#else
+STAGE_MENU     =       0
+#endif
+
+#ifdef BITMAP
+STAGE_BITMAP   =       STAGE_FLAG_BMP4
+X=BITMAP
+#else
+STAGE_BITMAP   =       0
+#endif
+
+#ifdef LCF_NOSERIAL
+STAGE_SERIAL   =       0
+#else
+STAGE_SERIAL   =       STAGE_FLAG_SERIAL
+#endif
+
+#ifdef TEXT
+X=TEXT
+#endif
+
+
+       .text
+
+       .globl  _main
+       .org    0
+
+_main: jmp     start
+
+#if    NO_FS || DEBUG_NEW
+firstseg:      dw      0
+# if   DEBUG_NEW
+#  define CHECK_FS call fs_check
+# else
+# define CHECK_FS
+# endif
+#endif
+#ifndef CHECK_FS
+# define CHECK_FS
+#endif
+
+       .org    6
+
+! Boot device parameters. They are set by the installer.
+
+sig:           .ascii  "LILO"
+version:       .word   VERSION
+mapstamp:      .long   0
+
+stage:         .word   STAGE_SECOND|STAGE_SERIAL|STAGE_MENU|STAGE_BITMAP
+
+port:  .byte   0               ; COM port (0 = unused, 1 = COM1, etc.)
+sparam:        .byte   0               ; serial port parameters (0 = unused)
+
+timout: .word  0               ; input timeout
+delay: .word   0               ; boot delay
+ms_len:        .word   0               ; initial greeting message
+
+
+kt_cx: .word   0               ; keyboard translation table
+kt_dx: .word   0
+kt_al: .byte   0
+
+flag2: .byte   0               ; second stage specific flags
+
+
+! GDT for "high" loading
+
+       .align  16
+
+gdt:   ; space for BIOS
+       .blkb   0x10
+       ; source
+       .word   0xffff          ; no limits
+       .byte   0
+       .word   LOADSEG>>4      ; start: 0x10000
+       .byte   0x93            ; permissions
+       .word   0               ; padding for 80286 mode :-(
+       ; destination
+       .word   0xffff          ; no limits
+       .word   0               ; start - filled in by user
+       .byte   0
+       .byte   0x93            ; permissions
+       .word   0               ; padding for 80286 mode :-(
+       ; space for BIOS
+       .blkb   0x10
+
+start: cld                     ; only CLD in the code; there is no STD
+#if   ! NO_FS
+       push    ds
+       pop     fs              ; address parameters from here
+#endif
+#if    NO_FS || DEBUG_NEW
+       seg     cs
+       mov     firstseg,ds     ; save DS here
+#endif
+
+       seg     cs
+       mov     [init_dx],dx    ; save DX passed in from first.S
+
+       int     0x12            ; get memory available
+       CHECK_FS
+#if EBDA_EXTRA
+       sub     ax,#EBDA_EXTRA  ; allocate extra EBDA
+#endif
+       shl     ax,#6           ; convert to paragraphs
+       sub     ax,#Dataend/16
+       mov     es,ax           ; destination address
+       push    cs
+       pop     ds
+       xor     si,si
+       xor     di,di
+       xor     ax,ax
+       mov     cx,#max_secondary/2     ; count of words to move
+       rep
+         movsw
+       add     di,#BSSstart-max_secondary
+       mov     cx,#BSSsize/2
+       rep
+         stosw
+       push    es
+       push    #continue
+       retf                    ; branch to continue address
+continue:
+
+#ifdef DELL_DIRTY_HACK
+;;;    push    dx              ; preserve DX (already saved)
+       mov     ax,#0x1200      ; enable video (VGA)
+       mov     bl,#0x36        ; (probably a nop on EGA or MDA)
+       int     0x10            ; video call
+       CHECK_FS
+;;;    pop     dx              ; restore DX on Dell geforce nVidia card
+#endif
+
+
+#ifndef LCF_NOSERIAL
+       call    serial_setup    ; set up the COM port, if any
+#endif
+
+#ifndef LCF_NODRAIN
+       mov     cx,#32          ; drain type-ahead buffer ?
+drkbd: mov     ah,#1           ; is a key pressed ?
+       int     0x16
+       jz      comcom          ; no -> done
+       xor     ah,ah           ; get the key
+       int     0x16
+       loop    drkbd
+#endif
+
+comcom:
+       CHECK_FS
+       mov     al,#0x4c        ; display an 'L'
+       call    display
+       push    #0              ; get pointer to disk parameter table in DS:SI
+       pop     ds
+       lds     si,[0x78]       ; 0x78 = 4*0x1E
+#ifndef LCF_XL_SECS
+       cmp     byte ptr (si+4),#9 ; okay ?
+       ja      dskok           ; yes -> do not patch
+#endif
+       push    cs              ; get pointer to new area in ES:DI
+       pop     es
+       mov     di,#dskprm
+       mov     cx,#6           ; copy 12 bytes
+       rep
+       movsw
+       seg     es              ; patch number of sectors
+#ifndef LCF_XL_SECS
+       mov     byte ptr (di-8),#18
+#else
+       mov     byte ptr (di-8),#LCF_XL_SECS
+#endif
+       push    #0
+       pop     ds
+       cli                     ; paranoia
+       mov     [0x78],#dskprm
+       mov     [0x7a],es
+       sti
+dskok:
+#ifndef        LCF_NOSERIAL
+       seg     cs              ; clear the break flag
+       mov     byte ptr break,#0
+#endif
+       call    instto          ; get timer interrupt
+       CHECK_FS
+;;;    jmp     restrt          ; get going
+
+! Restart here after a boot error
+
+restrt: mov    bx,cs           ; adjust segment registers
+       mov     ds,bx
+       mov     es,bx
+
+       sub     bx,#MAX_SETUPSECS*0x20+0x20     ; segment for setup code &
+                                               ;   bootsect
+       mov     cx,#INITSEG
+       cmp     bx,cx
+       jbe     restrt1
+       mov     bx,cx           ; BX is the smaller segment #
+restrt1:
+       mov     word ptr [map],#MAP
+       mov     [initseg],bx    ; set up INITSEG (was 0x9000)
+       lea     cx,(bx+0x20)
+       mov     [setupseg],cx   ; set up SETUPSEG (was 0x9020)
+       mov     cx,cs
+       sub     cx,bx           ; subtract [initseg]
+       shl     cx,#4           ; get stack size
+       mov     ss,bx           ; must lock with move to SP below
+       mov     sp,cx           ; data on the stack)
+#if DEBUG_NEW
+       pusha
+
+       mov     bx,#msg_where
+       call    say
+       mov     ax,[initseg]
+       call    wout
+
+       mov     ax,[setupseg]
+       call    swout
+
+       mov     ax,cs
+       call    swout
+
+       mov     ax,ss
+       call    swout
+       mov     al,#0x3A        ; colon
+       call    display
+       mov     ax,sp
+       call    wout
+
+       mov     al,#32          ; space
+       call    display
+
+       BEG_FS
+       SEG_FS          ; external parameters ?
+       mov     ax,[EX_OFF+6]   ; DH:DL as passed to first.S
+       END_FS
+       call    swout
+
+       mov     ax,[init_dx]    ; DX into second Stage
+       call    swout
+
+#ifdef LCF_NOKEYBOARD
+       call    nkbdbg0
+       .ascii " flags2="
+       .byte   0
+nkbdbg0: pop   bx
+       call    say
+       mov     al,[par2_flag2]
+       call    bout
+#endif
+
+       call    crlf
+
+#if REG_DUMP
+       call    frd0
+ .ascii "Registers at startup of first stage loader:\n"
+ .ascii " AX   BX   CX   DX   SI   DI   BP   DS   ES\n"
+       .byte   0
+frd0:  pop     bx
+       call    say
+
+       BEG_FS  
+       SEG_FS          ; external parameters ?
+       mov     ax,[EX_OFF-2-4] ; AX
+       call    wout
+       SEG_FS          ; external parameters ?
+       mov     ax,[EX_OFF-8-4] ; BX
+       call    swout
+       SEG_FS          ; external parameters ?
+       mov     ax,[EX_OFF-4-4] ; CX
+       call    swout
+       SEG_FS          ; external parameters ?
+       mov     ax,[EX_OFF-6-4] ; DX
+       call    swout
+       SEG_FS          ; external parameters ?
+       mov     ax,[EX_OFF-14-4]        ; SI
+       call    swout
+       SEG_FS          ; external parameters ?
+       mov     ax,[EX_OFF-16-4]        ; DI
+       call    swout
+       SEG_FS          ; external parameters ?
+       mov     ax,[EX_OFF-12-4]        ; BP
+       call    swout
+       SEG_FS          ; external parameters ?
+       mov     ax,[EX_OFF-18+16]       ; DS
+       call    swout
+       SEG_FS          ; external parameters ?
+       mov     ax,[EX_OFF-20+16]       ; ES
+       call    swout
+       END_FS
+
+       call    crlf
+#endif
+
+       popa
+#endif
+       cmp     dword [sig],#EX_MAG_HL  ; "LILO"
+       jne     crshbrn2
+       cmp     dword [mcmdbeg+6],#0x4547414d   ; "MAGE"  from BOOT_IMAGE
+       jne     crshbrn2
+       cmp     BYTE [stage],#STAGE_SECOND
+#if 1
+       jne     crshbrn
+       cmp     WORD [version],#VERSION
+#endif
+crshbrn2: jne  crshbrn
+       mov     [cmdbeg],#acmdbeg       ; probably unattended boot
+
+       mov     di,#devmap      ; place to store the device map
+#ifdef LCF_FIRST6
+       mov     ah,[init_dx]    ; AH is physical device
+       BEG_FS
+       SEG_FS
+       mov     al,[par1_secondary+0+SSDIFF]    ; map device logical
+       END_FS
+#else
+       mov     ax,[init_dx]    ; AH is flags & device, AL is physical device
+       xchg    ah,al
+       and     ax,#DEV_MASK_asm<<8 | DEV_MASK_asm      ; mask to pure device codes
+#endif
+       cmp     ah,al
+       je      end_tt
+#if DEBUG_NEW
+       pusha
+       call    wout            ; TT entry, maybe
+       call    crlf
+       popa
+#endif
+       stosw                   ; set up the translation from map -> boot
+end_tt:
+       xor     ax,ax
+       stosw
+
+ldsc:
+       BEG_FS
+       SEG_FS
+       mov     eax,[par1_mapstamp]
+       END_FS
+       cmp     eax,[par2_mapstamp]
+       jne     timeerr
+
+       call    kt_read         ; read the KEYTABLE
+
+       call    build_vol_tab
+
+       mov     bx,#DESCR
+       mov     si,#KEYTABLE+256+mt_descr
+descr_more:
+       lodsw   
+       xchg    cx,ax
+       lodsw
+       xchg    dx,ax
+       lodsb
+       call    cread
+       jc      near fdnok      ; error -> retry
+       add     bh,#2           ; increment address
+       cmp     si,#KEYTABLE+256+mt_descr+sa_size*MAX_DESCR_SECS_asm
+       jb      descr_more
+
+       mov     si,#DESCR       ; compute a checksum of the descriptor table
+       mov     di,#SECTOR_SIZE*MAX_DESCR_SECS-4
+
+       push    dword #CRC_POLY1
+       call    crc32
+       add     di,si
+       cmp     eax,dword (di)
+       jz      nochkerr
+
+
+! Timestamp error
+timeerr:
+       mov     bx,#msg_time
+       jmp     zz
+
+! Checksum error
+chkerr:
+       mov     bx,#msg_chkerr
+       jmp     zz              ; go wait
+
+crshbrn:
+       mov     bx,#msg_sigerr  ; signature not found
+zz:    call    say
+zzz:   hlt                     ; wait for interrupt
+       jmp     zzz             ; sit here forever
+
+
+nochkerr:
+#ifdef DEBUG
+       pusha
+       mov     bx,#nochker_msg
+       call    say
+       popa
+       jmp     nochkerr1
+nochker_msg:
+       .ascii  "Descriptor checksum okay\n"
+       .byte   0
+nochkerr1:
+#endif
+#ifdef LCF_VIRTUAL
+; remove those items that have "vmdisable", if virtual boot
+       call    vmtest
+       jnc     virtual_done
+       mov     di,#DESCR0      ; point at first descriptor
+vir_loop:
+       test    byte ptr [id_name](di),#0xFF    ; test for NUL name
+       jz      virtual_done
+       test    word ptr [id_flags](di),#FLAG_VMDISABLE
+       jz      vir_skip
+
+       push    di
+       lea     si,[id_size](di)
+vir_loop1:
+       mov     cx,#id_size
+       rep
+          movsb
+       test    byte ptr [id_name](di),#0xFF
+       jnz     vir_loop1
+
+       pop     di
+       jmp     vir_loop
+
+vir_skip:
+       add     di,#id_size
+       jmp     vir_loop
+
+virtual_done:
+#endif
+#ifdef LCF_NOKEYBOARD
+; remove those items that have "nokbdisable", if nokeyboard boot
+       call    kbtest
+       jc      kbd_done
+       mov     di,#DESCR0      ; point at first descriptor
+kbd_loop:
+       test    byte ptr [id_name](di),#0xFF    ; test for NUL name
+       jz      kbd_done
+       test    word ptr [id_flags](di),#FLAG_NOKBDISABLE
+       jz      kbd_skip
+
+       push    di
+       lea     si,[id_size](di)
+kbd_loop1:
+       mov     cx,#id_size
+       rep
+          movsb
+       test    byte ptr [id_name](di),#0xFF
+       jnz     kbd_loop1
+
+       pop     di
+       jmp     kbd_loop
+
+kbd_skip:
+       add     di,#id_size
+       jmp     kbd_loop
+
+kbd_done:
+#endif
+
+#if defined(MENU) || defined(BITMAP)
+       xor     bx,bx           ; defaults are all zero
+       mov     [dimage],bx     ; set default image to boot
+       mov     [abs_cx],bx     ; upper left of scroll area
+                               ; means screen is not cleared
+#endif
+
+       mov     bx,#KEYTABLE+256
+       mov     al,(bx+mt_flag)
+       BEG_FS
+       SEG_FS          ; get possible FLAG_NOBD
+       or      byte ptr [par1_prompt+SSDIFF],al
+       END_FS
+#ifdef MENU
+       call    title_stuff
+#endif
+       mov     bx,#DFLCMD
+;BEG_FS
+;SEG_FS
+       mov     cx,mt_dflcmd+KEYTABLE+256               ;DFCMD_OFF
+;SEG_FS
+       mov     dx,mt_dflcmd+2+KEYTABLE+256
+;SEG_FS
+       mov     al,mt_dflcmd+4+KEYTABLE+256
+;END_FS
+       call    cread
+       jc      fdnok           ; error -> retry
+       mov     bx,#DFLCMD
+       cmp     word ptr (bx),#DC_MAGIC ; okay ?
+       jne     bdcmag          ; no -> do not write
+#ifndef LCF_READONLY
+       mov     word ptr (bx),#DC_MGOFF ; erase the magic number
+       call    cmd_write       ; write out the command line
+#if 0
+; 22.6.2 -- removed, because this is worse that the first
+; command lock bug
+       mov     si,#DESCR0
+       lea     di,(bx+2)
+       mov     cx,#16
+       rep
+        movsb
+; 22.6.2
+#endif
+
+#endif
+       jmp     dokay           ; continue
+bdcmag:        mov     byte ptr (bx+2),#0 ; disable the command line
+       jmp     dokay           ; go on
+fdnok: 
+#if     0
+        xor    ax,ax           ; reset FDC
+       mov     dl,al
+       int     0x13
+#endif
+       br      ldsc            ; retry
+
+! List all known boot images
+
+list:  mov     byte ptr (bx),#0 ; set EOL marker
+       call    crlf
+#ifdef MENU
+       inc     word [suppress] ; suppress console output
+#endif
+       mov     si,#DESCR0      ; list all images
+       mov     cx,#IMAGES
+       xor     dl,dl           ; DL counts the images
+lloop: testb   (si),#0xff      ; done ?
+       jz      ldone           ; yes
+       mov     bx,si           ; display the name
+       call    say
+       add     si,#MAX_IMAGE_NAME+4
+       inc     dl              ; count the image
+       test    dl,#3           ; inside line -> go on
+       jnz     fill
+       call    crlf
+       jmp     imgdne          ; next image
+fill:  push    bx              ; fill with spaces
+       mov     al,#0x20
+       call    display
+       pop     bx
+       inc     bx
+       cmp     bx,si
+       jbe     fill
+imgdne:        add     si,#id_size-MAX_IMAGE_NAME-4
+       loop    lloop           ; next image
+ldone: test    dl,#3           ; already at BOL ?
+       jz      atbol           ; yes -> no CRLF
+       call    crlf
+atbol: 
+#ifdef MENU
+       dec     word [suppress]
+#endif
+       br      iloop           ; done
+
+! Ready to process user input
+
+dokay: mov     bx,#ospc        ; display 'O '
+       call    say
+/* ifdef HIGHMEM_MAX */
+       xor     eax,eax
+       mov     dword ptr [hma],eax
+/* #endif */
+       mov     ospc,al         ; disable the message
+       mov     word ptr vgaovr,#VGA_NOCOVR ; disable VGA override
+;;     BEG_FS
+;;     SEG_FS
+       xchg    ax,par2_delay           ;DSC_OFF-8+SSDIFF
+;;     END_FS
+       or      old_del,ax      ; remember delay
+       mov     nodfl,#iloop    ; interactive prompt if falling through
+#ifdef LCF_NOKEYBOARD
+       call    kbtest          ; keyboard present?
+#ifndef LCF_NOSERIAL
+       jc      kbd_present
+; no PC keyboard on the system, is there a serial port in use?
+       cmp     byte ptr [par2_port],#0
+       jz      skip_prompt     ; no serial keyboard either
+#else
+       jnc     skip_prompt     ; skip check for prompt if no keyboard
+#endif
+kbd_present:
+#endif
+       BEG_FS
+       SEG_FS          ; enter boot prompt ?
+       test    byte ptr par1_prompt+SSDIFF,#FLAG_PROMPT        ;DSC_OFF+15+SSDIFF,#0
+       END_FS
+       jnz     extp            ; yes -> check for external parameters
+skip_prompt:
+       mov     nodfl,#bfirst   ; boot first image if falling through
+       call    waitsh          ; wait for a shifting key
+       jc      iloop           ; key pressed -> enter interactive mode
+
+! Check for external parameters
+
+extp:  BEG_FS
+       SEG_FS          ; external parameters ?
+       cmp     byte ptr EX_OFF+6,#EX_DL_MAG
+       END_FS
+       jne     noex            ; no -> go on
+       BEG_FS
+       SEG_FS
+       mov     bl,EX_OFF+7     ; get drive
+       SEG_FS          ; clear flag
+       mov     byte ptr EX_OFF+6,bl    ; clear flag
+       SEG_FS          ; load the signature pointer
+       les     bx,EX_OFF
+       END_FS
+       seg     es
+       cmp     dword ptr (bx),#EX_MAG_HL       ; "LILO"
+       jne     noex            ; no -> go on
+       BEG_FS
+       SEG_FS
+       mov     si,EX_OFF+4     ; pointer to the command line
+       END_FS
+       seg     es
+       cmp     byte ptr (si),#0 ; empty ?
+       je      iloop           ; yes -> enter interactive mode
+       jmp     niloop          ; enter non-interactive mode
+
+! No external parameters after timeout -> boot first image
+
+noex:  push    cs              ; restore ES
+       pop     es
+       mov     si,#DFLCMD+2    ; default command line ?
+       cmp     byte ptr (si),#0
+       jne     niloop          ; yes -> use it
+       mov     ax,nodfl        ; no idea how to tell as86 to do jmp (addr) :-(
+       jmp     ax              ; fall through
+
+
+; Command input processor
+
+iloop:
+#if defined(MENU) || defined(BITMAP)
+       call    menu_setup
+#endif
+
+#ifndef BITMAP
+;;     BEG_FS
+;;     SEG_FS          ; message disabled ?
+       cmp     word ptr par2_msg_len,#0                ;MSG_OFF+SSDIFF,#0
+;;     END_FS
+       je      nomsg           ; yes -> skip this
+       call    crlf
+;BEG_FS
+;SEG_FS                ; load the message file
+       mov     cx,mt_msg+KEYTABLE+256                  ;MSG_OFF+SSDIFF+2
+;SEG_FS
+       mov     dx,mt_msg+2+KEYTABLE+256
+;SEG_FS
+       mov     al,mt_msg+4+KEYTABLE+256
+;END_FS
+       mov     bx,[map]
+       call    sread
+       call    loadfile
+
+       xor     bx,bx           ; set the terminating NUL and disable further
+                               ; messages
+       xchg    bx,par2_msg_len         ;MSG_OFF+SSDIFF
+
+       push    #SYSSEG
+       pop     ds
+       mov     byte ptr (bx),#0
+       xor     bx,bx           ; display the message
+       call    say
+
+       push    cs              ; restore segment registers
+       pop     ds
+#endif
+
+nomsg: push    cs              ; disable external parameters
+       pop     es
+
+       mov     cmdbeg,#acmdbeg ; probably unattended boot
+       mov     si,#usrinpm     ; interactive mode
+niloop:                                ; ES may point to external params
+       mov     bx,#msg_p       ; display boot prompt
+       call    say
+       mov     bx,#cmdline     ; move cursor to the end of the line
+clend: mov     al,(bx)
+       or      al,al           ; at end ?
+       jz      cledne          ; yes -> go on
+       push    bx              ; display the character
+       call    display
+       pop     bx
+       inc     bx              ; next one
+       jne     clend
+cledne:        mov     byte ptr prechr,#32 ; character before command line is a space
+
+! Input loop
+
+input: seg     es              ; interactive mode ?
+       cmp     byte ptr (si),#UI_MAGIC
+       je      kbinp           ; yes -> get keyboard input
+       seg     es              ; get non-interactive input
+       mov     al,(si)
+       inc     si
+       jmp     gotinp          ; go on
+       
+tolist:
+#ifdef BITMAP
+       call    menu_exit
+#endif
+       br      list            ; ...
+
+kbinp: 
+       mov     cx,#brto        ; get a key
+       call    getkey
+#ifdef BITMAP
+       cmp     byte [abs_cx+1],#0
+       je      noNull          ; skip cursor keys after Tab
+#endif
+#if defined(MENU) || defined(BITMAP)
+       cmp     al,#0xE0        ; extended keyboard
+       je      toNull
+       or      al,al           ;
+toNull:        je      near null       ; cursor control
+#endif
+#ifndef MENU
+noNull:        or      al,al           ; keyboard NUL input?
+       je      input           ; yes, skip Keyboard NUL
+; stored command line NUL is handled differently
+#endif
+gotinp:        cmp     al,#9           ; TAB ?
+       je      tolist          ; yes -> list images
+       cmp     al,#63          ; "?" ?
+       je      tolist          ; yes -> list images
+       or      al,al           ; NUL ?
+       je      nul             ; yes -> go on
+       cmp     al,#8           ; BS ?
+       je      todelch         ; yes -> erase one character
+       cmp     al,#13          ; CR ?
+       je      cr              ; yes -> go on
+       cmp     al,#127         ; DEL ?
+       je      todelch         ; yes -> erase one character
+       ja      input           ; non-printable -> ignore it
+       cmp     al,#21          ; ^U ?
+       je      todell          ; yes -> erase the line
+       cmp     al,#24          ; ^X ?
+       je      todell          ; yes -> erase the line
+       cmp     al,#32          ; ignore non-printable characters except space
+       jb      input
+       ja      noblnk          ; no space -> go on
+       cmp     (bx-1),al       ; second space in a row ?
+       je      input           ; yes -> ignore it
+noblnk:        cmp     bx,#cmdline+CL_LENGTH-1 ; at end of buffer ?
+       je      input           ; yes -> ignore
+       xor     ah,ah           ; cmdline is always NUL terminated
+       mov     (bx),ax         ; store in the buffer
+       inc     bx              ; increment pointer
+       push    bx
+       call    display         ; echo
+#if defined(MENU) || defined(BITMAP)
+       push    ax
+       call    find_image      ; we want the side effect of the hilite
+       pop     ax
+#endif
+       pop     bx
+       cmp     bx,#cmdline+1   ; first character ?
+       jne     input           ; no -> next input
+#ifdef LCF_IGNORECASE
+       call    upcase          ; convert to upper case
+#endif
+       mov     cx,#IMAGES      ; check if we have a single-key entry
+       mov     di,#DESCR0
+       mov     ah,al
+sklp:  test    word ptr (di+id_flags),#FLAG_SINGLE ; single-key entry ?
+       jz      sknext          ; no -> try next
+       mov     al,(di)         ; get first character
+#ifdef LCF_IGNORECASE
+       call    upcase          ; convert to upper case
+#endif
+       cmp     al,ah           ; do we have a match ?
+       jne     sknext          ; no -> try next
+       cmp     byte ptr (di+1),#0 ; at end ?
+       je      cr              ; yes -> run it
+sknext:        add     di,#id_size     ; test next entry
+       loop    sklp            ; next one
+       br      input           ; done -> get more input
+
+todelch:br     delch           ; ...
+todell:        br      delline         ; ...
+
+! End of input, process the command line
+
+nul:   push    bx              ; automatic boot - wait for timeout
+       mov     ax,old_del
+       call    waitsh
+       pop     bx
+       jnc     crnul           ; no key pressed -> continue
+       mov     bx,#msg_int     ; interrupted -> display a message
+       call    say
+       mov     byte ptr cmdline,#0     ; clear the command line
+       br      iloop           ; return to interactive prompt
+
+cr:
+;;22.7 mov     word par2_timeout,#0xffff       ; kill timeout
+#ifdef LCF_HP_TTRC
+       push    ax              ; HP TTRC boot fail workaround.
+       mov     ax, #3          ; 2000/10 <yumoto@jpn.hp.com>
+       call    setto           ; reload timer
+short_wait:
+       test    byte ptr timeout,#1 ; timed out ?
+       jz      short_wait      ; No, remain loop..
+       pop     ax
+#endif
+       mov     cmdbeg,#mcmdbeg ; probably manual boot
+crnul:
+#ifndef LCF_NOSERIAL
+       mov     byte ptr break,#0 ; clear the break flag
+#endif
+       push    cs              ; set ES to CS
+       pop     es
+       xor     al,al           ; mark end
+       mov     (bx),al
+       mov     si,#cmdline     ; copy command line to save buffer
+       mov     di,#lkcbuf
+       mov     byte ptr dolock,#0 ; disable locking
+
+cpsav: lodsb                   ; copy one byte
+       stosb
+       or      al,al           ; at end ?
+       jnz     cpsav           ; no -> go on
+
+       cmp     bx,#cmdline     ; empty line ?
+       je      notrspc         ; yes -> boot first image
+       cmp     byte ptr (bx-1),#32 ; trailing space ?
+       jne     notrspc         ; no -> go on
+       dec     bx              ; remove the space
+       mov     byte ptr (bx),al
+notrspc:mov    si,#cmdline     ; scan the command line for "vga=", "kbd=",
+       mov     di,si           ; "lock" or "mem="
+chkvga:
+
+#ifdef LCF_BDATA
+vsktnbd:
+       cmp     dword ptr (si),#0x64626f6e      ; "nobd"
+       jne     vsktv
+       cmp     byte (si+4),#32                 ; terminated with SP or NUL?
+       jnbe    vsktv
+       BEG_FS
+       SEG_FS          ; enter boot prompt ?
+       or      byte ptr par1_prompt+SSDIFF,#FLAG_NOBD  ; suppress BIOS data collection
+       END_FS
+       jmp     vskwd           ; skip word
+#endif
+vsktv:
+       cmp     dword ptr (si),#0x3d616776      ; "vga="
+       jne     vsktk
+       call    setvga          ; set VGA mode
+       jc      near iloop      ; error -> get next command
+       jmp     vskdb           ; proceed by discarding last blank
+vsktk:
+       cmp     dword ptr (si),#0x3d64626b      ; "kbd="
+       jne     vsktl
+       call    putkbd          ; pre-load keyboard buffer
+       jmp     vskdb           ; proceed by discarding last blank
+vsktl:
+       cmp     dword ptr (si),#0x6b636f6c      ; "lock"
+       jne     vsktm
+       cmp     byte (si+4),#32         ; space?
+       jnbe    vsktm
+       mov     byte ptr dolock,#1 ; enable locking
+vskwd: add     si,#4           ; skip word
+vskdb: dec     di              ; discard last blank
+       jmp     vsknb           ; continue
+vsktm:
+#if DEBUG_INITRD
+       cmp     dword ptr (si),#0x3d647269      ; "ird="
+#else
+       cmp     dword ptr (si),#0x3d6d656d      ; "mem="
+#endif
+       jne     vsknb
+       call    getmem          ; get the user-provided memory limit
+vsknb:
+       lodsb                   ; copy one byte
+       stosb
+       cmp     al,#32          ; space ?
+       je      chkvga          ; yes -> look for options again
+       or      al,al           ; at end ?
+       jnz     vsknb           ; no -> go on
+       call    crlf            ; write CR/LF
+       cmp     di,#cmdline+1   ; empty line ?
+emptyl:        je      bfirst          ; yes -> boot first image
+       jmp     bcmd            ; boot the specified image
+
+! Find the boot image and start it
+
+bcmd:
+       call    find_image
+       jc      near boot       ; eureka, it was found
+
+       mov     bx,#msg_nf      ; not found -> display a message
+       call    say
+       br      iloop           ; get more input
+
+! Delete one character
+
+delch: cmp     bx,#cmdline     ; at the beginning ?
+       je      toinput         ; yes -> do nothing
+       dec     bx              ; move the pointer
+       push    bx              ; display[B BS,SPC,BS
+       mov     bx,#bs
+       call    say
+#if defined(MENU) || defined(BITMAP)
+       pop     bx
+       push    bx
+       mov     byte (bx),#0    ; NUL terminate the line
+       mov     ax,#cmdline
+       sub     ax,bx
+       jz      delch6
+       call    find_image
+       jmp     delch9
+
+delch6:
+#if defined(LCF_VIRTUAL) || defined(LCF_NOKEYBOARD)
+       mov     ax,[vimage]
+#endif
+       mov     bx,[dimage]
+       cmp     ax,bx
+       je      delch9
+       xchg    ax,bx
+       call    lowlite
+       xchg    ax,bx
+       call    hilite
+delch9:
+#endif
+       pop     bx
+toinput:br     input           ; go on
+
+! Delete the entire line
+
+delline:
+#if !defined(MENU) && !defined(BITMAP)
+       cmp     bx,#cmdline     ; done ?
+       je      toinput         ; yes -> go on
+       push    bx              ; display BS,SPC,BS
+       mov     bx,#bs
+       call    say
+       pop     bx
+       dec     bx              ; move the pointer
+       jmp     delline         ; next one
+#else
+       call    menu_delline
+       push    bx              ; delch will do a pop
+       xor     ax,ax
+       jmp     delch6
+#endif
+
+! Boot first after timeout
+
+brto:  call    crlf            ; display a CRLF
+       jmp     brfrst          ; boot
+
+! Boot the first image
+
+bfirst:        mov     byte ptr lkcbuf,#0  ; clear default
+       cmp     byte ptr cmdline,#0 ; is there a default ?
+       jne     bcmd            ; yes -> boot that image
+brfrst:        
+       mov     bx,#DESCR0      ; boot the first image
+
+#if defined(LCF_VIRTUAL) && defined(LCF_NOKEYBOARD)
+       xor     ax,ax           ; mask = 0
+       call    vmtest
+       jnc     brfrst0v        ; not virtual
+       mov     ax,#FLAG_VMDEFAULT
+brfrst0v:
+       call    kbtest
+       jc      brfrst0k
+       mov     ax,#FLAG_NOKBDEFAULT
+brfrst0k:
+
+       mov     cx,#IMAGES
+brfrst1: test  word ptr (bx+id_flags),ax
+       jnz     brfrst3
+       add     bx,#id_size
+       loop    brfrst1 
+
+       mov     bx,#DESCR0      ; restore default
+brfrst3:
+#else
+#ifdef LCF_VIRTUAL
+       call    vmtest
+       jnc     brfrst3         ; not virtual, boot BX
+
+       mov     cx,#IMAGES
+brfrst1: test  word ptr (bx+id_flags),#FLAG_VMDEFAULT
+       jnz     brfrst3
+       add     bx,#id_size
+       loop    brfrst1 
+
+       mov     bx,#DESCR0      ; restore default
+brfrst3:
+#endif /* LCF_VIRTUAL */
+#ifdef LCF_NOKEYBOARD
+       call    kbtest
+       jc      brfrst3k                ; not virtual, boot BX
+
+       mov     cx,#IMAGES
+brfrst1k: test word ptr (bx+id_flags),#FLAG_NOKBDEFAULT
+       jnz     brfrst3k
+       add     bx,#id_size
+       loop    brfrst1k
+
+       mov     bx,#DESCR0      ; restore default
+brfrst3k:
+#endif /* LCF_NOKEYBOARD */
+
+#endif /* if !both */
+
+       mov     si,bx           ; copy the name to the command line
+       mov     di,#cmdline
+bfcpl: lodsb                   ; copy one character
+       mov     (di),al
+       inc     di
+       or      al,al           ; NUL ?
+       jnz     bfcpl           ; no -> next one
+
+! Boot the image BX points to (with password check)
+
+boot:
+       mov     word par2_timeout,#0xffff       ; kill timeout  (22.7)
+       mov     si,#cmdline     ; locate start of options
+locopt:        lodsb
+       or      al,al           ; NUL ?
+       je      optfnd          ; yes -> no options
+       cmp     al,#32          ; space ?
+       jne     locopt          ; no -> continue searching
+       cmp     byte ptr (si),#0 ; followed by NUL ?
+       jne     optfnd          ; no -> go on
+       mov     byte ptr (si-1),#0 ; discard trailing space
+optfnd:        dec     si              ; adjust pointer
+       mov     options,si      ; store pointer for later use
+#ifdef BITMAP
+#ifdef RETAIN
+       test    word ptr [id_flags](bx),#FLAG_RETAIN    ; keep bitmap?
+       jz      bmp_terminate
+       xor     ax,ax           ; time out immediately
+       call    waitsh          ; check for break (Shift, Alt, ScrollLock,...)
+       jnc     bmp_retain
+bmp_terminate:
+#endif
+       call    menu_exit
+bmp_retain:
+#endif
+
+#ifdef LCF_VIRTUAL
+       test    word ptr [id_flags](bx),#FLAG_VMWARN
+       jz      boot9
+       call    vmtest          ; 'vmwarn' there, is it actually virt. boot
+       jnc     boot9
+; VMWARN set, and is virtual boot, so issue comment
+;;     BEG_FS
+;;     SEG_FS
+       mov     word ptr par2_timeout,#0xffff   ; cancel timeout
+;;     END_FS
+
+       push    bx              ; save image descriptor ptr
+       mov     bx,#msg_vmwarn
+       call    say
+       mov     cx,#vmwto       ; timeout exit
+       call    getkey
+
+       push    ax
+       cmp     al,#0x20        ; compare to Space
+       jb      boot3           ; no echo if ctrl char
+       call    display         ; echo
+boot3: call    crlf
+       pop     ax
+
+       pop     bx              ; restore image descriptor ptr
+       cmp     al,#0x79        ; y is yes
+       je      boot9
+       cmp     al,#0x59        ; Y is yes
+       je      boot9
+
+vmwto:
+       br      iloop
+
+boot9:
+#endif
+       test    byte ptr (bx+id_flags),#FLAG_PASSWORD   ; use a password
+       jz      toboot          ; no -> boot
+       test    byte ptr (bx+id_flags),#FLAG_RESTR      ; restricted ?
+       jz      dopw            ; no -> get the password
+       cmp     byte ptr (si),#0 ; are there any options ?
+       jne     dopw            ; yes -> password required
+toboot:        br      doboot          ; ...
+dopw:
+#if defined(CRC_PASSWORDS) || defined(SHS_PASSWORDS)
+       push    bx              ; save the image descriptor
+;;     BEG_FS
+;;     SEG_FS
+       mov     word ptr par2_timeout,#0xffff   ; cancel timeout
+;;     END_FS
+       mov     bx,#msg_pw      ; display a prompt
+       call    say
+
+       push    bp              ; save BP
+       mov     bp,sp           ; save SP in BP
+       sub     sp,#CL_LENGTH   ; allocate space for PW string
+       mov     si,sp           ; si points at string
+       xor     di,di           ; di counts characters
+pwloop:
+#ifdef DEBUG
+       pusha
+       mov     ax,si
+       call    wout
+       mov     al,#32
+       call    display
+       mov     ax,di
+       call    wout
+       call    crlf
+       popa
+#endif
+       mov     cx,#pwtime      ; get timeout exit
+       call    getkey
+       
+       cmp     al,#13          ; CR ?
+       je      pwcr            ; yes -> handle it
+       cmp     al,#21          ; ^U ?
+       je      pwdell          ; yes -> erase line
+       cmp     al,#24          ; ^X
+       je      pwdell
+       cmp     al,#8           ; BS ?
+       je      pwdelch         ; yes -> erase one character
+       cmp     al,#127         ; DEL
+       je      pwdelch
+       ja      pwloop          ; ignore other non-printable characters
+       cmp     al,#32
+       jb      pwloop
+
+       cmp     di,#CL_LENGTH   ; check for buffer overflow
+       jae     pwloop          ; ingnore further input
+       seg     ss
+       mov     (si),al         ; store char in buffer
+       inc     si
+       inc     di
+       mov     al,#42          ; echo '*'
+       call    display
+       jmp     pwloop          ; loop back for more
+
+pwdelch: or    di,di
+       jz      pwloop 
+       call    pwbs
+       dec     si
+       dec     di
+       jmp     pwloop
+
+pwdell:        inc     di
+pwdel: dec     di
+       jz      pwloop
+       call    pwbs
+       dec     si
+       jmp     pwdel
+
+pwbs:  mov     bx,#bs
+       call    say
+       ret
+
+pwcr:  
+       xor     cx,cx           ; signal okay
+pwtime:                                ; CX != 0 if enter here
+       inc     cx
+       call    crlf
+
+       sub     si,di           ; point SI at start of buffer
+       push    es              ; save ES
+
+#if !defined(SHS_PASSWORDS)
+       mov     bx,(bp+2)       ; restore image descriptor pointer
+       push    ss
+       pop     es              ; ES:SI points at char string
+
+#if MAX_PW_CRC>=1
+       push    dword #CRC_POLY1
+       call    crc32
+#ifdef DEBUG
+       pusha
+       push    ax
+       mov     ax,di
+       call    wout
+       mov     al,#32
+       call    display
+       pop     ax
+
+       push    eax
+       call    dout
+       call    crlf
+       popa
+#endif
+
+       cmp     eax,(bx+id_password_crc)
+       jne     pwcleanup
+#endif
+
+; insert other checks in here
+#if MAX_PW_CRC>=2
+       push    dword #CRC_POLY2
+       call    crc32
+       cmp     eax,(bx+id_password_crc+4)
+       jne     pwcleanup
+#endif
+
+#if MAX_PW_CRC>=3
+       push    dword #CRC_POLY3
+       call    crc32
+       cmp     eax,(bx+id_password_crc+8)
+       jne     pwcleanup
+#endif
+
+#if MAX_PW_CRC>=4
+       push    dword #CRC_POLY4
+       call    crc32
+       cmp     eax,(bx+id_password_crc+12)
+       jne     pwcleanup
+#endif
+
+#if MAX_PW_CRC>=5
+       push    dword #CRC_POLY5
+       call    crc32
+       cmp     eax,(bx+id_password_crc+16)
+       jne     pwcleanup
+#endif
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+       dec     cx                      ; signal all okay
+#else          /* SHS_PASSWORDS */
+; DI is the count
+; SS:SI is the password string
+       push    di
+       push    si
+       call    _shsInit
+       call    _shsUpdate
+       call    _shsFinal
+       mov     bx,(bp+2)       ; restore image descriptor pointer
+       lea     di,(bx+id_password_crc)
+       mov     si,#shs_digest
+       mov     cx,#MAX_PW_CRC*4
+; ES==DS
+       repe
+           cmpsb
+
+       pop     si              ; restore buffer ptr
+       pop     di              ; clear stack
+       push    ss
+       pop     es              ; ES=SS
+
+       je      pwcleanup       ; CX will be 0
+       inc     cx              ; CX is > 0
+#endif         /* !defined(SHS_PASSWORDS) */
+
+pwcleanup:
+       push    cx
+       mov     cx,#CL_LENGTH
+       mov     di,si
+       xor     ax,ax
+       rep                     ; wipe out password in memory
+           stosb
+       pop     cx
+       pop     es              ; restore the saved ES
+
+       mov     sp,bp
+       pop     bp
+       pop     bx
+       or      cx,cx           ; test CX==0 means all okay
+       jz      doboot
+; fall into pwfail     
+
+#else
+       push    bx              ; save the image descriptor
+       lea     si,(bx+MAX_IMAGE_NAME+1) ; get a pointer to the password string
+       mov     bx,#msg_pw      ; display a prompt
+       call    say
+pwagain:xor    cl,cl           ; CL counts characters after a mismatch
+pwloop:        push    cx              ; get a key
+       mov     cx,#pwtime
+       call    getkey
+       pop     cx
+       cmp     al,#13          ; CR ?
+       je      pwcr            ; yes -> handle it
+       cmp     al,#21          ; ^U ?
+       je      pwdell          ; yes -> erase line
+       cmp     al,#24          ; ^X
+       je      pwdell
+       cmp     al,#8           ; BS ?
+       je      pwdelch         ; yes -> erase one character
+       cmp     al,#127         ; DEL
+       je      pwdelch
+       ja      pwloop          ; ignore other non-printable characters
+       cmp     al,#32
+       jb      pwloop
+       or      cl,cl           ; counting bad input ?
+       jnz     pwbad           ; yes -> do it
+       cmp     al,(si)         ; correct input ?
+       je      pwgood          ; yes -> go on
+pwbad: inc     cl              ; count error
+       jnz     pwgood          ; no overflow -> go on
+       dec     cl              ; adjust it
+       jmp     pwcr            ; terminate input
+pwgood:        inc     si              ; good character -> go on
+       jmp     pwloop
+pwdell:        pop     si              ; reset the pointer
+       push    si
+       add     si,#MAX_IMAGE_NAME+1
+       jmp     pwagain         ; get password again
+pwdelch:pop    bx              ; at the beginning of the line ?
+       push    bx
+       add     bx,#MAX_IMAGE_NAME+1
+       cmp     si,bx
+       je      pwloop          ; yes -> ignore it
+       dec     si              ; remove one character
+       sub     cl,#1
+       jnc     pwloop          ; no underflow -> go on
+       inc     cl              ; adjust it
+       jmp     pwloop          ; next character
+pwtime:        pop     cx              ; drop CX ...
+       mov     cl,#1           ; ... and fail
+pwcr:  call    crlf
+       pop     bx              ; restore the image descriptor
+       or      cl,cl           ; no errors ?
+       jnz     pwfail          ; no -> fail
+       cmp     byte ptr (si),#0 ; at end ?
+       je      doboot          ; yes -> continue booting
+#endif /* CRC_PASSWORDS */
+
+pwfail:        mov     bx,#msg_pf      ; display an error message
+       call    say
+       br      iloop           ; get next input
+
+! Boot the image BX points to
+
+doboot:        mov     byte ptr prechr,#61 ; switch to equal sign
+       push    bx              ; save image descr
+       mov     bx,#msg_l       ; say hi
+       call    say
+       pop     bx              ; display the image name
+       push    bx
+       call    say
+       pop     si
+
+       push    si
+       add     si,#id_start    ; form address
+       
+;  Now load the kernel sectors
+       xor     ax,ax
+       mov     word ptr (gdt+0x1b),ax ; set GDT to "load low"
+       mov     byte ptr (gdt+0x1f),al
+       mov     moff,ax         ; map is not loaded yet
+
+       lodsw                   ; address of the first map sector
+       xchg    cx,ax
+       lodsw
+       xchg    dx,ax
+        lodsb
+
+       push    si              ; save SI
+
+#ifdef DEBUG
+        push    ax              ;
+       mov bx,#step0
+       call say
+        pop     ax              ;
+#endif
+       mov     bx,[map]                ; load the first map sector
+       call    sread
+#ifdef DEBUG
+       mov bx,#step0b
+       call say
+#endif
+       mov     bx,#DFLCMD      ; load the default command line
+;BEG_FS
+;SEG_FS
+       mov     cx,mt_dflcmd+KEYTABLE+256
+;SEG_FS
+       mov     dx,mt_dflcmd+2+KEYTABLE+256
+;SEG_FS
+       mov     al,mt_dflcmd+4+KEYTABLE+256
+;END_FS
+       call    cread
+       push    word ptr (DFLCMD) ; push magic number
+       mov     bx,#DFLCMD      ; load the fallback sector
+       call    load1
+       pop     ax              ; valid magic number ?
+#ifndef LCF_READONLY
+       cmp     ax,#DC_MAGIC
+       je      dclok           ; yes -> can write
+       cmp     ax,#DC_MGOFF
+       jne     nofbck          ; invalid -> must not write
+dclok: mov     bx,#DFLCMD      ; fallback data present ?
+       cmp     word ptr (bx),#DC_MAGIC
+       jne     nofbck          ; no -> go on
+       call    cmd_write       ; write out the command line
+nofbck:
+#endif
+#ifdef DEBUG
+       mov bx,#step1
+       call say
+#endif
+       mov     bx,#DFLCMD      ; load the options sector
+       call    load1
+       mov     si,cmdbeg       ; copy non-options part of command line
+       mov     di,#PARMLINE
+       mov     cx,#CL_LENGTH-1 ; max number of characters to copy
+
+cpnocl:        
+#if DNAME
+       cmp     si,#cmdline
+#else
+       cmp     si,options      ; at beginning of options ?
+#endif
+       je      cpnodn          ; yes -> go on
+       movsb                   ; copy one byte
+       loop    cpnocl          ; next one
+       jmp     cpovfl          ; signal overflow
+
+cpnodn:        
+#if DNAME
+       pop     ax              ; get saved pointer
+       pop     si              ; get saved descriptor
+       push    si
+       push    ax
+cpdname:
+       lodsb
+       or      al,al
+       jz      cpdname9
+       stosb
+       dec     cx
+       jmp     cpdname
+cpdname9:      
+#endif
+       mov     si,#DFLCMD      ; constant options ?
+       cmp     byte ptr (si),#0
+       je      nocopt          ; no -> go on
+       mov     al,#32          ; add a space
+       stosb
+       dec     cx              ; count character
+       jz      cpovfl
+cpcodsp:
+#if DEBUG_INITRD
+       cmp     dword ptr (si),#0x3d647269      ; "ird="
+#else
+       cmp     dword ptr (si),#0x3d6d656d      ; "mem="
+#endif
+       jne     cpnotmem
+       call    getmem          ; get the user-provided memory limit
+cpnotmem:
+       lodsb                   ; fetch next byte
+       cmp     al,#32          ; space ?
+       je      cpcodsp         ; yes -> discard it
+cpcolp:        or      al,al           ; NUL ?
+       jz      cpcodn          ; yes -> done
+       stosb                   ; store byte
+       dec     cx              ; count character
+       jz      cpovfl
+       cmp     al,#32          ; a space ?
+       je      cpcodsp         ; yes -> discard next
+       lodsb                   ; get next byte
+       jmp     cpcolp
+
+cpcodn:        seg     es
+       cmp     byte ptr (di-1),#32 ; last was space ?
+       jne     nocopt          ; no -> go on
+       dec     di              ; discard it
+       inc     cx              ; **
+nocopt:        mov     si,options      ; append variable options
+cpvalp:        lodsb                   ; copy one byte
+       stosb
+       or      al,al           ; NUL ?
+       jz      cpdone          ; done?
+       loop    cpvalp          ; count and loop back
+cpovfl:        mov     (di),cl         ; CX is zero
+#if DEBUG_NEW
+       dec     cx              ; count 1 more character
+#endif
+cpdone:
+
+
+#if DEBUG_NEW
+       push    cx
+       mov     bx,#msg_pl      ; parameter line message
+       call    say
+       pop     cx
+       mov     ax,#CL_LENGTH-1
+       sub     ax,cx
+       call    wout
+       call    crlf
+#endif
+
+#ifdef DEBUG
+       mov bx,#step2
+       call say
+#endif
+       mov     es,[initseg]    ; load the original boot sector
+       xor     bx,bx           ; load now
+       call    load1
+       pop     si              ; restore SI
+       lodsw                   ; get flags bit map
+       xchg    bx,ax           ; move to BX
+       lodsw                   ; copy parameters ... VGA mode ... (done)
+       cmp     word ptr vgaovr,#VGA_NOCOVR ; VGA mode not overridden on
+                               ; command line ?
+       je      vganorm         ; no -> go on
+       mov     ax,vgaovr       ; use that value
+       jmp     vgaset
+vganorm:test   bx,#FLAG_VGA
+       jz      novga
+vgaset:        seg     es
+        mov    [VGA_SET],ax    ; magic offset in the boot sector
+novga: push    bx              ; use flags (BX) later
+       test    bx,#FLAG_LOCK   ; ... lock target ?
+       jnz     lockit          ; yup -> do it
+       cmp     byte ptr dolock,#0 ; did user ask to lock new target ?
+       je      nolock          ; no -> go on
+lockit:
+#ifndef LCF_READONLY
+       mov     bx,#lkwbuf      ; save the command line
+       mov     word (bx),#DC_MAGIC     ;
+       push    es
+       push    si
+
+        push    ds                      ;
+        pop     es                      ;
+       call    cmd_write               ; write out the command line
+
+       pop     si
+       pop     es
+#endif
+nolock:
+#ifdef DEBUG
+       mov bx,#step3
+       call say
+#endif
+       xor     cx,cx
+       seg     es
+         add   cl,[VSS_NUM]
+;;;    or      cx,cx
+       jnz     lsetup
+       mov     cl,#SETUPSECS   ; default is to load four sectors
+lsetup:        
+       mov     es,[setupseg]   ; load the setup codes
+
+#ifdef MEMORY_CHECK
+       mov     ax,cx           ; number of sectors to AX
+       shl     ax,#5           ; convert to paragraphs (9-4)
+       mov     bx,es
+       add     bx,ax
+       add     bx,#STACK>>4    ; allow for stack space in paragraphs
+       mov     ax,cs           ;
+       cmp     bx,ax
+       jbe     enough_mem
+       mov     bx,#msg_mem     ; we are very short on memory
+       call    say
+
+enough_mem:
+#endif
+
+       xor     bx,bx           ; other operating system)
+lsloop:        push    cx
+       call    loadopt
+       pop     cx
+       loop    lsloop
+#ifdef DEBUG
+       mov bx,#step4
+       call say
+#endif
+       pop     bx              ; get flags
+       test    bx,#FLAG_MODKRN ; "modern" kernel ?
+       jz      loadlow         ; no -> avoid all patching and such
+       seg     es              ; set loader version
+       mov     byte ptr (16),#LOADER_VERSION
+
+       test    bx,#FLAG_LOADHI ; load kernel high
+       jz      nohigh
+       
+       seg     es
+       mov     ax,word ptr (20+1) ; get start address  00 1000 00
+       mov     (gdt+0x1b),ax
+       seg     es
+       mov     al,byte ptr (20+3) ; get hi-byte of address
+       mov     (gdt+0x1f),al
+nohigh:
+
+       seg     es              ; version >= 1 ?
+       cmp     word ptr (6),#NEW_HDR_VERSION
+       jbe     noheap          ; no -> do not patch heap
+       mov     ax,cs
+       sub     ax,[initseg]    ; find no. of paragraphs available
+       shl     ax,4
+       add     ax,#SLA_SIZE_DYN
+       seg     es
+       mov     word ptr (36),ax
+       seg     es              ; patch flags
+       or      byte ptr (17),#LFLAG_USE_HEAP
+noheap:
+       pop     si              ; restore pointer to DESCR to load
+
+       push    [gdt+0x1b]
+       mov     al,[gdt+0x1f]
+       push    ax
+
+       call    load_initrd     ; load the initrd & patch header
+
+       pop     ax
+       mov     [gdt+0x1f],al
+       pop     bx
+       mov     [gdt+0x1b],bx
+
+       cbw
+       or      ax,bx           ; load low ?
+
+       je      loadlow         ; yes -> do it
+       xor     ax,ax           ; GDT is already set up ...
+       mov     es,ax
+       mov     bx,#gdt
+#if DEBUG_NEW
+       push    bx
+       mov     bx,#msg_high
+       call    say
+       pop     bx
+#endif
+       call    lfile           ; load the system ...
+       jmp     launch2         ; ... and run it
+loadlow:
+#if DEBUG_NEW
+       push    bx
+       mov     bx,#msg_low
+       call    say
+       pop     bx
+#endif
+       call    loadfile        ; load the system
+launch2:
+
+       jmp     launch          ; go !
+
+loadfile:
+       push    #SYSSEG         ; load a file at SYSSEG:0000
+       pop     es
+       xor     bx,bx
+lfile: call    load
+       jmp     lfile
+
+! Load one sector. Issue an error at EOF.
+
+load1: call    loadit          ; load the sector
+       mov     bx,#msg_eof     ; we only get here at EOF
+       call    say
+       br      restrt
+
+loadit:        call    load            ; load it
+       pop     ax              ; drop return address of load1
+       ret
+
+! Load one sector. Start the system at EOF.
+
+loadopt:call   loadit          ; load the sector
+       jmp     launch          ; go
+
+! Load one sequence of sectors. Leave outer function at EOF.
+
+load:  push    es              ; save ES:BX
+       push    bx
+lfetch:        mov     si,moff         ; get map offset
+       mov     bx,[map]
+       mov     cx,(bx+si)      ; get address
+       mov     dx,(bx+si+2)
+       mov     al,(bx+si+4)
+       or      cx,cx           ; at EOF ?
+       jnz     noteof          ; no -> go on
+       or      dx,dx
+       jnz     noteof
+       pop     bx              ; restore ES:BX
+       pop     es
+       pop     ax              ; pop return address
+       ret                     ; return to outer function
+noteof:        add     si,#sa_size     ; increment pointer
+       mov     moff,si
+       cmp     si,#SECTOR_SIZE - sa_size + 1           ; page end ?
+       jb      near doload
+
+       mov     moff,#0         ; reset pointer
+       push    cs              ; adjust ES
+       pop     es
+
+        mov     bl,hinib        ; this might get clobbered
+        push    bx              ; so save it
+       mov     bx,[map]                ; load map page
+       call    sread
+        pop     ax              ; restore the hi-nibble
+       mov     hinib,al        ; 
+
+       mov     al,#0x2e        ; print a dot
+       call    display
+       jmp     lfetch          ; try again
+
+! Start the kernel
+
+launch:
+; terminate emulation if CD boot
+       test    byte ptr [par2_flag2],#FLAG2_EL_TORITO  ; a CD?
+       jz      not_el_torito
+       mov     si,#Map         ; empty command packet
+       mov     byte ptr (si),#0x13     ; size of command packet
+       mov     ax,#0x4b00      ; terminate emulation
+;;;;   mov     dl,al           ; DL is 0
+       mov     dl,[init_dx]    ; terminate boot device
+       int     0x13
+not_el_torito:
+#ifdef MENU
+       call    menu_exit       ; make the menu area vanish
+#endif
+       call    crlf            ; display a CRLF
+
+/* 'outb' was removed in 22.5.5; but the HW stop is required by some BIOSs */
+       mov     dx,#0x3f2       ; stop the floppy motor
+       xor     ax,ax
+       out     dx,al           ; outb
+       mov     dl,al
+       int     0x13            ; reset the FDC  (AH=0)
+
+       mov     es,[initseg]    ; adjust segment registers
+       mov     di,#PARMLINE    ; set parameter line offset
+       mov     ax,cs           ; find where we are loaded
+       sub     ax,[initseg]    ; find no. of paragraphs available
+       shl     ax,4            ; convert para. to bytes
+       add     di,ax
+       seg     es
+       cmp     dword ptr CL_HEADER_ID,#0x53726448      ; "HdrS" (reversed)
+       je      chkver          ; go check header version
+mbchain:
+
+! it must be the chain loader
+
+#ifdef LCF_BDATA
+       BEG_FS
+       SEG_FS                  ; suppress BIOS data collection
+       or      byte ptr par1_prompt+SSDIFF,#FLAG_NOBD  ; suppress BIOS data collection
+       END_FS
+#endif
+                       ; ES:DI will point at param line (chain.b)
+       push    ds              ; save DS
+       mov     ds,[setupseg]   ; point at chain loader(?) header
+; DS points at chain loader
+       cmp     dword [parC_signature],#EX_MAG_HL ;
+       jne     not_chain
+       cmp     word [parC_stage],#STAGE_CHAIN
+       jne     not_chain
+       cmp     word [parC_version],#VERSION
+       jne     not_chain
+       mov     dx,[parC_drive] ; get drive
+;;;    call    map_device      ; map drive -- uses CS to address "devmap"
+       mov     [parC_drive],dl ; store mapped drive
+       mov     [parC_devmap],#devmap   ; save our drive mapping
+       mov     [parC_devmap+2],cs      ; our DS register
+not_chain:
+       pop     ds
+       BEG_FS
+       SEG_FS
+       mov     dx,[EX_OFF+6]   ; pass DX from first stage
+       END_FS
+#if DEBUG_NEW
+       mov     bx,#nohdrs
+       call    say
+       jmp     cl_wait
+#else
+       br      start_setup2
+#endif
+
+chkver:
+       mov     bh,[gdt+0x1f]           ; check for kernel/initrd conflict
+       shl     ebx,#8
+       mov     bx,[gdt+0x1b]           ; form kernel final load address
+       shl     ebx,#8
+       mov     eax,[rdbeg]             ; initrd beg address (0 if none)
+       or      eax,eax
+       jz      no_overwrite
+       sub     eax,ebx
+       jae     no_overwrite
+       mov     bx,#msg_confl
+       br      zz
+
+no_overwrite:
+#if DEBUG_NEW
+       mov     bx,#hdr1
+       call    say
+       seg     es
+       mov     ax,CL_HDRS_VERSION
+       call    wout
+       mov     bx,#hdr2
+       call    say
+       push    di
+#endif
+       seg     es
+       cmp     word ptr CL_HDRS_VERSION,#NEW_VERSION  ; check for
+                               ; new cmdline protocol
+       jb      protocol201
+
+! and now the new protocol
+
+       mov     ax,es           ; form long address
+       movzx   edx,ax          ; zero extend segment part to EDX
+       movzx   edi,di          ; zero extend offset
+       shl     edx,4           ; make segment into address
+       add     edx,edi         ; form long absolute address
+       seg     es
+       mov     CL_POINTER,edx  ; and pass the address
+#if DEBUG_NEW
+       push    edx             
+       call    dout
+       jmp     cl_wait
+#else
+       jmp     start_setup
+#endif
+
+! the old command line passing protocol
+
+protocol201:
+       seg     es
+       mov     CL_MAGIC_ADDR,#CL_MAGIC ; set magic number
+       seg     es
+       mov     word ptr CL_OFFSET,di
+#if DEBUG_NEW
+       mov     ax,es
+       call    wout
+       mov     al,#0x3A        ; issue colon    
+       call    display
+       mov     ax,di
+       call    wout
+cl_wait:
+       mov     bx,#hdr4
+       call    say
+       pop     bx
+       push    ds
+       push    es
+       pop     ds
+       call    strlen
+       pop     ds
+       call    wout
+
+       call    crlf
+       call    crlf
+       jmp     start_setup
+
+#endif
+start_setup:                   ; kernel boot comes here
+#if DEBUG_NEW
+       mov     bx,#msg_real
+#ifdef LCF_VIRTUAL
+       call    vmtest
+       jnc     boot_real_msg_v
+       mov     bx,#msg_virtual
+boot_real_msg_v:
+#endif
+#ifdef LCF_NOKEYBOARD
+       call    kbtest
+       jc      boot_real_msg_k
+       mov     bx,#msg_no_keyboard
+boot_real_msg_k:
+#endif
+       call    say
+#endif
+#ifdef LCF_BDATA
+       mov     bx,#msg_bc
+       call    say
+       BEG_FS
+       SEG_FS          ; suppress BIOS data collection?
+       test    byte ptr par1_prompt+SSDIFF,#FLAG_NOBD  ; suppress?
+       END_FS
+       jz      start_setup3
+       mov     bx,#msg_by
+       call    say
+       jmp     start_setup2
+start_setup3:
+
+#ifndef LCF_READONLY
+       or      byte ptr [KEYTABLE+256+mt_flag],#FLAG_NOBD      ; suppress
+#if DEBUG_NEW
+       call    crlf
+#endif
+       call    kt_write
+#endif
+
+#if DEBUG_NEW
+;;;    call    pause
+       mov     ah,#2           ; get keyboard flags
+       int     0x16
+       and     al,#0x70        ; Caps, Num, Scroll Lock flags
+       cmp     al,#0x70
+       je      near zzz        ; fail with all 3 on
+#endif
+
+       BEG_FS
+       SEG_FS
+       mov     dx,[EX_OFF+6]   ; pass in DX from first stage
+       END_FS
+
+       push    es              ; save ES
+       call    is_prev_mapper  ; is there a previous mapper
+       jz      no_remove
+       seg es
+         mov   word (di),#0    ; sterilize it
+no_remove:
+       pop     es              ; and restore ES
+
+       call    io_biosdata
+
+       mov     bx,#msg_s
+       call    say
+#ifndef LCF_READONLY
+; if the BIOS data collection was successful, do not suppress it on future boots
+       and     byte ptr [KEYTABLE+256+mt_flag],#~FLAG_NOBD     ;  no suppress
+       call    kt_write
+#endif
+#endif /* ifdef LCF_BDATA */
+
+start_setup2:                  ; chain loader boot comes here
+#if DEBUG_NEW
+       call    pause           ; last chance to use the timer
+#else
+       mov     ax,#1500/55     ; about 1.5 second
+       call    setto           ; set timeout
+vpaus1:        test    byte ptr timeout,#-1
+       jz      vpaus1
+#endif
+       call    remto           ; free timer interrupt
+
+       push    es              ; is initseg
+       pop     ds              ; DS = 0x9000 (initseg)
+#if 0
+       push    es
+       pop     fs
+       push    es
+       pop     gs
+#endif
+
+       add     sp,#SETUP_STACK_DYN     ; increase stack size over this code
+if ~*&1                                        ; align to an odd memory location
+       nop
+endif
+       jmpi    0,SETUPSEG              ; segment part is a variable
+setupseg       =       *-2             ;   setupseg is filled in now
+initseg:       .word   INITSEG
+
+
+! Load one sector (called from load)
+
+doload:        pop     bx              ; restore ES:BX
+       pop     es
+
+! Load a sequence of sectors, possibly moving into "high memory" (> 1 MB)
+! afterwards.
+
+xread: push    ax              ; ES == 0 ?
+       mov     ax,es
+       or      ax,ax
+       pop     ax
+       jz      rdhigh          ; yes -> read into high memory
+#ifdef DEBUG
+       br      sread
+#else
+       jmp     sread
+#endif
+rdhigh:        push    bx              ; okay - DS:BX points to GDT in this case
+       mov     bx,#LOADSEG     ; adjust ES:BX
+       mov     es,bx
+       xor     bx,bx
+       call    sread           ; load the sector(s)
+        mov     tempal,al
+       pop     bx              ; get pointer to GDT
+       push    ax              ; just in case ...
+       push    cx
+       push    si
+       mov     si,bx           ; turn ES:SI into pointer to GDT
+       push    ds
+       pop     es
+       xor     cx,cx           ; number of words to move
+       mov     ch,tempal
+#ifdef DEBUG
+       push    si
+       push    bx
+       push    cx
+       mov     al,(si+0x14)
+       call    bout
+       mov     ax,(si+0x12)
+       call    wout
+       mov     bx,#mov_ar
+       call    say
+       mov     ah,(si+0x1f)
+       mov     al,(si+0x1c)
+       call    wout
+       mov     ax,(si+0x1a)
+       call    wout
+       mov     bx,#mov_sz
+       call    say
+       pop     ax
+       push    ax
+       call    wout
+       call    crlf
+       pop     cx
+       pop     bx
+       pop     si
+#endif
+       push    [gdt+0x1e]
+       push    bx              ; do the transfer. (save BX, CX and SI because
+       push    cx              ; we are paranoid)
+       push    si
+       mov     ah,#0x87        ; Move Extended Memory Block
+       int     0x15
+       pop     si
+       pop     cx
+       pop     bx
+       jc      badmov          ; failed ...
+       pop     ax              ; check the GDT
+       cmp     ah,[gdt+0x1f]   ; catch a BIOS that does not handle 386
+                               ; addresses (>16Mb)
+       jne     badmov+1        ; AH error code will be hi byte of address
+       shr     cx,#8-1         ; convert words to bytes/256
+       sub     ax,ax           ; put ES back to 0
+       add     (si+0x1b),cx
+       adc     (si+0x1f),al
+       mov     es,ax           ; put ES back to 0
+       pop     si
+       pop     cx
+       pop     ax
+       ret                     ; done
+
+badmov:        pop     bx              ; discard GDT
+       push    ax              ; save the error code
+       mov     bx,#msg_bm      ; tell the user ...
+       jmp     reset           ; (standard procedure calls say & bout)
+
+! Load a sequence of sectors
+
+sread: push    bx              ; save registers
+       push    cx
+       push    dx
+       call    cread
+       mov     di,ax           ; save AL return count
+       jc      rerror          ; error -> complain
+       pop     dx              ; restore registers
+       pop     cx
+rokay: pop     bx
+        shl     ax,8            ; convert sectors to bytes
+        add     ah,ah
+       jc      dowrap          ; loaded an entire segment -> advance ES
+       add     bx,ax           ; move BX
+       jnc     nowrap          ; same segment -> go on
+dowrap:        mov     ax,es           ; move ES
+       add     ax,#0x1000
+       mov     es,ax
+nowrap:
+       mov     ax,di           ; restore the block count in AL
+aret:  ret                     ; done
+
+! Read error - try a second time and give up if that fails too
+
+rerror:
+       push    ax
+       mov     bx,#msg_re      ; say something
+reset: call    say
+       pop     ax              ; display the error code
+       mov     al,ah
+       call    bout
+       call    crlf            ; a CR/LF
+       mov     moff,#0         ; restore initial state
+#if DEBUG_NEW
+       pop     ax
+       call    swout           ; DX
+       pop     ax
+       call    swout           ; CX
+       pop     ax
+       call    swout           ; BX
+       call    crlf
+#endif
+       br      restrt
+
+! Convert character in AL to upper case
+
+upcase:        cmp     al,#0x61        ; lower case character ? ('a')
+       jb      nolower         ; no -> go on
+       cmp     al,#0x7a        ; 'z'
+       ja      nolower
+       sub     al,#0x20        ; convert to upper case
+nolower:ret                    ; done
+
+pause:
+#if !DEBUG_NEW
+       pusha
+       mov     ax,#3200/55     ; delay 3+ seconds
+       call    setto
+delay1:        test    byte ptr timeout,#-1
+       jz      delay1
+       popa
+#else
+       pusha
+       mov     ah,#0x86        ; delay in microseconds
+       mov     cx,#5<<4        ; 3 seconds; forget DX
+       int     0x15
+       popa
+#endif
+       ret
+
+
+
+#if DEBUG_NEW
+
+!  display a double word, pushed into the stack
+
+dout:  push    bp
+       mov     bp,sp
+       push    ax
+
+       mov     ax,(bp+6)       ; get high order
+       call    wout
+       mov     ax,(bp+4)       ; get low order
+       call    wout
+
+       pop     ax
+       leave
+       ret     4
+
+! display a space, followed by a word in AX
+
+swout: push    ax
+       mov     al,#32
+       call    display
+       pop     ax
+; and fall into  wout
+
+! Display a hexadecimal word/byte/nibble
+
+wout:  push    ax
+       xchg    al,ah
+       call    bout
+       pop     ax
+; must fall into  bout
+#endif
+
+bout:  push    ax              ; save byte
+       shr     al,#4           ; display upper nibble
+       call    nout
+       pop     ax
+nout:  and     al,#0x0F        ; lower nible only
+       daa                     ; smaller conversion routine
+       add     al,#0xF0
+       adc     al,#0x40        ; AL is hex char [0..9A..F]
+       jmp     display         ; display it
+
+! part of the 'say' routine
+! actual entry point is below at 'say:'
+
+say_loop:
+       cmp     al,#10          ; \n ?
+       jne     nonl            ; no -> go on
+       mov     al,#13          ; display a CRLF
+       call    display
+       mov     al,#10
+nonl:
+       cmp     al,#12          ; ^L ?
+       jne     nocls           ; no -> go on
+#ifdef MENU
+       call    menu_form_feed  ; simulate a FF
+#else
+#ifdef BITMAP
+       cmp     BYTE [abs_cx+1],#0      ; graphic screen on?
+       jne     tosnext
+#endif
+       push    bx
+       mov     ah,#0xf         ; clear the local screen
+       int     0x10
+       xor     ah,ah
+       int     0x10
+       pop     bx
+#endif
+tosnext: jmp   snext           ; next character
+nocls: call    display         ; display, tty-style
+snext:
+       inc     bx              ; next one
+! fall into  say               ; process next character
+
+! Display a NUL-terminated string on the console
+
+say:   mov     al,(bx)         ; get byte
+       or      al,al           ; NUL ?
+       jnz     say_loop        ; not the end
+       ret
+
+
+! Display CR/LF
+
+crlf:  mov     al,#13          ; CR
+       call    display
+       mov     al,#10          ; LF
+;;;    jmp     display
+; fall into  display
+
+! Display one character on the console
+
+display:
+       push    bx              ; save BX
+
+#ifndef LCF_NOSERIAL
+       call    serdisp
+#endif
+#if defined(MENU) || defined(BITMAP)
+       seg     cs
+       cmp     word [suppress],#0
+       jnz     dispret
+
+#ifdef MENU
+       push    ds
+
+       push    cs
+       pop     ds
+
+       push    dx
+
+       cmp     byte [abs_cx+1],#0      ; is special scrolling in effect?
+       je      goshowit        ; jump if no special handling
+       call    mn_getcursor    ; get cursor pos. in DX
+       
+       cmp     al,#8           ; is it BS
+       jne     scroll1
+       or      dl,dl           ; at col. 0?
+       jne     goshowit
+; must simulate a BS
+       mov     dl,[mn_max_row_col]     ; move to EOL
+       mov     al,#0x0a        ; change to LF
+       dec     dh              ; back up first of two lines
+       jmp     scroll_set      ; set new cursor pos. & ring BEL
+
+scroll1:
+       cmp     al,#0x0a        ; test for LF / NL
+       jne     scroll2
+       cmp     dh,[mn_max_row_col+1]  ; bottom row
+       jae     scrollit
+scroll2:
+       cmp     al,#0x20        ; printing char?
+       jb      goshowit
+       cmp     dx,[mn_max_row_col]     ; bottom corner
+       jne     goshowit
+
+scrollit:
+       pusha
+       mov     ax,#0x601       ; scroll up 1 line
+       mov     bh,[mn_at_mono]
+       mov     cx,[abs_cx]
+       mov     dx,[mn_max_row_col]
+       int     0x10            ; do the scroll
+       popa
+scroll_set:
+       dec     dh
+       call    mn_setcursor    ; set cursor up 1 row
+goshowit:
+       pop     dx
+
+       pop     ds
+#endif
+#endif
+#ifndef LCF_NOVGA
+;;;    xor     bh,bh           ; display on screen
+       mov     bx,#7           ; set color for TEXT interface
+       mov     ah,#14
+       int     0x10
+#endif
+dispret:
+       pop     bx              ; restore BX
+       ret
+
+
+#ifndef LCF_NOSERIAL
+serdisp:push   dx              ; wait for space in the send buffer
+       seg     cs
+       mov     dx,slbase
+       or      dx,dx
+       jz      serret
+       add     dx,#5
+       push    ax
+serwait:in     al,dx
+       test    al,#0x10        ; break -> set break flag
+       jz      nobrk
+       seg     cs
+       mov     byte ptr break,#1
+nobrk: test    al,#0x20        ; ready to send ?
+       jz      serwait         ; no -> wait
+       sub     dx,#5           ; send the character
+       pop     ax
+       out     dx,al
+serret:        pop     dx              ; done
+       ret
+#endif
+
+! Get a key (CX = timeout exit)
+
+getkey: ;; BEG_FS
+;;     SEG_FS          ; set the timeout
+       mov     ax,par2_timeout         ;DSC_OFF-10+SSDIFF
+;;     END_FS
+       call    setto
+gwtkey:        mov     ah,#1           ; is a key pressed ?
+       int     0x16
+       jnz     gotkey          ; yes -> get it
+#ifndef LCF_NOSERIAL
+       mov     dx,slbase       ; using a serial port ?
+       or      dx,dx
+       jz      gnokey          ; no -> wait
+       add     dx,#5           ; character ready ?
+       in      al,dx
+       test    al,#1
+       jz      gnokey          ; no -> wait
+       sub     dx,#5           ; get it
+       in      al,dx
+       and     al,#0x7f        ; strip 8th bit
+       jnz     gotch           ; ignore NULs
+#endif
+gnokey:        
+#if defined(MENU) || defined(BITMAP)
+#ifdef BITMAP
+       cmp     byte [abs_cx+1],#0
+       je      no_timer_display
+#endif
+       call    timer_display
+no_timer_display:
+#endif
+       test    byte ptr timeout,#1 ; timed out ?
+       jz      gwtkey          ; no -> wait
+       pop     ax              ; discard return address
+       jmp     cx              ; jump to timeout handler
+gotkey:        xor     ah,ah           ; read a key
+       int     0x16
+       push    bx              ; keyboard translation (preserve BX)
+       mov     bx,#KEYTABLE
+       xlatb
+       pop     bx
+gotch:
+#ifdef LCF_ONE_SHOT
+       BEG_FS
+       SEG_FS          ; always enter prompt ?
+       test    byte ptr par1_prompt+SSDIFF,#FLAG_PROMPT
+       END_FS
+       jz      noosht          ; yes -> do not disable timeout
+#endif
+;                      disable timeout
+       test    byte ptr par2_flag2,#FLAG2_UNATTENDED
+       jnz     nocancel
+       mov     word ptr par2_timeout,#0xffff
+nocancel:
+noosht:
+       ret                     ; done
+
+! Shift wait loop (AX = timeout, returns CY set if interrupred)
+
+waitsh:        call    setto           ; set timeout
+actlp: mov     ah,#2           ; get shift keys
+       int     0x16
+#if defined(LCF_VIRTUAL) && DEBUG_NEW
+       and     al,#0x1f        ; anything set ? (except NumLock or CapsLock)
+#else
+       and     al,#0x5f        ; anything set ? (except NumLock)
+#endif
+       jnz     shpress         ; yes -> return with CY set
+; 22.7.1 begin
+       mov     ah,#1           ; get status
+       int     0x16
+       jnz     shpress         ; key pressed
+; 22.7.1 end
+#ifndef LCF_NOSERIAL
+       mov     dx,slbase       ; using a serial port ?
+       or      dx,dx
+       jz      acnosp          ; no -> go on
+       cmp     byte ptr break,#0 ; break received ?
+       jnz     shpress         ; yes -> return with CY set
+       add     dx,#5           ; check for pending break
+       in      al,dx
+       test    al,#0x10
+       jnz     shpress         ; break received -> return with CY set
+#endif
+acnosp:        test    byte ptr timeout,#1 ; timed out ?
+       jz      actlp           ; no -> wait
+       clc                     ; clear carry
+       ret                     ; done
+shpress:stc                    ; set carry
+       ret                     ; done
+
+! Timeout handling
+
+instto:        push    ds              ; install the timeout handler
+       push    #0
+       pop     ds
+
+       cli                     ; no interrupts
+       mov     eax,[0x1c*4]    ; get the old vector
+       seg     cs
+       mov     [int1c_l],eax   ; save H & L parts
+       mov     [0x1c*4],#tick  ; install new vector
+       mov     [0x1c*4+2],cs
+       sti                     ; done
+       pop     ds
+       ret
+
+remto: push    es              ; remove the interrupt handler
+       push    #0
+       pop     es
+
+       mov     eax,[int1c_l]   ; restore the old vector
+       seg     es
+       mov     [0x1c*4],eax    ; **
+       pop     es
+       ret
+
+! AX = ticks, 0xffff = no timeout
+
+setto: or      ax,ax           ; time out immediately ?
+       jz      toimmed         ; yes -> do it
+       cli                     ; set timeout value
+       mov     cntdown,ax
+       mov     byte ptr timeout,#0 ; clear timed-out flag
+       sti                     ; done
+       ret
+toimmed:mov    byte ptr timeout,#0xff ; set the timed-out flag
+       ret                     ; done
+
+tick:  pushf                   ; save flags
+       seg     cs              ; no timeout ?
+       cmp     word ptr cntdown,#0xffff
+       je      notzro          ; yes -> go on
+       seg     cs              ; decrement counter
+       dec     word ptr cntdown
+       jnz     notzro          ; not zero -> go on
+       seg     cs              ; set timeout flag
+       mov     byte ptr timeout,#0xff
+notzro:
+       seg     cs
+       push    dword [int1c_l]
+       iret                    ; continue with old interrupt
+
+kt_set:
+;;     BEG_FS
+;;     SEG_FS          ; load the keyboard translation table
+       mov     cx,par2_keytab          ;MSG_OFF+SSDIFF+7
+;;     SEG_FS
+       mov     dx,par2_keytab+2                ;MSG_OFF+SSDIFF+9
+;;     SEG_FS
+       mov     al,par2_keytab+4                ;MSG_OFF+SSDIFF+11
+;;     END_FS
+       mov     bx,#KEYTABLE
+       ret
+
+#ifndef LCF_READONLY
+
+! Sector write; used for the keytable only
+
+kt_write:
+       push    es
+       push    ds
+       pop     es
+       call    kt_set          ; set for KEYTABLE i/o
+
+       BEG_FS
+       SEG_FS          ; BIOS data collection worked before?
+       test    byte ptr par1_prompt+SSDIFF,#FLAG_BD_OKAY
+       END_FS
+       jnz     kt_nowrite
+
+       test    byte ptr [par2_flag2],#FLAG2_EL_TORITO  ; a CD?
+       jnz     kt_nowrite
+
+       call    cwrite
+kt_nowrite:
+       pop     es
+       ret
+
+! Sector write; used for the stored command line only
+
+cmd_write:     
+;BEG_FS
+;SEG_FS
+       mov     cx,mt_dflcmd+KEYTABLE+256
+;SEG_FS
+       mov     dx,mt_dflcmd+2+KEYTABLE+256
+;SEG_FS
+       mov     al,mt_dflcmd+4+KEYTABLE+256
+;END_FS
+; fall into cwrite
+;
+;  General sector write
+;
+cwrite:
+#ifdef FLAG_RAID_NOWRITE
+       BEG_FS
+       SEG_FS
+       test    byte ptr par1_prompt+SSDIFF,#FLAG_RAID_NOWRITE ; no writes?
+       END_FS
+       jnz     cwok            ; jump if no writing allowed
+#endif
+       BEG_FS
+       SEG_FS
+       test    byte ptr par1_prompt+SSDIFF,#FLAG_RAID  ; is it a RAID write
+       END_FS
+       jnz     cmd_raid_wrt
+
+        mov     byte ptr (dsk_wrflag),#WR_ENABLE      ; flag write operation
+        call    cread
+        mov     byte ptr (dsk_wrflag),#0        ; flag read operation
+
+       jnc     cwok            ; no error - return
+cnok:
+       pusha
+       cmp     ah,#3           ; write protect error
+       je      cnok3
+       push    ax              ; save error code in AH
+       mov     bx,#msg_wrerr
+       call    say
+       pop     ax
+       mov     al,ah           ; error code
+       call    bout
+       call    crlf            ; leave space
+       jmp     cnok5
+cnok3:
+       mov     bx,#msg_wrerr3  ; write protect
+       call    say
+cnok5:
+       popa
+        stc                     ; flag error  JRC
+cwok:
+#if DEBUG_NEW
+       pushf
+       call    pause
+       popf
+#endif
+       ret                     ; done
+
+cmd_raid_wrt:
+       test    dl,#RAID_REL_FLAG       ; relocation called for?
+       jnz     crw1
+       mov     ah,#0x99                ; flag error
+       jmp     cnok
+crw1:
+       push    si
+       mov     si,[rmask]              ; get raid physical device mask
+cwrm = LINEAR_FLAG|LBA32_FLAG|LBA32_NOCOUNT|RAID_REL_FLAG|0X80
+       and     dl,#cwrm                ; save flags, set device to 80
+
+cwr2:  shr     si,#1
+       jnc     cwr3
+       pusha
+        mov     byte ptr (dsk_wrflag),#WR_ENABLE      ; flag write operation
+        call    cread_physical         ; read the PHYSICAL device #
+        mov     byte ptr (dsk_wrflag),#0        ; flag read operation
+       popa
+
+cwr3:  inc     dx
+       or      si,si           ; clears the carry
+       jnz     cwr2
+
+       pop     si
+;;;    clc                     ; signal no error
+       jmp     cwok
+
+cwr_cnt:       .byte   0       ; device code count
+cwr_flags:     .byte   0       ; saved flags
+
+#endif
+
+kt_read:               ; KEYTABLE read
+       call    kt_set          ; set for KEYTABLE i/o
+       call    cread
+       jc      keyerr
+       mov     si,#KEYTABLE    ; compute a checksum of the keytable
+       mov     di,#SECTOR_SIZE - 8     ; skip the last 4+4 bytes
+       push    dword #CRC_POLY1
+       call    crc32
+       add     di,si
+       cmp     eax,dword (di)
+       jz      nokeyerr
+
+! Checksum error
+keyerr:
+       mov     bx,#msg_chkkey
+       br      zz              ; go wait
+nokeyerr:
+       ret
+
+! Sector read
+!  enter with AL, CX, DX, ES, BX set for read
+!  trashes CX and DI
+!
+cread:                 ; entry point for mapped device r/w
+       call    map_device      ; DL (logical) -> DL (physical)
+
+cread_physical:                ; same entry, device is not mapped
+
+        test    dl,#LINEAR_FLAG|LBA32_FLAG
+        jnz     use_linear
+
+        push    ax              ;save the count
+       mov     ah,#2           ;read command
+        call    dsk_do_rw       ; int 0x13 with retries
+        pop     cx              ;Carry Set means error on read
+        mov     al,cl           ;count in AL, error code in AH
+        ret
+
+use_linear:
+        mov     ah,hinib        ;will be zero for LINEAR
+        xchg    al,dh           ;AX is possible address 
+       test    dl,#LBA32_FLAG  ;test for LBA32/LINEAR  *****
+       jz      lnread          ;pure LINEAR            *****
+        test    dl,#LBA32_NOCOUNT
+        jz      lnread
+        mov     ah,dh           ;former count is really hi-nibble
+        mov     hinib,ah
+        mov     dh,#1           ;set count to 1
+lnread:
+        xchg    di,ax           ;hi-address to DI
+        mov     al,dh           ;count to AL
+
+       test    dl,#RAID_REL_FLAG               ; ******
+       jz      ln_do_read                      ; ******
+
+       call    translate               ; in volume.S
+
+ln_do_read:
+        call    lba_read
+        mov     al,cl           ;count returned in AL, error code in AH
+        ret                     ;Carry Set means error on read
+
+#ifdef LCF_VIRTUAL
+; vmtest -- return Carry=1 if in virtual (VMware) mode
+;          return Carry=0 if in real mode
+;
+vmtest:
+#ifndef LCF_SUSPEND
+       pushad                  ; save all extended registers
+       smsw    ax
+       rcr     al,1            ; PE bit in AL to Carry
+       jc      vm_ret          ; exit if virtual mode
+#if DEBUG_NEW
+       mov     ah,#2           ; get keyboard flags
+       int     0x16
+       and     al,#0x50        ; Caps, Scroll Lock flags
+       cmp     al,#0x40
+       je      vm_vir          ; Caps only means virtual boot simulated
+#endif
+;
+;  If no vmdefault, vmdisable, or vmwarn keywords were used, then we do not
+;  care about virtual mode.  Do not touch the hardware, and always return
+;  Carry=0.
+;
+       test    byte ptr [par2_flag2],#FLAG2_VIRTUAL    ; any vmXXX keywords?
+       jz      vm_ret          ; TEST clears the carry, always
+;
+;  VMware(R) test for virtual mode
+;
+       mov     eax,#0x564D5868 ; EAX: in = 'VMXh'   out = version
+       xor     ebx,ebx         ; EBX:               out = 'VMXh' under vmware
+       mov     edi,eax
+       mov     dx,#0x5658      ;  DX: in = 'VX'
+       mov     ecx,#10         ; ECX: in = VMXGetVersion
+       in      eax,dx
+       cmp     ebx,edi         ; test for vmware
+       clc                     ; NOT vmware if Carry==0
+       jne     vm_ret          ; not vmware
+
+       inc     eax             ; carry is not affected by INC
+       jz      vm_ret          ; invalid version number == 0xFFFFFFFF
+
+vm_vir:
+       stc                     ; signal virtual mode
+
+vm_ret:        popad           ; restore all the extended registers
+       ret
+
+#else  /* LCF_SUSPEND changes the interpretation of "virtual" */
+       pusha
+       push    es
+       test    byte ptr [vm_cache],#0xFF       ; test cached value
+       jnz     vm_ret
+
+       mov     byte ptr [vm_cache],#2          ; not virtual
+
+       push    ds
+       pop     es              ; ES:BX
+       mov     bx,#MAP         ; use this buffer
+       mov     cx,#1           ; sector 1
+       mov     dx,#0x80        ; dos C: drive
+       mov     al,cl           ; 1 sector
+       call    cread           ;
+       jc      vm_ret          ; not virtual if error
+
+       mov     cx,#PARTITION_ENTRIES           ; count 4 PT entries
+       lea     bx,[PART_TABLE_OFFSET](bx)      ; first partition entry
+vm_pt1:
+       test    byte ptr (bx),#0x80             ; active
+       jz      vm_pt2
+       cmp     byte ptr (bx+4),#LCF_SUSPEND    ; suspend partition
+       jne     vm_pt2
+       mov     byte ptr [vm_cache],#1          ; suspend is active
+vm_pt2:
+       lea     bx,[PARTITION_ENTRY](bx)        ; bump pointer
+       loop    vm_pt1
+
+vm_ret:
+       mov     al,[vm_cache]           ; get cached value
+       shr     al,#1
+       pop     es
+       popa
+       ret
+
+vm_cache:
+       .byte   0               ; 0=unknown, 1=virtual, 2=non-virtual
+
+#endif /* LCF_SUSPEND */
+#endif /* LCF_VIRTUAL */
+
+
+#if LCF_NOKEYBOARD
+; kbtest -- return Carry=1 if IBM PC/AT keyboard is present
+;       -- return Carry=0 if no IBM keyboard is present
+;
+kbtest:
+       push    ax
+;
+;  If neither nokbdefault nor nokbdisable was used, we do not touch
+;  the keyboard hardware.  Always report Carry=1 (keyboard present).
+;
+       test    byte ptr [par2_flag2],#FLAG2_NOKBD
+       jz      kbtest8
+
+#if DEBUG_NEW
+       pusha
+       mov     bx,#msg_kbtest
+       call    say             ; tell about keyboard test
+       popa
+#endif
+    /* mardy */
+       cli                     ; added 5/17/2006
+       mov     al,#0xee        ; echo command
+       out     #0x60,al
+wait_kbd_ctrl_ready:
+       in      al,#0x64
+       and     al,#0x01
+       jz      wait_kbd_ctrl_ready  ; read status port while it is not ready
+       in      al,#0x60
+       sti                     ; added 5/17/2006
+       xor     al,#0xee        ; XOR clears the carry
+       jne     kbtest9
+               ; if we got the same byte, the keyboard is attached
+    /* mardy */
+#if DEBUG_NEW
+       mov     ah,#2           ; get keyboard flags
+       int     0x16
+       and     al,#0x20        ; Num Lock flag
+       jz      kbtest9         ; AND cleared the carry
+#endif
+kbtest8:
+       stc             ; flag keyboard present
+kbtest9:
+       pop     ax
+       ret
+#endif /* LCF_NOKEYBOARD */
+
+
+#if 1
+; crc32 -- calculate CRC-32 checksum
+;
+;      call:
+;              push    dword #POLYNOMIAL
+;
+;              ES:SI   char string pointer
+;              DI      count of characters
+;
+;              call    crc32
+;
+;    CRC-32 is returned in EAX  or  DX:AX
+;              the arguments are popped from the stack
+;
+crc32:
+               push    bp
+               mov     bp,sp
+
+               push    si
+               push    di
+               push    bx
+               push    cx
+
+               xor     eax,eax         ; initialize CRC
+               dec     eax             ; EAX = 0xFFFFFFFF
+               inc     di
+crc32a:
+               dec     di
+               jz      crc32d
+               mov     cx,#8           ; count 8 bits
+               seg es
+               mov     bl,(si)         ; get next character
+               inc     si
+crc32b:                shl     bx,#1           ; get hi bit of char in BH
+               shl     eax,#1          ; shift hi bit out of CRC
+               adc     bh,#0           ; add carry to BH
+               shr     bh,#1           ; put bit in carry
+               jnc     crc32c          ; skip the xor
+               xor     eax,(bp+4)      ; xor in the polynomial
+crc32c:
+               loop    crc32b          ; loop back for 8 bits
+               jmp     crc32a
+
+crc32d:                
+               not     eax             ; finialize CRC
+
+               pop     cx
+               pop     bx
+               pop     di
+               pop     si
+               
+               leave
+               ret     4
+#endif
+/* ifdef HIGHMEM_MAX */
+; enter with BX == Ramdisk size (in 4k pages)
+;
+rd_setup:
+       push    bx              ; save Ramdisk size in pages
+       mov     eax,[hma]       ; user specified?
+       or      eax,eax
+#ifdef LCF_INITRDLOW
+       jnz     rd_have_hma
+#else          /* ifndef LCF_INITRDLOW */
+       jnz     near rd_have_hma
+       BEG_FS
+       SEG_FS
+       test    byte ptr par1_prompt+SSDIFF,#FLAG_LARGEMEM
+       END_FS
+       jz      near no_e801
+
+; try the E820 memory map first
+       xor     edx,edx                 ; flag nothing found
+       xor     esi,esi                 ; flag size==0
+       xor     ebx,ebx
+       ;jmp    e8go                    ; circumvented due to BIOS problems
+       br      no_e801                 ; skip to backup plan
+e8go2: or      ebx,ebx                 ; test for end
+       jz      e8go5
+e8go:  push    edx                     ; save best prospect
+       mov     eax,#0xe820
+       mov     edx,#0x534d4150 ;'SMAP'
+       mov     ecx,#20
+       mov     di,#memmap
+       int     0x15                    ; get memory map
+       pop     edx                     ; restore what we have found so far
+       jc      no_e820
+       cmp     eax,#0x534d4150 ;'SMAP'
+       jne     no_e820
+       cmp     ecx,#20
+       jne     no_e820
+#if 0
+       mov     eax,memmap      ; get start
+       mov     ecx,memmap+4    ; get high part
+       cmp     word memmap+16,#1       ; available?
+       jne     e8no1                   ; go on to next
+       or      ecx,ecx
+       jnz     e8go2
+       cmp     eax,#0x100000   ; compare to 1Mb
+       ja      e8go2
+       add     eax,memmap+8    ; get final address
+       adc     ecx,memmap+12   ;
+       shrd    eax,ecx,#10     ; convert to 1k blocks (legacy)
+       cmp     eax,#4*1024     ; compare to 4Mb
+       jb      no_e820
+       xchg    eax,edx         ; save in edx
+       jmp     e8go2
+
+e8no1: shrd    eax,ecx,#10     ; convert to 1k blocks
+       cmp     eax,#1024       ; compare to 1Mb
+       jb      e8go2           ; loop if too small
+       cmp     eax,edx         ; check against HMA
+       jae     e8go2
+       xchg    eax,edx         ; compensate for buggy BIOS
+       jmp     e8go2           ; remember in EDX & loop
+#else
+       cmp     word memmap+16,#1       ; available?
+       jne     e8go2
+       mov     eax,memmap+4    ; hi part of start
+       shrd    memmap,eax,#10  ; convert start to 1k
+       mov     eax,memmap+12   ; hi part of size
+       shrd    memmap+8,eax,#10 ; convert to 1k
+       cmp     dword memmap,#1024      ; below 1M
+       jb      e8go2           ; below 1M, no interest
+       cmp     esi,memmap+8    ; check size
+       ja      e8go2           ; want largest
+       mov     edx,memmap      ; start (in 1k)
+       mov     esi,memmap+8    ; size (in 1k)
+       add     edx,esi         ; HMA in 1k
+       jmp     e8go2
+#endif
+e8go5: or      edx,edx         ; find anything?
+       jz      no_e820
+       xchg    eax,edx
+       jmp     rd_have_hma
+no_e820:
+; above failed, try the older E801 block count interface
+       xor     cx,cx           ; some BIOSs are buggy
+       xor     dx,dx
+       mov     ax,#0xe801      ; call
+       stc
+       int     0x15
+       jc      no_e801
+       or      cx,cx
+       jz      e801cx
+       mov     ax,cx
+e801cx:        or      dx,dx
+       jz      e801dx
+       mov     bx,dx
+e801dx:        
+       movzx   ebx,bx
+       movzx   eax,ax
+       shl     ebx,#6          ; convert 64k to 1k
+       mov     ecx,#16*1024
+       cmp     eax,ebx         ; compare sizes
+       ja      e801eax
+       add     ebx,ecx         ; add in 16M
+       mov     eax,ebx         ; and use this value
+       jmp     rd_have_hma
+e801eax:
+       add     eax,#1024       ; add 1M
+       cmp     eax,ecx         ; is it 16M
+       jne     rd_have_hma
+       add     eax,ebx         ; add in ebx
+       jmp     rd_have_hma
+#endif /* ifndef LCF_INITRDLOW */
+no_e801:
+; above two methods failed, try the old 0x88 function
+       mov     ah,#0x88        ; get count of extended memory blocks
+       int     0x15
+       movzx   eax,ax          ; extend to dword
+       add     eax,#1024       ; add in base 1M
+;
+rd_have_hma:   ; have the HMA / 1k in EAX
+#if DEBUG_NEW
+       push    eax
+       shl     eax,10          ; convert to address
+       push    eax
+       call    crlf
+       call    dout            ; pops its argument
+       mov     bx,#msg_hma
+       call    say
+       pop     eax
+#endif
+       mov     ebx,#15*1024    ; 15Mb
+       cmp     eax,ebx         ; compare to 15M
+       jbe     rd_use_eax      ; use lower value
+       BEG_FS
+       SEG_FS
+       test    byte ptr par1_prompt+SSDIFF,#FLAG_LARGEMEM
+       END_FS
+       jnz     large_okay
+       xchg    eax,ebx         ; limit to 15Mb
+large_okay:
+       mov     ebx,#HIGHMEM_MAX/1024
+#ifdef NEW3_HDR_VERSION
+       push    ds
+       mov     ds,[initseg]    ; load the original boot sector
+       cmp     word ptr [CL_HDRS_VERSION],#NEW3_HDR_VERSION
+       jb      not203
+       mov     ebx,[CL_RAMDISK_MAX]
+#if DEBUG_NEW
+       pop     cx
+       push    cx
+       mov     ds,cx
+       pushad
+       push    ebx
+       mov     bx,#hdr3
+       call    say
+       call    dout
+       call    crlf
+       popad
+#endif
+       dec     ebx
+       shr     ebx,#10         ; divide by 1024
+       inc     ebx
+not203:
+       pop     ds
+#endif /* ifdef NEW3_HDR_VERSION */
+       cmp     eax,ebx
+       jb      rd_use_eax
+;;;rd_use_smaller:
+       xchg    eax,ebx         ; must use the smaller
+rd_use_eax:
+       pop     bx              ; get size in pages
+       shr     eax,2           ; convert to pages
+       movzx   ebx,bx          ; zero high part of size
+       sub     eax,ebx         ; start address of ramdisk to EAX
+#if DEBUG_INITRD
+       cmp     dword ptr [hma],#0x180000/1024 ; 1.5Mb
+       jb      drd_use_eax
+       cmp     dword ptr [hma],#0xF00000/1024  ; 15Mb
+       jae     drd_use_eax
+       mov     eax,[hma]       ; HMA is initrd start
+       shr     eax,2
+drd_use_eax:
+#endif
+#if 0
+       cmp     eax,#256        ; we probably need more than 1M for the
+       ja      rd_okay         ;   kernel to be useful ...
+       mov     bx,#msg_rd      ; complain
+;;;    call    say             ; is at zz
+       br      zz              ; and halt 
+#else
+       cmp     eax,#4*256      ; Ramdisk loaded below 4Mb
+       jae     rd_okay         ;   kernel to be useful ...
+       mov     bx,#msg_rd4M    ; complain
+       call    say             ; is at zz
+#endif
+rd_okay:
+       shl     eax,4           ; shift (12-8) -> 4
+       mov     [rdbeg+1],ax    ; set up beginning address
+       mov     [gdt+0x1b],ax   ; set the GDT for the moves
+       shr     eax,16          ; get hi-byte of address
+       mov     [rdbeg+3],al    ; set rest of address
+       mov     [gdt+0x1f],al   ; and in the GDT, too
+       ret
+/* endif / ifdef HIGHMEM_MAX */
+
+
+/* enter with SI pointing to DESCRIPTOR 
+       DS = CS
+       ES unknown
+       SI - points at the descriptor
+*/
+load_initrd:
+       push    [map]
+       push    [moff]
+       mov     word ptr [map],#MAP2
+       push    ds
+       pop     es
+       mov     ax,(si+id_flags)        ; get FLAG_TOOBIG, if any
+#if FLAG_LARGEMEM!=FLAG_TOOBIG
+# error "FLAG_LARGEMEM and FLAG_TOOBIG must be equal"
+#endif
+       and     al,#FLAG_TOOBIG         ; separate flag
+       BEG_FS
+       SEG_FS
+       or      byte ptr par1_prompt+SSDIFF, al ; set FLAG_LARGEMEM
+       END_FS
+       add     si,#id_rd_size  ; point at ramdisk size long
+! take care of the RAM disk first
+       xor     eax,eax
+       mov     (rdbeg),eax     ; clear address
+       lodsd
+       mov     (rdszl),eax     ; set rdszl+rdszh
+       add     eax,#4095       ; round up &
+       shr     eax,#12         ; convert to pages
+       xchg    bx,ax           ; copy to BX
+       lodsw                   ; address of the first map sector
+       xchg    cx,ax
+       lodsw
+       xchg    dx,ax
+        lodsb                   
+       or      bx,bx           ; no RAM disk ?
+       jz      noramd          ; yes -> skip it 2
+
+       push    si              ; save SI, ES, and BX (RD size)
+       push    es
+       push    bx
+       mov     bx,[map]                ; load the first map sector
+       call    sread
+       mov     moff,#0
+#ifdef DEBUG
+       mov bx,#stepa
+       call say
+#endif
+/* ifdef HIGHMEM_MAX */
+       pop     bx
+       call    rd_setup
+/* endif */
+       cmp     dword ptr (rdbeg),#0
+       je      nordpt          ; no -> no need to patch header for that
+; setrdp:
+#if DEBUG_NEW
+       push    dword (rdbeg)   ; print RAM disk address
+       mov     bx,#msg_rd2
+       call    say
+       call    dout
+       call    crlf
+#endif
+       mov     es,[setupseg]   ; load the setup codes
+       mov     eax,(rdbeg)     ; get RAM disk start address
+       seg     es
+       mov     (24),eax        ; store in header
+       mov     eax,rdszl
+       seg     es
+       mov     (28),eax        ; set RAM disk size
+nordpt:        
+       push    #0              ; ES=0 is our secret code to load via GDT
+       pop     es
+       mov     bx,#gdt
+       call    lfile           ; load it
+#if 1
+       mov     al,#0x20        ; print a space
+       call    display
+#endif
+       pop     es              ; restore ES and SI
+       pop     si
+noramd:
+       pop     [moff]
+       pop     [map]
+       ret
+
+#ifndef LCF_NOSERIAL
+serLI: .byte   13,10,0x4c,0x49         ; cr,lf,"LI"
+
+BAUD_BASE = 115200                     ; divisor == 1
+divisor:
+       .byte   BAUD_BASE / 19200       ; must be same as bsect.c table
+       .byte   BAUD_BASE / 38400
+       .byte   BAUD_BASE / 57600
+       .byte   BAUD_BASE / 115200
+       .byte   BAUD_BASE / 2400
+       .byte   BAUD_BASE / 2400
+       .byte   BAUD_BASE / 2400
+       .byte   BAUD_BASE / 2400
+
+; serial_setup -- do the setup for the serial line communications
+;
+;      No registers are saved
+;
+serial_setup:
+;;     BEG_FS
+;;     SEG_FS
+       mov     dx,par2_port    ; use a COM port ?
+                       ; watch out, loads par2_ser_param
+;;     END_FS
+       dec     dl
+       js      nocom           ; no -> go on
+       xor     ax,ax           ; initialize the serial port
+       xchg    al,dh
+
+       push    ax
+       push    dx
+
+;;;    or      al,#0x06        ; stop bits = 2, nbits = 7 or 8
+                               ; this OR is not needed yet (21.7)
+       int     0x14            ; Communications Port INIT
+
+       push    #0x40
+       pop     ds
+
+       pop     bx              ; was DX
+
+       shl     bx,#1
+       mov     dx,(bx)         ; get the port address from the BIOS
+
+       seg     cs              ; keep it
+       mov     slbase,dx
+
+       pop     bx              ; special baud rate test -- was AX
+
+       test    bl,#0x04                ; stop bits == 2?
+       cli                     ; do not disturb any code below
+       jz      stdbps          ; standard BPS
+
+       shr     bx,#5           ; index divisor array
+       seg     cs
+       mov     bl,divisor(bx)
+
+spcbps:                                ; CLI: do not disturb ...
+       push    dx              ; save base address
+       add     dx,#3           ; enable divisor latch access
+       in      al,dx
+       or      al,#0x80
+       out     dx,al
+       pop     dx              ; set new divisor
+       push    dx
+       xchg    ax,bx
+       out     dx,al
+       inc     dx
+       mov     al,ah
+       out     dx,al
+       inc     dx              ; disable divisor latch access
+       inc     dx
+       xchg    ax,bx
+       and     al,#0x7f
+       out     dx,al
+       pop     dx              ; restore base address
+
+stdbps:                        ; CLI: redundant if fell in from above
+       push    dx
+       add     dx,#4           ; address Modem Control Reg.
+#if 0
+       in      al,dx
+       or      al,#3           ; turn on DTR and RTS
+#else
+       mov     al,#3           ; turn on DTR and RTS
+#endif
+       out     dx,al
+       pop     dx
+       sti                     ; done
+       
+       mov     cx,#32          ; drain the queue (if any)
+drain: in      al,dx
+       loop    drain
+       add     dx,#5           ; clear the status register
+       in      al,dx
+
+    ; send "\r\nLI" to the serial port
+
+       mov     si,#serLI
+       mov     cx,#4
+ser1:  seg     cs
+       lodsb
+       call    serdisp
+       loop    ser1
+
+nocom:
+       ret
+
+#endif         /* LCF_NOSERIAL */
+
+
+
+#ifdef SHS_PASSWORDS
+#include "shs3.S"
+#endif
+#include "read.S"
+#include "volume.S"
+#define SECOND_STAGE_LOADER
+#include "mapper.S"
+#undef SECOND_STAGE_LOADER
+#ifdef LCF_BDATA
+#include "bdata.h"
+#include "biosdata.S"
+#endif
+#if defined(MENU) || defined(BITMAP) || DEBUG_NEW
+#include "strlen.S"
+#endif
+#ifdef MENU
+#include "graph.S"
+#include "menu.S"
+#include "crt.S"
+#endif
+#ifdef BITMAP
+#include "bitmap.S"
+#include "vesainfo.h"
+#include "display4.S"
+#endif
+
+! Put tokens into keyboard buffer
+
+putkbd:        add     si,#4           ; skip over "kbd="
+       push    es
+       xor     ax,ax           ; set ES to zero
+       mov     es,ax
+pknext:        lodsb                   ; get next byte
+       or      al,al           ; NUL ?
+       jz      pkdone          ; yes -> done
+       cmp     al,#32          ; blank ?
+       jne     pkrd            ; no -> read scan code
+pkdone:        dec     si              ; return last character
+       pop     es              ; done
+       ret
+pkrd:  xor     cx,cx           ; clear accumulator
+pkrdlp:        cmp     al,#97          ; lower case character ?
+       jb      pknol           ; no -> go on
+       sub     al,#32          ; make upper case
+pknol: sub     al,#48          ; normalize
+       cmp     al,#10          ; >"9" ?
+       jb      pkok            ; no -> okay
+       cmp     al,#17          ; <"A" ?
+       jb      pksyn           ; yes -> syntax error
+       sub     al,#7           ; adjust
+       cmp     al,#16          ; >"F" ?
+       jae     pksyn           ; yes -> syntax error
+pkok:  shl     cx,1            ; shift CX
+       jc      pksyn           ; carry means trouble
+       shl     cx,1
+       jc      pksyn
+       shl     cx,1
+       jc      pksyn
+       shl     cx,1
+       jc      pksyn
+       add     cl,al           ; put in lowest nibble
+       lodsb                   ; get next byte
+       or      al,al           ; NUL ?
+       jz      pkend           ; yes -> at end
+       cmp     al,#32          ; space ?
+       je      pkend           ; yes -> at end
+       cmp     al,#44          ; comma ?
+       je      pkmore          ; yes -> end of token
+       jmp     pkrdlp          ; token continues
+pksyn: mov     bx,#msg_pks     ; complain
+       call    say
+pkfls: lodsb                   ; flush to end of option
+       or      al,al
+       jz      pkdone
+       cmp     al,#32
+       je      pkdone
+       jmp     pkfls
+pkend: call    pkput           ; store token
+       jmp     pkdone          ; ... and return
+pkmore:        call    pkput           ; store token
+       jmp     pknext          ; handle next token
+pkput: seg     es              ; get buffer pointer
+       mov     bx,[KBEND]
+       mov     dx,bx
+       add     dx,#2           ; increment it
+       cmp     dx,#KBHIGH      ; (wrap around end)
+       jb      pknadj
+       mov     dx,#KBLOW
+pknadj: seg    es              ; buffer full ?
+       cmp     dx,[KBBEG]
+       je      pkfull          ; yes -> error
+       seg     es              ; store scan code
+       mov     (bx+0x400),cx
+       seg     es              ; store new pointer
+       mov     [KBEND],dx
+       ret                     ; done
+pkfull:        mov     bx,#msg_pkf     ; complain
+       call    say
+       pop     ax              ; discard return address
+       jmp     pkfls           ; abort
+
+! Set VGA mode
+
+setvga:        add     si,#4           ; skip over "vga="
+       push    si              ; save SI
+       mov     bx,#vgatab      ; scan VGA table
+svgatb:        pop     si              ; get pointer to option value
+       push    si
+       mov     cx,(bx)         ; get VGA code
+       or      cx,cx           ; at end ?
+       jz      vganum          ; yes -> must be numeric
+       inc     bx              ; compare the strings
+       inc     bx
+vgacmp:        lodsb
+       call    upcase          ; (case-insensitive)
+       mov     ah,(bx)
+       inc     bx
+       or      ah,ah           ; at end ?
+       jnz     vgamore         ; no -> go on
+       or      al,al           ; at end of line ?
+       jz      vgafnd          ; yes -> found it
+       cmp     al,#32          ; space ?
+       je      vgafnd          ; yes -> found it
+       jmp     svgatb          ; try next entry otherwise
+vgamore:cmp    al,ah
+       je      vgacmp          ; equal -> next character
+vgaskp:        mov     al,(bx)         ; skip to end of reference string
+       inc     bx
+       or      al,al
+       jnz     vgaskp
+       jmp     svgatb          ; try next entry
+vgafnd:        pop     ax              ; drop SI
+
+vgaput:        dec     si              ; read last character again
+vgaput1: mov   vgaovr,cx       ; set VGA mode
+       clc                     ; okay, done
+       ret
+
+vganum:        pop     si              ; get SI
+#if 1
+       call    strtoul
+       jc      vgaerr
+       mov     cx,ax
+       or      dx,dx
+       jnz     vgaerr
+       jmp     vgaput1
+#else
+       xor     cx,cx
+       mov     ah,cl
+       test    byte ptr (si),#0xff ; no value ?
+       jz      vgaerr          ; yes -> error
+vgadig:        lodsb                   ; get the next character
+       or      al,al           ; at end ?
+       jz      vgaput          ; yes -> done
+       cmp     al,#32
+       je      vgaput
+       cmp     al,#48          ; is it a digit ?  (0x30=48="0")
+       jb      vgaerr          ; no -> error
+       cmp     al,#57          ; 57=0x39="9"
+       ja      vgaerr
+       sub     al,#48          ; cx = cx*10+al-'0'
+       imul    cx,#10
+       add     cx,ax
+       jnc     vgadig          ; next one
+#endif
+
+vgaerr:        mov     bx,#msg_v       ; display an error message
+       call    say
+/* ifdef HIGHMEM_MAX */
+       xor     eax,eax
+       mov     dword ptr [hma],eax
+/* endif */
+       stc                     ; return an error
+       ret
+
+vgatab:
+#ifdef NORMAL_VGA
+       .word   ASK_VGA
+       .ascii  "ASK"
+       .byte   0
+       .word   EXTENDED_VGA
+       .ascii  "EXTENDED"
+       .byte   0
+       .word   EXTENDED_VGA
+       .ascii  "EXT"
+       .byte   0
+       .word   NORMAL_VGA
+       .ascii  "NORMAL"
+       .byte   0
+#endif
+       .word   0
+
+
+! get numeric string suffixed with "KkMmGg"
+! updates SI
+
+get_K:
+       push    cx              ; save CX
+
+       call    strtoull        ; get number in DX:AX
+       jc      gmthis2         ; signal conversion error
+
+       mov     bl,(si)         ; get next character
+       or      bl,#0x20        ; convert to lower case
+       cmp     bl,#0x6b        ; 'K' or 'k' ?
+       je      gmthis          ; yes -> do not change
+#if 1
+       mov     cx,#20          ; divide or multiply by 2^20
+       cmp     bl,#0x67        ; 'G' or 'g' ?
+       je      gmmul
+#endif
+       mov     cx,#10          ; divide or multiply by 2^10
+       cmp     bl,#0x6d        ; 'M' or 'm' ?
+       je      gmmul
+
+! no Suffix
+       dec     si              ; will increment later
+       
+gmdivl:
+       shr     eax,cl          ; shift by CL
+       jmp     gmthis          ; done
+gmmul:
+gmmull:
+       shl     eax,1           ; shift by 1 each time
+       jc      gmvbig          ; very big if overflow
+       loop    gmmull          ; ten times
+
+! exit with no error
+
+gmthis:
+       inc     si
+       clc                     ; signal no error
+gmthis2:
+       mov     bl,(si)         ; next character to BL
+#if 0
+       jc      gmdebug1
+       pushad
+       push    eax
+       call    dout
+       mov     bx,#msg_gk
+       call    say
+       popad
+gmdebug1:
+#endif
+       pop     cx              ; restore register
+       ret
+
+gmvbig:
+       mov     eax,#HIGHMEM_MAX/1024
+       jmp     gmthis
+
+
+! Set memory limit
+
+getmem:
+       push    si              ; save SI for copying
+       add     si,#4           ; advance to number?
+       call    get_K
+       jc      gmcopy          ; error, just copy it
+
+       cmp     bl,#0x40        ; is it '@'
+       jne     gm22
+! <size>@<start> format (2.4 kernels)
+       push    eax             ; save size
+       inc     si              ; skip '@'
+       call    get_K
+       pop     edx             ; restore size
+       jc      memerr
+       cmp     eax,#1024       ; start : 1meg
+       ja      gmcopy          ; just copy if above
+       add     eax,edx         ; EAX = hma/1024
+       cmp     eax,#2048       ; high : 2meg
+       jbe     gmcopy
+gm22:
+       or      bl,#0x20
+       cmp     bl,#0x20        ; NUL or SPACE
+#if 0
+       jne     memerr
+#else
+       jne     gmcopy          ; allow <size>#<start> and <size>$<start>
+#endif
+       cmp     dword ptr [hma],#0      ; set already?
+       jne     gmnocopy
+       mov     dword ptr [hma],eax     ; set it        
+gmcopy:        pop     si
+gmret: ret
+gmnocopy:  pop bx
+       ret
+
+
+memerr:
+       mov     bx,#msg_me      ; numeric conversion error
+       call    say
+       br      restrt
+
+strtoull:                      ; numeric conversion to EAX
+       call    strtoul
+       push    dx
+       push    ax
+       pop     eax
+       ret
+
+strtoul:          /* string to unsigned long in DX:AX */
+       xor     ax,ax
+       xor     dx,dx
+       mov     cx,#10          ; default radix is decimal
+       cmp     byte ptr (si),#0x39
+       ja      s2lbad          ; error if > '9'
+       cmp     byte ptr (si),#0x30        ; == '0'?
+       jb      s2lbad          ; error if < '0'
+       jne     s2lnext
+       inc     si
+       dec     cx
+       dec     cx              ; assume octal : CX = 8
+       
+       cmp     byte ptr (si),#0x58        ; == 'X'?
+       je      s2lhex
+       cmp     byte ptr (si),#0x78        ; == 'x'?
+       jne     s2lnext
+s2lhex: add    cx,cx           ; it is hexadecimal
+       inc     si
+s2lnext:
+        xor     bx,bx
+        mov     bl,(si)         ; get next character
+
+       or      bl,#0x20        ; convert to lower case
+       sub     bl,#0x30        ; - '0'
+       jb      s2ldone
+       cmp     bl,cl           ; compare to radix
+       jb      s2lmul
+       add     bl,#0x30-0x61+10
+       cmp     bl,cl           ; compare to radix
+       jnb     s2ldone
+s2lmul:
+        push    dx              ; save high order
+       mul     cx              ; multiply by radix
+       add     ax,bx
+       adc     dx,#0           ; carry possible only in radix 10
+       pop     bx
+       push    dx
+       xchg    ax,bx
+       mul     cx
+       or      dx,dx
+       jnz     s2lbad
+       pop     dx
+       add     dx,ax
+       jc      s2lbad
+       xchg    ax,bx
+       inc     si
+       jmp     s2lnext
+
+s2lbad:        
+       stc
+       ret
+       
+s2ldone:
+       clc 
+       ret
+
+/* new 22.7 */
+; find_image
+;      if there is something on the command line
+;      return the image number it selects
+;
+;      enter with:
+;              nothing
+;      exit with:
+;              If nothing selected:
+;                  Carry Clear
+;                  AX==0
+;              If an image is selected:
+;              (fuzzy selection or exact selection)
+;                  Carry SET
+;                  AX==#image
+;                  BX==pointer to descriptor
+;                  
+;
+;      side effect:
+;              The selected image is hi-lited if the menu is displayed
+;
+find_image:
+       push    cx
+       push    si
+       push    di
+       
+       mov     cx,#IMAGES      ; test all names
+       mov     si,#DESCR0
+       xor     bx,bx           ; clear BX
+       push    si
+
+fi_nextn:
+       mov     di,#cmdline
+       test    byte ptr (si),#0xFF     ; null descriptor at end
+       jz      fi_nomore
+
+fi_nextc:
+       mov     al,(si)         ; get next character in descr
+       inc     si
+#ifdef LCF_IGNORECASE
+       call    upcase
+#endif
+       mov     ah,al
+       mov     al,(di)         ; get next char in cmdline
+       inc     di
+#ifdef LCF_IGNORECASE
+       call    upcase
+#endif
+       or      al,al           ; NUL in command line
+       je      fi_pmat
+       cmp     al,#32          ; SPACE in command line
+       jne     fi_cmp
+
+; have partial match, set BX conditionally
+fi_pmat:
+       or      ah,ah           ; NUL in descriptor name
+       jz      fi_found        ; EXACT match found
+
+       test    byte ptr par2_flag2,#FLAG2_UNATTENDED   ; (22.7)
+       jnz     fi_skipn        ; no partial match if unattended
+
+       or      bx,bx
+       jnz     fi_skipn        ; already set
+       pop     bx
+       push    bx
+       jmp     fi_skipn        ; go to next
+
+fi_cmp:
+       cmp     al,ah           ; character equal ?
+       je      fi_nextc        ; compare next character
+
+; advance to next descriptor
+fi_skipn:
+       pop     si
+       add     si,#id_size     ; test next name
+       push    si
+       loop    fi_nextn
+
+fi_nomore:
+       pop     si
+       or      bx,bx           ; fuzzy match?
+       jnz     fi_fuzzy
+
+#if defined(MENU) || defined(BITMAP)
+       mov     ax,[dimage]
+       call    lowlite         ; no match, nothing hi-lited
+;;;    mov     word [dimage],#0
+#endif
+       xor     ax,ax           ; clears the carry
+fi_exit:
+       pop     di
+       pop     si
+       pop     cx
+       ret
+       
+fi_found:
+       pop     bx              ; BX is matched descriptor
+fi_fuzzy:
+       mov     ax,bx
+       sub     ax,#DESCR0
+       mov     cl,#id_size
+       div     cl
+       cbw
+#if defined(MENU) || defined(BITMAP)
+       mov     di,[dimage]
+       mov     [dimage],ax
+       cmp     byte [abs_cx+1],#0      ; see if menu is displayed
+       je      fi_nochange
+       cmp     ax,di
+       je      fi_nochange2
+       xchg    ax,di
+       call    lowlite
+       xchg    ax,di
+fi_nochange2:
+       call    hilite
+fi_nochange:
+#endif
+       stc
+       jmp     fi_exit
+/* end new 22.7 */
+
+#if DEBUG_NEW
+; check that nobody has changed the FS register
+fs_check:
+       push    ax
+       mov     ax,fs
+       seg cs
+       cmp     ax,[firstseg]
+       je      fs_check_okay
+; oops, somebody changed it !!!
+       pop     ax      ; restore
+       pop     ax      ; get return
+       push    cs
+       pop     ds
+       sub     ax,#3   ; length of call
+       call    wout
+       mov     bx,#msg_fs_changed
+       br      zz
+fs_check_okay:
+#if CHECK_FS_VERBOSE
+       pusha
+       mov     bp,sp
+       mov     ax,16+2(bp)
+       sub     ax,#3
+       call    wout
+       mov     bx,#msg_fs_okay
+       push    ds
+       push    cs
+       pop     ds
+       call    say
+       pop     ds
+       popa
+#endif
+fs_check_ret:
+       pop     ax
+       ret
+msg_fs_changed:
+       .ascii  " <- loc where FS is clobbered\n"
+       .byte   0
+#if CHECK_FS_VERBOSE
+msg_fs_okay:
+       .ascii  " <- FS okay\n"
+       .byte   0
+#endif
+#endif
+
+! Some messages
+
+msg_p: .ascii  "boot: "
+       .byte   0
+
+msg_l: .ascii  "Loading "
+       .byte   0
+
+msg_bc:        .ascii  "BIOS data check "
+       .byte   0
+
+msg_s: .ascii  "successful\n"
+       .byte   0
+
+msg_by:        .ascii  "bypassed\n"
+       .byte   0
+
+msg_re:        .byte   10
+       .ascii  "Error 0x"
+       .byte   0
+
+msg_nf:        .ascii  "No such image. [Tab] shows a list."
+       .byte   10,0
+
+msg_time:
+       .ascii  "O - Timestamp mismatch\n"
+       .byte   0
+
+msg_chkerr:
+       .ascii  "O - Descriptor checksum error\n"
+       .byte   0
+
+msg_chkkey:
+       .ascii  "O - Keytable read/checksum error\n"
+       .byte   0
+
+msg_confl:
+       .ascii  "Kernel and Initrd memory conflict\n"
+       .byte   0
+
+msg_sigerr:
+       .ascii  "O - Signature not found\n"
+       .byte   0
+
+msg_me: .byte  10
+       .ascii  "vga/mem=  requires a numeric value"
+       .byte   10,0
+
+msg_wrerr:     .ascii  "\nMap file write; BIOS error code = 0x"
+       .byte   0
+
+msg_wrerr3:    .ascii  "\nMap file: WRITE PROTECT\n"
+       .byte   0
+
+#ifdef MEMORY_CHECK
+msg_mem: .ascii        "EBDA is big; kernel setup stack overlaps LILO second stage"
+       .byte   10,0
+#endif
+
+#ifdef LCF_VIRTUAL
+msg_vmwarn:
+       .ascii  "WARNING:  Booting in Virtual environment\n"
+       .ascii  "Do you wish to continue? [y/n] "
+       .byte   0
+#endif
+
+#if DEBUG_NEW
+sdx:   .ascii  " DX="
+       .byte   0
+
+msg_pl:        .ascii  "\nParameter line = "
+       .byte   0
+#ifdef LCF_NOKEYBOARD
+msg_kbtest:
+       .ascii  "**PC/AT Keyboard test**\n"
+       .byte   0
+#endif
+
+#if defined(LCF_VIRTUAL) || defined(LCF_NOKEYBOARD)
+msg_real:
+       .ascii  "Performing REAL MODE boot\n"
+       .byte   0
+
+#ifdef LCF_VIRTUAL
+msg_virtual:
+       .ascii  "Performing VIRTUAL MODE boot\n"
+       .byte   0
+#endif
+#ifdef LCF_NOKEYBOARD
+msg_no_keyboard:
+       .ascii  "Performing NO KEYBOARD DEFAULT boot\n"
+       .byte   0
+#endif
+#endif
+
+msg_where:
+       .ascii  "\nINIT SETUP CODE SS:SP  EX_OFF_DX 2ndDX\n"
+       .byte   0
+
+msg_low: .ascii        " low"
+       .byte   0
+
+msg_high:  .ascii " high"
+       .byte   0
+
+hdr1:  .ascii  "\nHeader 0x"
+       .byte   0
+
+hdr2:  .ascii  " cmdline at "
+       .byte   0
+
+hdr4:  .ascii  "   length = 0x"
+       .byte   0
+
+hdr3:  .ascii  "\nRamdisk_max "
+       .byte   0
+
+nohdrs:        .ascii  "\nNo cmdline passed"
+       .byte   0
+
+msg_rd2: .byte 10
+       .ascii  "RAM disk loaded at: "
+       .byte   0
+
+msg_hma: .ascii        " is the HMA\n"
+       .byte   0
+
+msg_gk:        .ascii  " returned by 'get_K'\n"
+       .byte   0
+
+#endif
+
+msg_int:.byte  10
+       .ascii  "*Interrupted*"
+       .byte   10,0
+
+msg_eof:.byte  10
+       .ascii  "Unexpected EOF"
+       .byte   10,0
+
+msg_pw:        .ascii  "Password: "
+       .byte   0
+
+msg_pf:        .ascii  "Sorry."
+       .byte   10,0
+
+msg_v: .byte   10
+       .ascii  "Valid vga values are ASK, NORMAL, EXTENDED or a "
+       .ascii  "decimal number."
+       .byte   10,0
+
+msg_pks:.byte  10
+       .ascii  "Invalid hexadecimal number. - Ignoring remaining items."
+       .byte   10,0
+
+msg_pkf:.byte  10
+       .ascii  "Keyboard buffer is full. - Ignoring remaining items."
+       .byte   10,0
+
+msg_bm:        .byte   10
+       .ascii  "Block move error 0x"
+       .byte   0
+
+#if 0
+msg_rd:        .byte   10
+       .ascii  "Not enough memory for RAM disk"
+       .byte   10,0
+#else
+msg_rd4M: .byte        10
+       .ascii  "Initial ramdisk loads below 4Mb; "
+       .ascii  "kernel overwrite is possible."
+       .byte   10,0
+#endif
+
+ospc:  .ascii  "O"
+#ifdef LCF_BEEP
+       .byte   7
+#endif
+#ifdef LCF_VERSION
+       .ascii  " "     
+       .ascii  SA(VERSION_MAJOR)
+       .ascii  "."
+       .ascii  SA(VERSION_MINOR)
+       .ascii  VERSION_EDIT
+#endif
+       .byte   32,0
+
+bs:    .byte   8,32,8,0
+
+#ifdef DEBUG
+stepa: .ascii  " RAM disk,"
+       .byte   0
+step0: .ascii  " map page,"
+       .byte   0
+step0b:        .ascii  " fallback,"
+       .byte   0
+step1: .ascii  " options,"
+       .byte   0
+step1b:        .ascii  " fallback,"
+       .byte   0
+step2: .ascii  " boot,"
+       .byte   0
+step3: .ascii  " setup,"
+       .byte   0
+step4: .ascii  " system "
+       .byte   0
+
+sax:   .ascii  "AX="
+       .byte   0
+sbx:   .ascii  " BX="
+       .byte   0
+scx:   .ascii  " CX="
+       .byte   0
+ses:   .ascii  " ES="
+       .byte   0
+sdone: .byte   10
+       .byte   0
+
+mov_ar:        .ascii  " -> "
+       .byte   0
+mov_sz:        .ascii  ", words "
+       .byte   0
+#endif
+
+       .even
+
+init_dx:       .word   0
+
+#if defined(MENU) || defined(BITMAP)
+suppress:.word 0               ; suppress console output (MUST be word)
+#endif
+hinib:  .byte   0               ; hi-nibble of address
+tempal:        .byte   0
+moff:  .word   0               ; map offset
+map:   .word   MAP             ; map to use
+
+cntdown:.word  0               ; count-down
+timeout:.byte  0               ; timed out
+
+dolock:        .byte   0
+
+int1c_l:.word  0               ; old timer interrupt
+int1c_h:.word  0
+
+old_del:.word  0               ; delay before booting
+
+nodfl: .word   0               ; action if no defaults are present
+
+#ifndef LCF_NOSERIAL
+slbase:        .word   0               ; serial port base (or 0 if unused)
+break: .byte   0               ; break received flag
+#endif
+
+usrinpm:.byte  UI_MAGIC
+
+cmdbeg:        .word   0
+options:.word  0
+
+rdbeg: .word   0,0             ; RAM dist begin address (dword)
+
+rdszl: .word   0               ; RAM disk size
+rdszh: .word   0
+
+vgaovr:        .word   0               ; VGA mode overwrite
+
+/* ifdef HIGHMEM_MAX */
+hma:   .word   0,0             ; Highest Memory Address
+memmap:        .word   0,0,0,0,0,0,0,0,0,0
+/* endif */
+dskprm:        .word   0,0,0,0,0,0
+
+       .even                   ; control alignment from here down
+acmdbeg:.ascii "auto "
+mcmdbeg:.ascii "BOOT_IMAGE"
+prechr:        .byte   32              ; space: guard double blank supression
+                               ; equal sign: variable assignment
+cmdline:.byte  0
+
+#ifdef BITMAP
+_line  =       cmdline+CL_LENGTH               ; must be 640 bytes long
+#endif
+       .org    *+4
+theend:
+
+lkwbuf =       cmdline+CL_LENGTH+2     ; this is a word
+lkcbuf =       lkwbuf+2
+theend2 =      lkcbuf+CL_LENGTH        ; lkcbuf is 256
+
+the_end1       = theend+511
+theends        =       the_end1/512
+       .org    theends*512-4
+       .long   X
+       .align  512
+max_secondary:
+
+#if 0
+/* the older version 21 layout */
+Map            =       max_secondary + SECTOR_SIZE
+Dflcmd         =       Map + SECTOR_SIZE
+Map2           =       Dflcmd
+Descr          =       Dflcmd + SECTOR_SIZE
+Keytable       =       Descr + SECTOR_SIZE*MAX_DESCR_SECS_asm
+ParmBSS                =       Keytable + SECTOR_SIZE
+#else
+/* a possible 22.5.6 layout puts the descriptors last */
+Map            =       max_secondary + SECTOR_SIZE
+Dflcmd         =       Map + SECTOR_SIZE
+Map2           =       Dflcmd
+Keytable       =       Dflcmd + SECTOR_SIZE
+Descr          =       Keytable + SECTOR_SIZE
+ParmBSS                =       Descr + SECTOR_SIZE*MAX_DESCR_SECS_asm
+#endif
+
+#if COMMAND_LINE_SIZE > 256
+BSSstart       =       ParmBSS
+Parmline       =       BSSstart + SECTOR_SIZE
+#else
+Parmline       =       ParmBSS
+BSSstart       =       Parmline + CL_LENGTH
+#endif
+
+!************************************
+!  BSS data:
+!     moved from  volume.S 
+
+#define BSS_DATA
+       .org    BSSstart
+#include "volume.S"
+#ifdef SHS_PASSWORDS
+#include "shs3.S"
+#endif
+
+       .align  512
+BSSend =       *
+BSSsize                =       BSSend-BSSstart
+
+
+Dataend                =       Parmline + SECTOR_SIZE
+
+       .org    max_secondary
+
+
+
+#if 0
+DESCR0 = DESCR+2
+#else
+DESCR0 = DESCR
+#endif
diff --git a/src/shs2.c b/src/shs2.c
new file mode 100644 (file)
index 0000000..64a2fcc
--- /dev/null
@@ -0,0 +1,243 @@
+/* shs2.c -- NIST proposed Secure Hash Standard
+*/
+/*
+   Written 2 September 1992, Peter C. Gutmann,
+   This implementation placed in the public domain.
+
+   Transcribed 2 October 2001, John Coffman.
+   Modified for FIPS PUB 180-1 (supercedes FIPS PUB 180)
+
+*/
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <string.h>
+
+#include "lilo.h"
+
+#ifdef SHS_PASSWORDS
+
+#include "shs2.h"
+
+#define SHS_DEBUG  0
+#define SHS_EXPAND 1
+
+/*  The SHS f() - functions */
+
+#define f1(x,y,z) ((x&y)|(~x&z))
+#define f2(x,y,z) (x^y^z)
+#define f3(x,y,z) ((x&y)|(x&z)|(y&z))
+#define f4(x,y,z) (x^y^z)
+
+/*  The SHS Mysterious Constants */
+
+#define K1 0x5A827999L
+#define K2 0x6ED9EBA1L
+#define K3 0x8F1BBCDCL
+#define K4 0xCA62C1D6L
+
+/*  SHS initial values */
+
+#define h0init 0x67452301L
+#define h1init 0xEFCDAB89L
+#define h2init 0x98BADCFEL
+#define h3init 0x10325476L
+#define h4init 0xC3D2E1F0L
+
+/*  32-bit rotate -- uses shift kludge */
+
+#define ROT(n,X) ((X<<n)|(X>>(32-n)))
+
+
+
+/*  The initial expanding function */
+
+#if SHS_EXPAND
+#define expand(count) temp=W[count-3]^W[count-8]^W[count-14]^W[count-16], W[count]=ROT(1,temp)
+#define w(t) W[t]
+#else
+#define w(t) (t<16?W[t]:(temp=W[(t+13)&15]^W[(t+8)&15]^W[(t+2)&15]^W[t&15],\
+W[t&15]=ROT(1,temp)))
+#endif
+
+/*  The four SHS sub-rounds  */
+#define subRound1(count) \
+   temp = f1(B,C,D) + K1 + E + w(count) + ROT(5,A),\
+   E = D,\
+   D = C,\
+   C = ROT(30,B),\
+   B = A,\
+   A = temp
+
+#define subRound2(count) \
+   temp = f2(B,C,D) + K2 + E + w(count) + ROT(5,A),\
+   E = D,\
+   D = C,\
+   C = ROT(30,B),\
+   B = A,\
+   A = temp
+
+#define subRound3(count) \
+   temp = f3(B,C,D) + K3 + E + w(count) + ROT(5,A),\
+   E = D,\
+   D = C,\
+   C = ROT(30,B),\
+   B = A,\
+   A = temp
+
+#define subRound4(count) \
+   temp = f4(B,C,D) + K4 + E + w(count) + ROT(5,A),\
+   E = D,\
+   D = C,\
+   C = ROT(30,B),\
+   B = A,\
+   A = temp
+
+
+SHS_INFO shsInfo;    /* global */
+static
+#if SHS_EXPAND
+   LONG W[80];
+#else
+   LONG W[16];
+#endif
+
+
+/*  initialize the SHS values  */
+void shsInit(void)
+{
+   shsInfo.digest[0] = h0init;
+   shsInfo.digest[1] = h1init;
+   shsInfo.digest[2] = h2init;
+   shsInfo.digest[3] = h3init;
+   shsInfo.digest[4] = h4init;
+
+   shsInfo.countLo = shsInfo.countHi = 0L;
+}
+
+
+/*  perform the SHS transformation  */
+
+static void shsTransform(void)
+{
+   int i;
+   LONG A, B, C, D, E, temp;
+
+/*  Step A.  Copy the data buffer into the work buffer */
+/*  done  */
+#if SHS_DEBUG>=1
+   for (i=0; i<16; i++)  printf("W[%d] = %08lX\n", i, W[i]);
+#endif
+
+/*  Step B.  Expand the 16 words into 64 temporary data words */
+#if SHS_EXPAND
+   for (i=16; i<80; i++)  expand(i);
+#endif
+
+/*  Step C.  Set up first buffer */
+   A = shsInfo.digest[0];
+   B = shsInfo.digest[1];
+   C = shsInfo.digest[2];
+   D = shsInfo.digest[3];
+   E = shsInfo.digest[4];
+
+/*  Step D.  Serious mangling, divided into 4 sub-rounds */
+   i = 0;
+   for (; i<20; i++)  subRound1(i);
+   for (; i<40; i++)  subRound2(i);
+   for (; i<60; i++)  subRound3(i);
+   for (; i<80; i++)  subRound4(i);
+
+/*  Step E.  Build message digest */
+   shsInfo.digest[0] += A;
+   shsInfo.digest[1] += B;
+   shsInfo.digest[2] += C;
+   shsInfo.digest[3] += D;
+   shsInfo.digest[4] += E;
+
+}
+
+#ifdef LITTLE_ENDIAN
+static void byteReverse(LONG buffer[], int byteCount)
+{
+   int count;
+   LONG value;
+
+   byteCount /= sizeof(LONG);
+   for (count=0; count<byteCount; count++) {
+      value = (buffer[count]<<16) | (buffer[count]>>16);
+      buffer[count] = ((value&0xff00ff00L)>>8)|((value&0x00ff00ffL)<<8);
+   }
+}
+#endif
+
+
+/*  Update SHS for a block of data */
+
+void shsUpdate(BYTE *buffer, int count)
+{
+   int remain;
+
+/* calculate index of space remaining in the work buffer */
+   remain = shsInfo.countLo & (SHS_BLOCKSIZE-1);
+
+/* update bitcount */
+   if ( (shsInfo.countLo + (LONG)count) < shsInfo.countLo )
+      shsInfo.countHi++;     /* carry into high bitcount */
+   shsInfo.countLo += (LONG)count;
+
+/* Process data in SHS_BLOCKSIZE chunks */
+   while (count >= SHS_BLOCKSIZE-remain) {
+      memcpy((BYTE*)&W+remain, buffer, SHS_BLOCKSIZE-remain);
+#ifdef LITTLE_ENDIAN
+      byteReverse(W, SHS_BLOCKSIZE);
+#endif
+      shsTransform();
+      buffer += SHS_BLOCKSIZE-remain;
+      count -= SHS_BLOCKSIZE-remain;
+      remain = 0;
+   }
+
+/* Handle any remaining bytes of data */
+   if (count) memcpy((BYTE*)&W+remain, buffer, count);
+}
+
+
+/*  Finalize the SHS function */
+void shsFinal(void)
+{
+   int count;
+
+/* Compute number of bytes mod 64 */
+   count = shsInfo.countLo & (SHS_BLOCKSIZE-1);
+
+/* Set the first char of padding to 0x80.  This is safe since there is
+      always at least one byte free */
+   ((BYTE*)W)[count++] = 0x80;
+
+/* Pad out to 56 mod 64 */
+   if (count > 56) {
+      memset((BYTE*)W + count, 0, SHS_BLOCKSIZE-count);
+#ifdef LITTLE_ENDIAN
+      byteReverse(W, SHS_BLOCKSIZE);
+#endif
+      shsTransform ();
+
+/* Now fill the next block with 56 bytes */
+      memset( W, 0, SHS_BLOCKSIZE-8);
+   }
+   else { /* Pad block to 56 bytes */
+      memset((BYTE*)W + count, 0, (SHS_BLOCKSIZE-8)-count);
+   }
+#ifdef LITTLE_ENDIAN
+   byteReverse(W, SHS_BLOCKSIZE-8);
+#endif
+/* Append length in bits and transform */
+   W[14] = (shsInfo.countHi<<3) + (shsInfo.countLo>>29);
+   W[15] = shsInfo.countLo<<3;
+
+   shsTransform ();
+}
+#endif /* SHS_PASSWORDS */
+/* end shs2.c */
+
diff --git a/src/shs2.h b/src/shs2.h
new file mode 100644 (file)
index 0000000..ac5073d
--- /dev/null
@@ -0,0 +1,47 @@
+/* shs2.h -- NIST secure hash standard */
+/*
+   Written 2 September 1992, Peter C. Gutmann,
+   This implementation placed in the public domain.
+
+   Transcribed 2 October 2001, John Coffman.
+
+*/
+
+#ifndef _SHS2_H
+#define _SHS2_H
+
+/*  Useful typedef's & defines */
+
+typedef unsigned char BYTE;
+typedef unsigned int  LONG;
+
+/*  The SHS block size and message digest sizes, in bytes */
+
+#define SHS_BLOCKSIZE      64
+#define SHS_DIGESTSIZE     20
+
+/*  The structure for storing SHS information */
+
+typedef struct {
+   LONG digest[5];         /* message digest */
+   LONG countLo, countHi;  /* 64-bit bitcount */
+   } SHS_INFO;
+
+extern SHS_INFO shsInfo;
+
+/*  Whether the machine is little-endian */
+
+#ifdef BIG_ENDIAN
+#undef BIG_ENDIAN
+#endif
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN
+#endif
+
+void shsInit(void);
+void shsUpdate(BYTE *buffer, int count);
+void shsFinal(void);
+
+#endif
+/* end shs.h */
+
diff --git a/src/shs3.S b/src/shs3.S
new file mode 100644 (file)
index 0000000..3d25402
--- /dev/null
@@ -0,0 +1,336 @@
+; shs3.S
+/*
+Copyright 2000-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+;
+;;;    group   dgroup _data
+
+;;;    segment _data public align=16 class=data
+
+;              global  _shsInfo
+#ifdef BSS_DATA
+#if 0
+               .align  4
+_shsInfo:
+shs_digest:    .blkb   5*4
+shs_count:     .blkb   2*4
+
+Wshs:        .blkb     16*4
+#else
+_shsInfo       =       *
+shs_digest     =       *
+               .org    *+5*4
+shs_count      =       *
+               .org    *+2*4
+
+Wshs           =       *
+               .org    *+16*4
+#endif
+#else
+
+;;;    segment _text public align=16 class=code
+
+#define Ashs eax
+#define Bshs esi
+#define Cshs ecx
+#define Dshs edx
+#define Eshs edi
+#define temp_shs ebp
+
+shsTransform:
+       push    bp
+       push    di
+       push    si
+
+       mov     di,#shs_digest    ;##
+       mov     Ashs,dword (di)
+       mov     Bshs,dword (di+4)
+       mov     Cshs,dword (di+8)
+       mov     Dshs,dword (di+12)
+       mov     Eshs,dword (di+16)
+       sub     bx,bx              ; count = 0
+
+;      align   4              ;align
+shs_F356:
+       mov     temp_shs,Bshs
+       and     temp_shs,Cshs
+       push    Bshs
+       not     Bshs
+       and     Bshs,Dshs
+       or      temp_shs,Bshs
+       pop     Bshs
+       add     temp_shs,#0x5a827999    ;##
+
+       call    shsTransCommon
+       
+       cmp     bx,#20*4                ;##
+       jb      shs_F356
+
+;      align   4              ;align
+shs_F359:
+       mov     temp_shs,Dshs
+       xor     temp_shs,Cshs
+       xor     temp_shs,Bshs
+       add     temp_shs,#0x6ed9eba1
+
+       call    shsTransCommon
+
+       cmp     bx,#40*4
+       jb      shs_F359
+
+;      align   4              ;align
+shs_F362:
+       mov     temp_shs,Cshs
+       and     temp_shs,Bshs
+       push    Cshs
+       or      Cshs,Bshs
+       and     Cshs,Dshs
+       or      temp_shs,Cshs
+       pop     Cshs
+       sub     temp_shs,#0x70e44324
+
+       call    shsTransCommon
+       
+       cmp     bx,#60*4
+       jb      shs_F362
+
+;      align   4              ;align
+shs_F365:
+       mov     temp_shs,Dshs
+       xor     temp_shs,Cshs
+       xor     temp_shs,Bshs
+       sub     temp_shs,#0x359d3e2a
+
+       call    shsTransCommon
+
+       cmp     bx,#80*4
+       jb      shs_F365
+
+       mov     bx,#shs_digest   ;##
+       add     dword (bx),Ashs
+       add     dword (bx+4),Bshs
+       add     dword (bx+8),Cshs
+       add     dword (bx+12),Dshs
+       add     dword (bx+16),Eshs
+
+       pop     si
+       pop     di
+       pop     bp
+       ret     
+
+;      align   4
+shsTransCommon:
+       add     temp_shs,Eshs
+       mov     Eshs,Dshs
+       mov     Dshs,Cshs
+       ror     Bshs,2
+       mov     Cshs,Bshs
+       mov     Bshs,Ashs
+       rol     Ashs,5
+       add     temp_shs,Ashs
+       cmp     bx,#16*4
+       jae     shsJ1
+       mov     Ashs,dword Wshs(bx)
+       jmp     shsJ2
+shsJ1:
+       push    bx
+       add     bx,#13*4
+       and     bx,#15*4
+       mov     Ashs,dword Wshs(bx)
+       sub     bx,#5*4
+       and     bx,#15*4
+       xor     Ashs,dword Wshs(bx)
+       sub     bx,#6*4
+       and     bx,#15*4
+       xor     Ashs,dword Wshs(bx)
+       sub     bx,#2*4
+       and     bx,#15*4
+       xor     Ashs,dword Wshs(bx)
+       rol     Ashs,1
+       mov     dword Wshs(bx),Ashs
+       pop     bx
+shsJ2:
+       add     Ashs,temp_shs
+       add     bx,#4
+       ret
+
+;      align   4
+byteReverse:
+       push    di
+       mov     cx,#16     ;##
+       mov     di,#Wshs            ;##
+
+;      align   4              ;align
+shs_F376:
+       mov     eax,dword (di)
+;;;    bswap   eax
+       xchg    ah,al
+       rol     eax,16
+       xchg    ah,al
+
+       stosd
+       loop    shs_F376
+
+       pop     di
+       ret
+
+
+
+;      align   4
+
+;      global  _shsInit, _shsUpdate, _shsFinal
+_shsInit:
+       push    bp
+       mov     bp,sp
+;      push    ds
+       push    di
+
+       mov     di,#shs_digest                  ;##
+       mov     dword (di),#0x67452301          ;##
+       mov     dword (di+4),#0xefcdab89
+       mov     dword (di+8),#0x98badcfe
+       mov     dword (di+12),#0x10325476
+       mov     dword (di+16),#0xc3d2e1f0       ;##
+       sub     eax,eax
+       mov     dword (di+20),eax
+       mov     dword (di+24),eax
+
+       pop     di
+;      pop     ds
+       leave
+       ret
+
+
+;      align   4
+
+_shsUpdate:
+       push    bp
+       mov     bp,sp
+
+;       buffer  [bp+4]
+;       count   [bp+6]
+
+       push    si
+       push    di
+;      push    ds
+
+       push    ds
+       pop     es
+
+;   remain = shsInfo.countLo & (SHS_BLOCKSIZE-1);
+       mov     di,[shs_count]
+       and     di,#63     ;##
+
+       movzx   eax,word (bp+6)      ;count
+       add     [shs_count],eax
+       adc     dword [shs_count+4],#0 ;##
+
+       mov     si,(bp+4)       ;buffer
+
+shs_J4:
+       mov     cx,#64     ;##
+       sub     cx,di      ;CX = SHS_BLOCKSIZE-remain
+       cmp     ax,cx      ; count >= SHS_BLOCKSIZE-remain
+       jb      shs_J6
+
+       add     di,#Wshs            ;##
+       sub     ax,cx      ; count -= SHS_BLOCKSIZE-remain
+       push    ax
+       rep
+#ifdef SHS_PASSWORDS
+         seg ss
+#endif
+            movsb         ;memcpy
+
+       call    byteReverse
+       call    shsTransform
+
+       pop     ax
+       sub     di,di      ;remain
+       jmp     shs_J4
+shs_J6:
+       add     di,#Wshs            ;##
+       mov     cx,ax
+       rep
+#ifdef SHS_PASSWORDS
+         seg ss
+#endif
+            movsb
+
+;      pop     ds
+       pop     di
+       pop     si
+       leave
+       ret
+
+;      align   4
+_shsFinal:
+       push    bp
+       mov     bp,sp
+       push    si
+       push    di
+;      push    ds
+
+       push    ds
+       pop     es
+
+       mov     di,[shs_count]
+       and     di,#63     ;##
+       mov     byte Wshs(di),#0x80     ;##
+       inc     di
+       sub     ax,ax
+       cmp     di,#56     ;##
+       jbe     shs_J10
+; count > 56
+       mov     cx,#64
+       sub     cx,di      ;SHS_BLOCKSIZE - count
+       add     di,#Wshs            ;##
+       rep
+            stosb
+
+       call    byteReverse
+       call    shsTransform
+
+       mov     cx,#56                   ;##
+       mov     di,#Wshs                    ;##
+       sub     ax,ax
+       jmp     shs_J11
+shs_J10:
+       mov     cx,#56     ;##
+       sub     cx,di
+       add     di,#Wshs            ;##
+shs_J11:
+       rep
+            stosb
+       call    byteReverse
+       mov     eax,[shs_count]
+       mov     ebx,[shs_count+4]
+       shld    ebx,eax,3
+       shl     eax,3
+       mov     [Wshs+14*4],ebx
+       mov     [Wshs+15*4],eax
+       call    shsTransform
+
+;      pop     ds
+       pop     di
+       pop     si
+       leave
+       ret
+
+#undef Ashs
+#undef Bshs
+#undef Cshs
+#undef Dshs
+#undef Eshs
+#undef temp_shs
+
+#endif /* BSS_DATA */
+
+; end shs3.S
+
diff --git a/src/strlen.S b/src/strlen.S
new file mode 100644 (file)
index 0000000..a64725e
--- /dev/null
@@ -0,0 +1,31 @@
+/* strlen.S
+
+ Copyright 2000-2004 John Coffman.
+ All rights reserved.
+
+ Licensed under the terms contained in the file 'COPYING' in the 
+ source directory.
+
+*/
+
+;
+; strlen:  find length of a string
+;      enter with:
+;              DS:BX = pointer to string
+;
+;      return with:
+;              AX = length of string
+;
+strlen:
+       mov     ax,bx
+strlen1:
+       test    byte (bx),#0xFF
+       jz      strlen2
+       inc     bx
+       jmp     strlen1
+strlen2:
+       sub     bx,ax
+       xchg    ax,bx
+       ret
+
+; end strlen.S
diff --git a/src/temp.c b/src/temp.c
new file mode 100644 (file)
index 0000000..2c6dd10
--- /dev/null
@@ -0,0 +1,133 @@
+/* temp.c  -  Temporary file registry */
+/* 
+Copyright 1992-1998 Werner Almesberger.
+Copyright 1999-2006 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "lilo.h"
+#include "common.h"
+#ifndef LILO_BINARY
+#include "temp.h"
+#include "loader.i"
+
+
+typedef struct _temp {
+    char *name;
+    struct _temp *next;
+} TEMP;
+
+
+static TEMP *list = NULL;
+
+
+void temp_register(char *name)
+{
+    TEMP *new;
+
+    new = alloc_t(TEMP);
+    new->name = stralloc(name);
+    new->next = list;
+    list = new;
+}
+
+
+void temp_unregister(char *name)
+{
+    TEMP **walk,*this;
+
+    for (walk = &list; *walk; walk = &(*walk)->next)
+       if (!strcmp(name,(*walk)->name)) {
+           this = *walk;
+           *walk = this->next;
+           free(this->name);
+           free(this);
+           return;
+       }
+    die("Internal error: temp_unregister %s",name);
+}
+
+
+void temp_remove(void)
+{
+    TEMP *next;
+
+    while (list) {
+       next = list->next;
+       if (remove(list->name) < 0)
+           warn("(temp) %s: %s",list->name,strerror(errno));
+       else if (verbose>=2) printf("Removed temporary file %s\n",list->name);
+       free(list->name);
+       free(list);
+       list = next;
+    }
+}
+
+
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef LCF_BUILTIN
+void process(char *file, char *name)
+{
+    struct stat buf;
+    int fd;
+    int nchar, nrd, i;
+#define NBUF 16
+    unsigned char data[NBUF];
+    
+    if ((fd = open(file, O_RDONLY)) < 0) exit(1);
+    if (fstat(fd, &buf)) exit(1);
+    
+    nchar = buf.st_size;
+    printf("struct { int size; unsigned char data[%d]; } %s = { %d, {",
+       nchar, name, nchar);
+    while (nchar>0) {
+       nrd = (nchar>NBUF ? NBUF : nchar);
+       if (read(fd, data, nrd) != nrd) exit(1);
+       for (i=0; i<nrd; i++) {
+           printf("%c%3d", i?',':'\n', (int)data[i]);
+       }
+       nchar -= nrd;
+       if (nchar>0) printf(",");
+    }
+    printf("}};\n");
+    close(fd);
+    return;
+}
+#endif
+
+int main(void)
+{
+    printf("/* begin loader ***/\n");
+#ifdef LCF_BUILTIN
+    process("first.b", "First");
+    process("second.b", "Second");
+    process("third.b", "Third");
+    process("bitmap.b", "Bitmap");
+    process("mbr.b", "Mbr");
+    process("mbr2.b", "Mbr2");
+    process("chain.b", "Chain");
+#ifndef LCF_SOLO_CHAIN
+    process("os2_d.b", "Os2_d");
+#endif
+#endif
+    printf("/*** end loader ***/\n");
+    return 0;
+}
+
+#endif
diff --git a/src/temp.h b/src/temp.h
new file mode 100644 (file)
index 0000000..a25f32b
--- /dev/null
@@ -0,0 +1,30 @@
+/* temp.h  -  Temporary file registry
+
+Copyright 1992-1995 Werner Almesberger.
+Copyright 1999-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+
+#ifndef TEMP_H
+#define TEMP_H
+
+#define temp_check(x) ((x)!=LILO)
+
+void temp_register(char *name);
+
+/* Registers a file for removal at exit. */
+
+void temp_unregister(char *name);
+
+/* Removes the specified file from the temporary file list. */
+
+void temp_remove(void);
+
+/* Removes all temporary files. */
+
+#endif
diff --git a/src/version.h b/src/version.h
new file mode 100644 (file)
index 0000000..107dc08
--- /dev/null
@@ -0,0 +1,11 @@
+/* version.h   */
+
+#ifndef VERSION_H
+#define VERSION_H
+
+#define VERSION_MAJOR 23
+#define VERSION_MINOR 1
+#define VERSION_EDIT  ""
+#define VERSION_DATE "04-Nov-2010"
+
+#endif
diff --git a/src/vesainfo.h b/src/vesainfo.h
new file mode 100644 (file)
index 0000000..c4b7354
--- /dev/null
@@ -0,0 +1,74 @@
+/* vesainfo.h */
+/*
+Copyright 2003-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+*/
+
+#ifndef _VESAINFO_H
+#define _VESAINFO_H
+
+#ifndef LILO_ASM
+#pragma pack(2)
+
+typedef
+   union {
+      char  space[512];
+      struct {
+         char  Signature[4];
+         short Version;
+         char  *OEMstring;             /* far pointer */
+         int  Capabilities;
+         short *VideoModePtr;          /* far pointer */
+         } ident;
+      struct {
+         short ModeAttributes;
+         char  WinAAttributes;
+         char  WinBAttributes;
+         short WinGranularity;
+         short WinSize;
+         short WinASegment;
+         short WinBSegment;
+         char *WinFuncPtr;          /* window swapping function */
+         short BytesPerScanLine;
+
+         /* Optional Information */
+         short Xresolution;
+         short Yresolution;
+ unsigned char XcharSize;
+ unsigned char YcharSize;
+         char  NumberOfPlanes;
+         char  BitsPerPixel;
+ unsigned char NumberOfBanks;
+         char  MemoryModel;
+ unsigned char BankSize;
+         } info;
+      } VESAINFO;
+
+#pragma pack()
+
+#else  /* LILO_ASM is defined */
+v_Signature    = 0             ; offset to Signature (int)
+v_Capabilities = 10            ; offset to Capabilities (int)
+
+v_ModeAttributes = 0           ; short
+v_WinAAttributes = 2           ; char
+v_WinBAttributes = 3           ; char
+v_WinGranularity = 4           ; short
+v_WinSize      = 6             ; short
+v_WinASegment  = 8             ; short
+v_WinBSegment  = 10            ; short
+v_WinFuncPointer = 12          ; far pointer
+v_BytesPerScanLine = 16                ; short
+
+#endif
+
+#define SIG_VBE2 0x32454256
+#define SIG_VESA 0x41534556
+
+#endif
+/* end vesainfo.h */
+
diff --git a/src/volume.S b/src/volume.S
new file mode 100644 (file)
index 0000000..322f9e3
--- /dev/null
@@ -0,0 +1,613 @@
+#if 0
+;  volume.S  is
+Copyright 2003-2004 John Coffman.
+All rights reserved.
+
+Licensed under the terms contained in the file 'COPYING' in the 
+source directory.
+
+#endif
+
+#ifdef BSS_DATA
+
+#if 0
+vtab:  .blkw   MAX_BIOS_DEVICES_asm*2  ; volume IDs indexed by
+                                       ;  REAL bios device code
+
+rtab:  .blkw   MAX_BIOS_DEVICES_asm*2  ; raid offsets indexed the same
+
+
+devmap:        .blkw   MAX_BIOS_DEVICES+2      ; device code map
+                                       ; logical -> physical
+                                       ; (lo-byte::hi-byte)
+#endif
+
+vtab   =       *
+       .org    *+MAX_BIOS_DEVICES_asm*4        ; volume IDs indexed by
+                                       ;  REAL bios device code
+
+rtab   =       *
+       .org    *+MAX_BIOS_DEVICES_asm*4        ; raid offsets indexed the same
+
+
+devmap =       *
+       .org    *+MAX_BIOS_DEVICES*2+4  ; device code map
+                                       ; logical -> physical
+                                       ; (lo-byte::hi-byte)
+
+#else
+
+rmask: .word   0               ; physical raid mask
+
+; build_vol_tab        -- Build the table of volume IDs
+;                      and fill in the device translate table
+;
+;   Enter with:
+;      DS=ES=CS
+;
+;   Exit with:
+;      Nothing
+;
+;   Side effects:      The volume ID table is built
+;                      The from:to device translate table is filled in
+;
+;
+build_vol_tab:
+       pusha
+
+       xor     cx,cx           ; depend on this being preserved
+       xor     dx,dx
+       xchg    [devmap],dx     ; clear our First Stage mapping
+
+       call    is_prev_mapper  ; is there a previous mapper
+       jz      bvt0
+
+; have previous mapper active
+
+; ****** 22.5.7
+       push    di
+       or      dx,dx           ; any translation?
+       jz      bvt003
+bvt001:
+       seg es
+       mov     ax,(di)         ; get previous translation
+       inc     di
+       inc     di
+       or      ax,ax
+       jz      bvt003
+       cmp     al,dh           ; does it affect us?
+       jne     bvt001
+       mov     [init_dx],ah    ; update physical device
+bvt003:
+       pop     di
+; ****** 22.5.7
+
+       seg es
+         mov   (di),cx         ; sterilize it
+bvt0:  
+       push    cs
+       pop     es              ; restore ES
+
+; ****** 22.5.8
+       mov     di,#KEYTABLE+256+mt_serial_no
+       mov     cx,#MAX_BIOS_DEVICES_asm
+       xor     eax,eax
+       repe
+         scasd                 ; scan for any serial nos in table
+       je      bvt90           ; if none, skip reading vol_ids
+                               ;    as there will be no translations
+; ****** 22.5.8
+
+
+       xor     cx,cx           ; start at hard drive 0 (0x80)
+       mov     di,#vtab        ; place to put IDs
+bvt1:
+       call    read_vol_id     ; get VolumeID in EAX
+       stosd                   ; store in table
+       or      eax,eax         ; test for zero
+       jz      bvt9            ; end, or no volume ID
+
+; now see if there will be a translation
+       push    di
+       push    cx
+
+; ****** 22.5.9
+       mov     cx,di           ; 4*table count to CX
+       mov     di,#vtab
+       sub     cx,di           ; 4*count
+       shr     cx,#2           ; table count
+       dec     cx
+       jz      bvt1.5          ; table empty
+       repne                   ; repeat while no match
+         scasd
+       jne     bvt1.5
+
+       mov     bx,#msg_dupl    ; duplicate message
+       call    say
+#if !DEBUG_NEW
+       call    pause
+#endif
+       pop     cx
+       pop     di
+
+       mov     dword (di-4),#0 ; zero the duplicated volumeID
+       jmp     bvt9            ; skip to next on duplication
+
+bvt1.5:
+; ****** 22.5.9
+       mov     si,#KEYTABLE+256+mt_serial_no
+       mov     cx,#MAX_BIOS_DEVICES_asm
+       mov     di,si
+bvt2:  jcxz    bvt7
+       repne                   ; repeat while not matching
+         scasd
+       jne     bvt7            ; jump if no match
+#if 0
+; print the raw serial_no match
+       pushad
+       push    eax
+       call    dout
+       call crlf
+       popad
+#endif
+       lea     dx,(di-4)       ; DX is address of match
+       sub     dx,si           ; DX is 4*index
+       shr     dx,#2           ; DX is input device #
+       pop     bx              ; BX is real device #
+       push    bx
+       cmp     bx,dx           
+; ****** 22.5.9
+;;;    je      bvt2            ; equal means no translation
+       je      bvt7            ; equal means no translation
+; ****** 22.5.9
+       mov     dh,bl           ;
+       or      dx,#0x8080      ; make into HD bios codes
+#if 0
+; print the raw TT entry
+       pusha
+       mov     ax,dx
+       call    wout
+       call    crlf
+       popa
+#endif
+       push    si
+       mov     bx,#devmap      ; scan the device translation table
+bvt4:
+       mov     si,(bx)         ; get from(low):to(high)  pair
+       inc     bx
+       inc     bx              ; bump pointer by 2
+       cmp     si,dx           ; duplicate?
+       je      bvt5
+
+       or      si,si           ; not duplicate; at end?
+       jnz     bvt4
+
+       mov     (bx-2),dx       ; put at end of table
+       mov     (bx),si         ; and mark new end
+bvt5:
+       pop     si
+; ****** 22.5.9
+;;;    jmp     bvt2
+; ****** 22.5.9
+
+bvt7:
+       pop     cx
+       pop     di
+bvt9:
+       inc     cx
+       cmp     cx,#MAX_BIOS_DEVICES_asm
+       jb      bvt1
+
+bvt90:
+; now build the RAID offset table
+
+       mov     si,#KEYTABLE+256+mt_raid_offset
+       mov     dx,[KEYTABLE+256+mt_raid_dev_mask]
+       xor     bx,bx           ; count thru devices
+bvt91:
+       xor     eax,eax         ; may store 0
+       shr     dx,#1           ; is it raid?
+       jnc     bvt92           ; not a raid device
+
+       lodsd                   ; get raid offset
+       push    eax             ; save value in stack
+
+       mov     eax,[KEYTABLE+256+mt_serial_no](bx)
+       mov     di,#vtab        ; physical table address
+       mov     cx,#MAX_BIOS_DEVICES_asm
+       repne
+         scasd                 ; scan for a match
+       jne     bvt_not_found   ; the logical volume is not there       
+       lea     di,(di-4-vtab)  ; DI is 4*index into table
+       mov     cx,di
+       shr     cx,#2           ; make 0..15
+       mov     ax,#1
+       shl     ax,cl           ; mask bit in right position
+       or      [rmask],ax
+       pop     dword ptr rtab(di)      ; store RAID offset
+       jmp     bvt92
+bvt_not_found:
+       pop     eax             ; clean up the stack
+bvt92:
+       add     bx,#4           ;
+       cmp     bx,#MAX_BIOS_DEVICES_asm*4
+       jb      bvt91
+
+#if DEBUG_NEW
+       mov     bx,#msg_voltab
+       call    say
+       mov     si,#vtab
+       mov     di,#rtab
+       mov     cx,#MAX_BIOS_DEVICES_asm
+;;;    mov     dx,[KEYTABLE+256+mt_raid_dev_mask] ; was logical mask
+       mov     dx,[rmask]              ; get physical mask value
+
+; truncate all the empty entries from the end of the list
+;
+bvtA:  mov     bx,cx
+       dec     bx
+       shl     bx,#2
+       cmp     dword ptr (bx+si),#0
+       jne     bvtA2
+       loop    bvtA            ; 22.6.1
+
+bvtA2: inc     cx
+
+bvtX:
+       lodsd                   ; get volume serial number
+       push    eax
+       call    dout            ; print it
+       shr     dx,#1
+       mov     bx,#msg_star
+       jc      bvtX1
+       mov     bx,#msg_nostar
+bvtX1:
+       call    say
+       push    dword (di)
+       call    dout
+       add     di,#4
+       call    crlf
+       loop    bvtX            ; loop back
+
+       call    crlf
+
+; now the device translate table:
+
+       mov     bx,#msg_tt
+       call    say
+       mov     si,#devmap
+bvtB:  lodsw                   ; get from,to pair
+       push    ax
+       call    bout
+       mov     bx,#msg_arr
+       call    say
+       pop     ax      
+       xchg    al,ah
+       push    ax
+       call    bout
+       call    crlf
+       pop     ax
+       or      ax,ax
+       jnz     bvtB
+       call    pause   
+#endif
+       popa            ; restore all the regs
+       ret
+
+msg_dupl:
+       .ascii  "O\nError: Duplicated Volume ID\n"
+       .byte   0
+#if DEBUG_NEW
+
+msg_voltab:
+       .ascii  "The physical VolumeID / Raid1-reloc table\n"
+       .byte   0
+msg_star:      .ascii  " * "
+       .byte   0
+msg_nostar:    .ascii  "   "
+       .byte   0
+msg_space = msg_nostar
+
+msg_tt:        .ascii  "The device translate table:\n"
+       .byte   0
+msg_arr:  .ascii       " -> "
+       .byte   0
+msg_plus: .ascii       " + "
+       .byte   0
+msg_rw:        .ascii  "RAID physical write: "
+       .byte   0
+#endif
+
+#ifdef LCF_READAHEAD
+; ****** 22.6.1 begin
+;
+; enable_readahead     -- Enable readahead on an EDD drive
+;
+;   Enter with:
+;      DL = hard disk BIOS code 
+;      ES=DS=CS
+;
+;   Return:
+;      Nothing         -- enable read-ahead, if possible
+;
+enable_readahead:
+       pusha
+#if DEBUG_NEW
+       push    dx              ; save device code
+       xchg    ax,dx
+       call    bout
+       pop     dx              ; restore device code
+#endif
+       mov     bx,#0x55AA      ;magic number
+       mov     ah,#0x41        ;function call
+       int     0x13
+       jc      enrd9
+       cmp     bx,#0xAA55      ;magic return
+       jne     enrd9
+       test    cl,#EDD_SUBSET|EDD_PACKET       ; some EDD support?
+       jz      enrd9
+#if 0
+       cmp     ah,#0x21        ; EDD version 1.1 or later?
+       jb      enrd9
+#endif
+
+       mov     ax,#0x4E00      ; enable prefetch
+       int     0x13
+#if DEBUG_NEW
+       mov     al,#'-          ; '
+       jc      enrd8_d
+       test    ah,ah           ; check return code in AH
+       jnz     enrd8_d
+       mov     al,#'+          ; '
+  enrd8_d:
+       call    display
+#endif
+
+enrd9:
+#if DEBUG_NEW
+       call    crlf
+#endif
+       popa
+       ret
+; ****** 22.6.1 end
+#endif
+
+
+; read_vol_id  -- Read the volume ID off of a drive
+;
+;   Enter with:
+;      CX = drive number to read (hard disk 0..15)
+;      ES=DS=CS
+;
+;   Return:
+;      Carry Clear on success
+;      EAX = volume ID         (0 means no ID)
+;
+;      Carry set on error
+;      EAX = 0
+;
+;
+read_vol_id:
+       push    bx
+       push    dx
+       push    cx
+       push    di
+
+       push    cx
+       push    es              ; paranoia (floppies touch it)
+
+       mov     ah,#8           ; get number of drives in DL
+       mov     dl,#0x80
+       call    dsk_do_int13    ; retry 5 times
+
+       pop     es
+       pop     cx              ; restore device code
+
+       jc      rvi_9
+       cmp     cl,dl
+       jae     rvi_9
+
+       mov     dl,cl
+       mov     cx,#1
+       mov     bx,#Map
+       or      dl,#0x80
+       mov     dh,ch
+; ****** 22.6.1
+#ifdef LCF_READAHEAD
+       call    enable_readahead
+#endif
+; ****** 22.6.1
+       mov     ax,#0x201       ; read
+       call    dsk_do_int13
+       jc      rvi_9
+
+       seg es
+         mov   eax,(bx+PART_TABLE_OFFSET-6)    ; fetch return
+       jmp     rvi_exit
+rvi_9:
+       xor     eax,eax
+       stc
+rvi_exit:
+       pop     di
+       pop     cx
+       pop     dx
+       pop     bx
+       ret
+
+
+; map_device -- Take the logical device code in DL and map it
+;              into the physical device code preserving all flags
+;      22.5.6  Any RAID relocated device code maps to the boot device code
+;
+;  Enter with:
+;      DL containing logical device code & flags
+;      DS register not guaranteed
+;
+;  Exit with:
+;      DL containing physical device code & same flags
+;
+;
+map_device:
+       push    si              ; save working registers
+       push    ax
+       push    bx
+       mov     si,#devmap      ; point at translation table
+       mov     bl,dl
+       and     bl,#DEV_MASK_asm        ; from device code in BL
+#if 1
+; ****** 22.5.6
+       seg cs
+       mov     ah,[init_dx]    ; get boot device code
+       test    dl,#RAID_REL_FLAG
+       jnz     bios_tt_match   ; it is RAID, go use the boot device code
+; ***** 22.5.6
+#endif
+bios_tt_next:
+       seg cs                  ; DS may be bad
+         lodsw                 ; get from/to pair
+       or      ax,ax           ; end of list?
+       jz      bios_tt_done
+       cmp     al,bl
+       jne     bios_tt_next
+; got a match
+bios_tt_match:
+       and     dl,#0xFF-DEV_MASK_asm   ; save flags
+       or      dl,ah           ; put on the TO device code
+bios_tt_done:
+       pop     bx
+       pop     ax
+       pop     si
+       ret
+
+
+#if 0
+
+; rev_map_device -- Take the physical device code in DL and map it
+;              into the logical device code preserving all flags
+;
+;  Enter with:
+;      DL containing physical device code & flags
+;
+;  Exit with:
+;      DL containing logical device code & same flags
+;
+;
+rev_map_device:
+       push    si              ; save working registers
+       push    ax
+       push    bx
+       mov     si,#devmap      ; point at translation table
+       mov     bl,dl
+       and     bl,#DEV_MASK_asm        ; TO device code in BL
+bios_tt_next:
+       lodsw                   ; get from/to pair
+       or      ax,ax           ; end of list?
+       jz      bios_tt_done
+       cmp     ah,bl
+       jne     bios_tt_next
+; got a match
+       and     dl,#0xFF-DEV_MASK_asm   ; save flags
+       or      dl,al           ; put on the FROM device code
+bios_tt_done:
+       pop     bx
+       pop     ax
+       pop     si
+       ret
+#endif
+
+
+; translate -- test for a raid device, and do the offsetting
+;
+;  Enter with:
+;      DI:CX   LBA32 or LINEAR address
+;      DL      physical device code & flags (RAID_REL_FLAG is set)
+;      AL      sector count
+;      ES:BX   buffer pointer for R/W
+;
+;  Exit with:
+;      DI:CX   updated if RAID translation takes place
+;      All other registers are unchanged
+;
+;
+translate:
+       push    bp
+       mov     bp,sp
+
+       cmp     word [rmask],#0         ; any translate bits set?
+       jnz     trans_1
+
+; this special cases the initial Keytable read, when no setup has been done
+       BEG_FS
+       SEG_FS
+       add     cx,par1_raid_offset+SSDIFF      ; ***** RAID ******
+       SEG_FS
+       adc     di,par1_raid_offset+2+SSDIFF    ; ***** RAID ******
+       END_FS
+       jmp     trans_ret
+
+trans_1:
+       push    di
+       push    cx      ; form  dword (bp-4)
+
+       mov     di,dx           ; DI gets full device code
+       and     di,#DEV_MASK_asm & 0x7F
+#if DEBUG_NEW
+       pusha
+       cmp     byte ptr [dsk_wrflag],#0
+       jz      trans_01
+       mov     bx,#msg_rw
+       call    say
+       mov     ax,di
+       or      ax,#0x80
+       call    bout
+       mov     bx,#msg_space
+       call    say
+       push    (bp-4+2)
+       push    (bp-4)
+       call    dout
+trans_01:
+       popa
+#endif
+       shl     di,#2   ; index into array
+
+       mov     cx,[rtab](di)   ; get low relocation value
+       mov     di,[rtab+2](di) ; get high relocation value
+#if DEBUG_NEW
+       pusha
+       cmp     byte ptr [dsk_wrflag],#0
+       jz      trans_02
+       mov     bx,#msg_plus
+       call    say
+       push    di
+       push    cx
+       call    dout
+       mov     bx,#msg_arr
+       call    say
+trans_02:
+       popa
+#endif
+
+       add     (bp-4),cx       ; relocate
+       adc     (bp-4+2),di     ;  **
+
+       pop     cx
+       pop     di
+#if DEBUG_NEW
+       pusha
+       cmp     byte ptr [dsk_wrflag],#0
+       jz      trans_03
+       push    di
+       push    cx
+       call    dout
+       call    crlf
+trans_03:
+       popa
+#endif
+
+trans_ret:
+       pop     bp
+       ret
+
+#endif /* BSS_DATA */
+
+/* end  volume.S */