/*
 * Copyright (C) 2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#include "config.h"

#include <assert.h>
#include <getopt.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

char *progname;
int opt_d;
int opt_h;
int opt_i;
int opt_s;

static const char *string[10000];
static unsigned int nstrings = 0;

static struct choice {
	uint8_t val;
	uint16_t str;
} *choice[10000];
static unsigned int nchoices = 0;

#if 0
static struct {
	const char *title;
	const char *contents[25];
	unsigned int contents_nr[25];
} dialog[] = {
	{
		"Load SETUP Defaults", {
		"====================================",
		"=                                  =",
		"=   Load SETUP Defaults (Y/N)? *   =",
		"=                                  =",
		"====================================",
	}},
	{
		"Enter Password", {
		"|||||||||||||||||||||||||||||||",
		"| Enter Password:   ********  |",
		"|||||||||||||||||||||||||||||||",
	}},
	{
		"Confirm Password", {
		"|||||||||||||||||||||||||||||||",
		"| Confirm Password: ********  |",
		"|||||||||||||||||||||||||||||||",
	}},
	{
		"PASSWORD DISABLED", {
		"||||||||||||||||||||||||||||||||||||",
		"|      PASSWORD DISALBED !!!       |",
		"|   Press any key to continue...   |",
		"||||||||||||||||||||||||||||||||||||",
	}},
	{
		"SAVE to CMOS and EXIT", {
		"||||||||||||||||||||||||||||||||||||",
		"|                                  |",
		"|  SAVE to CMOS and EXIT (Y/N)? *  |",
		"|                                  |",
		"||||||||||||||||||||||||||||||||||||",
	}},
	{
		"Quit Without Saving", {
		"|||||||||||||||||||||||||||||||||||",
		"|                                 |",
		"|  Quit Without Saving (Y/N)? *   |",
		"|                                 |",
		"|||||||||||||||||||||||||||||||||||",
	}},
};
#endif

static struct {
	const char *title;
	const char *contents[25];
	unsigned int contents_nr[25];
} page[] = {
	{
		"CMOS SETUP UTILITY", {
		"                                                                                ",
		"                                                                                ",
		"                                                                                ",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@ ESC : Quit                              ^ v > <   : Select Item              @",
		"@ F10 : Save & Exit Setup                 (Shift)F2 : Change Color             @",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@                                                                              @",
		"@                                                                              @",
		"@                                                                              @",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
	}},
	{
		"STANDARD CMOS SETUP", {
		"                                                                                ",
		"                                                                                ",
		"                                                                                ",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@                                                                              @",
		"@    Date (mm:dd:yy) :                                                         @",
		"@    Time (hh:mm:ss) :                                                         @",
		"@                                                                              @",
		"@    HARD DISKS         TYPE    SIZE   CYLS HEAD PRECOMP LANDZ SECTOR  MODE    @",
		"@    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   @",
		"@    Primary Master   :                                                        @",
		"@    Primary Slave    :                                                        @",
		"@    Secondary Master :                                                        @",
		"@    Secondary Slave  :                                                        @",
		"@                                                                              @",
		"@    Drive A :                          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@    Drive B :                          @          Base Memory:       K        @",
		"@    Floppy 3 Mode Support :            @      Extended Memory:       K        @",
		"@                                       @         Other Memory:       K        @",
		"@    Video   :                          @      @@@@@@@@@@@@@@@@@@@@@@@         @",
		"@    Halt On :                          @                             K        @",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@ ESC : Quit               ^ v > <   : Select Item       PU/PD/+/- : Modify    @",
		"@ F1  : Help               (Shift)F2 : Change Color                            @",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
	}},
	{
		"BIOS FEATURES SETUP", {
		"                                                                                ",
		"                                                                                ",
		"                                                                                ",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@ Virus Warning              :          @ Video  BIOS Shadow  :                @",
		"@ CPU Internal Cache         :          @ C8000-CBFFF Shadow  :                @",
		"@ External Cache             :          @ CC000-CFFFF Shadow  :                @",
		"@ CPU L2 Cache ECC Checking  :          @ D0000-D3FFF Shadow  :                @",
		"@ Quick Power On Self Test   :          @ D4000-D7FFF Shadow  :                @",
		"@ CPU Update Data            :          @ D8000-DBFFF Shadow  :                @",
		"@ Boot Sequence              :          @ DC000-DFFFF Shadow  :                @",
		"@ Swap Floppy Drive          :          @                                      @",
		"@ VGA Boot From              :          @                                      @",
		"@ Boot Up Floppy Seek        :          @                                      @",
		"@ Boot Up NumLock Status     :          @                                      @",
		"@ Typematic Rate Setting     :          @                                      @",
		"@ Typematic Rate (Chars/Sec) :          @                                      @",
		"@ Typematic Delay (Msec)     :          @                                      @",
		"@ Security Option            :          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@ PCI/VGA Palette Snoop      :          @ ESC : Quit        ^v<> : Select Item @",
		"@ MPS Version Control For OS :          @ F1  : Help        PU/PD/+/- : Modify @",
		"@ OS Select For DRAM > 64MB  :          @ F5  : Old Values  (Shift)F2 : Color  @",
		"@                                       @ F7  : Load Setup Defaults            @",
		"@                                       @                                      @",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
	}},
	{
		"CHIPSET FEATURES SETUP", {
		"                                                                                ",
		"                                                                                ",
		"                                                                                ",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@ Auto Configuration       :            @ CPU Temperature Select   :           @",
		"@ DRAM Speed Selection     :            @ CPU1 Fan Failure Control :           @",
		"@ Memory Buffer Strength   :            @ CPU2 Fan Failure Control :           @",
		"@ DRAM Data Integrity Mode :            @ Current CPU Temperature  :           @",
		"@ Video RAM Cacheable      :            @ Current CPU Fan Status   :           @",
		"@ Memory Hole At 15M-16M   :            @ Current +12V Voltage     :           @",
		"@ Delayed Transaction      :            @ Current -12V Voltage     :           @",
		"@ SDRAM RAS-to-CAS Delay   :            @ Current +5V Voltage      :           @",
		"@ SDRAM RAS Precharge Time :            @ Current -5V Voltage      :           @",
		"@ SDRAM CAS latency Time   :            @ Current Battery Life     :           @",
		"@                                       @ CPU VCore Voltage        :           @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@                                       @ ESC : Quit        ^v<> : Select Item @",
		"@                                       @ F1  : Help        PU/PD/+/- : Modify @",
		"@                                       @ F5  : Old Values  (Shift)F2 : Color  @",
		"@                                       @ F7  : Load Setup Defaults            @",
		"@                                       @                                      @",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
	}},
	{
		"POWER MANAGEMENT SETUP", {
		"                                                                                ",
		"                                                                                ",
		"                                                                                ",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@ Power Management     :                @ ** Reload Global Timer Events **     @",
		"@ PM Control by APM    :                @ IRQ[3-7,9-15],NMI    :               @",
		"@                                       @ Primary IDE 0        :               @",
		"@ Suspend Mode         :                @ Primary IDE 1        :               @",
		"@ HDD Power Down       :                @ Secondary IDE 0      :               @",
		"@ Suspend Mode Option  :                @ Secondary IDE 1      :               @",
		"@ VGA Active Monitor   :                @ Floppy Disk          :               @",
		"@ Soft-Off by PWR-BTTN :                @ Serial Port          :               @",
		"@ CPUFAN Off In Suspend:                @ Parallel Port        :               @",
		"@ Resume by Alarm      :                @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @                                      @",
		"@                                       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@                                       @ ESC : Quit        ^v<> : Select Item @",
		"@                                       @ F1  : Help        PU/PD/+/- : Modify @",
		"@                                       @ F5  : Old Values  (Shift)F2 : Color  @",
		"@                                       @ F7  : Load Setup Defaults            @",
		"@                                       @                                      @",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
	}},
	{
		"PNP/PCI CONFIGURATION", {
		"                                                                                ",
		"                                                                                ",
		"                                                                                ",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@ PNP OS Installed         :            @ Used MEM base addr  :                @",
		"@ Resources Controlled By  :            @ Used MEM Length     :                @",
		"@ Reset Configuration Data :            @                                      @",
		"@                                       @                                      @",
		"@ IRQ-3  assigned to :                  @                                      @",
		"@ IRQ-4  assigned to :                  @                                      @",
		"@ IRQ-5  assigned to :                  @                                      @",
		"@ IRQ-7  assigned to :                  @                                      @",
		"@ IRQ-9  assigned to :                  @                                      @",
		"@ IRQ-10 assigned to :                  @                                      @",
		"@ IRQ-11 assigned to :                  @                                      @",
		"@ IRQ-12 assigned to :                  @                                      @",
		"@ IRQ-14 assigned to :                  @                                      @",
		"@ IRQ-15 assigned to :                  @                                      @",
		"@ DMA-0  assigned to :                  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@ DMA-1  assigned to :                  @ ESC : Quit        ^v<> : Select Item @",
		"@ DMA-3  assigned to :                  @ F1  : Help        PU/PD/+/- : Modify @",
		"@ DMA-5  assigned to :                  @ F5  : Old Values  (Shift)F2 : Color  @",
		"@ DMA-6  assigned to :                  @ F7  : Load Setup Defaults            @",
		"@ DMA-7  assigned to :                  @                                      @",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
	}},
	{
		"INTEGRATED PERIPHERALS", {
		"                                                                                ",
		"                                                                                ",
		"                                                                                ",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@ IDE HDD Block Mode       :            @                                      @",
		"@ IDE Primary Master PIO   :            @                                      @",
		"@ IDE Primary Slave  PIO   :            @                                      @",
		"@ IDE Secondary Master PIO :            @                                      @",
		"@ IDE Secondary Slave  PIO :            @                                      @",
		"@ IDE Primary Master UDMA  :            @                                      @",
		"@ IDE Primary Slave  UDMA  :            @                                      @",
		"@ IDE Secondary Master UDMA:            @                                      @",
		"@ IDE Secondary Slave  UDMA:            @                                      @",
		"@ On-Chip Primary   PCI IDE:            @                                      @",
		"@ On-Chip Secondary PCI IDE:            @                                      @",
		"@ Onboard PCI SCSI Chip    :            @                                      @",
		"@ SCSI Terminator Enable   :            @                                      @",
		"@ USB Keyboard Support     :            @                                      @",
		"@                                       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
		"@ Onboard FDD Controller   :            @ ESC : Quit        ^v<> : Select Item @",
		"@ Onboard Serial Port 1    :            @ F1  : Help        PU/PD/+/- : Modify @",
		"@ Onboard Serial Port 2    :            @ F5  : Old Values  (Shift)F2 : Color  @",
		"@ Onboard Parallel Port    :            @ F7  : Load Setup Defaults            @",
		"@ Onboard Parallel Mode    :            @                                      @",
		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
	}},
};

static struct {
	const char *entry_type;
	unsigned int reg_first;
	unsigned int reg_last;
	const char *reg_type;
	const char *reg_name;
	struct {
		unsigned int bit_first;
		unsigned int bit_last;
		const char *bit_menu;
		unsigned int bit_menu_nr;
		const char *bit_desc;
		unsigned int bit_x;
		unsigned int bit_y;
		struct {
			unsigned int val;
			const char *choice;
			unsigned int choice_nr;
		} choice[256];
	} bits[16];
} data[] = {
	   { "menu", 0, 0, NULL, NULL, {
		{ 1, 0,
		"CMOS SETUP UTILITY", 0,
		"", 5, 4, {
			{ 0, "STANDARD CMOS SETUP" },
		}},
		{ 2, 0,
		"CMOS SETUP UTILITY", 0,
		"", 5, 6, {
			{ 0, "BIOS FEATURES SETUP" },
		}},
		{ 3, 0,
		"CMOS SETUP UTILITY", 0,
		"", 5, 8, {
			{ 0, "CHIPSET FEATURES SETUP" },
		}},
		{ 4, 0,
		"CMOS SETUP UTILITY", 0,
		"", 5, 10, {
			{ 0, "POWER MANAGEMENT SETUP" },
		}},
		{ 5, 0,
		"CMOS SETUP UTILITY", 0,
		"", 5, 12, {
			{ 0, "PNP/PCI CONFIGURATION" },
		}},
		{ 6, 0,
		"CMOS SETUP UTILITY", 0,
		"", 5, 14, {
			{ 0, "INTEGRATED PERIPHERALS" },
		}},
		{ 0, 1,
		"CMOS SETUP UTILITY", 0,
		"", 5, 16, {
			{ 0, "LOAD SETUP DEFAULTS" },
		}},
		{ 1, 1,
		"CMOS SETUP UTILITY", 0,
		"", 45, 4, {
			{ 0, "USER PASSWORD" },
		}},
		{ 2, 1,
		"CMOS SETUP UTILITY", 0,
		"", 45, 6, {
			{ 0, "IDE HDD AUTO DETECTION" },
		}},
		{ 3, 1,
		"CMOS SETUP UTILITY", 0,
		"", 45, 8, {
			{ 0, "SAVE & EXIT SETUP" },
		}},
		{ 4, 1,
		"CMOS SETUP UTILITY", 0,
		"", 45, 10, {
			{ 0, "EXIT WITHOUT SAVING" },
		}},
	},
	}, { "cmos", 0x00, 0x00, "uint8_t", "seconds", { },
	}, { "cmos", 0x01, 0x01, "uint8_t", "seconds_alarm", { },
	}, { "cmos", 0x02, 0x02, "uint8_t", "minutes", { },
	}, { "cmos", 0x03, 0x03, "uint8_t", "minutes_alarm", { },
	}, { "cmos", 0x04, 0x04, "uint8_t", "hours", { },
	}, { "cmos", 0x05, 0x05, "uint8_t", "hours_alarm", { },
	}, { "cmos", 0x06, 0x06, "uint8_t", "day_of_week", { },
	}, { "cmos", 0x07, 0x07, "uint8_t", "day_of_month", { },
	}, { "cmos", 0x08, 0x08, "uint8_t", "month", { },
	}, { "cmos", 0x09, 0x09, "uint8_t", "year", { },
	}, { "cmos", 0x0a, 0x0a, "uint8_t", "stat_reg_a", { },
	}, { "cmos", 0x0b, 0x0b, "uint8_t", "stat_reg_b", { },
	}, { "cmos", 0x0c, 0x0c, "uint8_t", "stat_reg_c", { },
	}, { "cmos", 0x0d, 0x0d, "uint8_t", "stat_reg_d", { },
	}, { "cmos", 0x0e, 0x0e, "uint8_t", "x0e", { },
	}, { "cmos", 0x0f, 0x0f, "uint8_t", "x0f", { },

	}, { "cmos", 0x10, 0x10, "uint8_t", "fd_config", {
		{ 7, 4,
		"STANDARD CMOS SETUP", 0,
		"Drive A", 0, 0, {
			{ 4, "1.44M, 3.5 in. " },
			{ 5, "2.88M, 3.5 in. " },
			{ 0, "None           " },
			{ 1, "360K , 5.25 in." },
			{ 2, "1.2M , 5.25 in." },
			{ 3, "720K , 3.5 in. " },
		}},
		{ 3, 0,
		"STANDARD CMOS SETUP", 0,
		"Drive B", 0, 0, {
			{ 0, "None           " },
			{ 1, "360K , 5.25 in." },
			{ 2, "1.2M , 5.25 in." },
			{ 3, "720K , 3.5 in. " },
			{ 4, "1.44M, 3.5 in. " },
			{ 5, "2.88M, 3.5 in. " },
		}}
	},

	}, { "cmos", 0x11, 0x11, "uint8_t", "x11", {
		{ 7, 7,
		"BIOS FEATURES SETUP", 0,
		"Boot Up NumLock Status", 0, 0, {
			{ 1, "On " },
			{ 0, "Off" },
		}},
		/* 6, 5, ? */
		{ 4, 4,
		"BIOS FEATURES SETUP", 0,
		"CC000-CFFFF Shadow", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 3, 3,
		"BIOS FEATURES SETUP", 0,
		"C8000-CBFFF Shadow", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		/* 2, 2, ? */
		{ 1, 1,
		NULL, 0,
		"BIOS Password Enabled", 0, 0, {
		}},
		{ 0, 0,
		"BIOS FEATURES SETUP", 0,
		"Security Option", 0, 0, {
			{ 0, "Setup " },
			{ 1, "System" },
		}},
	},

	}, { "cmos", 0x12, 0x12, "uint8_t", "hd_config", {
		{ 7, 4,
		NULL, 0,
		"Drive C", 0, 0, {
		}},
		{ 3, 0,
		NULL, 0,
		"Drive D", 0, 0, {
		}},
	},

	}, { "cmos", 0x13, 0x13, "uint8_t", "x13", {
		{ 7, 7,
		"BIOS FEATURES SETUP", 0,
		"Typematic Rate Setting", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 6, 4,
		"BIOS FEATURES SETUP", 0,
		"Typematic Rate (Chars/Sec)", 0, 0, {
			{ 0, "6 " },
			{ 1, "8 " },
			{ 2, "10" },
			{ 3, "12" },
			{ 4, "15" },
			{ 5, "20" },
			{ 6, "24" },
			{ 7, "30" },
		}},
		{ 3, 2,
		"BIOS FEATURES SETUP", 0,
		"Typematic Delay (Msec)", 0, 0, {
			{ 0, "250 " },
			{ 1, "500 " },
			{ 2, "750 " },
			{ 3, "1000" },
		}},
		/* 1, 1, ? */
		{ 0, 0,
		"BIOS FEATURES SETUP", 0,
		"Boot Up Floppy Seek", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
	},

	}, { "cmos", 0x14, 0x14, "uint8_t", "x14", {
		{ 7, 6,
		NULL, 0,
		"Number of Floppy Drives", 0, 0, {
			{ 0, "1" },
			{ 1, "2" },
			{ 2, "3" },
			{ 3, "4" },
		}},
		{ 5, 4,
		"STANDARD CMOS SETUP", 0,
		"Video", 0, 0, {
			{ 0, "EGA/VGA" },
			{ 1, "CGA 40 " },
			{ 2, "CGA 80 " },
			{ 3, "MONO   " },
		}},
		{ 3, 3,
		NULL, 0,
		"Display enabled", 0, 0, {
		}},
		{ 2, 2,
		NULL, 0,
		"Keyboard enabled", 0, 0, {
		}},
		{ 1, 1,
		NULL, 0,
		"Math Coprocessor installed", 0, 0, {
			{ 1, "Yes" },
			{ 0, "No " },
		}},
		{ 0, 0,
		NULL, 0,
		"Floppy drive installed", 0, 0, {
			{ 1, "Yes" },
			{ 0, "No " },
		}},
	},

	}, { "cmos", 0x15, 0x16, "uint16_t", "basemem_1kb", {
		{ 15, 0,
		NULL, 0,
		"Base Memory (in KB)", 0, 0, {
			{ 0x280, "640KB" },
		}},
	},

	}, { "cmos", 0x17, 0x18, "uint16_t", "extmem_1kb", { },

	}, { "cmos", 0x19, 0x19, "uint8_t", "hd_extconfig0", {
		{ 7, 0,
		"STANDARD CMOS SETUP", 0,
		"type", 24, 10, {
			{ 0x2f, "Auto" },
			{ 0x2e, "User" },
			{ 0xfc, "None" },
		}},
	},

	}, { "cmos", 0x1a, 0x1a, "uint8_t", "hd_extconfig1", {
		{ 7, 0,
		"STANDARD CMOS SETUP", 0,
		"type", 24, 11, {
			{ 0x2f, "Auto" },
			{ 0x2e, "User" },
			{ 0xfc, "None" },
		}},
	},

	}, { "cmos", 0x1b, 0x1b, "uint8_t", "x1b", {
		{ 7, 7,
		"BIOS FEATURES SETUP", 0,
		"PCI/VGA Palette Snoop", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		/* 6, 4, ? */
		{ 3, 3,
		"BIOS FEATURES SETUP", 0,
		"DC000-DFFFF Shadow", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 2, 2,
		"BIOS FEATURES SETUP", 0,
		"D8000-DBFFF Shadow", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 1, 1,
		"BIOS FEATURES SETUP", 0,
		"D4000-D7FFF Shadow", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 0, 0,
		"BIOS FEATURES SETUP", 0,
		"D0000-D3FFF Shadow", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
	},

	}, { "cmos", 0x1c, 0x1d, "uint16_t", "password", { },

	}, { "cmos", 0x1e, 0x25, "struct {\n"
			"\t\tuint16_t cyls;\n"
			"\t\tuint8_t heads;\n"
			"\t\tuint16_t precomp;\n"
			"\t\tuint16_t landing;\n"
			"\t\tuint8_t secs;\n"
		"\t} PACKED", "hd_config_user1", { },

	}, { "cmos", 0x26, 0x2d, "struct {\n"
			"\t\tuint16_t cyls;\n"
			"\t\tuint8_t heads;\n"
			"\t\tuint16_t precomp;\n"
			"\t\tuint16_t landing;\n"
			"\t\tuint8_t secs;\n"
		"\t} PACKED", "hd_config_user0", { },

	}, { "cmos", 0x2e, 0x2e, "uint8_t", "chk0_high", { },
	}, { "cmos", 0x2f, 0x2f, "uint8_t", "chk0_low", { },

	}, { "cmos", 0x30, 0x31, "uint16_t", "mem_1kb", { },

	}, { "cmos", 0x32, 0x32, "uint8_t", "century", { },

	}, { "cmos", 0x33, 0x33, "uint8_t", "x33", {
		{ 7, 7,
		NULL, 0,
		"128k AT memory extension?", 0, 0, {
			{ 1, "present" },
			{ 0, "not present" },
		}},
		/* 6, 0, ? */
	},

	}, { "cmos", 0x34, 0x35, "uint8_t", "x34", { },
	}, { "cmos", 0x34, 0x35, "uint8_t", "x35", { },
	}, { "cmos", 0x36, 0x36, "uint8_t", "x36", { },
	}, { "cmos", 0x37, 0x37, "uint8_t", "x37", { },

	}, { "cmos", 0x38, 0x38, "uint8_t", "x38", {
		{ 7, 7,
		"CHIPSET FEATURES SETUP", 0,
		"SDRAM CAS latency Time", 0, 0, {
			{ 0, "2" },
			{ 1, "3" },
		}},
	},

	}, { "cmos", 0x39, 0x39, "uint8_t", "x39", { },
	}, { "cmos", 0x3a, 0x3a, "uint8_t", "x3a", { },

	}, { "cmos", 0x3b, 0x3b, "uint8_t", "x3b", {
		{ 7, 4,
		NULL, 0,
		"Screen colors for setup", 0, 0, {
			{ 0, "Yellow/White on Blue" },
			{ 1, "Magenta/White on Blue" },
			{ 2, "Yellow/Black on Green" },
			{ 3, "Yellow/Green on Cyan" },
			{ 4, "Black/Yellow on Cyan" },
			{ 5, "Brown/White on Cyan" },
			{ 6, "White/Green on Red" },
			{ 7, "White/White on Red" },
			{ 8, "Green/White on Magenta" },
			{ 9, "Yellow/Red on Magenta" },
			{ 10, "Red/White on Grey" },
			{ 11, "Yellow/White on Grey" },
			{ 12, "Cyan/White on Grey" },
			{ 13, "Cyan/Yellow on Black" },
			{ 14, "White on Black (Monochrome)" },
			{ 15, "Green/Red on Black" },
		}},
		/* 3, 2, ? */
		{ 1, 1,
		"BIOS FEATURES SETUP", 0,
		"CPU Internal Cache", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		{ 0, 0,
		"BIOS FEATURES SETUP", 0,
		"External Cache", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
	},

	}, { "cmos", 0x3c, 0x3c, "uint8_t", "x3c", {
		{ 7, 7,
		"BIOS FEATURES SETUP", 0,
		"Virus Warning", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		{ 6, 6,
		"BIOS FEATURES SETUP", 0,
		"OS Select For DRAM > 64MB", 0, 0, {
			{ 0, "Non-OS2" },
			{ 1, "OS2    " },
		}},
		/* 5, 5, ? */
		{ 4, 4,
		"BIOS FEATURES SETUP", 0,
		"Quick Power On Self Test", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		{ 3, 0,
		"BIOS FEATURES SETUP", 0,
		"Boot Sequence", 0, 0, {
			{ 3, "CDROM,C,A" }, /* Original Default: 0! */
			{ 4, "D,A,SCSI " },
			{ 5, "E,A,SCSI " },
			{ 6, "F,A,SCSI " },
			{ 7, "SCSI,A,C " },
			{ 8, "SCSI,C,A " },
			{ 9, "C only   " },
			{ 10, "LS/ZIP,C" },
			{ 0, "A,C,SCSI " },
			{ 1, "C,A,SCSI " },
			{ 2, "C,CDROM,A" },
		}},
	},

	}, { "cmos", 0x3d, 0x3d, "uint8_t", "x3d", { }, /* CPU Info FIXME */

	}, { "cmos", 0x3e, 0x3e, "uint8_t", "x3e", {
		{ 7, 7,
		"BIOS FEATURES SETUP", 0,
		"Video  BIOS Shadow", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		/* 6, 5, ? */
		{ 4, 4,
		"BIOS FEATURES SETUP", 0,
		"Swap Floppy Drive", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 3, 3,
		"BIOS FEATURES SETUP", 0,
		"CPU Update Data", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		{ 2, 0,
		"STANDARD CMOS SETUP", 0,
		"Halt On", 0, 0, {
			{ 0, "All Errors      " },
			{ 1, "No Errors       " },
			{ 2, "All,But Keyboard" },
			{ 4, "All,But Diskette" },
			{ 6, "All,But Disk/Key" },
		}},
	},

	}, { "cmos", 0x3f, 0x3f, "uint8_t", "x3f", {
#if 0
		{ 7, 0,
		NULL, 0,
		"Unknown", 0, 0, {
			{ 0x12, "Unknown" },
		}},
#endif
	},

	}, { "cmos", 0x40, 0x40, "uint8_t", "x40", {
		{ 1, 1,
		"BIOS FEATURES SETUP", 0,
		"VGA Boot From", 0, 0, {
			{ 0, "AGP" },
			{ 1, "PCI " },
		}},
	},

	}, { "cmos", 0x41, 0x41, "uint8_t", "x41", {
		{ 7, 7,
		"CHIPSET FEATURES SETUP", 0,
		"Video RAM Cacheable", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 6, 5,
		"CHIPSET FEATURES SETUP", 0,
		"Memory Buffer Strength", 0, 0, {
			{ 1, "Middle" },
			{ 2, "Low   " },
			{ 0, "High  " },
		}},
		{ 4, 4,
		"CHIPSET FEATURES SETUP", 0,
		"Memory Hole At 15M-16M", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
	},

	}, { "cmos", 0x42, 0x42, "uint8_t", "x42", {
		{ 7, 7,
		"CHIPSET FEATURES SETUP", 0,
		"Auto Configuration", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		{ 6, 6,
		"CHIPSET FEATURES SETUP", 0,
		"DRAM Speed Selection", 0, 0, {
			{ 0, "Normal" },
			{ 1, "Fast  " },
		}},
		{ 5, 5,
		"CHIPSET FEATURES SETUP", 0,
		"SDRAM RAS-to-CAS Delay", 0, 0, {
			{ 1, "Fast" },
			{ 0, "Slow" },
		}},
#if 0
		{ 4, 4,
		"CHIPSET FEATURES SETUP", 0,
		"DRAM Speed Selection", 0, 0, {
			{ 0, "Normal" },
			{ 1, "Fast  " },
		}},
#else
		{ 4, 4,
		"CHIPSET FEATURES SETUP", 0,
		"SDRAM RAS Precharge Time", 0, 0, {
			{ 1, "Fast" },
			{ 0, "Slow" },
		}},
#endif
	},

	}, { "cmos", 0x43, 0x43, "uint8_t", "x43", {
		{ 7, 6,
		"CHIPSET FEATURES SETUP", 0,
		"DRAM Data Integrity Mode", 0, 0, {
			{ 0, "Non-ECC" },
			{ 3, "ECC    " },
		}},
		{ 5, 5,
		"BIOS FEATURES SETUP", 0,
		"MPS Version Control For OS", 0, 0, {
			{ 1, "1.4" },
			{ 0, "1.1" },
		}},
		/* 4, 4, ? */
		{ 3, 3,
		"CHIPSET FEATURES SETUP", 0,
		"Delayed Transaction", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		/* 2, 2, ? */
		{ 1, 0,
		"INTEGRATED PERIPHERALS", 0,
		"SCSI Terminator Enable", 0, 0, {
			{ 3, "Both     " },
			{ 0, "None     " },
			{ 1, "Low Byte " },
			{ 2, "High Byte" },
		}},
	},

	}, { "cmos", 0x44, 0x44, "uint8_t", "x44", {
		{ 4, 4,
		"BIOS FEATURES SETUP", 0,
		"CPU L2 Cache ECC Checking", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
	},

	}, { "cmos", 0x45, 0x45, "uint8_t", "x45", {
		{ 7, 7,
		"INTEGRATED PERIPHERALS", 0,
		"Onboard PCI SCSI Chip", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		{ 6, 4,
		"INTEGRATED PERIPHERALS", 0,
		"IDE Primary Slave  PIO", 0, 0, {
			{ 0, "Auto  " },
			{ 1, "Mode 0" },
			{ 2, "Mode 1" },
			{ 3, "Mode 2" },
			{ 4, "Mode 3" },
			{ 5, "Mode 4" },
		}},
		{ 3, 3,
		"INTEGRATED PERIPHERALS", 0,
		"IDE HDD Block Mode", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		{ 2, 0,
		"INTEGRATED PERIPHERALS", 0,
		"IDE Primary Master PIO", 0, 0, {
			{ 0, "Auto  " },
			{ 1, "Mode 0" },
			{ 2, "Mode 1" },
			{ 3, "Mode 2" },
			{ 4, "Mode 3" },
			{ 5, "Mode 4" },
		}},
	},

	}, { "cmos", 0x46, 0x46, "uint8_t", "x46", {
		{ 7, 7,
		"INTEGRATED PERIPHERALS", 0,
		"On-Chip Primary   PCI IDE", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		{ 6, 4,
		"INTEGRATED PERIPHERALS", 0,
		"IDE Secondary Slave  PIO", 0, 0, {
			{ 0, "Auto  " },
			{ 1, "Mode 0" },
			{ 2, "Mode 1" },
			{ 3, "Mode 2" },
			{ 4, "Mode 3" },
			{ 5, "Mode 4" },
		}},
		{ 3, 3,
		"INTEGRATED PERIPHERALS", 0,
		"On-Chip Secondary PCI IDE", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		{ 2, 0,
		"INTEGRATED PERIPHERALS", 0,
		"IDE Secondary Master PIO", 0, 0, {
			{ 0, "Auto  " },
			{ 1, "Mode 0" },
			{ 2, "Mode 1" },
			{ 3, "Mode 2" },
			{ 4, "Mode 3" },
			{ 5, "Mode 4" },
		}},
	},

	}, { "cmos", 0x47, 0x47, "uint8_t", "x47", {
		{ 4, 4,
		"INTEGRATED PERIPHERALS", 0,
		"IDE Primary Slave  UDMA", 0, 0, {
			{ 1, "Auto    " },
			{ 0, "Disabled" },
		}},
		{ 3, 3,
		"INTEGRATED PERIPHERALS", 0,
		"IDE Secondary Slave  UDMA", 0, 0, {
			{ 1, "Auto    " },
			{ 0, "Disabled" },
		}},
		{ 2, 2,
		"INTEGRATED PERIPHERALS", 0,
		"IDE Secondary Master UDMA", 0, 0, {
			{ 1, "Auto    " },
			{ 0, "Disabled" },
		}},
		{ 1, 1,
		"INTEGRATED PERIPHERALS", 0,
		"USB Keyboard Support", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 0, 0,
		"INTEGRATED PERIPHERALS", 0,
		"IDE Primary Master UDMA", 0, 0, {
			{ 1, "Auto    " },
			{ 0, "Disabled" },
		}},
	},

	}, { "cmos", 0x48, 0x48, "uint8_t", "x48", { }, /* Unknown FIXME */

	}, { "cmos", 0x49, 0x49, "uint8_t", "x49", {
		{ 7, 5,
		"INTEGRATED PERIPHERALS", 0,
		"Onboard Serial Port 2", 0, 0, {
			{ 5, "Auto    " },
			{ 0, "Disabled" },
			{ 1, "COM1/3F8" },
			{ 2, "COM2/2F8" },
			{ 3, "COM3/3E8" },
			{ 4, "COM4/2E8" },
		}},
		{ 4, 2,
		"INTEGRATED PERIPHERALS", 0,
		"Onboard Serial Port 1", 0, 0, {
			{ 1, "COM1/3F8" },
			{ 2, "COM2/2F8" },
			{ 3, "COM3/3E8" },
			{ 4, "COM4/2E8" },
			{ 5, "Auto    " },
			{ 0, "Disabled" },
		}},
		/* 1, 1, ? FIXME */
		{ 0, 0,
		"INTEGRATED PERIPHERALS", 0,
		"Onboard FDD Controller", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
	},

	}, { "cmos", 0x4a, 0x4a, "uint8_t", "x4a", { },
	}, { "cmos", 0x4b, 0x4b, "uint8_t", "x4b", { },

	}, { "cmos", 0x4c, 0x4c, "uint8_t", "x4c", {
		{ 1, 0,
		"INTEGRATED PERIPHERALS", 0,
		"Onboard Parallel Port", 0, 0, {
			{ 2, "378/IRQ7" },
			{ 3, "278/IRQ5" },
			{ 0, "Disabled" },
			{ 1, "3BC/IRQ7" },
		}},
	},

	}, { "cmos", 0x4d, 0x4d, "uint8_t", "x4d", { },
	}, { "cmos", 0x4e, 0x4e, "uint8_t", "x4e", { },
	}, { "cmos", 0x4f, 0x4f, "uint8_t", "x4f", { },

	}, { "cmos", 0x50, 0x50, "uint8_t", "x50", {
		{ 3, 3,
		"POWER MANAGEMENT SETUP", 0,
		"PM Control by APM", 0, 0, {
			{ 1, "Yes" },
			{ 0, "No " },
		}},
		{ 1, 1,
		"POWER MANAGEMENT SETUP", 0,
		"Power Management", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
	},

	}, { "cmos", 0x51, 0x51, "uint8_t", "x51", { },

	}, { "cmos", 0x52, 0x52, "uint8_t", "x52", {
		{ 7, 4,
		"POWER MANAGEMENT SETUP", 0,
		"HDD Power Down", 0, 0, {
			{ 0, "Disable" },
			{ 1, "1 Min  " },
			{ 2, "2 Min  " },
			{ 3, "3 Min  " },
			{ 4, "4 Min  " },
			{ 5, "5 Min  " },
			{ 6, "6 Min  " },
			{ 7, "7 Min  " },
			{ 8, "8 Min  " },
			{ 9, "9 Min  " },
			{ 10, "10 Min " },
			{ 11, "11 Min " },
			{ 12, "12 Min " },
			{ 13, "13 Min " },
			{ 14, "14 Min " },
			{ 15, "15 Min " },
		}},
		{ 3, 0,
		"POWER MANAGEMENT SETUP", 0,
		"Suspend Mode", 0, 0, {
			{ 0, "Disable" }, /* FIXME */
			{ 2, "1 Min  " },
			{ 3, "2 Min  " },
			{ 4, "4 Min  " },
			{ 5, "8 Min  " },
			{ 6, "12 Min " },
			{ 7, "20 Min " },
			{ 8, "30 Min " },
			{ 9, "40 Min " },
			{ 10, "1 Hour " },
		}},
	},

	}, { "cmos", 0x53, 0x53, "uint8_t", "x53", {
		{ 7, 7,
		"POWER MANAGEMENT SETUP", 0,
		"Soft-Off by PWR-BTTN", 0, 0, {
			{ 0, "Instant-Off " },
			{ 1, "Delay 4 Sec." },
		}},
		{ 1, 1,
		"POWER MANAGEMENT SETUP", 0,
		"VGA Active Monitor", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 0, 0,
		"POWER MANAGEMENT SETUP", 0,
		"CPUFAN Off In Suspend", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
	},

	}, { "cmos", 0x54, 0x54, "uint8_t", "x54", {
		{ 2, 2,
		"POWER MANAGEMENT SETUP", 0,
		"Suspend Mode Option", 0, 0, {
			{ 0, "PowerOn Suspend" },
			{ 1, "Suspend to Disk" },
		}},
		{ 0, 0,
		"POWER MANAGEMENT SETUP", 0,
		"Resume by Alarm", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
	},

	}, { "cmos", 0x55, 0x55, "uint8_t", "alarm_day", { },
	}, { "cmos", 0x56, 0x56, "uint8_t", "alarm_hour", { },
	}, { "cmos", 0x57, 0x57, "uint8_t", "alarm_min", { },

	}, { "cmos", 0x58, 0x58, "uint8_t", "x58", { },

	}, { "cmos", 0x59, 0x59, "uint8_t", "x59", {
		{ 7, 7,
		"POWER MANAGEMENT SETUP", 0,
		"Secondary IDE 1", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 6, 6,
		"POWER MANAGEMENT SETUP", 0,
		"Primary IDE 1", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 5, 5,
		"POWER MANAGEMENT SETUP", 0,
		"Parallel Port", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 4, 4,
		"POWER MANAGEMENT SETUP", 0,
		"Serial Port", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		{ 3, 3,
		"POWER MANAGEMENT SETUP", 0,
		"Floppy Disk", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
		{ 2, 2,
		"POWER MANAGEMENT SETUP", 0,
		"Secondary IDE 0", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 1, 1,
		"POWER MANAGEMENT SETUP", 0,
		"Primary IDE 0", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Enabled " },
		}},
		{ 0, 0,
		"POWER MANAGEMENT SETUP", 0,
		"IRQ[3-7,9-15],NMI", 0, 0, {
			{ 1, "Enabled " },
			{ 0, "Disabled" },
		}},
	},

	}, { "cmos", 0x5a, 0x5a, "uint8_t", "x5a", { },
	}, { "cmos", 0x5b, 0x5b, "uint8_t", "x5b", { },
	}, { "cmos", 0x5c, 0x5c, "uint8_t", "x5c", { },

	}, { "cmos", 0x5d, 0x5d, "uint8_t", "x5d", {
		{ 7, 6,
		"STANDARD CMOS SETUP", 0,
		"Floppy 3 Mode Support", 0, 0, {
			{ 0, "Disabled" },
			{ 1, "Drive A " },
			{ 2, "Drive B " },
			{ 3, "Both    " },
		}},
		{ 2, 2,
		"PNP/PCI CONFIGURATION", 0,
		"PNP OS Installed", 0, 0, {
			{ 0, "No " },
			{ 1, "Yes " },
		}},
		{ 1, 1,
		"PNP/PCI CONFIGURATION", 0,
		"Reset Configuration Data", 0, 0, {
			{ 0, "Enabled " },
			{ 1, "Disabled" },
		}},
		{ 0, 0,
		"PNP/PCI CONFIGURATION", 0,
		"Resources Controlled By", 0, 0, {
			{ 1, "Manual" },
			{ 0, "Auto  " },
		}},
	},

	}, { "cmos", 0x5e, 0x5e, "uint8_t", "x5e", {
		{ 7, 7,
		"PNP/PCI CONFIGURATION", 0,
		"IRQ-12 assigned to", 0, 0, {
			{ 1, "Legacy ISA " },
			{ 0, "PCI/ISA PNP" },
		}},
		{ 6, 6,
		"PNP/PCI CONFIGURATION", 0,
		"IRQ-11 assigned to", 0, 0, {
			{ 0, "PCI/ISA PNP" },
			{ 1, "Legacy ISA " },
		}},
		{ 5, 5,
		"PNP/PCI CONFIGURATION", 0,
		"IRQ-10 assigned to", 0, 0, {
			{ 0, "PCI/ISA PNP" },
			{ 1, "Legacy ISA " },
		}},
		{ 4, 4,
		"PNP/PCI CONFIGURATION", 0,
		"IRQ-9  assigned to", 0, 0, {
			{ 0, "PCI/ISA PNP" },
			{ 1, "Legacy ISA " },
		}},
		{ 3, 3,
		"PNP/PCI CONFIGURATION", 0,
		"IRQ-7  assigned to", 0, 0, {
			{ 1, "Legacy ISA " },
			{ 0, "PCI/ISA PNP" },
		}},
		{ 2, 2,
		"PNP/PCI CONFIGURATION", 0,
		"IRQ-5  assigned to", 0, 0, {
			{ 0, "PCI/ISA PNP" },
			{ 1, "Legacy ISA " },
		}},
		{ 1, 1,
		"PNP/PCI CONFIGURATION", 0,
		"IRQ-4  assigned to", 0, 0, {
			{ 1, "Legacy ISA " },
			{ 0, "PCI/ISA PNP" },
		}},
		{ 0, 0,
		"PNP/PCI CONFIGURATION", 0,
		"IRQ-3  assigned to", 0, 0, {
			{ 1, "Legacy ISA " },
			{ 0, "PCI/ISA PNP" },
		}},
	},

	}, { "cmos", 0x5f, 0x5f, "uint8_t", "x5f", {
		{ 7, 7,
		"PNP/PCI CONFIGURATION", 0,
		"DMA-7  assigned to", 0, 0, {
			{ 0, "PCI/ISA PNP" },
			{ 1, "Legacy ISA " },
		}},
		{ 6, 6,
		"PNP/PCI CONFIGURATION", 0,
		"DMA-6  assigned to", 0, 0, {
			{ 0, "PCI/ISA PNP" },
			{ 1, "Legacy ISA " },
		}},
		{ 5, 5,
		"PNP/PCI CONFIGURATION", 0,
		"DMA-5  assigned to", 0, 0, {
			{ 0, "PCI/ISA PNP" },
			{ 1, "Legacy ISA " },
		}},
		{ 4, 4,
		"PNP/PCI CONFIGURATION", 0,
		"DMA-3  assigned to", 0, 0, {
			{ 0, "PCI/ISA PNP" },
			{ 1, "Legacy ISA " },
		}},
		{ 3, 3,
		"PNP/PCI CONFIGURATION", 0,
		"DMA-1  assigned to", 0, 0, {
			{ 0, "PCI/ISA PNP" },
			{ 1, "Legacy ISA " },
		}},
		{ 2, 2,
		"PNP/PCI CONFIGURATION", 0,
		"DMA-0  assigned to", 0, 0, {
			{ 0, "PCI/ISA PNP" },
			{ 1, "Legacy ISA " },
		}},
		{ 1, 1,
		"PNP/PCI CONFIGURATION", 0,
		"IRQ-15 assigned to", 0, 0, {
			{ 1, "Legacy ISA " },
			{ 0, "PCI/ISA PNP" },
		}},
		{ 0, 0,
		"PNP/PCI CONFIGURATION", 0,
		"IRQ-14 assigned to", 0, 0, {
			{ 1, "Legacy ISA " },
			{ 0, "PCI/ISA PNP" },
		}},
	},

	}, { "cmos", 0x60, 0x60, "uint8_t", "x60", {
		/* 7, 7, ? */
		/* 6, 6, ? */
		/* 5, 5, ? */
		{ 4, 3,
		"PNP/PCI CONFIGURATION", 0,
		"Used MEM Length", 0, 0, {
			{ 0, "8K " },
			{ 1, "16K" },
			{ 2, "32K" },
			{ 3, "64K" },
		}},
		{ 2, 0,
		"PNP/PCI CONFIGURATION", 0,
		"Used MEM base addr", 0, 0, {
			{ 0, "N/A " },
			{ 1, "C800" },
			{ 2, "CC00" },
			{ 3, "D000" },
			{ 4, "D400" },
			{ 5, "D800" },
			{ 6, "DC00" },
		}},
	},

	}, { "cmos", 0x61, 0x61, "uint8_t", "x61", { },
	}, { "cmos", 0x62, 0x62, "uint8_t", "x62", { },
	}, { "cmos", 0x63, 0x63, "uint8_t", "x63", { },
	}, { "cmos", 0x64, 0x64, "uint8_t", "x64", { },
	}, { "cmos", 0x65, 0x65, "uint8_t", "x65", { },
	}, { "cmos", 0x66, 0x66, "uint8_t", "x66", { },

	}, { "cmos", 0x67, 0x67, "uint8_t", "hd_extconfig2", {
		{ 7, 0,
		"STANDARD CMOS SETUP", 0,
		"type", 24, 12, {
			{ 0x2f, "Auto" },
			{ 0x2e, "User" },
			{ 0, "None" },
		}},
	},

	}, { "cmos", 0x68, 0x6f, "struct {\n"
			"\t\tuint16_t cyls;\n"
			"\t\tuint8_t heads;\n"
			"\t\tuint16_t precomp;\n"
			"\t\tuint16_t landing;\n"
			"\t\tuint8_t secs;\n"
		"\t} PACKED", "hd_config_user2", { },

	}, { "cmos", 0x70, 0x70, "uint8_t", "hd_extconfig3", {
		{ 7, 0,
		"STANDARD CMOS SETUP", 0,
		"type", 24, 13, {
			{ 0x2f, "Auto" },
			{ 0x2e, "User" },
			{ 0, "None" },
		}},
	},

	}, { "cmos", 0x71, 0x78, "struct {\n"
			"\t\tuint16_t cyls;\n"
			"\t\tuint8_t heads;\n"
			"\t\tuint16_t precomp;\n"
			"\t\tuint16_t landing;\n"
			"\t\tuint8_t secs;\n"
		"\t} PACKED", "hd_config_user3", { },

	}, { "cmos", 0x79, 0x79, "uint8_t", "x79", {
		{ 7, 6,
		"STANDARD CMOS SETUP", 0,
		"Primary Slave MODE", 70, 11, {
			{ 3, " AUTO " },
			{ 0, "NORMAL" },
			{ 1, " LBA  " },
			{ 2, "LARGE " },
		}},
		{ 5, 4,
		"STANDARD CMOS SETUP", 0,
		"Primary Master MODE", 70, 10, {
			{ 3, " AUTO " },
			{ 0, "NORMAL" },
			{ 1, " LBA  " },
			{ 2, "LARGE " },
		}},
		{ 3, 2,
		"STANDARD CMOS SETUP", 0,
		"Secondary Slave MODE", 70, 13, {
			{ 3, " AUTO " },
			{ 0, "NORMAL" },
			{ 1, " LBA  " },
			{ 2, "LARGE " },
		}},
		{ 1, 0,
		"STANDARD CMOS SETUP", 0,
		"Secondary Master MODE", 70, 12, {
			{ 3, " AUTO " },
			{ 0, "NORMAL" },
			{ 1, " LBA  " },
			{ 2, "LARGE " },
		}},
	},

	}, { "cmos", 0x7a, 0x7a, "uint8_t", "x7a", { },
	}, { "cmos", 0x7b, 0x7b, "uint8_t", "x7b", { },
	}, { "cmos", 0x7c, 0x7c, "uint8_t", "x7c", { },

	}, { "cmos", 0x7d, 0x7d, "uint8_t", "chk1_high", { },
	}, { "cmos", 0x7e, 0x7e, "uint8_t", "chk1_low", { },

	}, { "cmos", 0x7f, 0x7f, "uint8_t", "x7f", { },
	}
};

static void
gen_bios_cmos(void)
{
	uint8_t cmos[256];
	unsigned int var;
	unsigned int bit;
	uint16_t sum;
	int ret;

	memset(cmos, 0, sizeof(cmos));

	/* Setup Defaults */
	for (var = 0; var < sizeof(data) / sizeof(data[0]); var++) {
		if (strcmp(data[var].entry_type, "cmos") != 0) {
			continue;
		}
		for (bit = 0; data[var].bits[bit].bit_desc; bit++) {
			switch (data[var].reg_last - data[var].reg_first + 1) {
			case 1:
				/* One Byte Var */
				cmos[data[var].reg_first] |= data[var].bits[bit].choice[0].val << data[var].bits[bit].bit_last;
				break;
			case 2: {
				/* Two Byte Var */
				uint16_t *tmp = (uint16_t *)&cmos[data[var].reg_first];
				*tmp |= data[var].bits[bit].choice[0].val << data[var].bits[bit].bit_last;
				break;
			    }
			default:
				assert(0);
			}
		}
	}

	/* Fix Checksum 0 */
	sum = 0;
	for (var = 0x10; var < 0x2e; var++) {
		sum += cmos[var];
	}
	cmos[0x2e] = sum >> 8;
	cmos[0x2f] = sum & 0xff;

	/* Fix Checksum 1 */
	sum = 0;
	for (var = 0x40; var < 0x7d; var++) {
		sum += cmos[var];
	}
	cmos[0x7d] = sum >> 8;
	cmos[0x7e] = sum & 0xff;

	ret = write(1, cmos, sizeof(cmos));
	assert(ret == sizeof(cmos));
}

static void
gen_cmos_inc_h(void)
{
	unsigned int var;

	printf("/*\n");
	printf(" * Generated by %s.\n", progname);
	printf(" */\n");

	printf("\n");

	printf("struct cmos {\n");
	for (var = 0; var < sizeof(data) / sizeof(data[0]); var++) {
		if (strcmp(data[var].entry_type, "cmos") != 0) {
			continue;
		}
		printf("/*%02x*/\t%s %s;\n",
				data[var].reg_first,
				data[var].reg_type,
				data[var].reg_name);
	}
	printf("} PACKED;\n");
}

static unsigned int
merge(const char *str)
{
	unsigned int nr;

	for (nr = 0; ; nr++) {
		if (nr == nstrings) {
			string[nstrings] = strdup(str);
			assert(string[nstrings]);
			return nstrings++;
		}
		if (strcmp(string[nr], str) == 0) {
			return nr;
		}
	}
}

static unsigned int
choice_add(unsigned int val, const char *desc)
{
	choice[nchoices] = malloc(sizeof(*choice[nchoices]));
	assert(choice[nchoices]);
	choice[nchoices]->val = val;
	choice[nchoices]->str = merge(desc);
	return nchoices++;
}

static int
lookup(const char *s, const char *d)
{
	const char *p;

	if (strncmp(s, d, strlen(d)) != 0) {
		return 0;
	}
	p = s + strlen(d);
	while (*p == ' ') {
		p++;
	}
	if (*p != ':') {
		return 0;
	}
	p++;
	if (*p != ' ') {
		return 0;
	}
	p++;
	return p - s;
}

static void
gen_setup_c(void)
{
	unsigned int p;
	unsigned int var;
	unsigned int bit;
	unsigned int n;
	unsigned int x;
	unsigned int y;

	/*
	 * Fill page and position.
	 */
	for (var = 0; var < sizeof(data) / sizeof(data[0]); var++) {
		for (bit = 0; data[var].bits[bit].bit_desc; bit++) {
			if (! data[var].bits[bit].bit_menu) {
				data[var].bits[bit].bit_menu_nr = 0xff;
				continue;
			}

			/* Lookup Page */
			for (p = 0; ; p++) {
				if (p == sizeof(page) / sizeof(page[0])) {
					/* Page not found. */
					fprintf(stderr, "%s: Error: %s: %s.\n",
							progname,
							data[var].bits[bit].bit_menu,
							"Menu not found");
					exit(1);
				}
				if (strcmp(page[p].title, data[var].bits[bit].bit_menu) == 0) {
					break;
				}
			}
			data[var].bits[bit].bit_menu_nr = p;

			if (data[var].bits[bit].bit_x == 0
			 && data[var].bits[bit].bit_y == 0) {
				/* Lookup Position */
				for (y = 0; y < 25; y++) {
					for (x = 0; x < 80; x++) {
						unsigned int offset;

						offset = lookup(&page[p].contents[y][x],
							data[var].bits[bit].bit_desc);
						if (offset) {
							x += offset;
							goto found;
						}
					}
				}
				/* Description not found. */
				fprintf(stderr, "%s: Error: %s: %s.\n",
						progname,
						data[var].bits[bit].bit_desc,
						"Description not found");
				exit(1);

			found:	;
				data[var].bits[bit].bit_x = x;
				data[var].bits[bit].bit_y = y;
			}
		}
	}

	/*
	 * Substitute choices.
	 */
	for (var = 0; var < sizeof(data) / sizeof(data[0]); var++) {
		for (bit = 0; data[var].bits[bit].bit_desc; bit++) {
			unsigned int v;

			for (v = 0; data[var].bits[bit].choice[v].choice; v++) {
				data[var].bits[bit].choice[v].choice_nr
						= choice_add(data[var].bits[bit].choice[v].val,
							data[var].bits[bit].choice[v].choice);
			}
		}
	}

	/*
	 * Fix special characters in pages.
	 */
	for (p = 0; p < sizeof(page) / sizeof(page[0]); p++) {
		char line[81];
		char buf[81];

		sprintf(buf, "ROM PCI/ISA BIOS (%s)", PACKAGE_VERSION);
		for (x = 0; x < 40 - strlen(buf) / 2; x++) {
			line[x] = ' ';
		}
		strcpy(&line[x], buf);
		x += strlen(buf);
		for ( ; x < 80; x++) {
			line[x] = ' ';
		}
		line[x] = '\0';
		page[p].contents_nr[0] = merge(line);

		sprintf(buf, "%s", page[p].title);
		for (x = 0; x < 40 - strlen(buf) / 2; x++) {
			line[x] = ' ';
		}
		strcpy(&line[x], buf);
		x += strlen(buf);
		for ( ; x < 80; x++) {
			line[x] = ' ';
		}
		line[x] = '\0';
		page[p].contents_nr[1] = merge(line);

		sprintf(buf, "University Erlangen-Nuremberg");
		for (x = 0; x < 40 - strlen(buf) / 2; x++) {
			line[x] = ' ';
		}
		strcpy(&line[x], buf);
		x += strlen(buf);
		for ( ; x < 80; x++) {
			line[x] = ' ';
		}
		line[x] = '\0';
		page[p].contents_nr[2] = merge(line);

		for (y = 3; y < 25; y++) {
			for (x = 0; x < 80; x++) {
				uint8_t c;

				c = page[p].contents[y][x];
				if (c == '@') {
					if (x == 0 && y == 3) {
						c = 201;
					} else if (x == 0 && y == 24) {
						c = 200;
					} else if (x == 0 && page[p].contents[y][x + 1] == '@') {
						c = 199;
					} else if (x == 0) {
						c = 186;

					} else if (x == 79 && y == 3) {
						c = 187;
					} else if (x == 79 && y == 24) {
						c = 188;
					} else if (x == 79 && page[p].contents[y][x - 1] == '@') {
						c = 182;
					} else if (x == 79) {
						c = 186;

					} else if (y == 3 && page[p].contents[y + 1][x] == '@') {
						c = 209;
					} else if (y == 3) {
						c = 205;

					} else if (y == 24 && page[p].contents[y - 1][x] == '@') {
						c = 207;
					} else if (y == 24) {
						c = 205;

					} else if (page[p].contents[y][x - 1] == '@'
						&& page[p].contents[y][x + 1] == '@'
						&& page[p].contents[y + 1][x] == '@'
						&& page[p].contents[y - 1][x] == '@') {
						/*
						 *  |
						 * -+-
						 *  |
						 */
						c = 197;

					} else if (page[p].contents[y][x - 1] == '@'
						&& page[p].contents[y][x + 1] == '@'
						&& page[p].contents[y + 1][x] == '@') {
						/*
						 * -+-
						 *  |
						 */
						c = 194;

					} else if (page[p].contents[y][x - 1] == '@'
						&& page[p].contents[y][x + 1] == '@'
						&& page[p].contents[y - 1][x] == '@') {
						/*
						 *  |
						 * -+-
						 */
						c = 193;

					} else if (page[p].contents[y][x + 1] == '@'
						&& page[p].contents[y + 1][x] == '@'
						&& page[p].contents[y - 1][x] == '@') {
						/*
						 * |
						 * +-
						 * |
						 */
						c = 195;

					} else if (page[p].contents[y][x - 1] == '@'
						&& page[p].contents[y + 1][x] == '@'
						&& page[p].contents[y - 1][x] == '@') {
						/*
						 *  |
						 * -+
						 *  |
						 */
						c = 180;

					} else if (page[p].contents[y][x + 1] == '@'
						&& page[p].contents[y + 1][x] == '@') {
						/*
						 * +-
						 * |
						 */
						c = 218;

					} else if (page[p].contents[y][x + 1] == '@'
						&& page[p].contents[y - 1][x] == '@') {
						/*
						 * |
						 * +-
						 */
						c = 192;

					} else if (page[p].contents[y][x - 1] == '@'
						&& page[p].contents[y + 1][x] == '@') {
						/*
						 * -+
						 *  |
						 */
						c = 191;

					} else if (page[p].contents[y][x - 1] == '@'
						&& page[p].contents[y - 1][x] == '@') {
						/*
						 *  |
						 * -+
						 */
						c = 217;

					} else if (page[p].contents[y][x + 1] == '@') {
						c = 196;

					} else if (page[p].contents[y][x - 1] == '@') {
						c = 196;

					} else if (page[p].contents[y + 1][x] == '@') {
						c = 179;

					} else if (page[p].contents[y - 1][x] == '@') {
						c = 179;

					} else {
						assert(0);
					}

				} else if (c == '^'
					&& x + 6 <= 79
					&& page[p].contents[y][x + 2] == 'v'
					&& page[p].contents[y][x + 4] == '>'
					&& page[p].contents[y][x + 6] == '<') {
					c = 24;
				} else if (c == '^'
					&& x + 3 <= 79
					&& page[p].contents[y][x + 1] == 'v'
					&& page[p].contents[y][x + 2] == '<'
					&& page[p].contents[y][x + 3] == '>') {
					c = 24;
				} else if (c == 'v'
					&& 0 <= x - 2
					&& page[p].contents[y][x - 2] == '^'
					&& x + 4 <= 79
					&& page[p].contents[y][x + 2] == '>'
					&& page[p].contents[y][x + 4] == '<') {
					c = 25;
				} else if (c == 'v'
					&& 0 <= x - 1
					&& page[p].contents[y][x - 1] == '^'
					&& x + 3 <= 79
					&& page[p].contents[y][x + 1] == '<'
					&& page[p].contents[y][x + 2] == '>') {
					c = 25;
				} else if (c == '>'
					&& 0 <= x - 4
					&& page[p].contents[y][x - 4] == '^'
					&& page[p].contents[y][x - 2] == 'v'
					&& x + 2 <= 79
					&& page[p].contents[y][x + 2] == '<') {
					c = 27;
				} else if (c == '<'
					&& 0 <= x - 2
					&& page[p].contents[y][x - 2] == '^'
					&& page[p].contents[y][x - 1] == 'v'
					&& x + 1 <= 79
					&& page[p].contents[y][x + 1] == '>') {
					c = 27;
				} else if (c == '<'
					&& 0 <= x - 6
					&& page[p].contents[y][x - 6] == '^'
					&& page[p].contents[y][x - 4] == 'v'
					&& page[p].contents[y][x - 2] == '>') {
					c = 26;
				} else if (c == '>'
					&& 0 <= x - 3
					&& page[p].contents[y][x - 3] == '^'
					&& page[p].contents[y][x - 2] == 'v'
					&& page[p].contents[y][x - 1] == '<') {
					c = 26;
				}
				line[x] = c;
			}
			line[x] = '\0';
			page[p].contents_nr[y] = merge(line);
		}
	}
	/*
	 * Print info comment.
	 */
	printf("/* This files was generated by setup_gen.c */\n");

	/*
	 * Print strings.
	 */
	printf("static const char * const string[] = {\n");
	for (n = 0; n < nstrings; n++) {
		printf("\t\"%s\",\n", string[n]);
	}
	printf("};\n");

	/*
	 * Print choices.
	 */
	printf("static const struct choice {\n");
	printf("\tuint8_t val;\n");
	printf("\tuint16_t str;\n");
	printf("} choice[] = {\n");
	for (n = 0; n < nchoices; n++) {
		printf("\t{ %u, %u },\n", choice[n]->val, choice[n]->str);
	}
	printf("};\n");

	/*
	 * Print pages.
	 */
	printf("static const unsigned short page[][25] = {\n");
	for (p = 0; p < sizeof(page) / sizeof(page[0]); p++) {
		printf("\t{");
		for (y = 0; y < 25; y++) {
			printf(" %d,", page[p].contents_nr[y]);
		}
		printf("},\n");
	}
	printf("};\n");

	/*
	 * Print tables.
	 */
	printf("static const struct data {\n");
	printf("\tuint8_t cmos_reg;\n");
	printf("\tuint8_t bit_first;\n");
	printf("\tuint8_t bit_last;\n");
	printf("\tuint8_t menu_nr;\n");
	printf("\tuint8_t pos_x;\n");
	printf("\tuint8_t pos_y;\n");
	printf("\tuint16_t choice_nr;\n");
	printf("\tuint8_t choice_count;\n");
	printf("} data[] = {\n");
	for (var = 0; var < sizeof(data) / sizeof(data[0]); var++) {
		for (bit = 0; data[var].bits[bit].bit_desc; bit++) {
			for (n = 0; data[var].bits[bit].choice[n].choice; n++) {
			}
			printf("\t{ %u, %u, %u, %u, %u, %u, %u, %u },\n",
					data[var].reg_first,
					data[var].bits[bit].bit_first,
					data[var].bits[bit].bit_last,
					data[var].bits[bit].bit_menu_nr,
					data[var].bits[bit].bit_x,
					data[var].bits[bit].bit_y,
					data[var].bits[bit].choice[0].choice_nr,
					n);
		}
	}
	printf("};\n");
}

static void __attribute__((__noreturn__))
usage(int retval)
{
	fprintf(stderr, "Usage: %s -[d|h|i]\n", progname);
	fprintf(stderr, "\t-d: generate bios.cmos file\n");
	fprintf(stderr, "\t-h: show help (this text)\n");
	fprintf(stderr, "\t-i: generate cmos_inc.h file\n");
	exit(retval);
}

int
main(int argc, char **argv)
{
	int c;

	/*
	 * Get program name.
	 */
	progname = *argv;

	/*
	 * Get options.
	 */
	while ((c = getopt(argc, argv, "dhis")) != -1) {
		switch (c) {
		case 'd':
			opt_d = 1;
			break;
		case 'h':
			opt_h = 1;
			break;
		case 'i':
			opt_i = 1;
			break;
		case 's':
			opt_s = 1;
			break;
		default:
			usage(1);
		}
	}

	/*
	 * Check options.
	 */
	if (opt_d + opt_h + opt_i + opt_s != 1) {
		usage(1);
	}

	/*
	 * Do work.
	 */
	if (opt_d) {
		gen_bios_cmos();
	} else if (opt_h) {
		usage(0);
	} else if (opt_i) {
		gen_cmos_inc_h();
	} else { assert(opt_s);
		gen_setup_c();
	}

	return 0;
}
