--- /dev/null
+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)
+
--- /dev/null
+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.
--- /dev/null
+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)
--- /dev/null
+# -*- 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
--- /dev/null
+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".
+
--- /dev/null
+#!/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
--- /dev/null
+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
+
--- /dev/null
+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.
+
--- /dev/null
+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
--- /dev/null
+#! /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
--- /dev/null
+ 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.
--- /dev/null
+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
--- /dev/null
+# -*- 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 *~
+
--- /dev/null
+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
--- /dev/null
+ 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>
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+; 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:
+
+
--- /dev/null
+/* 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, ®, &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.h.ah = 0;
+ int86(0x10, ®, ®);
+#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, ®, ®);
+ 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.h.ah = 2; /* set cursor position */
+ reg.h.bh = 0;
+ reg.x.dx = 0x0000;
+ int86(0x10, ®, ®);
+#endif
+ } else {
+ reg.h.al = c;
+ reg.h.ah = 14;
+ reg.x.bx = 7;
+ int86(0x10, ®, ®);
+ }
+}
+
+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, ®, ®);
+ print_regs(®);
+
+ 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, ®, ®);
+ print_regs(®);
+ 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(®);
+
+ 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(®);
+ int86(0x15, ®, &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(®);
+ int86(0x15, ®, ®);
+ printf("\nReturns:\n ");
+ print_regs(®);
+ 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(®);
+ int86(0x10, ®, ®);
+ printf("\nReturns:\n ");
+ print_regs(®);
+ 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(®);
+ 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(®);
+ int86(0x10, ®, ®);
+ printf("\nReturns:\n ");
+ print_regs(®);
+ 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(®);
+ int86(0x10, ®, &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(®);
+ int86(0x10, ®, ®);
+ printf("\nReturns:\n ");
+ print_regs(®);
+ 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(®);
+ int86(0x13, ®, &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(®);
+ int86x(0x13, ®, ®, &sreg);
+ printf("\nReturns:\n ");
+ print_sregs(&sreg);
+ printf(" ");
+ print_regs(®);
+ 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(®);
+ int86(0x13, ®, ®);
+ printf("\nReturns:\n ");
+ print_regs(®);
+ 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, ®, ®);
+ 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(®);
+ int86(0x13, ®, &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(®);
+ int86x(0x13, ®, &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, ®, &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(®);
+ int86x(0x10, ®, &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(®);
+ int86x(0x10, ®, &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(®);
+ int86x(0x10, ®, &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();
+}
--- /dev/null
+/* 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.h.ah = 0;
+ int86(0x10, ®, ®);
+ } else {
+ reg.h.al = c;
+ reg.h.ah = 14;
+ reg.x.bx = 7;
+ int86(0x10, ®, ®);
+ }
+}
+
+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(®,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, ®, &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, ®, &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, ®, &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();
+ }
+}
--- /dev/null
+# -*- 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
--- /dev/null
+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.
--- /dev/null
+#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
--- /dev/null
+\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}
--- /dev/null
+% 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
+
+
--- /dev/null
+#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
--- /dev/null
+\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}
--- /dev/null
+#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
--- /dev/null
+\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}
--- /dev/null
+#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
--- /dev/null
+\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}
--- /dev/null
+#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
--- /dev/null
+\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}
--- /dev/null
+#!/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
--- /dev/null
+#!/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";
--- /dev/null
+%
+% 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}
--- /dev/null
+%
+% 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
--- /dev/null
+# -*- 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
+
--- /dev/null
+ 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
--- /dev/null
+# -*- 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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+# -*- 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))
+
--- /dev/null
+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).
+
--- /dev/null
+# 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
--- /dev/null
+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=
+====
--- /dev/null
+# 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,
--- /dev/null
+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
+====
--- /dev/null
+# 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,
--- /dev/null
+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=
+====
--- /dev/null
+# 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
--- /dev/null
+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=
+====
--- /dev/null
+# 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
--- /dev/null
+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
+====
--- /dev/null
+# 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
--- /dev/null
+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=
+====
--- /dev/null
+# 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
--- /dev/null
+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
+====
--- /dev/null
+#!/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;
+}
--- /dev/null
+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
--- /dev/null
+### 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_
+
--- /dev/null
+# -*- 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
--- /dev/null
+.\" '\" 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)
--- /dev/null
+'\" 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)
--- /dev/null
+'\" 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).
+
--- /dev/null
+'\" 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)
--- /dev/null
+#!/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
+
--- /dev/null
+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.
--- /dev/null
+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.
--- /dev/null
+ 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)
+
--- /dev/null
+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)
--- /dev/null
+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)
--- /dev/null
+ 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
--- /dev/null
+ 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)
+
+
--- /dev/null
+ 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)
--- /dev/null
+ 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.
+
--- /dev/null
+# -*- 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
--- /dev/null
+# /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
--- /dev/null
+#
+# 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 #
+#########################################
+
+
--- /dev/null
+#
+# 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 #
+#################################################
--- /dev/null
+# -*- 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
--- /dev/null
+/* 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 */
--- /dev/null
+; 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
--- /dev/null
+; 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
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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
+}
--- /dev/null
+/* 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
--- /dev/null
+!
+! 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
--- /dev/null
+/* 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(¶m2,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(¶m2.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(¶m2.keytab,1,0,0);
+#else
+ (void) map_write(¶m2.keytab,1,0);
+#endif
+ map_close(¶m2, 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 */
+}
+
+
--- /dev/null
+/* 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
--- /dev/null
+/* 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__ */
--- /dev/null
+/* 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
--- /dev/null
+; 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:
--- /dev/null
+/* 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 */
--- /dev/null
+#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
--- /dev/null
+/* 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
--- /dev/null
+#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
--- /dev/null
+/* 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;
+}
+
--- /dev/null
+/* 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
--- /dev/null
+/*
+; 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:
--- /dev/null
+/* 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
+
+
--- /dev/null
+#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 "$"
--- /dev/null
+/* 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
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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
--- /dev/null
+#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]
--- /dev/null
+/* 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, ¶ms);
+
+ 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
+
--- /dev/null
+/* 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
--- /dev/null
+#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
+
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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*)¶m2,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;
+}
--- /dev/null
+/* 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
+
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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__ */
+
--- /dev/null
+/* 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
--- /dev/null
+; 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 */
--- /dev/null
+; 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
--- /dev/null
+/*
+ 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
--- /dev/null
+#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
+
--- /dev/null
+/* 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;
+}
+
--- /dev/null
+/* 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
--- /dev/null
+/* 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
+
--- /dev/null
+/* 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 */
--- /dev/null
+; 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:
--- /dev/null
+/* 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;
+}
+
+
--- /dev/null
+/* 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);
+
--- /dev/null
+/*
+; 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
--- /dev/null
+#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
--- /dev/null
+/* 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 */
+
--- /dev/null
+/* 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 */
+
--- /dev/null
+; 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
+
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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 */
+
--- /dev/null
+#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 */